Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarion <marion.zepf@gmail.com>2013-09-10 22:04:43 (GMT)
committer Marion <marion.zepf@gmail.com>2013-09-10 22:04:43 (GMT)
commit27c87bbc282dcc72fcc137684831551556eb5e24 (patch)
tree584a85d38010d08c531dc71a98acbf92d5446c0e
parent3d3238126b293f2354b97d7d331fc502b70f198e (diff)
add Primitives for the 'push', 'pop', and 'is empty heap?' blocks
-rw-r--r--TurtleArt/taexportpython.py1
-rw-r--r--TurtleArt/talogo.py3
-rw-r--r--TurtleArt/taprimitive.py44
-rw-r--r--TurtleArt/tatype.py34
-rw-r--r--plugins/turtle_blocks_extras/turtle_blocks_extras.py14
-rw-r--r--util/codegen.py1
6 files changed, 63 insertions, 34 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
diff --git a/plugins/turtle_blocks_extras/turtle_blocks_extras.py b/plugins/turtle_blocks_extras/turtle_blocks_extras.py
index c75cbbd..04f83ff 100644
--- a/plugins/turtle_blocks_extras/turtle_blocks_extras.py
+++ b/plugins/turtle_blocks_extras/turtle_blocks_extras.py
@@ -39,7 +39,7 @@ from TurtleArt.tautils import (round_int, debug_output, get_path,
hat_on_top, listify, data_from_file)
from TurtleArt.tajail import (myfunc, myfunc_import)
from TurtleArt.taprimitive import (ArgSlot, ConstantArg, Primitive)
-from TurtleArt.tatype import (TYPE_BOOL, TYPE_CHAR, TYPE_INT, TYPE_NUMBER,
+from TurtleArt.tatype import (TYPE_BOOL, TYPE_BOX, TYPE_CHAR, TYPE_INT,
TYPE_OBJECT, TYPE_STRING)
@@ -475,7 +475,8 @@ program started'))
help_string=_('pushes value onto FILO (first-in \
last-out heap)'))
self.tw.lc.def_prim('push', 1,
- lambda self, x: primitive_dictionary['push'](x))
+ Primitive(self.tw.lc.heap.append,
+ arg_descs=[ArgSlot(TYPE_OBJECT)]))
define_logo_function('tapush', 'to tapush :foo\nmake "taheap fput \
:foo :taheap\nend\nmake "taheap []\n')
@@ -516,7 +517,7 @@ end\n')
help_string=_('pops value off FILO (first-in \
last-out heap)'))
self.tw.lc.def_prim('pop', 0,
- lambda self: primitive_dictionary['pop']())
+ Primitive(self.tw.lc.heap.pop, return_type=TYPE_BOX))
define_logo_function('tapop', 'to tapop\nif emptyp :taheap [stop]\n\
make "tmp first :taheap\nmake "taheap butfirst :taheap\noutput :tmp\nend\n')
@@ -539,8 +540,11 @@ make "tmp first :taheap\nmake "taheap butfirst :taheap\noutput :tmp\nend\n')
value_block=True,
help_string=_('returns True if heap is empty'))
self.tw.lc.def_prim('isheapempty2', 0,
- lambda self:
- primitive_dictionary['isheapempty2']())
+ # Python automatically converts the heap to a boolean in contexts
+ # where a boolean is needed
+ Primitive(Primitive.not_, return_type=TYPE_BOOL,
+ arg_descs=[ConstantArg(
+ Primitive(self.tw.lc.get_heap, return_type=TYPE_BOOL))]))
primitive_dictionary['print'] = self._prim_print
palette.add_block('comment',
diff --git a/util/codegen.py b/util/codegen.py
index 6e4d383..2390daf 100644
--- a/util/codegen.py
+++ b/util/codegen.py
@@ -398,6 +398,7 @@ class SourceGenerator(NodeVisitor):
def visit_Name(self, node):
self.write(node.id)
+ visit_TypedName = visit_Name
def visit_Str(self, node):
self.write(repr(node.s))