From c2937d9fdd30b1b896caf66851d6677924d07488 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Thu, 12 Aug 2010 17:57:55 +0000 Subject: reorg of module heirarchy --- (limited to 'TurtleArt/talogo.py') diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py new file mode 100644 index 0000000..318bb7e --- /dev/null +++ b/TurtleArt/talogo.py @@ -0,0 +1,1366 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2007-8, Playful Invention Company. +#Copyright (c) 2008-10, Walter Bender +#Copyright (c) 2008-10, Raúl Gutiérrez Segalés + +#Permission is hereby granted, free of charge, to any person obtaining a copy +#of this software and associated documentation files (the "Software"), to deal +#in the Software without restriction, including without limitation the rights +#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#copies of the Software, and to permit persons to whom the Software is +#furnished to do so, subject to the following conditions: + +#The above copyright notice and this permission notice shall be included in +#all copies or substantial portions of the Software. + +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +#THE SOFTWARE. + +import gtk +from time import clock +from math import sqrt +from random import uniform +from operator import isNumberType +from UserDict import UserDict +try: + from sugar.datastore import datastore +except: + pass + +from taconstants import PALETTES, PALETTE_NAMES, TAB_LAYER, BLACK, WHITE +from tagplay import play_audio, play_movie_from_file, stop_media +from tajail import myfunc, myfunc_import +from tautils import get_pixbuf_from_journal, movie_media_type, convert, \ + audio_media_type, text_media_type, round_int, chr_to_ord, \ + strtype +from gettext import gettext as _ + +class noKeyError(UserDict): + __missing__ = lambda x, y: 0 + +class symbol: + def __init__(self, name): + self.name = name + self.nargs = None + self.fcn = None + + def __str__(self): + return self.name + def __repr__(self): + return '#' + self.name + +class logoerror(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + +# Utility functions + +def numtype(x): + """ Is x a number type? """ + if type(x) == int: + return True + if type(x) == float: + return True + if type(x) == ord: + return True + return False + +def str_to_num(x): + """ Try to comvert a string to a number """ + xx = convert(x, float) + if type(xx) is float: + return xx + else: + xx, xflag = chr_to_ord(x) + if xflag: + return xx + else: + raise logoerror("#syntaxerror") + +def taand(x, y): + """ Logical and """ + return x&y + +def taor(x, y): + """ Logical or """ + return x|y + +def careful_divide(x, y): + """ Raise error on divide by zero """ + try: + return x/y + except ZeroDivisionError: + raise logoerror("#zerodivide") + except TypeError: + try: + return str_to_num(x) / str_to_num(y) + except ZeroDivisionError: + raise logoerror("#zerodivide") + except ValueError: + raise logoerror("#syntaxerror") + +def taequal(x, y): + """ Numeric and logical equal """ + try: + return float(x)==float(y) + except TypeError: + typex, typey = False, False + if strtype(x): + typex = True + if strtype(y): + typey = True + if typex and typey: + return x == y + try: + return str_to_num(x) == str_to_num(y) + except ValueError: + raise logoerror("#syntaxerror") + +def taless(x, y): + """ Compare numbers and strings """ + try: + return float(x)4: # There could be a '(', ')', '[' or ']'. + code.append(dock[4]) + if blk.name == 'savesvg': + self.tw.saving_svg = True + if blk.primitive is not None: # make a tuple (prim, blk) + code.append((blk.primitive, self.tw.block_list.list.index(blk))) + elif len(blk.values)>0: # Extract the value from content blocks. + if blk.name == 'number': + try: + code.append(float(blk.values[0])) + except ValueError: + code.append(float(ord(blk.values[0][0]))) + elif blk.name == 'string' or blk.name == 'title': + if type(blk.values[0]) == float or type(blk.values[0]) == int: + if int(blk.values[0]) == blk.values[0]: + blk.values[0] = int(blk.values[0]) + code.append('#s'+str(blk.values[0])) + else: + code.append('#s'+blk.values[0]) + elif blk.name == 'journal': + if blk.values[0] is not None: + code.append('#smedia_'+str(blk.values[0])) + else: + code.append('#smedia_None') + elif blk.name == 'description': + if blk.values[0] is not None: + code.append('#sdescr_'+str(blk.values[0])) + else: + code.append('#sdescr_None') + elif blk.name == 'audio': + if blk.values[0] is not None: + code.append('#saudio_'+str(blk.values[0])) + else: + code.append('#saudio_None') + else: + return ['%nothing%'] + else: + return ['%nothing%'] + if blk.connections is not None and len(blk.connections) > 0: + for i in range(1, len(blk.connections)): + b = blk.connections[i] + dock = blk.docks[i] + if len(dock)>4: # There could be a '(', ')', '[' or ']'. + for c in dock[4]: + code.append(c) + if b is not None: + code.extend(self.blocks_to_code(b)) + elif blk.docks[i][0] not in ['flow', 'unavailable']: + code.append('%nothing%') + return code + + def setup_cmd(self, string): + """ Execute the psuedocode. """ + self.tw.active_turtle.hide() # Hide the turtle while we are running. + self.procstop = False + blklist = self.readline(string) + self.step = self.start_eval(blklist) + + """ + Convert the pseudocode into a list of commands. + The block associated with the command is stored as the second element + in a tuple, e.g., (#forward, 16) + """ + def readline(self, line): + res = [] + while line: + token = line.pop(0) + bindex = None + if type(token) == tuple: + (token, bindex) = token + if isNumberType(token): + res.append(token) + elif token.isdigit(): + res.append(float(token)) + elif token[0] == '-' and token[1:].isdigit(): + res.append(-float(token[1:])) + elif token[0] == '"': + res.append(token[1:]) + elif token[0:2] == "#s": + res.append(token[2:]) + elif token == '[': + res.append(self.readline(line)) + elif token == ']': + return res + elif bindex is None or type(bindex) is not int: + res.append(self.intern(token)) + else: + res.append((self.intern(token), bindex)) + return res + + def start_eval(self, blklist): + """ Step through the list. """ + if self.tw.running_sugar: + self.tw.activity.stop_turtle_button.set_icon("stopiton") + elif self.tw.interactive_mode: + self.tw.toolbar_shapes['stopiton'].set_layer(TAB_LAYER) + self.running = True + self.icall(self.evline, blklist) + yield True + if self.tw.running_sugar: + self.tw.activity.stop_turtle_button.set_icon("stopitoff") + elif self.tw.interactive_mode: + self.tw.toolbar_shapes['stopiton'].hide() + yield False + self.running = False + + def icall(self, fcn, *args): + """ Add a function and its arguments to the program stack. """ + self.istack.append(self.step) + self.step = fcn(*(args)) + + def evline(self, blklist): + """ Evaluate a line of code from the list. """ + oldiline = self.iline + self.iline = blklist[:] + self.arglist = None + while self.iline: + token = self.iline[0] + bindex = None + if type(token) == tuple: + (token, bindex) = self.iline[0] + + # If the blocks are visible, highlight the current block. + if not self.tw.hide and bindex is not None: + self.tw.block_list.list[bindex].highlight() + + # In debugging modes, we pause between steps and show the turtle. + if self.tw.step_time > 0: + self.tw.active_turtle.show() + endtime = millis()+self.an_int(self.tw.step_time)*100 + while millis() 0: + self.tw.display_coordinates() + yield True + + def eval(self): + """ Evaluate the next token on the line of code we are processing. """ + token = self.iline.pop(0) + bindex = None + if type(token) == tuple: + (token, bindex) = token + + # Either we are processing a symbol or a value. + if type(token) == self.symtype: + # We highlight blocks here in case an error occurs... + # print "> ", token + if not self.tw.hide and bindex is not None: + self.tw.block_list.list[bindex].highlight() + self.icall(self.evalsym, token) + yield True + # and unhighlight if everything was OK. + if not self.tw.hide and bindex is not None: + self.tw.block_list.list[bindex].unhighlight() + res = self.iresult + else: + # print ": ", token + res = token + + self.ireturn(res) + yield True + + def evalsym(self, token): + """ Process primitive associated with symbol token """ + self.debug_trace(token) + self.undefined_check(token) + oldcfun, oldarglist = self.cfun, self.arglist + self.cfun, self.arglist = token, [] + + if token.nargs == None: + raise logoerror("#noinput") + for i in range(token.nargs): + self.no_args_check() + self.icall(self.eval) + yield True + self.arglist.append(self.iresult) + if self.cfun.rprim: + if type(self.cfun.fcn) == self.listtype: + print "evalsym rprim list: ", token + self.icall(self.ufuncall, self.cfun.fcn) + yield True + else: + # print "evalsym rprim: ", token + self.icall(self.cfun.fcn, *self.arglist) + yield True + result = None + else: + # print "evalsym: ", token + result = self.cfun.fcn(self, *self.arglist) + self.cfun, self.arglist = oldcfun, oldarglist + if self.arglist is not None and result == None: + raise logoerror("%s %s %s" % \ + (oldcfun.name, _("did not output to"), self.cfun.name)) + self.ireturn(result) + yield True + + def ufuncall(self, body): + """ ufuncall """ + self.ijmp(self.evline, body) + yield True + + def doevalstep(self): + """ evaluate one step """ + starttime = millis() + try: + while (millis()-starttime)<120: + try: + if self.step is not None: + self.step.next() + else: + return False + except StopIteration: + self.tw.turtles.show_all() + return False + except logoerror, e: + self.tw.showlabel('syntaxerror', str(e)[1:-1]) + self.tw.turtles.show_all() + return False + return True + + def ireturn(self, res=None): + """ return value """ + self.step = self.istack.pop() + self.iresult = res + + def ijmp(self, fcn, *args): + """ ijmp """ + self.step = fcn(*(args)) + + def debug_trace(self, token): + """ Display debugging information """ + if self.trace: + if token.name in PALETTES[PALETTE_NAMES.index('turtle')]: + my_string = "%s\n%s=%d\n%s=%d\n%s=%d\n%s=%d" % \ + (token.name, _('xcor'), int(self.tw.canvas.xcor), + _('ycor'), int(self.tw.canvas.ycor), _('heading'), + int(self.tw.canvas.heading), _('scale'), int(self.scale)) + elif token.name in PALETTES[PALETTE_NAMES.index('pen')]: + if self.tw.canvas.pendown: + penstatus = _('pen down') + else: + penstatus = _('pen up') + my_string = "%s\n%s\n%s=%d\n%s=%d\n%s=%.1f" % \ + (token.name, penstatus, _('color'), + int(self.tw.canvas.color), _('shade'), + int(self.tw.canvas.shade), _('pen size'), + self.tw.canvas.pensize) + else: + my_string = "%s\n" % (token.name) + for k, v in self.boxes.iteritems(): + my_string += "%s: %s\n" % (k, str(v)) + self.tw.showlabel('info', my_string) + return + + def undefined_check(self, token): + """ Make sure token has a definition """ + if token.fcn is not None: + return False + if token.name == '%nothing%': + errormsg = '' + else: + errormsg = "%s %s" % (_("I don't know how to"), _(token.name)) + raise logoerror(errormsg) + + def no_args_check(self): + """ Missing argument ? """ + if self.iline and self.iline[0] is not self.symnothing: + return + raise logoerror("#noinput") + + # + # Primitives + # + + def prim_clear(self): + """ Clear screen """ + stop_media(self) + self.tw.canvas.clearscreen() + + def prim_start(self): + """ Start block: recenter """ + if self.tw.running_sugar: + self.tw.activity.recenter() + + def prim_wait(self, time): + """ Show the turtle while we wait """ + self.tw.active_turtle.show() + endtime = millis()+self.an_int(time*1000) + while millis()