Add IntMonomorphizer.

This commit is contained in:
whitequark 2015-07-02 19:49:52 +03:00
parent 7ce9bdf54d
commit 196acb37f6
6 changed files with 51 additions and 9 deletions

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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))

View File

@ -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):