Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/TurtleArt
diff options
context:
space:
mode:
authorMarion <marion.zepf@gmail.com>2013-08-28 08:41:07 (GMT)
committer Marion <marion.zepf@gmail.com>2013-08-28 08:41:07 (GMT)
commit676ce91131ca56de318a6459d2ec697e9d6b1f74 (patch)
treec2fb835748221b83f687ea7ce6568a37239874f6 /TurtleArt
parent875d5c047747c2122865bbb60bc5b2edc0278feb (diff)
better handling for TATypeErrors coming from the type system
Diffstat (limited to 'TurtleArt')
-rw-r--r--TurtleArt/talogo.py7
-rw-r--r--TurtleArt/taprimitive.py31
-rw-r--r--TurtleArt/tatype.py43
3 files changed, 54 insertions, 27 deletions
diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py
index 3553a93..1c95c3b 100644
--- a/TurtleArt/talogo.py
+++ b/TurtleArt/talogo.py
@@ -38,6 +38,7 @@ import traceback
from tablock import (Block, media_blocks_dictionary)
from taconstants import (TAB_LAYER, DEFAULT_SCALE)
from tapalette import (block_names, value_blocks)
+from tatype import TATypeError
from tautils import (get_pixbuf_from_journal, data_from_file,
text_media_type, round_int, debug_output, find_group,
get_stack_name)
@@ -535,6 +536,12 @@ class LogoCode:
self.tw.showlabel('status', 'ValueError: ' +
str(ve))
return False
+ except TATypeError as tte:
+ if not self.tw.running_turtleart:
+ traceback.print_exc()
+ raise logoerror("%s %s %s %s" % (self.cfun.name,
+ _("doesn't like"), str(tte.bad_value),
+ _("as input")))
else:
return False
except StopIteration:
diff --git a/TurtleArt/taprimitive.py b/TurtleArt/taprimitive.py
index 912a9ef..301e849 100644
--- a/TurtleArt/taprimitive.py
+++ b/TurtleArt/taprimitive.py
@@ -276,15 +276,17 @@ class Primitive(object):
# arguments
error = None
+ list_failed = False
+ filler = None
for slot_list in slot_list_alternatives:
list_failed = False
new_slot_list = []
- fillers = list(arguments[:])
+ filler_list = list(arguments[:])
for slot in slot_list:
if isinstance(slot, ArgSlot):
- f = fillers.pop(0)
+ filler = filler_list.pop(0)
try:
- value = slot.fill(f)
+ value = slot.fill(filler)
except TATypeError as error:
list_failed = True
break
@@ -956,10 +958,11 @@ class PrimitiveDisjunction(Primitive,Disjunction):
if runtime_args and isinstance(runtime_args[0], LogoCode):
runtime_args = runtime_args[1:]
+ error = None
for prim in self:
try:
new_prim = prim.fill_slots(*runtime_args, **runtime_kwargs)
- except TATypeError:
+ except TATypeError as error:
# on failure, try the next one
continue
else:
@@ -967,7 +970,8 @@ class PrimitiveDisjunction(Primitive,Disjunction):
return new_prim()
# if we get here, all disjuncts failed
- raise TATypeError("all Primitives failed") # TODO better error message
+ if error is not None:
+ raise error
class ArgListDisjunction(Disjunction):
@@ -1003,18 +1007,21 @@ class ArgSlot(object):
return (self, )
def fill(self, argument, convert_to_ast=False):
- """ Fill this argument slot with the given argument """
+ """ Try to fill this argument slot with the given argument. If there
+ is a type problem, raise a TATypeError. """
if isinstance(argument, ast.AST):
convert_to_ast = True
elif convert_to_ast:
argument = value_to_ast(argument)
+ error = None
for slot in self.get_alternatives():
# check if the argument can fill this slot (type-wise)
if slot.wrapper is not None:
arg_type = get_type(slot.wrapper)[0]
else:
+ # TODO take call_arg into account?
arg_type = get_type(argument)[0]
converter = get_converter(arg_type, slot.type)
if converter is None:
@@ -1069,7 +1076,7 @@ class ArgSlot(object):
try:
converted_argument = convert(wrapped_argument, slot.type,
converter=converter)
- except TATypeError as ce:
+ except TATypeError as error:
# on failure, try the next slot
continue
else:
@@ -1077,11 +1084,11 @@ class ArgSlot(object):
return converted_argument
# if we haven't returned anything yet, then all alternatives failed
- traceback.print_exc()
- # TODO find appropriate logoerror message depending on type combination
- raise TATypeError("type mismatch while filling arg slot")
-
- return argument
+ if error is not None:
+ raise error
+ else:
+ raise TATypeError(bad_value=argument, bad_type=arg_type,
+ req_type=self.type)
class ArgSlotDisjunction(ArgSlot,Disjunction):
diff --git a/TurtleArt/tatype.py b/TurtleArt/tatype.py
index d4fec2b..6b0acd6 100644
--- a/TurtleArt/tatype.py
+++ b/TurtleArt/tatype.py
@@ -195,22 +195,34 @@ def get_call_ast(func_name, args=None, keywords=None):
class TATypeError(BaseException):
""" TypeError with the types from the hierarchy, not with Python types """
- def __init__(self, message, type1=None, type2=None):
- """ message -- the error message (type1 and type2 are inserted
- automatically iff message contains '%s' for them) """
+ def __init__(self, bad_value, bad_type=None, req_type=None, message=''):
+ """ bad_value -- the mis-typed value that caused the error
+ bad_type -- the type of the bad_value
+ req_type -- the type that the value was expected to have
+ message -- short statement about the cause of the error. It is
+ not shown to the user, but may appear in debugging output. """
+ self.bad_value = bad_value
+ self.bad_type = bad_type
+ self.req_type = req_type
self.message = message
- self.type1 = type1
- self.type2 = type2
def __str__(self):
- num = self.message.count('%s')
- if num == 2:
- msg = self.message % (self.type1, self.type2)
- elif num == 1:
- msg = self.message % (self.type1)
- else:
- msg = self.message
- return "TA TypeError: " + msg
+ msg = []
+ if self.message:
+ msg.append(self.message)
+ msg.append(" (")
+ msg.append("bad value: ")
+ msg.append(repr(self.bad_value))
+ if self.bad_type is not None:
+ msg.append(", bad type: ")
+ msg.append(repr(self.bad_type))
+ if self.req_type is not None:
+ msg.append(", req type: ")
+ msg.append(repr(self.req_type))
+ if self.message:
+ msg.append(")")
+ return "".join(msg)
+ __repr__ = __str__
def get_converter(old_type, new_type):
@@ -285,8 +297,9 @@ def convert(x, new_type, old_type=None, converter=None):
converter = get_converter(old_type, new_type)
if converter is None:
# no converter available
- raise TATypeError("type %s cannot be converted to type %s"
- % (repr(old_type), repr(new_type)))
+ raise TATypeError(bad_value=x, bad_type=old_type,
+ req_type=new_type, message=("found no converter"
+ " for this type combination"))
def _apply_converter(converter, y):
if is_an_ast: