forked from M-Labs/artiq
Add IntMonomorphizer.
This commit is contained in:
parent
7ce9bdf54d
commit
196acb37f6
|
@ -8,15 +8,18 @@ from . import prelude, types, transforms
|
||||||
|
|
||||||
class Module:
|
class Module:
|
||||||
def __init__(self, source_buffer, engine=diagnostic.Engine(all_errors_are_fatal=True)):
|
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)
|
asttyped_rewriter = transforms.ASTTypedRewriter(engine=engine)
|
||||||
typedtree = asttyped_rewriter.visit(parsetree)
|
|
||||||
self.globals = asttyped_rewriter.globals
|
|
||||||
|
|
||||||
inferencer = transforms.Inferencer(engine=engine)
|
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)
|
inferencer.visit(typedtree)
|
||||||
|
int_monomorphizer.visit(typedtree)
|
||||||
|
inferencer.visit(typedtree)
|
||||||
|
|
||||||
|
self.name = os.path.basename(source_buffer.name)
|
||||||
|
self.globals = asttyped_rewriter.globals
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_string(klass, source_string, name="input.py", first_line=1):
|
def from_string(klass, source_string, name="input.py", first_line=1):
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
from .asttyped_rewriter import ASTTypedRewriter
|
from .asttyped_rewriter import ASTTypedRewriter
|
||||||
from .inferencer import Inferencer
|
from .inferencer import Inferencer
|
||||||
|
from .int_monomorphizer import IntMonomorphizer
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
"""
|
||||||
|
:class:`ASTTypedRewriter` rewrites a parsetree (:mod:`pythonparser.ast`)
|
||||||
|
to a typedtree (:mod:`..asttyped`).
|
||||||
|
"""
|
||||||
|
|
||||||
from pythonparser import algorithm, diagnostic
|
from pythonparser import algorithm, diagnostic
|
||||||
from .. import asttyped, types, builtins, prelude
|
from .. import asttyped, types, builtins, prelude
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
"""
|
||||||
|
:class:`Inferencer` performs unification-based inference on a typedtree.
|
||||||
|
"""
|
||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from pythonparser import algorithm, diagnostic, ast
|
from pythonparser import algorithm, diagnostic, ast
|
||||||
from .. import asttyped, types, builtins
|
from .. import asttyped, types, builtins
|
||||||
|
@ -168,6 +172,7 @@ class Inferencer(algorithm.Visitor):
|
||||||
if coerced_node.type.find() == typ.find():
|
if coerced_node.type.find() == typ.find():
|
||||||
return coerced_node
|
return coerced_node
|
||||||
elif isinstance(coerced_node, asttyped.CoerceT):
|
elif isinstance(coerced_node, asttyped.CoerceT):
|
||||||
|
node = coerced_node
|
||||||
node.type, node.other_expr = typ, other_node
|
node.type, node.other_expr = typ, other_node
|
||||||
else:
|
else:
|
||||||
node = asttyped.CoerceT(type=typ, expr=coerced_node, other_expr=other_node,
|
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)):
|
elif any(map(builtins.is_float, node_types)):
|
||||||
typ = builtins.TFloat()
|
typ = builtins.TFloat()
|
||||||
elif any(map(builtins.is_int, node_types)):
|
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):
|
if all(widths):
|
||||||
typ = builtins.TInt(types.TValue(max(widths)))
|
typ = builtins.TInt(types.TValue(max(widths)))
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -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))
|
|
@ -168,8 +168,8 @@ class TFunction(Type):
|
||||||
if isinstance(other, TFunction) and \
|
if isinstance(other, TFunction) and \
|
||||||
self.args.keys() == other.args.keys() and \
|
self.args.keys() == other.args.keys() and \
|
||||||
self.optargs.keys() == other.optargs.keys():
|
self.optargs.keys() == other.optargs.keys():
|
||||||
for selfarg, otherarg in zip(self.args.values() + self.optargs.values(),
|
for selfarg, otherarg in zip(list(self.args.values()) + list(self.optargs.values()),
|
||||||
other.args.values() + other.optargs.values()):
|
list(other.args.values()) + list(other.optargs.values())):
|
||||||
selfarg.unify(otherarg)
|
selfarg.unify(otherarg)
|
||||||
self.ret.unify(other.ret)
|
self.ret.unify(other.ret)
|
||||||
elif isinstance(other, TVar):
|
elif isinstance(other, TVar):
|
||||||
|
|
Loading…
Reference in New Issue