forked from M-Labs/artiq
Split off builtins from types.
builtins will contain attribute definitions as well.
This commit is contained in:
parent
56bba3009d
commit
61434a8da3
63
artiq/py2llvm/builtins.py
Normal file
63
artiq/py2llvm/builtins.py
Normal file
@ -0,0 +1,63 @@
|
||||
"""
|
||||
The :mod:`builtins` module contains the builtin Python and ARTIQ
|
||||
types, such as int or float.
|
||||
"""
|
||||
|
||||
from . import types
|
||||
|
||||
class TNone(types.TMono):
|
||||
def __init__(self):
|
||||
super().__init__("NoneType")
|
||||
|
||||
class TBool(types.TMono):
|
||||
def __init__(self):
|
||||
super().__init__("bool")
|
||||
|
||||
class TInt(types.TMono):
|
||||
def __init__(self, width=None):
|
||||
if width is None:
|
||||
width = types.TVar()
|
||||
super().__init__("int", {"width": width})
|
||||
|
||||
class TFloat(types.TMono):
|
||||
def __init__(self):
|
||||
super().__init__("float")
|
||||
|
||||
class TTuple(types.Type):
|
||||
"""A tuple type."""
|
||||
|
||||
def __init__(self, elts=[]):
|
||||
self.elts = elts
|
||||
|
||||
def find(self):
|
||||
return self
|
||||
|
||||
def unify(self, other):
|
||||
if isinstance(other, TTuple) and len(self.elts) == len(other.elts):
|
||||
for selfelt, otherelt in zip(self.elts, other.elts):
|
||||
selfelt.unify(otherelt)
|
||||
elif isinstance(other, TVar):
|
||||
other.unify(self)
|
||||
else:
|
||||
raise UnificationError(self, other)
|
||||
|
||||
def __repr__(self):
|
||||
return "TTuple(%s)" % (", ".join(map(repr, self.elts)))
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, TTuple) and \
|
||||
self.elts == other.elts
|
||||
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
|
||||
class TList(types.TMono):
|
||||
def __init__(self, elt=None):
|
||||
if elt is None:
|
||||
elt = types.TVar()
|
||||
super().__init__("list", {"elt": elt})
|
||||
|
||||
|
||||
def is_numeric(typ):
|
||||
return isinstance(typ, types.TMono) and \
|
||||
typ.name in ('int', 'float')
|
@ -37,6 +37,8 @@ class TVar(Type):
|
||||
folded into this class.
|
||||
"""
|
||||
|
||||
attributes = ()
|
||||
|
||||
def __init__(self):
|
||||
self.parent = self
|
||||
|
||||
@ -99,34 +101,6 @@ class TMono(Type):
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
|
||||
class TTuple(Type):
|
||||
"""A tuple type."""
|
||||
|
||||
def __init__(self, elts=[]):
|
||||
self.elts = elts
|
||||
|
||||
def find(self):
|
||||
return self
|
||||
|
||||
def unify(self, other):
|
||||
if isinstance(other, TTuple) and len(self.elts) == len(other.elts):
|
||||
for selfelt, otherelt in zip(self.elts, other.elts):
|
||||
selfelt.unify(otherelt)
|
||||
elif isinstance(other, TVar):
|
||||
other.unify(self)
|
||||
else:
|
||||
raise UnificationError(self, other)
|
||||
|
||||
def __repr__(self):
|
||||
return "TTuple(%s)" % (", ".join(map(repr, self.elts)))
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, TTuple) and \
|
||||
self.elts == other.elts
|
||||
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
|
||||
class TValue(Type):
|
||||
"""
|
||||
A type-level value (such as the integer denoting width of
|
||||
@ -155,30 +129,6 @@ class TValue(Type):
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
|
||||
def TNone():
|
||||
"""The type of None."""
|
||||
return TMono("NoneType")
|
||||
|
||||
def TBool():
|
||||
"""A boolean type."""
|
||||
return TMono("bool")
|
||||
|
||||
def TInt(width=None):
|
||||
"""A generic integer type."""
|
||||
if width is None:
|
||||
width = TVar()
|
||||
return TMono("int", {"width": width})
|
||||
|
||||
def TFloat():
|
||||
"""A double-precision floating point type."""
|
||||
return TMono("float")
|
||||
|
||||
def TList(elt=None):
|
||||
"""A generic list type."""
|
||||
if elt is None:
|
||||
elt = TVar()
|
||||
return TMono("list", {"elt": elt})
|
||||
|
||||
|
||||
def is_var(typ):
|
||||
return isinstance(typ, TVar)
|
||||
@ -190,10 +140,6 @@ def is_mono(typ, name, **params):
|
||||
return isinstance(typ, TMono) and \
|
||||
typ.name == name and params_match
|
||||
|
||||
def is_numeric(typ):
|
||||
return isinstance(typ, TMono) and \
|
||||
typ.name in ('int', 'float')
|
||||
|
||||
|
||||
class TypePrinter(object):
|
||||
"""
|
||||
|
@ -1,5 +1,5 @@
|
||||
from pythonparser import source, ast, algorithm, diagnostic, parse_buffer
|
||||
from . import asttyped, types
|
||||
from . import asttyped, types, builtins
|
||||
|
||||
# This visitor will be called for every node with a scope,
|
||||
# i.e.: class, function, comprehension, lambda
|
||||
@ -222,9 +222,9 @@ class Inferencer(algorithm.Transformer):
|
||||
|
||||
def visit_Num(self, node):
|
||||
if isinstance(node.n, int):
|
||||
typ = types.TInt()
|
||||
typ = builtins.TInt()
|
||||
elif isinstance(node.n, float):
|
||||
typ = types.TFloat()
|
||||
typ = builtins.TFloat()
|
||||
else:
|
||||
diag = diagnostic.Diagnostic("fatal",
|
||||
"numeric type {type} is not supported", {"type": node.n.__class__.__name__},
|
||||
@ -239,19 +239,19 @@ class Inferencer(algorithm.Transformer):
|
||||
|
||||
def visit_NameConstant(self, node):
|
||||
if node.value is True or node.value is False:
|
||||
typ = types.TBool()
|
||||
typ = builtins.TBool()
|
||||
elif node.value is None:
|
||||
typ = types.TNone()
|
||||
typ = builtins.TNone()
|
||||
return asttyped.NameConstantT(type=typ, value=node.value, loc=node.loc)
|
||||
|
||||
def visit_Tuple(self, node):
|
||||
node = self.generic_visit(node)
|
||||
return asttyped.TupleT(type=types.TTuple([x.type for x in node.elts]),
|
||||
return asttyped.TupleT(type=builtins.TTuple([x.type for x in node.elts]),
|
||||
elts=node.elts, ctx=node.ctx, loc=node.loc)
|
||||
|
||||
def visit_List(self, node):
|
||||
node = self.generic_visit(node)
|
||||
node = asttyped.ListT(type=types.TList(),
|
||||
node = asttyped.ListT(type=builtins.TList(),
|
||||
elts=node.elts, ctx=node.ctx, loc=node.loc)
|
||||
return self.visit(node)
|
||||
|
||||
@ -307,7 +307,7 @@ class Inferencer(algorithm.Transformer):
|
||||
|
||||
def visit_SubscriptT(self, node):
|
||||
# TODO: support more than just lists
|
||||
self._unify(types.TList(node.type), node.value.type,
|
||||
self._unify(builtins.TList(node.type), node.value.type,
|
||||
node.loc, node.value.loc)
|
||||
return node
|
||||
|
||||
@ -325,10 +325,10 @@ class Inferencer(algorithm.Transformer):
|
||||
|
||||
def visit_UnaryOpT(self, node):
|
||||
if isinstance(node.op, ast.Not):
|
||||
node.type = types.TBool()
|
||||
node.type = builtins.TBool()
|
||||
else:
|
||||
operand_type = node.operand.type.find()
|
||||
if types.is_numeric(operand_type):
|
||||
if builtins.is_numeric(operand_type):
|
||||
node.type = operand_type
|
||||
elif not types.is_var(operand_type):
|
||||
diag = diagnostic.Diagnostic("error",
|
||||
@ -361,7 +361,7 @@ class Inferencer(algorithm.Transformer):
|
||||
def visit_Assign(self, node):
|
||||
node = self.generic_visit(node)
|
||||
if len(node.targets) > 1:
|
||||
self._unify(types.TTuple([x.type for x in node.targets]), node.value.type,
|
||||
self._unify(builtins.TTuple([x.type for x in node.targets]), node.value.type,
|
||||
node.targets[0].loc.join(node.targets[-1].loc), node.value.loc)
|
||||
else:
|
||||
self._unify(node.targets[0].type, node.value.type,
|
||||
@ -377,7 +377,7 @@ class Inferencer(algorithm.Transformer):
|
||||
def visit_For(self, node):
|
||||
node = self.generic_visit(node)
|
||||
# TODO: support more than just lists
|
||||
self._unify(TList(node.target.type), node.iter.type,
|
||||
self._unify(builtins.TList(node.target.type), node.iter.type,
|
||||
node.target.loc, node.iter.loc)
|
||||
return node
|
||||
|
||||
@ -395,7 +395,7 @@ class Inferencer(algorithm.Transformer):
|
||||
node.loc)
|
||||
]
|
||||
if node.value is None:
|
||||
self._unify(self.function.return_type, types.TNone(),
|
||||
self._unify(self.function.return_type, builtins.TNone(),
|
||||
self.function.name_loc, node.loc, makenotes)
|
||||
else:
|
||||
self._unify(self.function.return_type, node.value.type,
|
||||
|
Loading…
Reference in New Issue
Block a user