def visit(self, node: ProgramNode, scope: Scope): self.current_function = self.register_function('entry') idx = self.index instance = self.define_internal_local() result = self.define_internal_local() self.register_instruction(cil.AllocateNode('Main', instance)) typex = self.context.get_type('Main', (0, 0)) if typex.all_attributes(): self.register_instruction( cil.StaticCallNode(typex.name, typex.name, None, [cil.ArgNode(instance)], typex.name)) name = self.to_function_name('main', 'Main') self.register_instruction( cil.StaticCallNode('Main', 'main', result, [cil.ArgNode(instance)], 'Object')) self.register_instruction(cil.ReturnNode(0)) self.current_function = None self.void_data = self.register_data(VOID_NAME).name self.create_built_in() for declaration, child_scope in zip(node.declarations, scope.children): self.visit(declaration, child_scope) return cil.ProgramNode(self.dottypes, self.dotdata, self.dotcode, idx)
def visit(self, node: CallNode, scope: Scope): obj, otype = self.visit(node.obj, scope) meth = otype.get_method(node.id, node.pos) args_node = [cil.ArgNode(obj, self.index)] + self.handle_arguments( node.args, scope, meth.param_types) rtype = meth.return_type result = None if isinstance( rtype, VoidType) else self.define_internal_local() continue_label = cil.LabelNode(f'continue__{self.index}') isvoid = self.check_void(obj) self.register_instruction( cil.GotoIfFalseNode(isvoid, continue_label.label)) self.register_instruction(cil.ErrorNode('dispatch_error')) self.register_instruction(continue_label) if otype in [StringType(), IntType(), BoolType()]: self.register_instruction( cil.StaticCallNode(otype.name, node.id, result, args_node, rtype.name)) else: self.register_instruction( cil.DynamicCallNode(otype.name, obj, node.id, result, args_node, rtype.name)) return result, self._return_type(otype, node)
def handle_arguments(self, args, scope, param_types): args_node = [] args = [self.visit(arg, scope) for arg in args] for (arg, typex), param_type in zip(args, param_types): if typex.name in ['String', 'Int', 'Bool' ] and param_type.name == 'Object': auxiliar = self.define_internal_local() self.register_instruction(cil.BoxingNode(auxiliar, typex.name)) else: auxiliar = arg args_node.append(cil.ArgNode(auxiliar, self.index)) return args_node
def visit(self, node: InstantiateNode, scope: Scope): instance = self.define_internal_local() typex = self.context.get_type(node.lex, node.pos) typex = get_type(typex, self.current_type) self.register_instruction(cil.AllocateNode(typex.name, instance)) # calling the constructor to load all attributes # Si tiene atributos entonces tendrá constructor (esto se deberia optimizar mas) if typex.all_attributes(): self.register_instruction( cil.StaticCallNode(typex.name, typex.name, instance, [cil.ArgNode(instance)], typex.name)) return instance, typex
def visit(self, node: StaticCallNode, scope: Scope): meth = self.current_type.get_method(node.id, node.pos) args_node = [cil.ArgNode('self', self.index)] + self.handle_arguments( node.args, scope, meth.param_types) rtype = meth.return_type if isinstance(rtype, VoidType): result = None else: result = self.define_internal_local() self.register_instruction( cil.DynamicCallNode(self.current_type.name, 'self', node.id, result, args_node, rtype.name)) return result, self._return_type(self.current_type, node)