def macro_expand(self, fn_symbol, ast_node, words_needed): r'''This macro expands to an set-output-bit. set-output-bit port_name bit# ''' assert len(ast_node.args) == 2 assert len(ast_node.args[1]) == 1, \ "%s: incorrect number of arguments, expected 1, got %s" % \ (self.label, len(ast_node.args[1])) fn_symbol.side_effects = 1 pin = ast_node.args[1][0] #print "toggle: pin", pin, pin.symbol_id, pin.label pin_number = \ symbol_table.get_by_id(pin.symbol_id).word_word \ .get_value('pin_number') port_label, bit_number = output_pin.digital_pin_lookup[pin_number] #print "toggle: port_label", port_label, ", bit_number", bit_number ioreg_bit = ast.ast(kind='ioreg-bit', label='io.pin' + port_label, int1=bit_number) new_args = ( ast.ast.word('set-output-bit'), (ioreg_bit,), ) return ast_node.macro_expand(fn_symbol, words_needed, new_args, kind='call')
def prepare(self, fn_symbol, words_needed): r'''Called immediately after parsing, before writing to the database. Calls `prepare_args` on itself first, then prepare_<expect> on the word in the first arg. Also updates `fn_xref` and `symbol_table.symbol.side_effects` info so that these data will be known during the intermediate code generation phase that follows parsing. See prepare_args_ function for more info. .. _prepare_args: ucc.database.ast-module.html#prepare_args ''' if self.kind == 'call': self.prepare_args(fn_symbol, words_needed) if self.args and isinstance(self.args[0], ast) and \ self.args[0].kind == 'word': word_obj = symbol_table.get(self.args[0].label).word_obj fn_xref.calls(fn_symbol.id, word_obj.ww.symbol.id) prepare_method = word_obj.get_method('prepare', self.expect) return prepare_method(fn_symbol, self, words_needed) if self.kind == 'word': sym = symbol_table.get_by_id(self.symbol_id) if sym.context is None: words_needed.add(sym.label) if self.expect == 'lvalue': fn_xref.sets(fn_symbol.id, self.symbol_id) else: fn_xref.uses(fn_symbol.id, self.symbol_id) if self.kind in ('ioreg', 'ioreg-bit'): fn_symbol.side_effects = 1 return self
def gen_fun(fun_id, fun_label, fun_kind): if fun_kind == 'function': far_size = 2 else: far_size = 4 prolog = assembler.block(fun_id, 'flash', fun_label) prolog.append_inst('push', 'r29') prolog.append_inst('push', 'r28') for id, kind, param_num \ in crud.read_as_tuples('symbol_table', 'id', 'kind', 'int1', context=fun_id, order_by=('kind', 'desc', 'int1')): sym = symbol_table.get_by_id(id) far_size += 2 sym.address = -far_size if fun_kind == 'task': sym.ram_size = 2 if kind == 'parameter': prolog.append_inst('push', 'r%d' % (2 * param_num + 1)) prolog.append_inst('push', 'r%d' % (2 * param_num)) for id, name, next, next_conditional \ in crud.read_as_tuples('blocks', 'id', 'name', 'next', 'next_conditional', word_symbol_id=fun_id, order_by=('id',)): asm_block = assembler.block(fun_id, 'flash', name) if next: asm_block.next_label(next) for what, should, this, be \ in crud.read_as_tuples('triples', block_id=id, # FIX: finish... ): pass
def label(self, symbol_id, triple): r'''Attach 'symbol_id' as a "label" for 'triple'. A "label" is a symbol (variable) that the result of the `triple` must be stored into. One triple may have multiple labels attached to it, meaning that the result must be stored into multiple places. ''' self.labels[symbol_id] = triple if symbol_id in self.dirty_labels: self.dirty_labels.remove(symbol_id) if symbol_table.get_by_id(symbol_id).context is None: # This is a global variable! if symbol_id in self.sets_global: triple.add_hard_predecessor(self.sets_global[symbol_id]) self.sets_global[symbol_id] = triple if symbol_id in self.uses_global: for t in self.uses_global[symbol_id]: triple.add_soft_predecessor(t) del self.uses_global[symbol_id]
def word(cls, symbol_id, syntax_position_info = (None, None, None, None), **kws): r'''Returns an ast node for the 'symbol_id' word. 'symbol_id' may be either the integer id, or the label of the global word as a string. 'kws' are simply passed to __init__ as attributes, along with the 'kind' and the 'label' attributes. ''' line_start, column_start, line_end, column_end = syntax_position_info if isinstance(symbol_id, (str, unicode)): symbol_id = symbol_table.get(symbol_id).id return cls(kind='word', label=symbol_table.get_by_id(symbol_id).label, symbol_id=symbol_id, line_start=line_start, column_start=column_start, line_end=line_end, column_end=column_end, **kws)
def compile(self): r'''Generates intermediate code for this AST node. ''' if self.kind in ('approx', 'int', 'ratio'): return block.Current_block.gen_triple( self.kind, self.int1, self.int2, syntax_position_info= self.get_syntax_position_info()) if self.kind == 'string': name = crud.gensym('strlit') sym = symbol_table.symbol.create(name, 'const') asm_block = assembler.block(self.word_symbol.id, 'flash', name) asm_block.append_inst('int16', str(len(self.str1))) asm_block.append_inst('bytes', repr(self.str1)) asm_block.write() return block.Current_block.gen_triple( 'global', sym.id, syntax_position_info=self.get_syntax_position_info()) if self.kind == 'call': if self.args and isinstance(self.args[0], ast) and \ self.args[0].kind == 'word': word_obj = symbol_table.get(self.args[0].label).word_obj compile_method = word_obj.get_method('compile', self.expect) return compile_method(self) else: raise AssertionError("call indirect not supported yet") if self.kind == 'word': sym = symbol_table.get_by_id(self.symbol_id) if sym.context is None: word_obj = symbol_table.get_by_id(self.symbol_id).word_obj compile_method = word_obj.get_method('compile', self.expect) ans = compile_method(self) return ans if sym.kind in ('parameter', 'var'): return block.Current_block.gen_triple('local', sym, syntax_position_info=self.get_syntax_position_info()) raise ValueError("%s.compile: unknown symbol.kind %r" % sym.kind) if self.kind in ('no-op', 'None'): return None if self.kind == 'label': block.new_label(self.label, self.word_symbol.id) return None if self.kind == 'jump': block.Current_block.unconditional_to(self.label) return None if self.kind == 'if-true': arg_triples = self.compile_args() block.Current_block.true_to(arg_triples[0], self.label) return None if self.kind == 'if-false': arg_triples = self.compile_args() block.Current_block.false_to(arg_triples[0], self.label) return None if self.kind == 'series': self.compile_args() return None if self.kind in ('ioreg', 'ioreg-bit'): if self.expect in ('value', 'condition'): return block.Current_block.gen_triple( 'input' if self.kind == 'ioreg' else 'input-bit', string=self.label, int1=self.int1, syntax_position_info=self.get_syntax_position_info()) else: raise AssertionError("ast node[%s]: expect %s not supported " "for %s" % (self.id, self.expect, self.kind)) raise AssertionError("ast node[%s]: unknown ast kind -- %s" % (self.id, self.kind))