def FuncCallNode(self, node, scope, emit, tlevel): #there are two cases here. one is calling a function #that is the result of an expression (e.g. member lookup), #the other is calling a named function, which pushes #the value itself. func = node.type if len(node[1]) != len(func.children[0]): typespace.error("Wrong number of function arguments", node) for i, a in enumerate(func[0]): a2 = node[1][i] nt = a2.type if type(a2) == FuncCallNode: nt = a2.type.type if type(nt) == IdentNode: nt = TypeRefNode(nt.val) if not types_match(a.type, nt, typespace): typespace.error("Wrong type for argument %i." % (i + 1), node) #XXX REMEMBER TO RELINK THIS! self.opcode("LOAD_OPCODE_PTR", -2, "return address") jmpcode = len(self.codes) - 1 for a in node[1]: self.opcode("PUSH") emit(a, scope) if type(node[0]) == IdentNode: self.opcode("LOAD_REG_SYMBOL_PTR", [node[0].val, 0]) else: self.opcode("PUSH") emit(node[0], scope) self.opcode("LOAD_REG_PTR", 0) self.opcode("POP") if func.is_native: self.opcode("NATIVE_CALL", func.name) else: self.opcode("LONGJMP", 0, "call %s" % func.name) self.codes[jmpcode].arg = len(self.codes) #decrement locals offset. #we do this here since the #called function, not the caller, #pops the arguments. self.stacklevels[-1] -= len(func[0])
def FuncCallNode(self, node, scope, emit, tlevel): #there are two cases here. one is calling a function #that is the result of an expression (e.g. member lookup), #the other is calling a named function, which pushes #the value itself. func = node.type if len(node[1]) != len(func.children[0]): typespace.error("Wrong number of function arguments", node); for i, a in enumerate(func[0]): a2 = node[1][i] nt = a2.type if type(a2) == FuncCallNode: nt = a2.type.type if type(nt) == IdentNode: nt = TypeRefNode(nt.val) if not types_match(a.type, nt, typespace): typespace.error("Wrong type for argument %i."%(i+1), node); #XXX REMEMBER TO RELINK THIS! self.opcode("LOAD_OPCODE_PTR", -2, "return address") jmpcode = len(self.codes)-1 for a in node[1]: self.opcode("PUSH") emit(a, scope) if type(node[0]) == IdentNode: self.opcode("LOAD_REG_SYMBOL_PTR", [node[0].val, 0]); else: self.opcode("PUSH") emit(node[0], scope) self.opcode("LOAD_REG_PTR", 0); self.opcode("POP") if func.is_native: self.opcode("NATIVE_CALL", func.name) else: self.opcode("LONGJMP", 0, "call %s"%func.name); self.codes[jmpcode].arg = len(self.codes) #decrement locals offset. #we do this here since the #called function, not the caller, #pops the arguments. self.stacklevels[-1] -= len(func[0])
def VarDeclNode(self, node, scope, emit, tlevel): if node.local: if len(self.stacklevels) == 0: typespace.error("Global variable has local flag", node) node.stack_off = self.stacklevels[-1] self.opcode("PUSH", comment="declare %s"%node.val) if node.val in scope and types_match(node.type, scope[node.val].type, typespace): node.stack_off = scope[node.val].stack_off if len(self.stacklevels) > 1: node.local = True else: node.local = scope[node.val].local scope[node.val] = node if type(node[0]) != ExprNode or len(node[0]) > 0: n = AssignNode(IdentNode(node.val), node[0], "=") n.type = node.type self.AssignNode(n, scope, emit, tlevel)
def VarDeclNode(self, node, scope, emit, tlevel): if node.local: if len(self.stacklevels) == 0: typespace.error("Global variable has local flag", node) node.stack_off = self.stacklevels[-1] self.opcode("PUSH", comment="declare %s" % node.val) if node.val in scope and types_match(node.type, scope[node.val].type, typespace): node.stack_off = scope[node.val].stack_off if len(self.stacklevels) > 1: node.local = True else: node.local = scope[node.val].local scope[node.val] = node if type(node[0]) != ExprNode or len(node[0]) > 0: n = AssignNode(IdentNode(node.val), node[0], "=") n.type = node.type self.AssignNode(n, scope, emit, tlevel)