Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/TurtleArt/tabasics.py
diff options
context:
space:
mode:
authorMarion Zepf <marion.zepf@gmail.com>2013-10-27 02:06:05 (GMT)
committer Walter Bender <walter@sugarlabs.org>2013-10-27 02:06:05 (GMT)
commit629722d8859d1e8db47417673cb78963d41ce435 (patch)
treed188a0c26c724bc151c3449eb7a5613777f2ed40 /TurtleArt/tabasics.py
parent8ac55749fbe9672ea3f403c93713b403efac46af (diff)
python export
Diffstat (limited to 'TurtleArt/tabasics.py')
-rw-r--r--TurtleArt/tabasics.py544
1 files changed, 280 insertions, 264 deletions
diff --git a/TurtleArt/tabasics.py b/TurtleArt/tabasics.py
index 3d1eb10..08d0864 100644
--- a/TurtleArt/tabasics.py
+++ b/TurtleArt/tabasics.py
@@ -71,14 +71,9 @@ from gettext import gettext as _
from tapalette import (make_palette, define_logo_function)
from talogo import (primitive_dictionary, logoerror)
from tautils import (convert, chr_to_ord, round_int, strtype, debug_output)
-from taconstants import (COLORDICT, CONSTANTS)
-
-
-def _color_to_num(c):
- if COLORDICT[c][0] is None:
- return(COLORDICT[c][1])
- else:
- return(COLORDICT[c][0])
+from taconstants import (Color, CONSTANTS)
+from taprimitive import Primitive
+from taturtle import Turtle
def _num_type(x):
@@ -99,6 +94,16 @@ class Palettes():
def __init__(self, turtle_window):
self.tw = turtle_window
+ self.prim_cache = {
+ "check_number": Primitive(self.check_number, export_me=False),
+ "convert_value_for_move": Primitive(self.convert_value_for_move,
+ export_me=False),
+ "convert_for_cmp": Primitive(Primitive.convert_for_cmp,
+ constant_args={'decimal_point': self.tw.decimal_point}),
+ "convert_to_number": Primitive(Primitive.convert_to_number,
+ constant_args={'decimal_point': self.tw.decimal_point})
+ } # avoid several Primitives of the same function
+
self._turtle_palette()
self._pen_palette()
@@ -125,7 +130,6 @@ class Palettes():
colors=["#00FF00", "#00A000"],
help_string=_('Palette of turtle commands'))
- primitive_dictionary['move'] = self._prim_move
palette.add_block('forward',
style='basic-style-1arg',
label=_('forward'),
@@ -136,8 +140,9 @@ class Palettes():
self.tw.lc.def_prim(
'forward',
1,
- lambda self, x: primitive_dictionary['move'](
- self.tw.turtles.get_active_turtle().forward, x))
+ Primitive(Turtle.forward,
+ slot_wrappers={0: self.prim_cache["convert_value_for_move"]},
+ call_afterwards=self.after_move))
palette.add_block('back',
style='basic-style-1arg',
@@ -147,12 +152,12 @@ class Palettes():
logo_command='back',
help_string=_('moves turtle backward'))
self.tw.lc.def_prim('back', 1,
- lambda self, x:
- primitive_dictionary['move']
- (self.tw.turtles.get_active_turtle().forward, x,
- reverse=True))
+ Primitive(Turtle.forward,
+ slot_wrappers={0: Primitive(Primitive.minus,
+ slot_wrappers={0: self.prim_cache["convert_value_for_move"]
+ })},
+ call_afterwards=self.after_move))
- primitive_dictionary['clean'] = self._prim_clear
palette.add_block('clean',
style='basic-style-extended-vertical',
label=_('clean'),
@@ -163,9 +168,13 @@ turtle'))
self.tw.lc.def_prim(
'clean',
0,
- lambda self: primitive_dictionary['clean']())
+ Primitive(Primitive.group, constant_args={0: [
+ Primitive(self.tw.clear_plugins, call_me=False),
+ Primitive(self.tw.lc.prim_clear_helper, call_me=False,
+ export_me=False),
+ Primitive(self.tw.canvas.clearscreen, call_me=False),
+ Primitive(self.tw.turtles.reset_turtles, call_me=False)]}))
- primitive_dictionary['right'] = self._prim_right
palette.add_block('left',
style='basic-style-1arg',
label=_('left'),
@@ -175,8 +184,11 @@ turtle'))
help_string=_('turns turtle counterclockwise (angle \
in degrees)'))
self.tw.lc.def_prim(
- 'left', 1, lambda self,
- x: primitive_dictionary['right'](x, reverse=True))
+ 'left', 1,
+ Primitive(Turtle.right,
+ slot_wrappers={0: Primitive(Primitive.minus,
+ slot_wrappers={0: self.prim_cache["check_number"]})},
+ call_afterwards=self.after_right))
palette.add_block('right',
style='basic-style-1arg',
@@ -189,9 +201,10 @@ degrees)'))
self.tw.lc.def_prim(
'right',
1,
- lambda self, x: primitive_dictionary['right'](x))
+ Primitive(Turtle.right,
+ slot_wrappers={0: self.prim_cache["check_number"]},
+ call_afterwards=self.after_right))
- primitive_dictionary['arc'] = self._prim_arc
palette.add_block('arc',
style='basic-style-2arg',
label=[_('arc'), _('angle'), _('radius')],
@@ -202,8 +215,10 @@ degrees)'))
self.tw.lc.def_prim(
'arc',
2,
- lambda self, x, y: primitive_dictionary['arc'](
- self.tw.turtles.get_active_turtle().arc, x, y))
+ Primitive(Turtle.arc,
+ slot_wrappers={0: Primitive(float, export_me=False),
+ 1: Primitive(float, export_me=False)},
+ call_afterwards=self.after_arc))
define_logo_function('taarc', 'to taarc :a :r\nrepeat round :a \
[right 1 forward (0.0175 * :r)]\nend\n')
@@ -218,8 +233,12 @@ degrees)'))
self.tw.lc.def_prim(
'setxy2',
2,
- lambda self, x, y: primitive_dictionary['move'](
- self.tw.turtles.get_active_turtle().set_xy, x, y))
+ Primitive(Turtle.set_xy,
+ slot_wrappers={(0, 2): Primitive(Primitive.make_tuple,
+ slot_wrappers={0:self.prim_cache["convert_value_for_move"],
+ 1:self.prim_cache["convert_value_for_move"]
+ })},
+ call_afterwards=self.after_move))
define_logo_function('tasetxy', 'to tasetxy :x :y\nsetxy :x :y\nend\n')
primitive_dictionary['set'] = self._prim_set
@@ -234,8 +253,9 @@ towards the top of the screen.)'))
self.tw.lc.def_prim(
'seth',
1,
- lambda self, x: primitive_dictionary['set'](
- 'heading', self.tw.turtles.get_active_turtle().set_heading, x))
+ Primitive(Turtle.set_heading,
+ slot_wrappers={0: Primitive(float, export_me=False)},
+ call_afterwards=lambda value: self.after_set('heading',value)))
palette.add_block('xcor',
style='box-style',
@@ -248,8 +268,11 @@ the turtle (can be used in place of a number block)'),
self.tw.lc.def_prim(
'xcor',
0,
- lambda self: self.tw.turtles.get_active_turtle().get_xy()[0] /
- self.tw.coord_scale)
+ Primitive(Primitive.divide, constant_args={
+ 0: Primitive(Turtle.get_x, constant_args={
+ 0: Primitive(self.tw.turtles.get_active_turtle,
+ export_me=False)}),
+ 1: Primitive(self.tw.get_coord_scale)}))
palette.add_block('ycor',
style='box-style',
@@ -262,8 +285,11 @@ the turtle (can be used in place of a number block)'),
self.tw.lc.def_prim(
'ycor',
0,
- lambda self: self.tw.turtles.get_active_turtle().get_xy()[1] /
- self.tw.coord_scale)
+ Primitive(Primitive.divide, constant_args={
+ 0: Primitive(Turtle.get_y, constant_args={
+ 0: Primitive(self.tw.turtles.get_active_turtle,
+ export_me=False)}),
+ 1: Primitive(self.tw.get_coord_scale)}))
palette.add_block('heading',
style='box-style',
@@ -273,18 +299,15 @@ turtle (can be used in place of a number block)'),
value_block=True,
prim_name='heading',
logo_command='heading')
- self.tw.lc.def_prim(
- 'heading',
- 0,
- lambda self: self.tw.turtles.get_active_turtle().get_heading())
+ self.tw.lc.def_prim('heading', 0, Primitive(Turtle.get_heading))
- # This block is used for holding the remote turtle name
palette.add_block('turtle-label',
hidden=True,
style='blank-style',
- label=['remote turtle name'])
+ label=['turtle'])
# Deprecated
+ primitive_dictionary['move'] = self._prim_move
palette.add_block('setxy',
hidden=True,
style='basic-style-2arg',
@@ -298,7 +321,7 @@ turtle (can be used in place of a number block)'),
'setxy',
2,
lambda self, x, y: primitive_dictionary['move'](
- self.tw.turtles.get_active_turtle().set_xy, x, y,
+ self.tw.turtles.get_active_turtle().set_xy, (x, y),
pendown=False))
define_logo_function('tasetxypenup', 'to tasetxypenup :x :y\npenup\n\
setxy :x :y\npendown\nend\n')
@@ -324,7 +347,7 @@ shade)'))
self.tw.lc.def_prim(
'fillscreen',
2,
- lambda self, x, y: self.tw.canvas.fillscreen(x, y))
+ Primitive(self.tw.canvas.fillscreen))
palette.add_block('fillscreen2',
style='basic-style-3arg',
@@ -338,7 +361,7 @@ shade)'))
self.tw.lc.def_prim(
'fillscreen2',
3,
- lambda self, x, y, z: self.tw.canvas.fillscreen_with_gray(x, y, z))
+ Primitive(self.tw.canvas.fillscreen_with_gray))
define_logo_function('tasetbackground', 'to tasetbackground :color \
:shade\ntasetshade :shade\nsetbackground :color\nend\n')
@@ -354,8 +377,8 @@ turtle'))
self.tw.lc.def_prim(
'setcolor',
1,
- lambda self, x: primitive_dictionary['set'](
- 'color', self.tw.turtles.get_active_turtle().set_color, x))
+ Primitive(Turtle.set_color,
+ call_afterwards=lambda value: self.after_set('color', value)))
palette.add_block('setshade',
style='basic-style-1arg',
@@ -368,8 +391,8 @@ turtle'))
self.tw.lc.def_prim(
'setshade',
1,
- lambda self, x: primitive_dictionary['set'](
- 'shade', self.tw.turtles.get_active_turtle().set_shade, x))
+ Primitive(Turtle.set_shade,
+ call_afterwards=lambda value: self.after_set('shade', value)))
palette.add_block('setgray',
style='basic-style-1arg',
@@ -381,8 +404,8 @@ the turtle'))
self.tw.lc.def_prim(
'setgray',
1,
- lambda self, x: primitive_dictionary['set'](
- 'gray', self.tw.turtles.get_active_turtle().set_gray, x))
+ Primitive(Turtle.set_gray,
+ call_afterwards=lambda value: self.after_set('gray', value)))
palette.add_block('color',
style='box-style',
@@ -392,10 +415,7 @@ in place of a number block)'),
value_block=True,
prim_name='color',
logo_command='pencolor')
- self.tw.lc.def_prim(
- 'color',
- 0,
- lambda self: self.tw.turtles.get_active_turtle().get_color())
+ self.tw.lc.def_prim('color', 0, Primitive(Turtle.get_color))
palette.add_block('shade',
style='box-style',
@@ -404,10 +424,7 @@ in place of a number block)'),
value_block=True,
prim_name='shade',
logo_command=':shade')
- self.tw.lc.def_prim(
- 'shade',
- 0,
- lambda self: self.tw.turtles.get_active_turtle().get_shade())
+ self.tw.lc.def_prim('shade', 0, Primitive(Turtle.get_shade))
palette.add_block('gray',
style='box-style',
@@ -416,8 +433,7 @@ in place of a number block)'),
used in place of a number block)'),
value_block=True,
prim_name='gray')
- self.tw.lc.def_prim('gray', 0, lambda self:
- self.tw.turtles.get_active_turtle().get_gray())
+ self.tw.lc.def_prim('gray', 0, Primitive(Turtle.get_gray))
palette.add_block('penup',
style='basic-style-extended-vertical',
@@ -428,8 +444,7 @@ used in place of a number block)'),
self.tw.lc.def_prim(
'penup',
0,
- lambda self:
- self.tw.turtles.get_active_turtle().set_pen_state(False))
+ Primitive(Turtle.set_pen_state, constant_args={0: False}))
palette.add_block('pendown',
style='basic-style-extended-vertical',
@@ -440,8 +455,7 @@ used in place of a number block)'),
self.tw.lc.def_prim(
'pendown',
0,
- lambda self:
- self.tw.turtles.get_active_turtle().set_pen_state(True))
+ Primitive(Turtle.set_pen_state, constant_args={0: True}))
palette.add_block('penstate',
style='boolean-block-style',
@@ -451,7 +465,7 @@ used in place of a number block)'),
self.tw.lc.def_prim(
'penstate',
0,
- lambda self: self.tw.turtles.get_active_turtle().get_pen_state())
+ Primitive(Turtle.get_pen_state))
palette.add_block('setpensize',
style='basic-style-1arg',
@@ -463,8 +477,8 @@ used in place of a number block)'),
turtle'))
self.tw.lc.def_prim(
'setpensize', 1,
- lambda self, x: primitive_dictionary['set']
- ('pensize', self.tw.turtles.get_active_turtle().set_pen_size, x))
+ Primitive(Turtle.set_pen_size,
+ call_afterwards=lambda val: self.after_set('pensize', val)))
define_logo_function('tasetpensize',
'to tasetpensize :a\nsetpensize round :a\nend\n')
@@ -477,7 +491,7 @@ fill block)'))
self.tw.lc.def_prim(
'startfill',
0,
- lambda self: self.tw.turtles.get_active_turtle().start_fill())
+ Primitive(Turtle.start_fill))
palette.add_block('stopfill',
style='basic-style-extended-vertical',
@@ -488,7 +502,7 @@ start fill block)'))
self.tw.lc.def_prim(
'stopfill',
0,
- lambda self: self.tw.turtles.get_active_turtle().stop_fill())
+ Primitive(Turtle.stop_fill))
palette.add_block('pensize',
style='box-style',
@@ -501,7 +515,7 @@ in place of a number block)'),
self.tw.lc.def_prim(
'pensize',
0,
- lambda self: self.tw.turtles.get_active_turtle().get_pen_size())
+ Primitive(Turtle.get_pen_size))
define_logo_function('tapensize', 'to tapensize\noutput first round \
pensize\nend\n')
@@ -609,7 +623,6 @@ tasetshade :shade \n')
colors=["#FF00FF", "#A000A0"],
help_string=_('Palette of numeric operators'))
- primitive_dictionary['plus'] = self._prim_plus
palette.add_block('plus2',
style='number-style',
label='+',
@@ -618,10 +631,11 @@ tasetshade :shade \n')
prim_name='plus',
logo_command='sum',
help_string=_('adds two alphanumeric inputs'))
- self.tw.lc.def_prim(
- 'plus', 2, lambda self, x, y: primitive_dictionary['plus'](x, y))
+ self.tw.lc.def_prim('plus', 2,
+ # TODO re-enable use with lists
+ Primitive(Primitive.plus, slot_wrappers={
+ (0, 2): Primitive(Primitive.convert_for_plus)}))
- primitive_dictionary['minus'] = self._prim_minus
palette.add_block('minus2',
style='number-style-porch',
label=' –',
@@ -630,12 +644,20 @@ tasetshade :shade \n')
logo_command='taminus',
help_string=_('subtracts bottom numeric input from \
top numeric input'))
- self.tw.lc.def_prim(
- 'minus', 2, lambda self, x, y: primitive_dictionary['minus'](x, y))
+ self.tw.lc.def_prim('minus', 2,
+ # TODO re-enable use with lists
+ Primitive(Primitive.minus, slot_wrappers={
+ 0: Primitive(self.check_number,
+ export_me=False,
+ slot_wrappers={
+ 0: self.prim_cache["convert_to_number"]}),
+ 1: Primitive(self.check_number,
+ export_me=False,
+ slot_wrappers={
+ 0: self.prim_cache["convert_to_number"]})}))
define_logo_function('taminus', 'to taminus :y :x\noutput sum :x \
minus :y\nend\n')
- primitive_dictionary['product'] = self._prim_product
palette.add_block('product2',
style='number-style',
label='×',
@@ -643,11 +665,18 @@ minus :y\nend\n')
prim_name='product',
logo_command='product',
help_string=_('multiplies two numeric inputs'))
- self.tw.lc.def_prim(
- 'product', 2,
- lambda self, x, y: primitive_dictionary['product'](x, y))
+ self.tw.lc.def_prim('product', 2,
+ # TODO re-enable use with lists
+ Primitive(Primitive.multiply, slot_wrappers={
+ 0: Primitive(self.check_number,
+ export_me=False,
+ slot_wrappers={
+ 0: self.prim_cache["convert_to_number"]}),
+ 1: Primitive(self.check_number,
+ export_me=False,
+ slot_wrappers={
+ 0: self.prim_cache["convert_to_number"]})}))
- primitive_dictionary['division'] = self._prim_careful_divide
palette.add_block('division2',
style='number-style-porch',
label=' /',
@@ -656,11 +685,21 @@ minus :y\nend\n')
logo_command='quotient',
help_string=_('divides top numeric input \
(numerator) by bottom numeric input (denominator)'))
- self.tw.lc.def_prim(
- 'division', 2,
- lambda self, x, y: primitive_dictionary['division'](x, y))
+ self.tw.lc.def_prim('division', 2,
+ # TODO re-enable use with lists
+ Primitive(Primitive.divide, slot_wrappers={
+ 0: Primitive(self.check_number,
+ export_me=False,
+ slot_wrappers={
+ 0: self.prim_cache["convert_to_number"]}),
+ 1: Primitive(self.check_non_zero,
+ export_me=False,
+ slot_wrappers={
+ 0: Primitive(self.check_number,
+ export_me=False,
+ slot_wrappers={
+ 0: self.prim_cache["convert_to_number"]})})}))
- primitive_dictionary['id'] = self._prim_identity
palette.add_block('identity2',
style='number-style-1arg',
label='←',
@@ -668,10 +707,8 @@ minus :y\nend\n')
prim_name='id',
help_string=_('identity operator used for extending \
blocks'))
- self.tw.lc.def_prim('id', 1,
- lambda self, x: primitive_dictionary['id'](x))
+ self.tw.lc.def_prim('id', 1, Primitive(Primitive.identity))
- primitive_dictionary['remainder'] = self._prim_mod
palette.add_block('remainder2',
style='number-style-porch',
label=_('mod'),
@@ -680,10 +717,19 @@ blocks'))
logo_command='remainder',
help_string=_('modular (remainder) operator'))
self.tw.lc.def_prim('remainder', 2,
- lambda self, x, y:
- primitive_dictionary['remainder'](x, y))
+ Primitive(Primitive.modulo, slot_wrappers={
+ 0: Primitive(self.check_number,
+ export_me=False,
+ slot_wrappers={
+ 0: self.prim_cache["convert_to_number"]}),
+ 1: Primitive(self.check_non_zero,
+ export_me=False,
+ slot_wrappers={
+ 0: Primitive(self.check_number,
+ export_me=False,
+ slot_wrappers={
+ 0: self.prim_cache["convert_to_number"]})})}))
- primitive_dictionary['sqrt'] = self._prim_sqrt
palette.add_block('sqrt',
style='number-style-1arg',
label=_('√'),
@@ -692,7 +738,13 @@ blocks'))
logo_command='tasqrt',
help_string=_('calculates square root'))
self.tw.lc.def_prim('sqrt', 1,
- lambda self, x: primitive_dictionary['sqrt'](x))
+ Primitive(sqrt,
+ slot_wrappers={0: Primitive(self.check_non_negative,
+ slot_wrappers={0: Primitive(self.check_number,
+ slot_wrappers={0:
+ self.prim_cache["convert_to_number"]},
+ export_me=False)},
+ export_me=False)}))
primitive_dictionary['random'] = self._prim_random
palette.add_block('random',
@@ -717,7 +769,6 @@ output (random (:max - :min)) + :min\nend\n')
help_string=_('used as numeric input in mathematic \
operators'))
- primitive_dictionary['more'] = self._prim_more
palette.add_block('greater2',
style='compare-porch-style',
label=' >',
@@ -726,11 +777,11 @@ operators'))
prim_name='greater?',
logo_command='greater?',
help_string=_('logical greater-than operator'))
- self.tw.lc.def_prim(
- 'greater?', 2,
- lambda self, x, y: primitive_dictionary['more'](x, y))
+ self.tw.lc.def_prim('greater?', 2,
+ Primitive(Primitive.greater,
+ slot_wrappers={0: self.prim_cache["convert_for_cmp"],
+ 1: self.prim_cache["convert_for_cmp"]}))
- primitive_dictionary['less'] = self._prim_less
palette.add_block('less2',
style='compare-porch-style',
label=' <',
@@ -739,10 +790,11 @@ operators'))
prim_name='less?',
logo_command='less?',
help_string=_('logical less-than operator'))
- self.tw.lc.def_prim(
- 'less?', 2, lambda self, x, y: primitive_dictionary['less'](x, y))
+ self.tw.lc.def_prim('less?', 2,
+ Primitive(Primitive.less,
+ slot_wrappers={0: self.prim_cache["convert_for_cmp"],
+ 1: self.prim_cache["convert_for_cmp"]}))
- primitive_dictionary['equal'] = self._prim_equal
palette.add_block('equal2',
style='compare-style',
label='=',
@@ -752,8 +804,9 @@ operators'))
logo_command='equal?',
help_string=_('logical equal-to operator'))
self.tw.lc.def_prim('equal?', 2,
- lambda self, x, y:
- primitive_dictionary['equal'](x, y))
+ Primitive(Primitive.equals,
+ slot_wrappers={0: self.prim_cache["convert_for_cmp"],
+ 1: self.prim_cache["convert_for_cmp"]}))
palette.add_block('not',
style='not-style',
@@ -761,9 +814,8 @@ operators'))
prim_name='not',
logo_command='not',
help_string=_('logical NOT operator'))
- self.tw.lc.def_prim('not', 1, lambda self, x: not x)
+ self.tw.lc.def_prim('not', 1, Primitive(Primitive.not_))
- primitive_dictionary['and'] = self._prim_and
palette.add_block('and2',
style='boolean-style',
label=_('and'),
@@ -772,9 +824,8 @@ operators'))
special_name=_('and'),
help_string=_('logical AND operator'))
self.tw.lc.def_prim(
- 'and', 2, lambda self, x, y: primitive_dictionary['and'](x, y))
+ 'and', 2, Primitive(Primitive.and_))
- primitive_dictionary['or'] = self._prim_or
palette.add_block('or2',
style='boolean-style',
label=_('or'),
@@ -783,7 +834,7 @@ operators'))
special_name=_('or'),
help_string=_('logical OR operator'))
self.tw.lc.def_prim(
- 'or', 2, lambda self, x, y: primitive_dictionary['or'](x, y))
+ 'or', 2, Primitive(Primitive.or_))
def _flow_palette(self):
''' The basic Turtle Art flow palette '''
@@ -813,8 +864,11 @@ number of seconds'))
default=[None, None],
logo_command='forever',
help_string=_('loops forever'))
- self.tw.lc.def_prim('forever', 1, primitive_dictionary['forever'],
- True)
+ self.tw.lc.def_prim('forever', 1,
+ Primitive(self.tw.lc.prim_loop,
+ constant_args={0: Primitive(Primitive.controller_forever,
+ call_me=False)}),
+ True)
primitive_dictionary['repeat'] = self._prim_repeat
palette.add_block('repeat',
@@ -825,9 +879,14 @@ number of seconds'))
logo_command='repeat',
special_name=_('repeat'),
help_string=_('loops specified number of times'))
- self.tw.lc.def_prim('repeat', 2, primitive_dictionary['repeat'], True)
+ self.tw.lc.def_prim('repeat', 2,
+ Primitive(self.tw.lc.prim_loop,
+ slot_wrappers={0: Primitive(Primitive.controller_repeat,
+ slot_wrappers={0: Primitive(self.tw.lc.int,
+ slot_wrappers={0: self.prim_cache["check_number"]
+ })})}),
+ True)
- primitive_dictionary['if'] = self._prim_if
palette.add_block('if',
style='clamp-style-boolean',
label=[_('if'), _('then'), ''],
@@ -837,9 +896,8 @@ number of seconds'))
logo_command='if',
help_string=_('if-then operator that uses boolean \
operators from Numbers palette'))
- self.tw.lc.def_prim('if', 2, primitive_dictionary['if'], True)
+ self.tw.lc.def_prim('if', 2, Primitive(self.tw.lc.prim_if), True)
- primitive_dictionary['ifelse'] = self._prim_ifelse
palette.add_block('ifelse',
hidden=True, # Too big to fit palette
style='clamp-style-else',
@@ -850,7 +908,8 @@ operators from Numbers palette'))
special_name=_('if then else'),
help_string=_('if-then-else operator that uses \
boolean operators from Numbers palette'))
- self.tw.lc.def_prim('ifelse', 3, primitive_dictionary['ifelse'], True)
+ self.tw.lc.def_prim('ifelse', 3, Primitive(self.tw.lc.prim_ifelse),
+ True)
# macro
palette.add_block('ifthenelse',
@@ -867,7 +926,8 @@ boolean operators from Numbers palette'))
prim_name='nop',
special_name=_('horizontal space'),
help_string=_('jogs stack right'))
- self.tw.lc.def_prim('nop', 0, lambda self: None)
+ self.tw.lc.def_prim('nop', 0,
+ Primitive(Primitive.do_nothing, export_me=False))
palette.add_block('vspace',
style='basic-style-extended-vertical',
@@ -875,7 +935,8 @@ boolean operators from Numbers palette'))
prim_name='nop',
special_name=_('vertical space'),
help_string=_('jogs stack down'))
- self.tw.lc.def_prim('nop', 0, lambda self: None)
+ self.tw.lc.def_prim('nop', 0,
+ Primitive(Primitive.do_nothing, export_me=False))
primitive_dictionary['stopstack'] = self._prim_stopstack
palette.add_block('stopstack',
@@ -896,7 +957,6 @@ boolean operators from Numbers palette'))
colors=["#FFFF00", "#A0A000"],
help_string=_('Palette of variable blocks'))
- primitive_dictionary['start'] = self._prim_start
palette.add_block('start',
style='basic-style-head',
label=_('start'),
@@ -905,7 +965,11 @@ boolean operators from Numbers palette'))
help_string=_('connects action to toolbar run \
buttons'))
self.tw.lc.def_prim('start', 0,
- lambda self: primitive_dictionary['start']())
+ Primitive(Primitive.group, constant_args={0: [
+ Primitive(self.tw.lc.prim_start, call_me=False,
+ export_me=False),
+ Primitive(self.tw.lc.prim_define_stack,
+ constant_args={0: 'start'}, call_me=False)]}))
palette.add_block('string',
style='box-style',
@@ -922,9 +986,9 @@ buttons'))
default=_('action'),
logo_command='to action',
help_string=_('top of nameable action stack'))
- self.tw.lc.def_prim('nop3', 1, lambda self, x: None)
+ self.tw.lc.def_prim('nop3', 1, Primitive(self.tw.lc.prim_define_stack))
- primitive_dictionary['stack'] = self._prim_stack
+ primitive_dictionary['stack'] = Primitive(self.tw.lc.prim_invoke_stack)
palette.add_block('stack',
style='basic-style-1arg',
label=_('action'),
@@ -933,9 +997,10 @@ buttons'))
logo_command='action',
default=_('action'),
help_string=_('invokes named action stack'))
- self.tw.lc.def_prim('stack', 1, primitive_dictionary['stack'], True)
+ self.tw.lc.def_prim('stack', 1,
+ Primitive(self.tw.lc.prim_invoke_stack), True)
- primitive_dictionary['setbox'] = self._prim_setbox
+ primitive_dictionary['setbox'] = Primitive(self.tw.lc.prim_set_box)
palette.add_block('storeinbox1',
hidden=True,
style='basic-style-1arg',
@@ -946,9 +1011,7 @@ buttons'))
logo_command='make "box1',
help_string=_('stores numeric value in Variable 1'))
self.tw.lc.def_prim('storeinbox1', 1,
- lambda self, x:
- primitive_dictionary['setbox']
- ('box1', None, x))
+ Primitive(self.tw.lc.prim_set_box, constant_args={0: 'box1'}))
palette.add_block('storeinbox2',
hidden=True,
@@ -960,9 +1023,7 @@ buttons'))
logo_command='make "box2',
help_string=_('stores numeric value in Variable 2'))
self.tw.lc.def_prim('storeinbox2', 1,
- lambda self, x:
- primitive_dictionary['setbox']
- ('box2', None, x))
+ Primitive(self.tw.lc.prim_set_box, constant_args={0: 'box2'}))
palette.add_block('box1',
hidden=True,
@@ -972,7 +1033,8 @@ buttons'))
logo_command=':box1',
help_string=_('Variable 1 (numeric value)'),
value_block=True)
- self.tw.lc.def_prim('box1', 0, lambda self: self.tw.lc.boxes['box1'])
+ self.tw.lc.def_prim('box1', 0,
+ Primitive(self.tw.lc.prim_get_box, constant_args={0: 'box1'}))
palette.add_block('box2',
hidden=True,
@@ -982,7 +1044,8 @@ buttons'))
logo_command=':box2',
help_string=_('Variable 2 (numeric value)'),
value_block=True)
- self.tw.lc.def_prim('box2', 0, lambda self: self.tw.lc.boxes['box2'])
+ self.tw.lc.def_prim('box2', 0,
+ Primitive(self.tw.lc.prim_get_box, constant_args={0: 'box2'}))
palette.add_block('storein',
style='basic-style-2arg',
@@ -994,11 +1057,9 @@ buttons'))
help_string=_('stores numeric value in named \
variable'))
self.tw.lc.def_prim('storeinbox', 2,
- lambda self, x, y:
- primitive_dictionary['setbox']
- ('box3', x, y))
+ Primitive(self.tw.lc.prim_set_box))
- primitive_dictionary['box'] = self._prim_box
+ primitive_dictionary['box'] = Primitive(self.tw.lc.prim_get_box)
palette.add_block('box',
style='number-style-1strarg',
hidden=True,
@@ -1010,7 +1071,7 @@ variable'))
value_block=True,
help_string=_('named variable (numeric value)'))
self.tw.lc.def_prim('box', 1,
- lambda self, x: primitive_dictionary['box'](x))
+ Primitive(self.tw.lc.prim_get_box))
palette.add_block('hat1',
hidden=True,
@@ -1019,7 +1080,9 @@ variable'))
prim_name='nop1',
logo_command='to stack1\n',
help_string=_('top of Action 1 stack'))
- self.tw.lc.def_prim('nop1', 0, lambda self: None)
+ self.tw.lc.def_prim('nop1', 0,
+ Primitive(self.tw.lc.prim_define_stack,
+ constant_args={0: 'stack1'}))
palette.add_block('hat2',
hidden=True,
@@ -1028,9 +1091,10 @@ variable'))
prim_name='nop2',
logo_command='to stack2\n',
help_string=_('top of Action 2 stack'))
- self.tw.lc.def_prim('nop2', 0, lambda self: None)
+ self.tw.lc.def_prim('nop2', 0,
+ Primitive(self.tw.lc.prim_define_stack,
+ constant_args={0: 'stack2'}))
- primitive_dictionary['stack1'] = self._prim_stack1
palette.add_block('stack1',
hidden=True,
style='basic-style-extended-vertical',
@@ -1038,9 +1102,11 @@ variable'))
prim_name='stack1',
logo_command='stack1',
help_string=_('invokes Action 1 stack'))
- self.tw.lc.def_prim('stack1', 0, primitive_dictionary['stack1'], True)
+ self.tw.lc.def_prim('stack1', 0,
+ Primitive(self.tw.lc.prim_invoke_stack,
+ constant_args={0: 'stack1'}),
+ True)
- primitive_dictionary['stack2'] = self._prim_stack2
palette.add_block('stack2',
hidden=True,
style='basic-style-extended-vertical',
@@ -1048,7 +1114,10 @@ variable'))
prim_name='stack2',
logo_command='stack2',
help_string=_('invokes Action 2 stack'))
- self.tw.lc.def_prim('stack2', 0, primitive_dictionary['stack2'], True)
+ self.tw.lc.def_prim('stack2', 0,
+ Primitive(self.tw.lc.prim_invoke_stack,
+ constant_args={0: 'stack2'}),
+ True)
def _trash_palette(self):
''' The basic Turtle Art turtle palette '''
@@ -1084,9 +1153,7 @@ variable'))
''' Logical and '''
return x & y
- def _prim_arc(self, cmd, value1, value2):
- ''' Turtle draws an arc of degree, radius '''
- cmd(float(value1), float(value2))
+ def after_arc(self, *ignored_args):
if self.tw.lc.update_values:
self.tw.lc.update_label_value(
'xcor',
@@ -1119,46 +1186,39 @@ variable'))
break
self.tw.lc.ireturn()
yield True
-
- def _prim_if(self, boolean, blklist):
- ''' If bool, do list '''
- if boolean:
- self.tw.lc.icall(self.tw.lc.evline, blklist[:])
- yield True
- self.tw.lc.ireturn()
- yield True
-
- def _prim_ifelse(self, boolean, list1, list2):
- ''' If bool, do list1, else do list2 '''
- if boolean:
- self.tw.lc.ijmp(self.tw.lc.evline, list1[:])
- yield True
+
+ def convert_value_for_move(self, value):
+ ''' Perform type conversion and other preprocessing on the parameter,
+ so it can be passed to the 'move' primitive. '''
+ if value is None:
+ return value
+
+ def _convert_to_float(val):
+ if not _num_type(val):
+ raise logoerror("#notanumber")
+ return float(val)
+
+ if isinstance(value, (tuple, list)):
+ (val1, val2) = value
+ val1_float = _convert_to_float(val1)
+ val2_float = _convert_to_float(val2)
+ value_converted = (val1_float, val2_float)
else:
- self.tw.lc.ijmp(self.tw.lc.evline, list2[:])
- yield True
+ value_converted = _convert_to_float(value)
+ return value_converted
- def _prim_move(self, cmd, value1, value2=None, pendown=True,
+ def _prim_move(self, cmd, value1, pendown=True,
reverse=False):
''' Turtle moves by method specified in value1 '''
- pos = None
- if isinstance(value1, (tuple, list)):
- pos = value1
- value1 = pos[0]
- value2 = pos[1]
- if not _num_type(value1):
- raise logoerror("#notanumber")
- if value2 is None:
- if reverse:
- cmd(float(-value1))
- else:
- cmd(float(value1))
- else:
- if not _num_type(value2):
- raise logoerror("#notanumber")
- if pos is not None:
- cmd((float(value1), float(value2)), pendown=pendown)
- else:
- cmd(float(value1), float(value2), pendown=pendown)
+
+ value1_conv = self.convert_value_for_move(value1)
+
+ cmd(value1_conv, pendown=pendown)
+
+ self.after_move()
+
+ def after_move(self, *ignored_args):
+ ''' Update labels after moving the turtle '''
if self.tw.lc.update_values:
self.tw.lc.update_label_value(
'xcor',
@@ -1185,15 +1245,31 @@ variable'))
break
self.tw.lc.ireturn()
yield True
-
- def _prim_right(self, value, reverse=False):
- ''' Turtle rotates clockwise '''
+
+ def check_number(self, value):
+ ''' Check if value is a number. If yes, return the value. If no,
+ raise a logoerror. '''
if not _num_type(value):
raise logoerror("#notanumber")
- if reverse:
- self.tw.turtles.get_active_turtle().right(float(-value))
- else:
- self.tw.turtles.get_active_turtle().right(float(value))
+ return value
+
+ def check_non_negative(self, x, msg="#negroot"):
+ ''' Raise a logoerror iff x is negative. Otherwise, return x
+ unchanged.
+ msg -- the name of the logoerror message '''
+ if x < 0:
+ raise logoerror(msg)
+ return x
+
+ def check_non_zero(self, x, msg="#zerodivide"):
+ ''' Raise a logoerror iff x is zero. Otherwise, return x
+ unchanged.
+ msg -- the name of the logoerror message '''
+ if x == 0:
+ raise logoerror(msg)
+ return x
+
+ def after_right(self, *ignored_args):
if self.tw.lc.update_values:
self.tw.lc.update_label_value(
'heading',
@@ -1206,6 +1282,12 @@ variable'))
if self.tw.lc.update_values:
self.tw.lc.update_label_value(name, value)
+ def after_set(self, name, value=None):
+ ''' Update the associated value blocks '''
+ if value is not None:
+ if self.tw.lc.update_values:
+ self.tw.lc.update_label_value(name, value)
+
def _prim_setbox(self, name, x, val):
''' Define value of named box '''
if x is not None:
@@ -1256,11 +1338,6 @@ variable'))
self.tw.lc.ireturn()
yield True
- def _prim_start(self):
- ''' Start block: recenter '''
- if self.tw.running_sugar:
- self.tw.activity.recenter()
-
def _prim_stopstack(self):
''' Stop execution of a stack '''
self.tw.lc.procstop = True
@@ -1276,7 +1353,7 @@ variable'))
self.tw.lc.ireturn()
yield True
- # Math primitivies
+ # Math primitives
def _prim_careful_divide(self, x, y):
''' Raise error on divide by zero '''
@@ -1302,57 +1379,12 @@ variable'))
except TypeError:
raise logoerror("#notanumber")
- def _prim_equal(self, x, y):
- ''' Numeric and logical equal '''
- if isinstance(x, list) and isinstance(y, list):
- for i in range(len(x)):
- if x[i] != y[i]:
- return False
- return True
- try:
- return float(x) == float(y)
- except ValueError:
- typex, typey = False, False
- if strtype(x):
- typex = True
- if strtype(y):
- typey = True
- if typex and typey:
- return x == y
- try:
- return self._string_to_num(x) == self._string_to_num(y)
- except TypeError:
- raise logoerror("#syntaxerror")
-
- def _prim_less(self, x, y):
- ''' Compare numbers and strings '''
- if isinstance(x, list) or isinstance(y, list):
- raise logoerror("#syntaxerror")
- try:
- return float(x) < float(y)
- except ValueError:
- typex, typey = False, False
- if strtype(x):
- typex = True
- if strtype(y):
- typey = True
- if typex and typey:
- return x < y
- try:
- return self._string_to_num(x) < self._string_to_num(y)
- except TypeError:
- raise logoerror("#notanumber")
-
- def _prim_more(self, x, y):
- ''' Compare numbers and strings '''
- return self._prim_less(y, x)
-
def _prim_plus(self, x, y):
''' Add numbers, concat strings '''
- if x in COLORDICT:
- x = _color_to_num(x)
- if y in COLORDICT:
- y = _color_to_num(y)
+ if isinstance(x, Color):
+ x = int(x)
+ if isinstance(y, Color):
+ y = int(y)
if _num_type(x) and _num_type(y):
return(x + y)
elif isinstance(x, list) and isinstance(y, list):
@@ -1415,19 +1447,6 @@ variable'))
except ValueError:
raise logoerror("#syntaxerror")
- def _prim_sqrt(self, x):
- ''' Square root '''
- if _num_type(x):
- if x < 0:
- raise logoerror("#negroot")
- return sqrt(x)
- try:
- return sqrt(self._string_to_num(x))
- except ValueError:
- raise logoerror("#negroot")
- except TypeError:
- raise logoerror("#notanumber")
-
def _prim_random(self, x, y):
''' Random integer '''
if _num_type(x) and _num_type(y):
@@ -1445,14 +1464,10 @@ variable'))
except TypeError:
raise logoerror("#notanumber")
- def _prim_identity(self, x):
- ''' Identity function '''
- return(x)
-
# Utilities
def _string_to_num(self, x):
- ''' Try to comvert a string to a number '''
+ ''' Try to convert a string to a number '''
if isinstance(x, (int, float)):
return(x)
try:
@@ -1461,8 +1476,8 @@ variable'))
pass
if isinstance(x, list):
raise logoerror("#syntaxerror")
- if x in COLORDICT:
- return _color_to_num(x)
+ if isinstance(x, Color):
+ return int(x)
xx = convert(x.replace(self.tw.decimal_point, '.'), float)
if isinstance(xx, float):
return xx
@@ -1475,12 +1490,12 @@ variable'))
def _make_constant(self, palette, block_name, label, constant):
''' Factory for constant blocks '''
- if constant in COLORDICT:
- if COLORDICT[constant][0] is not None:
- value = str(COLORDICT[constant][0])
+ if isinstance(constant, Color):
+ if constant.color is not None:
+ value = str(constant.color)
else:
# Black or White
- value = '0 tasetshade %d' % (COLORDICT[constant][1])
+ value = '0 tasetshade %d' % (constant.shade)
else:
value = constant
palette.add_block(block_name,
@@ -1488,4 +1503,5 @@ variable'))
label=label,
prim_name=block_name,
logo_command=value)
- self.tw.lc.def_prim(block_name, 0, lambda self: constant)
+ self.tw.lc.def_prim(block_name, 0,
+ Primitive(Primitive.identity, constant_args={0: constant}))