compiler: monomorphize casts first, but more carefully.

This reverts 425cd7851, which broke the use of casts to define
integer width.

Instead of it, two steps are taken:
  * First, literals are monomorphized, leading to predictable result.
  * Second, casts are monomorphized, in a top-bottom way. I.e.
    consider the expression `int64(round(x))`. If round() was visited
    first, the intermediate precision would be 32-bit, which is
    clearly undesirable. Therefore, contextual rules should take
    priority over non-contextual ones.

Fixes #1252.
This commit is contained in:
whitequark 2019-02-07 06:07:55 +00:00
parent 0da799fa46
commit d6eb2b023a
2 changed files with 17 additions and 21 deletions

View File

@ -11,8 +11,6 @@ class CastMonomorphizer(algorithm.Visitor):
self.engine = engine self.engine = engine
def visit_CallT(self, node): def visit_CallT(self, node):
self.generic_visit(node)
if (types.is_builtin(node.func.type, "int") or if (types.is_builtin(node.func.type, "int") or
types.is_builtin(node.func.type, "int32") or types.is_builtin(node.func.type, "int32") or
types.is_builtin(node.func.type, "int64")): types.is_builtin(node.func.type, "int64")):
@ -30,3 +28,20 @@ class CastMonomorphizer(algorithm.Visitor):
node.args[0].type.unify(typ) node.args[0].type.unify(typ)
if types.is_builtin(node.func.type, "int") or \
types.is_builtin(node.func.type, "round"):
typ = node.type.find()
if types.is_var(typ["width"]):
typ["width"].unify(types.TValue(32))
self.generic_visit(node)
def visit_CoerceT(self, node):
if isinstance(node.value, asttyped.NumT) and \
builtins.is_int(node.type) and \
builtins.is_int(node.value.type) and \
not types.is_var(node.type["width"]) and \
types.is_var(node.value.type["width"]):
node.value.type.unify(node.type)
self.generic_visit(node)

View File

@ -26,22 +26,3 @@ class IntMonomorphizer(algorithm.Visitor):
return return
node.type["width"].unify(types.TValue(width)) node.type["width"].unify(types.TValue(width))
def visit_CallT(self, node):
self.generic_visit(node)
if types.is_builtin(node.func.type, "int") or \
types.is_builtin(node.func.type, "round"):
typ = node.type.find()
if types.is_var(typ["width"]):
typ["width"].unify(types.TValue(32))
def visit_CoerceT(self, node):
if isinstance(node.value, asttyped.NumT) and \
builtins.is_int(node.type) and \
builtins.is_int(node.value.type) and \
not types.is_var(node.type["width"]) and \
types.is_var(node.value.type["width"]):
node.value.type.unify(node.type)
self.generic_visit(node)