Split off builtins from types.

builtins will contain attribute definitions as well.
This commit is contained in:
whitequark 2015-06-13 10:29:26 +03:00
parent 56bba3009d
commit 61434a8da3
3 changed files with 78 additions and 69 deletions

63
artiq/py2llvm/builtins.py Normal file
View 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')

View File

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

View File

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