Add support for Attribute.

This commit is contained in:
whitequark 2015-06-13 13:50:56 +03:00
parent 23f33d7239
commit faaf189961
4 changed files with 34 additions and 10 deletions

View File

@ -26,6 +26,8 @@ class TFloat(types.TMono):
class TTuple(types.Type):
"""A tuple type."""
attributes = {}
def __init__(self, elts=[]):
self.elts = elts

View File

@ -37,8 +37,6 @@ class TVar(Type):
folded into this class.
"""
attributes = ()
def __init__(self):
self.parent = self
@ -71,6 +69,8 @@ class TVar(Type):
class TMono(Type):
"""A monomorphic type, possibly parametric."""
attributes = {}
def __init__(self, name, params={}):
self.name, self.params = name, params

View File

@ -224,6 +224,13 @@ class ASTTypedRewriter(algorithm.Transformer):
elts=node.elts, ctx=node.ctx, loc=node.loc)
return self.visit(node)
def visit_Attribute(self, node):
node = self.generic_visit(node)
node = asttyped.AttributeT(type=types.TVar(),
value=node.value, attr=node.attr, ctx=node.ctx,
dot_loc=node.dot_loc, attr_loc=node.attr_loc, loc=node.loc)
return self.visit(node)
def visit_Subscript(self, node):
node = self.generic_visit(node)
node = asttyped.SubscriptT(type=types.TVar(),
@ -231,13 +238,6 @@ class ASTTypedRewriter(algorithm.Transformer):
loc=node.loc)
return self.visit(node)
def visit_IfExp(self, node):
node = self.generic_visit(node)
node = asttyped.IfExpT(type=types.TVar(),
test=node.test, body=node.body, orelse=node.orelse,
if_loc=node.if_loc, else_loc=node.else_loc, loc=node.loc)
return self.visit(node)
def visit_BoolOp(self, node):
node = self.generic_visit(node)
node = asttyped.BoolOpT(type=types.TVar(),
@ -266,6 +266,13 @@ class ASTTypedRewriter(algorithm.Transformer):
loc=node.loc)
return self.visit(node)
def visit_IfExp(self, node):
node = self.generic_visit(node)
node = asttyped.IfExpT(type=types.TVar(),
test=node.test, body=node.body, orelse=node.orelse,
if_loc=node.if_loc, else_loc=node.else_loc, loc=node.loc)
return self.visit(node)
# Unsupported visitors
#
def visit_unsupported(self, node):
@ -275,7 +282,6 @@ class ASTTypedRewriter(algorithm.Transformer):
self.engine.process(diag)
# expr
visit_Attribute = visit_unsupported
visit_BinOp = visit_unsupported
visit_Call = visit_unsupported
visit_Compare = visit_unsupported
@ -373,6 +379,19 @@ class Inferencer(algorithm.Visitor):
self._unify(node.type["elt"], elt.type,
node.loc, elt.loc, self._makenotes_elts(node.elts, "a list element"))
def visit_AttributeT(self, node):
object_type = node.value.type.find()
if not types.is_var(object_type):
if node.attr in object_type.attributes:
# assumes no free type variables in .attributes
node.type = object_type.attributes[node.attr]
else:
diag = diagnostic.Diagnostic("error",
"type {type} does not have an attribute '{attr}'",
{"type": types.TypePrinter().name(object_type), "attr": node.attr},
node.attr_loc, [node.value.loc])
self.engine.process(diag)
def visit_SubscriptT(self, node):
# TODO: support more than just lists
self._unify(builtins.TList(node.type), node.value.type,

View File

@ -22,3 +22,6 @@ a = b
# CHECK-L: ${LINE:+1}: error: expected ~ operand to be of integer type, not float
~1.0
# CHECK-L: ${LINE:+1}: error: type int(width='a) does not have an attribute 'x'
(1).x