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
|
@ -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.
|
folded into this class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
attributes = ()
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.parent = self
|
self.parent = self
|
||||||
|
|
||||||
|
@ -99,34 +101,6 @@ class TMono(Type):
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not (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):
|
class TValue(Type):
|
||||||
"""
|
"""
|
||||||
A type-level value (such as the integer denoting width of
|
A type-level value (such as the integer denoting width of
|
||||||
|
@ -155,30 +129,6 @@ class TValue(Type):
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not (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):
|
def is_var(typ):
|
||||||
return isinstance(typ, TVar)
|
return isinstance(typ, TVar)
|
||||||
|
@ -190,10 +140,6 @@ def is_mono(typ, name, **params):
|
||||||
return isinstance(typ, TMono) and \
|
return isinstance(typ, TMono) and \
|
||||||
typ.name == name and params_match
|
typ.name == name and params_match
|
||||||
|
|
||||||
def is_numeric(typ):
|
|
||||||
return isinstance(typ, TMono) and \
|
|
||||||
typ.name in ('int', 'float')
|
|
||||||
|
|
||||||
|
|
||||||
class TypePrinter(object):
|
class TypePrinter(object):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from pythonparser import source, ast, algorithm, diagnostic, parse_buffer
|
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,
|
# This visitor will be called for every node with a scope,
|
||||||
# i.e.: class, function, comprehension, lambda
|
# i.e.: class, function, comprehension, lambda
|
||||||
|
@ -222,9 +222,9 @@ class Inferencer(algorithm.Transformer):
|
||||||
|
|
||||||
def visit_Num(self, node):
|
def visit_Num(self, node):
|
||||||
if isinstance(node.n, int):
|
if isinstance(node.n, int):
|
||||||
typ = types.TInt()
|
typ = builtins.TInt()
|
||||||
elif isinstance(node.n, float):
|
elif isinstance(node.n, float):
|
||||||
typ = types.TFloat()
|
typ = builtins.TFloat()
|
||||||
else:
|
else:
|
||||||
diag = diagnostic.Diagnostic("fatal",
|
diag = diagnostic.Diagnostic("fatal",
|
||||||
"numeric type {type} is not supported", {"type": node.n.__class__.__name__},
|
"numeric type {type} is not supported", {"type": node.n.__class__.__name__},
|
||||||
|
@ -239,19 +239,19 @@ class Inferencer(algorithm.Transformer):
|
||||||
|
|
||||||
def visit_NameConstant(self, node):
|
def visit_NameConstant(self, node):
|
||||||
if node.value is True or node.value is False:
|
if node.value is True or node.value is False:
|
||||||
typ = types.TBool()
|
typ = builtins.TBool()
|
||||||
elif node.value is None:
|
elif node.value is None:
|
||||||
typ = types.TNone()
|
typ = builtins.TNone()
|
||||||
return asttyped.NameConstantT(type=typ, value=node.value, loc=node.loc)
|
return asttyped.NameConstantT(type=typ, value=node.value, loc=node.loc)
|
||||||
|
|
||||||
def visit_Tuple(self, node):
|
def visit_Tuple(self, node):
|
||||||
node = self.generic_visit(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)
|
elts=node.elts, ctx=node.ctx, loc=node.loc)
|
||||||
|
|
||||||
def visit_List(self, node):
|
def visit_List(self, node):
|
||||||
node = self.generic_visit(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)
|
elts=node.elts, ctx=node.ctx, loc=node.loc)
|
||||||
return self.visit(node)
|
return self.visit(node)
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ class Inferencer(algorithm.Transformer):
|
||||||
|
|
||||||
def visit_SubscriptT(self, node):
|
def visit_SubscriptT(self, node):
|
||||||
# TODO: support more than just lists
|
# 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)
|
node.loc, node.value.loc)
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
@ -325,10 +325,10 @@ class Inferencer(algorithm.Transformer):
|
||||||
|
|
||||||
def visit_UnaryOpT(self, node):
|
def visit_UnaryOpT(self, node):
|
||||||
if isinstance(node.op, ast.Not):
|
if isinstance(node.op, ast.Not):
|
||||||
node.type = types.TBool()
|
node.type = builtins.TBool()
|
||||||
else:
|
else:
|
||||||
operand_type = node.operand.type.find()
|
operand_type = node.operand.type.find()
|
||||||
if types.is_numeric(operand_type):
|
if builtins.is_numeric(operand_type):
|
||||||
node.type = operand_type
|
node.type = operand_type
|
||||||
elif not types.is_var(operand_type):
|
elif not types.is_var(operand_type):
|
||||||
diag = diagnostic.Diagnostic("error",
|
diag = diagnostic.Diagnostic("error",
|
||||||
|
@ -361,7 +361,7 @@ class Inferencer(algorithm.Transformer):
|
||||||
def visit_Assign(self, node):
|
def visit_Assign(self, node):
|
||||||
node = self.generic_visit(node)
|
node = self.generic_visit(node)
|
||||||
if len(node.targets) > 1:
|
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)
|
node.targets[0].loc.join(node.targets[-1].loc), node.value.loc)
|
||||||
else:
|
else:
|
||||||
self._unify(node.targets[0].type, node.value.type,
|
self._unify(node.targets[0].type, node.value.type,
|
||||||
|
@ -377,7 +377,7 @@ class Inferencer(algorithm.Transformer):
|
||||||
def visit_For(self, node):
|
def visit_For(self, node):
|
||||||
node = self.generic_visit(node)
|
node = self.generic_visit(node)
|
||||||
# TODO: support more than just lists
|
# 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)
|
node.target.loc, node.iter.loc)
|
||||||
return node
|
return node
|
||||||
|
|
||||||
|
@ -395,7 +395,7 @@ class Inferencer(algorithm.Transformer):
|
||||||
node.loc)
|
node.loc)
|
||||||
]
|
]
|
||||||
if node.value is None:
|
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)
|
self.function.name_loc, node.loc, makenotes)
|
||||||
else:
|
else:
|
||||||
self._unify(self.function.return_type, node.value.type,
|
self._unify(self.function.return_type, node.value.type,
|
||||||
|
|
Loading…
Reference in New Issue