Пример #1
0
 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]
Пример #2
0
 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)))
Пример #3
0
 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
Пример #4
0
 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))
Пример #5
0
 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
Пример #6
0
 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