about summary refs log tree commit diff stats
path: root/miasm2/expression/expression.py
diff options
context:
space:
mode:
authorAjax <commial@gmail.com>2017-03-29 15:09:23 +0200
committerAjax <commial@gmail.com>2017-03-30 16:04:40 +0200
commit056d8496468f36e9388588e3e28bb2379403eb80 (patch)
treec601457c227af71a60d61c9576b9220144c5091e /miasm2/expression/expression.py
parentcedf19e7d73ca8d603f2e1ed7f5306db27678e65 (diff)
downloadmiasm-056d8496468f36e9388588e3e28bb2379403eb80.tar.gz
miasm-056d8496468f36e9388588e3e28bb2379403eb80.zip
Let ExprInt always use its Singleton capabilities
Remove the optionnal 'size' argument form, use pointer equality to speed
up comparision
Diffstat (limited to 'miasm2/expression/expression.py')
-rw-r--r--miasm2/expression/expression.py88
1 files changed, 42 insertions, 46 deletions
diff --git a/miasm2/expression/expression.py b/miasm2/expression/expression.py
index e134e503..94c3825d 100644
--- a/miasm2/expression/expression.py
+++ b/miasm2/expression/expression.py
@@ -30,7 +30,7 @@
 
 import itertools
 from operator import itemgetter
-from miasm2.expression.modint import *
+from miasm2.expression.modint import mod_size2uint, is_modint, size2mask
 from miasm2.core.graph import DiGraph
 import warnings
 
@@ -143,10 +143,6 @@ class Expr(object):
             Expr.args2expr[(cls, args)] = expr
         return expr
 
-    def __new__(cls, *args, **kwargs):
-        expr = object.__new__(cls, *args, **kwargs)
-        return expr
-
     def get_is_canon(self):
         return self in Expr.canon_exprs
 
@@ -187,23 +183,18 @@ class Expr(object):
             self.__hash = self._exprhash()
         return self.__hash
 
-    def pre_eq(self, other):
-        """Return True if ids are equal;
-        False if instances are obviously not equal
-        None if we cannot simply decide"""
-
-        if id(self) == id(other):
+    def __eq__(self, other):
+        if self is other:
             return True
+        elif self.use_singleton:
+            # In case of Singleton, pointer comparison is sufficient
+            # Avoid computation of hash and repr
+            return False
+
         if self.__class__ is not other.__class__:
             return False
         if hash(self) != hash(other):
             return False
-        return None
-
-    def __eq__(self, other):
-        res = self.pre_eq(other)
-        if res is not None:
-            return res
         return repr(self) == repr(other)
 
     def __ne__(self, a):
@@ -246,8 +237,7 @@ class Expr(object):
         return ExprOp("**",self, a)
 
     def __invert__(self):
-        s = self.size
-        return ExprOp('^', self, ExprInt(mod_size2uint[s](size2mask(s))))
+        return ExprOp('^', self, self.mask)
 
     def copy(self):
         "Deep copy of the expression"
@@ -398,25 +388,12 @@ class ExprInt(Expr):
     __slots__ = Expr.__slots__ + ["__arg"]
 
 
-    def __init__(self, num, size=None):
+    def __init__(self, arg, size):
         """Create an ExprInt from a modint or num/size
-        @arg: modint or num
-        @size: (optionnal) int size"""
-
+        @arg: 'intable' number
+        @size: int size"""
         super(ExprInt, self).__init__()
-
-        if is_modint(num):
-            self.__arg = num
-            self.__size = self.arg.size
-            if size is not None and num.size != size:
-                raise RuntimeError("size must match modint size")
-        elif size is not None:
-            if size not in mod_size2uint:
-                define_uint(size)
-            self.__arg = mod_size2uint[size](num)
-            self.__size = self.arg.size
-        else:
-            raise ValueError('arg must by modint or (int,size)! %s' % num)
+        # Work is done in __new__
 
     size = property(lambda self: self.__size)
     arg = property(lambda self: self.__arg)
@@ -427,10 +404,29 @@ class ExprInt(Expr):
     def __setstate__(self, state):
         self.__init__(*state)
 
-    def __new__(cls, arg, size=None):
-        if size is None:
-            size = arg.size
-        return Expr.get_object(cls, (arg, size))
+    def __new__(cls, arg, size):
+        """Create an ExprInt from a modint or num/size
+        @arg: 'intable' number
+        @size: int size"""
+
+        if is_modint(arg):
+            assert size == arg.size
+        # Avoid a common blunder
+        assert not isinstance(arg, ExprInt)
+
+        # Ensure arg is always a moduint
+        arg = int(arg)
+        if size not in mod_size2uint:
+            define_uint(size)
+        arg = mod_size2uint[size](arg)
+
+        # Get the Singleton instance
+        expr = Expr.get_object(cls, (arg, size))
+
+        # Save parameters (__init__ is called with parameters unchanged)
+        expr.__arg = arg
+        expr.__size = expr.__arg.size
+        return expr
 
     def __get_int(self):
         "Return self integer representation"
@@ -1321,28 +1317,28 @@ def canonize_expr_list_compose(l):
 
 
 def ExprInt1(i):
-    return ExprInt(uint1(i))
+    return ExprInt(i, 1)
 
 
 def ExprInt8(i):
-    return ExprInt(uint8(i))
+    return ExprInt(i, 8)
 
 
 def ExprInt16(i):
-    return ExprInt(uint16(i))
+    return ExprInt(i, 16)
 
 
 def ExprInt32(i):
-    return ExprInt(uint32(i))
+    return ExprInt(i, 32)
 
 
 def ExprInt64(i):
-    return ExprInt(uint64(i))
+    return ExprInt(i, 64)
 
 
 def ExprInt_from(e, i):
     "Generate ExprInt with size equal to expression"
-    return ExprInt(mod_size2uint[e.size](i))
+    return ExprInt(i, e.size)
 
 
 def get_expr_ids_visit(e, ids):