From 196acb37f640017e95425d808014eb5b289f734e Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 2 Jul 2015 19:49:52 +0300 Subject: [PATCH] Add IntMonomorphizer. --- artiq/compiler/module.py | 15 ++++++---- artiq/compiler/transforms/__init__.py | 1 + .../compiler/transforms/asttyped_rewriter.py | 5 ++++ artiq/compiler/transforms/inferencer.py | 7 ++++- .../compiler/transforms/int_monomorphizer.py | 28 +++++++++++++++++++ artiq/compiler/types.py | 4 +-- 6 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 artiq/compiler/transforms/int_monomorphizer.py diff --git a/artiq/compiler/module.py b/artiq/compiler/module.py index 82b1ef455..e3e8280f0 100644 --- a/artiq/compiler/module.py +++ b/artiq/compiler/module.py @@ -8,15 +8,18 @@ from . import prelude, types, transforms class Module: def __init__(self, source_buffer, engine=diagnostic.Engine(all_errors_are_fatal=True)): - parsetree, comments = parse_buffer(source_buffer, engine=engine) - self.name = os.path.basename(source_buffer.name) - asttyped_rewriter = transforms.ASTTypedRewriter(engine=engine) - typedtree = asttyped_rewriter.visit(parsetree) - self.globals = asttyped_rewriter.globals - inferencer = transforms.Inferencer(engine=engine) + int_monomorphizer = transforms.IntMonomorphizer(engine=engine) + + parsetree, comments = parse_buffer(source_buffer, engine=engine) + typedtree = asttyped_rewriter.visit(parsetree) inferencer.visit(typedtree) + int_monomorphizer.visit(typedtree) + inferencer.visit(typedtree) + + self.name = os.path.basename(source_buffer.name) + self.globals = asttyped_rewriter.globals @classmethod def from_string(klass, source_string, name="input.py", first_line=1): diff --git a/artiq/compiler/transforms/__init__.py b/artiq/compiler/transforms/__init__.py index 749508a5a..795c14c79 100644 --- a/artiq/compiler/transforms/__init__.py +++ b/artiq/compiler/transforms/__init__.py @@ -1,2 +1,3 @@ from .asttyped_rewriter import ASTTypedRewriter from .inferencer import Inferencer +from .int_monomorphizer import IntMonomorphizer diff --git a/artiq/compiler/transforms/asttyped_rewriter.py b/artiq/compiler/transforms/asttyped_rewriter.py index 065c05ee0..13ba60361 100644 --- a/artiq/compiler/transforms/asttyped_rewriter.py +++ b/artiq/compiler/transforms/asttyped_rewriter.py @@ -1,3 +1,8 @@ +""" +:class:`ASTTypedRewriter` rewrites a parsetree (:mod:`pythonparser.ast`) +to a typedtree (:mod:`..asttyped`). +""" + from pythonparser import algorithm, diagnostic from .. import asttyped, types, builtins, prelude diff --git a/artiq/compiler/transforms/inferencer.py b/artiq/compiler/transforms/inferencer.py index f78acea22..f4aa14d5e 100644 --- a/artiq/compiler/transforms/inferencer.py +++ b/artiq/compiler/transforms/inferencer.py @@ -1,3 +1,7 @@ +""" +:class:`Inferencer` performs unification-based inference on a typedtree. +""" + from collections import OrderedDict from pythonparser import algorithm, diagnostic, ast from .. import asttyped, types, builtins @@ -168,6 +172,7 @@ class Inferencer(algorithm.Visitor): if coerced_node.type.find() == typ.find(): return coerced_node elif isinstance(coerced_node, asttyped.CoerceT): + node = coerced_node node.type, node.other_expr = typ, other_node else: node = asttyped.CoerceT(type=typ, expr=coerced_node, other_expr=other_node, @@ -191,7 +196,7 @@ class Inferencer(algorithm.Visitor): elif any(map(builtins.is_float, node_types)): typ = builtins.TFloat() elif any(map(builtins.is_int, node_types)): - widths = map(builtins.get_int_width, node_types) + widths = list(map(builtins.get_int_width, node_types)) if all(widths): typ = builtins.TInt(types.TValue(max(widths))) else: diff --git a/artiq/compiler/transforms/int_monomorphizer.py b/artiq/compiler/transforms/int_monomorphizer.py new file mode 100644 index 000000000..3aeed9140 --- /dev/null +++ b/artiq/compiler/transforms/int_monomorphizer.py @@ -0,0 +1,28 @@ +""" +:class:`IntMonomorphizer` collapses the integer literals of undetermined +width to 32 bits, assuming they fit into 32 bits, or 64 bits if they +do not. +""" + +from pythonparser import algorithm, diagnostic +from .. import types, builtins + +class IntMonomorphizer(algorithm.Visitor): + def __init__(self, engine): + self.engine = engine + + def visit_NumT(self, node): + if builtins.is_int(node.type): + if types.is_var(node.type["width"]): + if -2**31 < node.n < 2**31-1: + width = 32 + elif -2**63 < node.n < 2**63-1: + width = 64 + else: + diag = diagnostic.Diagnostic("error", + "integer literal out of range for a signed 64-bit value", {}, + node.loc) + self.engine.process(diag) + return + + node.type["width"].unify(types.TValue(width)) diff --git a/artiq/compiler/types.py b/artiq/compiler/types.py index 4db3fa2be..239373768 100644 --- a/artiq/compiler/types.py +++ b/artiq/compiler/types.py @@ -168,8 +168,8 @@ class TFunction(Type): if isinstance(other, TFunction) and \ self.args.keys() == other.args.keys() and \ self.optargs.keys() == other.optargs.keys(): - for selfarg, otherarg in zip(self.args.values() + self.optargs.values(), - other.args.values() + other.optargs.values()): + for selfarg, otherarg in zip(list(self.args.values()) + list(self.optargs.values()), + list(other.args.values()) + list(other.optargs.values())): selfarg.unify(otherarg) self.ret.unify(other.ret) elif isinstance(other, TVar):