From 5b88ca833baddc54b2b5f79245d20acadbbfa07f Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Sat, 31 Dec 2011 21:35:13 +0000 Subject: internalized macro expansion of while and until blocks --- (limited to 'TurtleArt') diff --git a/TurtleArt/tablock.py b/TurtleArt/tablock.py index 35dd6d3..a0c0c2e 100644 --- a/TurtleArt/tablock.py +++ b/TurtleArt/tablock.py @@ -172,7 +172,6 @@ class Block: 'flow-style-tail': self._make_flow_style_tail, 'flow-style-1arg': self._make_flow_style_1arg, 'flow-style-boolean': self._make_flow_style_boolean, - 'flow-style-while': self._make_flow_style_while, 'flow-style-else': self._make_flow_style_else, 'collapsible-top': [self._make_collapsible_style_top, True, True], 'collapsible-top-no-arm': [self._make_collapsible_style_top, @@ -809,21 +808,6 @@ class Block: ['flow', False, self.svg.docks[3][0], self.svg.docks[3][1], ']']] - def _make_flow_style_while(self, svg): - self.svg.expand(self.dx + self.ex, self.ey) - self.svg.set_slot(True) - self.svg.set_tab(True) - self.svg.set_boolean(True) - self._make_block_graphics(svg, self.svg.basic_flow) - self.docks = [['flow', True, self.svg.docks[0][0], - self.svg.docks[0][1]], - ['bool', False, self.svg.docks[1][0], - self.svg.docks[1][1], '['], - ['flow', False, self.svg.docks[2][0], - self.svg.docks[2][1], ']['], - ['flow', False, self.svg.docks[3][0], - self.svg.docks[3][1], ']']] - def _make_flow_style_else(self, svg): self.svg.expand(self.dx + self.ex, self.ey) self.svg.set_slot(True) diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py index d0b7b46..3a0a4c0 100644 --- a/TurtleArt/taconstants.py +++ b/TurtleArt/taconstants.py @@ -227,6 +227,7 @@ VOICES = {'af': 'afrikaans', 'cy': 'welsh-test', 'el': 'greek', # Macros (groups of blocks) # MACROS = { + ''' 'until': [[0, 'forever', 0, 0, [None, 2, 1]], [1, 'vspace', 0, 0, [0, None]], @@ -239,6 +240,7 @@ MACROS = { [2, 'ifelse', 0, 0, [0, None, 3, 4, None]], [3, 'vspace', 0, 0, [2, None]], [4, 'stopstack', 0, 0, [2, None]]], + ''' 'kbinput': [[0, 'forever', 0, 0, [None, 1, None]], [1, 'kbinput', 0, 0, [0, 2]], diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py index b63098d..c7ef76c 100644 --- a/TurtleArt/talogo.py +++ b/TurtleArt/talogo.py @@ -67,6 +67,14 @@ class logoerror(Exception): def __str__(self): return repr(self.value) +class HiddenBlock: + + def __init__(self, name): + self.name = name + self.primitive = name + self.connections = [] + self.docks = [] + # Utility functions def _just_stop(): @@ -163,6 +171,11 @@ class LogoCode: self.stacks['stack2'] = None self.tw.saving_svg = False + # Save state in case there is a hidden macro expansion + saveblocks = None + saveblk = blk + savewhileblks = [] + if self.trace > 0: self.update_values = True else: @@ -173,10 +186,10 @@ class LogoCode: if b.name == 'hat1': code = self._blocks_to_code(b) self.stacks['stack1'] = self._readline(code) - if b.name == 'hat2': + elif b.name == 'hat2': code = self._blocks_to_code(b) self.stacks['stack2'] = self._readline(code) - if b.name == 'hat': + elif b.name == 'hat': if b.connections is not None and len(b.connections) > 1 and \ b.connections[1] is not None: code = self._blocks_to_code(b) @@ -189,8 +202,84 @@ class LogoCode: if int(float(x)) == x: x = int(x) self.stacks['stack3' + str(x)] = self._readline(code) + elif b.name in ['while', 'until']: + # Hidden macro expansion: Convert a while or until block into + # forever, ifelse, stopstack + if saveblocks is None: + saveblocks = blocks[:] + # Replace the while block + foreverblk = HiddenBlock('forever') + ifelseblk = HiddenBlock('ifelse') + stopstackblk = HiddenBlock('stopstack') + if b.connections is not None: + inflow = b.connections[0] + boolflow = b.connections[1] + whileflow = b.connections[2] + outflow = b.connections[3] + if inflow is not None: + i = inflow.connections.index(b) + inflow.connections[i] = foreverblk + else: + i = None + if outflow is not None: + j = outflow.connections.index(b) + outflow.connections[j] = foreverblk + else: + j = None + # Save the connections so we can restore them later + savewhileblks.append([b, i, j]) + # Assign the connections and build the docks + foreverblk.connections.append(inflow) + foreverblk.docks.append(['flow', True, 0, 0]) + foreverblk.connections.append(ifelseblk) + foreverblk.docks.append(['flow', False, 0, 0, '[']) + foreverblk.connections.append(outflow) + foreverblk.docks.append(['flow', False, 0, 0, ']']) + ifelseblk.connections.append(foreverblk) + ifelseblk.docks.append(['flow', True, 0, 0]) + ifelseblk.connections.append(boolflow) + ifelseblk.docks.append(['bool', False, 0, 0]) + if b.name == 'while': + ifelseblk.connections.append(whileflow) + ifelseblk.connections.append(stopstackblk) + else: # until + ifelseblk.connections.append(stopstackblk) + ifelseblk.connections.append(whileflow) + ifelseblk.docks.append(['flow', False, 0, 0, '[']) + ifelseblk.docks.append(['flow', False, 0, 0, '][']) + ifelseblk.connections.append(None) + ifelseblk.docks.append(['flow', False, 0, 0, ']']) + stopstackblk.connections.append(ifelseblk) + stopstackblk.docks.append(['flow', False, 0, 0]) + i = blocks.index(b) + if i == 0: + blocksleft = [] + else: + blocksleft = blocks[0:i] + if i == len(blocks) - 1: + blocksright = [] + else: + blocksright = blocks[i + 1:] + blocks = blocksleft[:] + blocks.append(foreverblk) + blocks.append(ifelseblk) + blocks.append(stopstackblk) + blocks.extend(blocksright) + if b == blk: + blk = foreverblk code = self._blocks_to_code(blk) + + if saveblocks is not None: + # Undo any hidden macro expansion + blocks = saveblocks[:] + blk = saveblk + for b in savewhileblks: + if b[1] is not None: + b[0].connections[0].connections[b[1]] = b[0] + if b[2] is not None: + b[0].connections[3].connections[b[2]] = b[0] + if run_flag: # debug_output("running code: %s" % (code), self.tw.running_sugar) self.start_time = time() @@ -211,7 +300,12 @@ class LogoCode: 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))) + # special case: expand 'while' and 'until' primitives + try: + code.append((blk.primitive, + self.tw.block_list.list.index(blk))) + except ValueError: + code.append(blk.primitive) # Hidden block elif len(blk.values) > 0: # Extract the value from content blocks. if blk.name == 'number': try: -- cgit v0.9.1