Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/TurtleArt/tatype.py
diff options
context:
space:
mode:
authorMarion <marion.zepf@gmail.com>2013-09-04 15:08:07 (GMT)
committer Marion <marion.zepf@gmail.com>2013-09-04 15:08:07 (GMT)
commit97b945e1e088c2e51d9a6233be49c401040883e9 (patch)
treeb9ae9cb56638f9bf7291b5b762f7ce942e7cc32b /TurtleArt/tatype.py
parentcc420f0e37c82275bb5d6b46d85aef9cb9fdae91 (diff)
parente0fcb7656caf8d35e3e4bfa9ce99729328f35b1d (diff)
Merge branch 'type-system' into type-system-while-until
Conflicts: TurtleArt/taprimitive.py -- preserve the semantics of both changes
Diffstat (limited to 'TurtleArt/tatype.py')
-rw-r--r--TurtleArt/tatype.py100
1 files changed, 76 insertions, 24 deletions
diff --git a/TurtleArt/tatype.py b/TurtleArt/tatype.py
index 164ba2a..9cb5433 100644
--- a/TurtleArt/tatype.py
+++ b/TurtleArt/tatype.py
@@ -49,7 +49,19 @@ class Type(object):
class TypeDisjunction(tuple,Type):
""" Disjunction of two or more Types (from the type hierarchy) """
- pass
+
+ def __init__(self, iterable):
+ self = tuple(iterable)
+
+
+ def __str__(self):
+ s = ["("]
+ for disj in self:
+ s.append(str(disj))
+ s.append(" or ")
+ s.pop()
+ s.append(")")
+ return "".join(s)
TYPE_OBJECT = Type('object', 0)
@@ -65,6 +77,9 @@ TYPE_STRING = Type('string', 9)
# TODO add list types
+BOX_AST = ast.Name(id='BOX', ctx=ast.Load)
+ACTION_AST = ast.Name(id='ACTION', ctx=ast.Load)
+
def get_type(x):
""" Return the most specific type in the type hierarchy that applies to x
and a boolean indicating whether x is an AST. If the type cannot be
@@ -101,6 +116,11 @@ def get_type(x):
return (TYPE_OBJECT, True)
else:
return (get_type(value)[0], True)
+ elif isinstance(x, ast.Subscript):
+ if x.value == BOX_AST:
+ return (TypeDisjunction((TYPE_OBJECT, TYPE_STRING, TYPE_NUMBER,
+ TYPE_FLOAT, TYPE_INT, TYPE_NUMERIC_STRING, TYPE_CHAR,
+ TYPE_COLOR)), True)
elif isinstance(x, ast.Call):
if isinstance(x.func, ast.Name):
if x.func.id == 'float':
@@ -163,24 +183,6 @@ TYPE_CONVERTERS = {
}
-def get_call_ast(func_name, args=None, kwargs=None):
- """ Return an AST representing the call to a function with the name
- func_name, passing it the arguments args (given as a list) and the
- keyword arguments kwargs (given as a dictionary). """
- if args is None:
- args = []
- keywords = []
- if kwargs is not None:
- for (key, value) in kwargs.iteritems():
- keywords.append(ast.keyword(arg=key, value=value))
- return ast.Call(func=ast.Name(id=func_name,
- ctx=ast.Load),
- args=args,
- keywords=keywords,
- starargs=None,
- kwargs=None)
-
-
class TATypeError(BaseException):
""" TypeError with the types from the hierarchy, not with Python types """
@@ -299,11 +301,7 @@ def convert(x, new_type, old_type=None, converter=None):
func = ast.Attribute(value=y,
attr=converter.im_func.__name__,
ctx=ast.Load)
- return ast.Call(func=func,
- args=[],
- keywords={},
- starargs=None,
- kwargs=None)
+ return get_call_ast(func)
else:
func_name = converter.__name__
return get_call_ast(func_name, [y])
@@ -320,3 +318,57 @@ def convert(x, new_type, old_type=None, converter=None):
return _apply_converter(converter, x)
+class TypedCall(ast.Call):
+ """ Like a Call AST, but with a return type """
+
+ def __init__(self, func, args=None, keywords=None, starargs=None,
+ kwargs=None, return_type=None):
+
+ if args is None:
+ args = []
+ if keywords is None:
+ keywords = []
+
+ ast.Call.__init__(self, func=func, args=args, keywords=keywords,
+ starargs=starargs, kwargs=kwargs)
+
+ self._return_type = return_type
+
+ @property
+ def return_type(self):
+ if self._return_type is None:
+ return get_type(self.func)
+ else:
+ return self._return_type
+
+
+def get_call_ast(func_name, args=None, kwargs=None, return_type=None):
+ """ Return an AST representing the call to a function with the name
+ func_name, passing it the arguments args (given as a list) and the
+ keyword arguments kwargs (given as a dictionary).
+ func_name -- either the name of a callable as a string, or an AST
+ representing a callable expression
+ return_type -- if this is not None, return a TypedCall object with this
+ return type instead """
+ if args is None:
+ args = []
+ # convert keyword argument dict to a list of (key, value) pairs
+ keywords = []
+ if kwargs is not None:
+ for (key, value) in kwargs.iteritems():
+ keywords.append(ast.keyword(arg=key, value=value))
+ # get or generate the AST representing the callable
+ if isinstance(func_name, ast.AST):
+ func_ast = func_name
+ else:
+ func_ast = ast.Name(id=func_name, ctx=ast.Load)
+ # if no return type is given, return a simple Call AST
+ if return_type is None:
+ return ast.Call(func=func_ast, args=args, keywords=keywords,
+ starargs=None, kwargs=None)
+ # if a return type is given, return a TypedCall AST
+ else:
+ return TypedCall(func=func_ast, args=args, keywords=keywords,
+ return_type=return_type)
+
+