Explorar o código

Forgot to add numerics rule file in earlier commits (A).

Taddeus Kroes %!s(int64=14) %!d(string=hai) anos
pai
achega
6b90f9308d
Modificáronse 1 ficheiros con 80 adicións e 0 borrados
  1. 80 0
      src/rules/numerics.py

+ 80 - 0
src/rules/numerics.py

@@ -0,0 +1,80 @@
+from ..node import ExpressionLeaf as Leaf, TYPE_INTEGER, TYPE_FLOAT, OP_DIV
+from ..possibilities import Possibility as P
+from .utils import nary_node
+
+
+def match_divide_numerics(node):
+    """
+    Combine two constants to a single constant in a division, if it does not
+    lead to a decrease in precision.
+
+    Example:
+    6 / 2      ->  3
+    3 / 2      ->  3 / 2  # 1.5 would mean a decrease in precision
+    3.0 / 2    ->  1.5
+    3 / 2.0    ->  1.5
+    3.0 / 2.0  ->  1.5
+    3 / 1.0    ->  3      # Exceptional case: division of integer by 1.0 keeps
+                          # integer precision
+    """
+    assert node.is_op(OP_DIV)
+
+    n, d = node
+    n_int = n.type == TYPE_INTEGER
+    n_float = n.type == TYPE_FLOAT
+    d_int = d.type == TYPE_INTEGER
+    d_float = d.type == TYPE_FLOAT
+    nv, dv = n.value, d.value
+    divide = False
+
+    if n_int and d_int:
+        # 6 / 2  ->  3
+        # 3 / 2  ->  3 / 2
+        divide = not divmod(nv, dv)[1]
+    else:
+        if d_float and dv == 1.0:
+            # 3 / 1.0  ->  3
+            dv = 1
+
+        # 3.0 / 2  ->  1.5
+        # 3 / 2.0  ->  1.5
+        # 3.0 / 2.0  ->  1.5
+        divide = True
+
+    return [P(node, divide_numerics, (nv, dv))] if divide else []
+
+
+def divide_numerics(root, args):
+    """
+    Combine two constants to a single constant in a division.
+
+    Examples:
+    6 / 2      ->  3
+    3.0 / 2    ->  1.5
+    3 / 2.0    ->  1.5
+    3.0 / 2.0  ->  1.5
+    3 / 1.0    ->  3
+    """
+    n, d = args
+
+    return Leaf(n / d)
+
+
+def add_numerics(root, args):
+    """
+    Combine two constants to a single constant in an n-ary plus.
+
+    Example:
+    2 + 3  ->  5
+    """
+    n0, n1, c0, c1 = args
+
+    scope = root.get_scope()
+
+    # Replace the left node with the new expression
+    scope[scope.index(n0)] = Leaf(c0 + c1)
+
+    # Remove the right node
+    scope.remove(n1)
+
+    return nary_node('+', scope)