def make_keyword(value): mappings = { 'true': [write_push('constant 0'), 'not'], 'false': [write_push('constant 0')], 'null': [write_push('constant 0')] } if value not in mappings.keys(): raise ValueError( 'Keyword {} not recorded to mapping values.'.format(value)) return mappings[value]
def process_term(self, node: Node): if node.desc == 'single': # constant / variable sub_node = node.children[0] if sub_node.type == TOKEN_KEYWORD and sub_node.value != 'this': return self.make_keyword(sub_node.value) elif sub_node.type == TOKEN_STR: return self.process_string(sub_node) else: return [write_push(self.make_variable(sub_node))] if node.desc == '(exp)': return self.process_expression(node.children[1]) if node.desc == 'unop(exp)': code = self.process_term(node.children[1]) code.append(unop[node.children[0].value]) return code if node.desc == 'var[exp]': code = [write_push(self.make_variable(node.children[0])) ] # push arr code.extend(self.process_expression(node.children[2])) # exp code.extend(['add', 'pop pointer 1', 'push that 0']) # *(arr[exp]) return code if node.desc == 'f(exps)': obj_name = 'this' func_name = node.children[0].value exps_cnt = node.children[2].desc['cnt'] code = [] if self.symbol_table.is_variable(obj_name): code.extend([ write_push('{} {}'.format( self.symbol_table.vm_kind_of(obj_name), self.symbol_table.index_of(obj_name))) ]) code.extend(self.process_expression_list(node.children[2])) code.extend(self.make_function(obj_name, func_name, exps_cnt)) return code if node.desc == 'a.b(exps)': exps_cnt = node.children[4].desc['cnt'] obj_name = node.children[0].value code = [] if self.symbol_table.is_variable(obj_name): code.extend([ write_push('{} {}'.format( self.symbol_table.vm_kind_of(obj_name), self.symbol_table.index_of(obj_name))) ]) code.extend(self.process_expression_list(node.children[4])) func_name = node.children[2].value code.extend(self.make_function(obj_name, func_name, exps_cnt)) return code raise Exception('Cannot compile node {node}'.format(node=str(node)))
def process_subroutine(self, node: Node): if len(node.children) != 7: raise Exception( 'Cannot process subroutine node: {node}'.format(node=node)) # format: method/function/constructor return_type name ( param_list ) body self.symbol_table.start_subroutine() self.reset_seq() # method: this -> argument 0, function don't do this. subroutine_type = node.children[0].value method_piece = [] if subroutine_type == SUBROUTINE_METHOD: self.symbol_table.define(name='this', type=self.current_class, kind=KIND_ARGUMENT) method_piece = ['push argument 0', 'pop pointer 0'] subroutine_name = node.children[2].value func_label = '{}.{}'.format(self.current_class, subroutine_name) self.process_parameter_list(node.children[4]) arg_cnt = len( self.symbol_table.class_table) - self.symbol_table.static_cnt() constructor_piece = [] if subroutine_type == SUBROUTINE_CONSTRUCTOR: self.symbol_table.define('this', self.current_class, KIND_POINTER) constructor_piece = [ write_push('constant {}'.format(arg_cnt)), write_call('Memory.alloc', 1), write_pop('pointer 0') ] body_code = self.process_subroutine_body(node.children[6]) local_var_cnt = self.symbol_table.local_cnt() code = [write_function(func_label, local_var_cnt) ] + constructor_piece + method_piece + body_code return code
def process_let(self, node: Node): if len(node.children) == 5: # let var_name = expr; var_node = node.children[1] value_node = node.children[3] code = self.process_expression(value_node) code.append(write_pop(self.make_variable(var_node))) return code elif len(node.children) == 8: # let var_name[expr] = expr; arr_node = node.children[1] index_expr = node.children[3] value_node = node.children[6] code = [write_push(self.make_variable(arr_node))] # push arr code.extend(self.process_expression(index_expr)) # exp1 code.extend(['add']) code.extend(self.process_expression(value_node)) # exp2 code.extend( ['pop temp 0', 'pop pointer 1', 'push temp 0', 'pop that 0']) return code raise Exception( 'Node {} is not a legal letStatement node.'.format(node))
def process_do(self, node: Node): # there is no a.b.c(args) call, so don't consider it. # do f(args); -> len = 6 # do a.b(args); -> len = 8 if len(node.children) not in [6, 8]: raise Exception( 'Do statement is not f(args) or a.b(args) formatted. Node: {node}' .format(node=node)) func_name = node.children[-5].value obj_name = node.children[-7].value if len( node.children) == 8 else 'this' code = [] if self.symbol_table.is_variable(obj_name): code.extend([ write_push('{} {}'.format( self.symbol_table.vm_kind_of(obj_name), self.symbol_table.index_of(obj_name))) ]) code.extend(self.process_expression_list(node.children[-3])) n_args = node.children[-3].desc['cnt'] code.extend(self.make_function(obj_name, func_name, n_args)) code.append(write_pop('temp 0')) # void function return return code
def process_return(self, node: Node): # if no expression exist, return constant 0 code = self.process_expression(node.children[1]) if node.children[1].type == 'expression' \ else [write_push('constant 0')] code.append('return') return code