diff options
author | Marion <marion.zepf@gmail.com> | 2013-09-10 22:04:43 (GMT) |
---|---|---|
committer | Marion <marion.zepf@gmail.com> | 2013-09-10 22:04:43 (GMT) |
commit | 27c87bbc282dcc72fcc137684831551556eb5e24 (patch) | |
tree | 584a85d38010d08c531dc71a98acbf92d5446c0e /TurtleArt | |
parent | 3d3238126b293f2354b97d7d331fc502b70f198e (diff) |
add Primitives for the 'push', 'pop', and 'is empty heap?' blocks
Diffstat (limited to 'TurtleArt')
-rw-r--r-- | TurtleArt/taexportpython.py | 1 | ||||
-rw-r--r-- | TurtleArt/talogo.py | 3 | ||||
-rw-r--r-- | TurtleArt/taprimitive.py | 44 | ||||
-rw-r--r-- | TurtleArt/tatype.py | 34 |
4 files changed, 53 insertions, 29 deletions
diff --git a/TurtleArt/taexportpython.py b/TurtleArt/taexportpython.py index 19cf48e..3f3a03e 100644 --- a/TurtleArt/taexportpython.py +++ b/TurtleArt/taexportpython.py @@ -50,6 +50,7 @@ tw = get_tw() BOX = {} ACTION = {} +heap = [] diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py index 20a374d..b496ea8 100644 --- a/TurtleArt/talogo.py +++ b/TurtleArt/talogo.py @@ -805,6 +805,9 @@ class LogoCode: name = float(name) return 'stack3' + str(name) + def get_heap(self): + return self.heap + def clear_value_blocks(self): if not hasattr(self, 'value_blocks_to_update'): return diff --git a/TurtleArt/taprimitive.py b/TurtleArt/taprimitive.py index 70762f1..b9e74bc 100644 --- a/TurtleArt/taprimitive.py +++ b/TurtleArt/taprimitive.py @@ -132,6 +132,8 @@ class Primitive(object): func_name = "canvas." elif self.wants_logocode(): func_name = "logo." + elif self.wants_heap(): + func_name = "heap." elif self.wants_tawindow(): func_name = "tw." # get the name of the function directly from the function itself @@ -270,21 +272,23 @@ class Primitive(object): debug_output("end " + repr(self)) # what does this primitive want as its first argument? - if new_prim.wants_turtle(): - first_arg = global_objects["turtles"].get_active_turtle() - elif new_prim.wants_turtles(): - first_arg = global_objects["turtles"] - elif new_prim.wants_canvas(): - first_arg = global_objects["canvas"] - elif new_prim.wants_logocode(): - first_arg = global_objects["logo"] - elif new_prim.wants_tawindow(): - first_arg = global_objects["window"] - else: - first_arg = None + first_arg = None + if not is_bound_method(new_prim.func): + if new_prim.wants_turtle(): + first_arg = global_objects["turtles"].get_active_turtle() + elif new_prim.wants_turtles(): + first_arg = global_objects["turtles"] + elif new_prim.wants_canvas(): + first_arg = global_objects["canvas"] + elif new_prim.wants_logocode(): + first_arg = global_objects["logo"] + elif new_prim.wants_heap(): + first_arg = global_objects["logo"].heap + elif new_prim.wants_tawindow(): + first_arg = global_objects["window"] # execute the actual function - if first_arg is None or is_bound_instancemethod(new_prim.func): + if first_arg is None: return_value = new_prim.func(*new_args, **new_kwargs) else: return_value = new_prim.func(first_arg, *new_args, **new_kwargs) @@ -464,6 +468,9 @@ class Primitive(object): text = ' ' + str(ast_to_value(new_arg_asts[0])) return ast_extensions.Comment(text) + elif self == LogoCode.get_heap: + return TypedName(id_='heap', return_type=self.return_type) + # NORMAL FUNCTION CALL # else: @@ -520,6 +527,12 @@ class Primitive(object): first argument? """ return self._wants(LogoCode) + def wants_heap(self): + """ Does this Primitive want to get the heap as its first argument? """ + return ((hasattr(self.func, '__self__') and + isinstance(self.func.__self__, list)) or + self.func in list.__dict__.values()) + def wants_tawindow(self): """ Does this Primitive want to get the TurtleArtWindow instance as its first argument? """ @@ -532,10 +545,7 @@ class Primitive(object): return not is_instancemethod(self.func) def _wants(self, theClass): - if is_instancemethod(self.func): - return self.func.im_class == theClass - else: - return False + return is_instancemethod(self.func) and self.func.im_class == theClass # treat the following methods in a special way when converting the # Primitive to an AST diff --git a/TurtleArt/tatype.py b/TurtleArt/tatype.py index 9a8c17d..3a14fbf 100644 --- a/TurtleArt/tatype.py +++ b/TurtleArt/tatype.py @@ -46,11 +46,9 @@ class Type(object): repr(type(other))) return self.value == other.value - def __repr__(self): - return repr(self.constant_name) - def __str__(self): return str(self.constant_name) + __repr__ = __str__ class TypeDisjunction(tuple,Type): @@ -137,7 +135,11 @@ def get_type(x): return (TYPE_STRING, True) # unary operands never change the type of their argument elif isinstance(x, ast.UnaryOp): - return get_type(x.operand) + if issubclass(x.op, ast.Not): + # 'not' always returns a boolean + return (TYPE_BOOL, True) + else: + return get_type(x.operand) # boolean and comparison operators always return a boolean if isinstance(x, (ast.BoolOp, ast.Compare)): return (TYPE_BOOL, True) @@ -159,11 +161,9 @@ def is_instancemethod(method): # TODO how to access the type `instancemethod` directly? return type(method).__name__ == "instancemethod" -def is_bound_instancemethod(method): - return is_instancemethod(method) and method.im_self is not None - -def is_unbound_instancemethod(method): - return is_instancemethod(method) and method.im_self is None +def is_bound_method(method): + return ((is_instancemethod(method) and method.im_self is not None) or + (hasattr(method, '__self__') and method.__self__ is not None)) def is_staticmethod(method): # TODO how to access the type `staticmethod` directly? @@ -311,8 +311,8 @@ def convert(x, new_type, old_type=None, converter=None): if old_type == new_type: return x - # special case: 'box' block as an AST - if isinstance(x, ast.Subscript) and x.value is BOX_AST: + # special case: 'box' block (or 'pop' block) as an AST + if is_an_ast and old_type == TYPE_BOX: new_type_ast = ast.Name(id=new_type.constant_name) return get_call_ast('convert', [x, new_type_ast], return_type=new_type) @@ -378,7 +378,7 @@ class TypedCall(ast.Call,TypedAST): class TypedSubscript(ast.Subscript,TypedAST): - """ Like a Subscript AST, but with a return type """ + """ Like a Subscript AST, but with a type """ def __init__(self, value, slice_, ctx=ast.Load, return_type=None): @@ -387,6 +387,16 @@ class TypedSubscript(ast.Subscript,TypedAST): self._return_type = return_type +class TypedName(ast.Name,TypedAST): + """ Like a Name AST, but with a type """ + + def __init__(self, id_, ctx=ast.Load, return_type=None): + + ast.Name.__init__(self, id=id_, ctx=ctx) + + self._return_type = 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 |