From 6f0bd6bec7e548cd1d031ce413a24f4b842b3fdf Mon Sep 17 00:00:00 2001 From: Marion Date: Sun, 11 Aug 2013 16:45:28 +0000 Subject: add Primitive for the '==' ('equals') block - Exported code does not yet do what it should. --- diff --git a/TurtleArt/tabasics.py b/TurtleArt/tabasics.py index 2b5b1fb..7702ad5 100644 --- a/TurtleArt/tabasics.py +++ b/TurtleArt/tabasics.py @@ -97,7 +97,9 @@ class Palettes(): 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) + export_me=False), + "convert_for_cmp": Primitive(Primitive.convert_for_cmp, + constant_args={'decimal_point': self.tw.decimal_point}) } # avoid several Primitives of the same function self._turtle_palette() @@ -754,8 +756,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', @@ -1447,7 +1450,7 @@ variable')) # 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: diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py index b1dc43e..4648993 100644 --- a/TurtleArt/taconstants.py +++ b/TurtleArt/taconstants.py @@ -110,6 +110,21 @@ class Color(object): return '%s (%s/%d/%d)' % (str(self.name), str(self.color), self.shade, self.gray) + def __eq__(self, other): + """ A Color is equivalent to + * another Color with the same color, shade, and gray values + * an integer, float, or long that equals int(self) """ + if isinstance(other, Color): + return (self.color == other.color and self.shade == other.shade + and self.gray == other.gray) + elif isinstance(other, (int, float, long)): + return int(self) == other + ## * a basestring that equals str(self) + #elif isinstance(other, basestring): + # return str(self) == other + else: + return False + # TODO implement addition def is_gray(self): diff --git a/TurtleArt/taprimitive.py b/TurtleArt/taprimitive.py index 4e0910e..8171c43 100644 --- a/TurtleArt/taprimitive.py +++ b/TurtleArt/taprimitive.py @@ -64,7 +64,8 @@ class Primitive(object): 'bitwise_or': ast.BitOr, 'and_': ast.And, 'or_': ast.Or, - 'not_': ast.Not} + 'not_': ast.Not, + 'equals': ast.Eq} def __init__(self, func, constant_args=None, slot_wrappers=None, call_afterwards=None, call_me=True, export_me=True): @@ -347,8 +348,11 @@ class Primitive(object): if isinstance(op, tuple): op = op[1] (left, right) = new_arg_asts - if op in (ast.And, ast.Or): + if issubclass(op, ast.boolop): return ast.BoolOp(op=op, values=[left, right]) + elif issubclass(op, ast.cmpop): + return ast.Compare(left=left, ops=[op], + comparators=[right]) else: return ast.BinOp(op=op, left=left, right=right) else: @@ -357,6 +361,16 @@ class Primitive(object): % (str(self.func.__func__.__name__), len(new_arg_asts))) + elif self == Primitive.convert_for_cmp: + # remove the 'convert_to_ast' keyword argument + my_kwarg_asts = {} + for (key, value) in new_kwarg_asts.iteritems(): + if key != 'convert_to_ast': + my_kwarg_asts[key] = value + return Primitive.convert_for_cmp(*new_arg_asts, + convert_to_ast=True, + **my_kwarg_asts) + # identity elif self == Primitive.identity: if len(new_arg_asts) == 1: @@ -615,6 +629,56 @@ class Primitive(object): otherwise. """ return not arg + @staticmethod + def convert_for_cmp(value, decimal_point='.', convert_to_ast=False): + """ Convert value such that it can be compared to something else. + 1. Convert a string containing a number into a float. + 2. Convert a single character to its ASCII integer value. + 3. Return all other values unchanged. """ + converted = None + conversion_ast = None + if convert_to_ast: + value_ast = value_to_ast(value) + + if isinstance(value, basestring): + # 1. string containing a number + replaced = value.replace(decimal_point, '.') + try: + converted = float(replaced) + except ValueError: + pass + else: + if convert_to_ast: + conversion_ast = get_call_ast('float', [value_ast]) + + # 2. single character + if converted is None: + try: + converted = ord(value) + except TypeError: + pass + else: + if convert_to_ast: + conversion_ast = get_call_ast('ord', [value_ast]) + + # 3. normal string or other type of value (nothing to do) + + if convert_to_ast: + if conversion_ast is None: + return value_ast + else: + return conversion_ast + else: + if converted is None: + return value + else: + return converted + + @staticmethod + def equals(arg1, arg2): + """ Return arg1 == arg2 """ + return arg1 == arg2 + class PrimitiveCall(Primitive): @@ -681,6 +745,15 @@ def value_to_ast(value, *args_for_prim, **kwargs_for_prim): raise ValueError("unknown type of raw value: " + repr(type(value))) +def get_call_ast(func_name, args=[], keywords={}): + return ast.Call(func=ast.Name(id=func_name, + ctx=ast.Load), + args=args, + keywords=keywords, + starargs=None, + kwargs=None) + + def call_me(something): """ Return True iff this is a Primitive and its call_me attribute is True, i.e. nothing is callable except for Primitives with -- cgit v0.9.1