def __init__(self): super().__init__(VYPaInt(), "readInt", []) self.add_block(AST_declaration(VYPaInt(), ["number"])) readi_block = AST_block() readi_block.add_instruction(READI(VYPaRegister.DestinationReg)) readi_block.stack.set(VYPaRegister.DestinationReg) self.add_block(readi_block) self.add_block(AST_return(AST_value(VYPaInt(), self.stack.top())))
def __init__(self): super().__init__(VYPaInt(), "length", [AST_variable(VYPaString(), "string")]) getsize_block = AST_block() getsize_block.add_instruction( GETSIZE(VYPaRegister.DestinationReg, self.function.stack.top())) getsize_block.stack.set(VYPaRegister.DestinationReg) self.add_block(getsize_block) self.add_block(AST_return(AST_value(VYPaInt(), self.stack.top())))
def __init__(self): super().__init__(VYPaString(), "stringConcat", [ AST_variable(VYPaString(), "s1"), AST_variable(VYPaString(), "s2") ]) self.add_block( AST_condition_body([ AST_declaration(VYPaString(), ["new_string"]), AST_COPY(AST_value(VYPaString(), VYPaRegister.DestinationReg), AST_variable_call("s1")), AST_assigment( AST_variable_call("new_string"), AST_value(VYPaString(), VYPaRegister.DestinationReg)), AST_RESIZE( AST_variable_call("new_string"), AST_expression( AST_ADD( AST_function_call("length", [AST_variable_call("s1")]), AST_function_call("length", [AST_variable_call("s2")])))), AST_declaration(VYPaInt(), ["i"]), AST_while( AST_expression( AST_LT( AST_variable_call("i"), AST_function_call("length", [AST_variable_call("s2")]))), [ AST_GETWORD(AST_value(VYPaInt(), str("$3")), AST_variable_call("s2"), AST_variable_call("i")), AST_SETWORD( AST_variable_call("new_string"), AST_expression( AST_ADD( AST_variable_call("i"), AST_function_call( "length", [AST_variable_call("s1")])), ), AST_value(VYPaInt(), str("$3"))), AST_assigment( AST_variable_call("i"), AST_expression( AST_ADD(AST_variable_call("i"), AST_value(VYPaInt(), 1)))) ]), AST_return(AST_variable_call("new_string")) ]))
def __init__(self): super().__init__("Object", None) self.add_declaration( AST_declaration(VYPaString(), ["**runtime_name**"])) to_string_function = AST_function( VYPaString(), "Object_toString", [AST_variable(VYPaClass("Object"), "this")]) to_string_function.add_block(AST_block().add_instruction( SET(VYPaRegister.ClassCallReg, self.stack.top()))) to_string_function.add_block( AST_return( AST_expression( AST_cast( VYPaString(), AST_value( VYPaInt(), self.stack.get(-1, VYPaRegister.ClassCallReg)))))) to_string_function.set_label(f"class_Object_func_toString") AST.get_root().add_function(to_string_function) get_class_function = AST_function( VYPaString(), "Object_getClass", [AST_variable(VYPaClass("Object"), "this")]) get_class_function.add_block( AST_return( AST_expression( AST_class_variable_call("this", "**runtime_name**")))) get_class_function.set_label(f"class_Object_func_getClass") AST.get_root().add_function(get_class_function) AST.root.add_class(self)
def get_instructions(self, parent): self.parent = parent self.stack_offset += parent.stack_offset self.instruction_tape.merge(self.expression.get_instructions(self)) self.check_types() if self.expression.type == VYPaInt( ) and self.casting_type == VYPaString(): self.type = VYPaString() self.add_instruction(INT2STRING(self.expression)) self.stack.push(AST_value(self.type, str(VYPaRegister.Accumulator))) else: this_offset = 0 class_name = self.expression.type.name self.add_instruction( SET(VYPaRegister.ClassCallReg, VYPaRegister.Accumulator)) while self.casting_type.name != class_name: this_offset -= len(AST.root.get_class(class_name).variables) class_name = AST.root.get_class(class_name).predecessor_name self.type = self.casting_type self.stack.push( AST_value( self.type, self.stack.get(this_offset, VYPaRegister.ClassCallReg))) self.add_expression_stack_offset() return self.instruction_tape
def get_instructions(self, parent): self.parent = parent self.stack_offset += parent.stack_offset self.instruction_tape.merge(self.expression.get_instructions(self)) self.type = VYPaInt() self.check_types() self.add_instruction(NOT(self.expression)) self.stack.push(AST_value(self.type, str(VYPaRegister.Accumulator))) self.add_expression_stack_offset() return self.instruction_tape
def get_instructions(self, parent): self.parent = parent self.stack_offset += parent.stack_offset self.instruction_tape.merge(self.left.get_instructions(self)) self.instruction_tape.merge(self.right.get_instructions(self)) if self.left.type == VYPaInt() and self.right.type == VYPaInt(): self.instruction = GTI self.type = VYPaInt() self.add_instruction(self.instruction(self.left, self.right)) elif self.left.type == VYPaString() and self.right.type == VYPaString( ): self.instruction = GTS self.type = VYPaString() self.add_instruction(self.instruction(self.left, self.right)) else: Exit(Error.SemanticError, "Types mismatch") pass self.stack.push(AST_value(self.type, str(VYPaRegister.Accumulator))) self.add_expression_stack_offset() return self.instruction_tape
def get_instructions(self, parent): self.parent = parent self.instruction_tape.clear() for name in self.variable_names: if self.type == VYPaInt(): parent.add_variable(self.declare_integer(name)) elif self.type == VYPaString(): parent.add_variable(self.declare_string(name)) elif self.type == VYPaVoid(): Exit(Error.SemanticError, "Can not create void variable") else: parent.add_variable(self.declare_class_instance(name)) return self.instruction_tape
def get_instructions(self, parent): self.parent = parent self.stack_offset += parent.stack_offset self.instruction_tape.merge(self.left.get_instructions(self)) self.instruction_tape.merge(self.right.get_instructions(self)) if self.left.type == VYPaInt() and self.right.type == VYPaInt(): self.instruction = ADDI self.check_types() self.type = VYPaInt() self.add_instruction(self.instruction(self.left, self.right)) self.stack.push(AST_value(self.type, str(VYPaRegister.Accumulator))) self.add_expression_stack_offset() elif self.left.type == VYPaString() and self.right.type == VYPaString(): self.check_types() self.type = VYPaString() self.instruction_tape.merge( AST_function_call("stringConcat", [self.left, self.right]).get_instructions(self) ) else: Exit(Error.TypesIncompatibility, "Can not add other types as primitives") return self.instruction_tape
def __init__(self): super().__init__(VYPaString(), "subStr", [ AST_variable(VYPaString(), "s"), AST_variable(VYPaInt(), "i"), AST_variable(VYPaInt(), "n") ]) self.add_block( AST_ifelse( AST_expression( AST_OR( AST_LT(AST_variable_call("n"), AST_value(VYPaInt(), 0)), AST_OR( AST_LT(AST_variable_call("i"), AST_value(VYPaInt(), 0)), AST_OR( AST_GT( AST_variable_call("i"), AST_function_call( "length", [AST_variable_call("s")])), AST_EQ( AST_variable_call("i"), AST_function_call( "length", [AST_variable_call("s")])))))), [AST_return(AST_expression(AST_value(VYPaString(), '""')))], [ AST_declaration(VYPaString(), ["new_substr"]), AST_declaration(VYPaInt(), ["j"]), AST_RESIZE(AST_variable_call("new_substr"), AST_variable_call("n")), AST_while( AST_expression( AST_AND( AST_LT(AST_variable_call("j"), AST_variable_call("n")), AST_LT( AST_variable_call("j"), AST_function_call( "length", [AST_variable_call("s")])))), [ AST_GETWORD( VYPaRegister.DestinationReg, AST_variable_call("s"), AST_expression( AST_ADD(AST_variable_call("i"), AST_variable_call("j")))), AST_SETWORD(AST_variable_call("new_substr"), AST_variable_call("j"), VYPaRegister.DestinationReg), AST_assigment( AST_variable_call("j"), AST_expression( AST_ADD(AST_variable_call("j"), AST_value(VYPaInt(), 1)))) ]), AST_return(AST_expression(AST_variable_call("new_substr"))) ]))
def get_instructions(self, parent): self.parent = parent global WHILE_BLOCK_COUNTS self.instruction_tape.add(LABEL(f"loop_{WHILE_BLOCK_COUNTS}")) self.instruction_tape.merge(self.condition.get_instructions(self)) self.instruction_tape.add( JUMPZ(f"end_loop_{WHILE_BLOCK_COUNTS}", AST_value(VYPaInt(), str(VYPaRegister.Accumulator)))) self.instruction_tape.merge(self.body.get_instructions(self)) self.stack.deallocate(len(self.variables)) self.instruction_tape.add(JUMP(f"loop_{WHILE_BLOCK_COUNTS}")) self.instruction_tape.add(LABEL(f"end_loop_{WHILE_BLOCK_COUNTS}")) WHILE_BLOCK_COUNTS += 1 return self.instruction_tape
def get_instructions(self, parent): self.parent = parent self.class_block = AST.root.get_class(self.name) if self.name != "Object": self.predecessor = AST_class_instance( self.class_block.predecessor_name) self.merge_instructions(self.predecessor.get_instructions(self)) self.add_instruction(COMMENT(f"Constructor of class {self.name}")) for declaration in self.class_block.declarations: self.merge_instructions(declaration.get_instructions(self)) if self.name == "Object": top_most_children = self while isinstance(top_most_children.parent, AST_class_instance): top_most_children = top_most_children.parent self.merge_instructions( AST_assigment( AST_variable_call("**runtime_name**"), AST_value( VYPaString(), f'"{top_most_children.name}"')).get_instructions(self)) self.merge_instructions( AST_declaration(VYPaClass(self.name), ["this"]).get_instructions(self)) self.merge_instructions( AST_assigment( AST_variable_call("this"), AST_value(VYPaInt(), VYPaRegister.StackPointer)).get_instructions(self)) constructor = AST.root.functions.get(f"{self.name}_{self.name}", None) if constructor and constructor.type == VYPaVoid() and len( constructor.params) == 1: self.merge_instructions( AST_expression( AST_function_call( f"{self.name}_{self.name}", [AST_variable_call("this")])).get_instructions(self)) self.add_instruction(SET(VYPaRegister.Accumulator, self.stack.top())) self.add_instruction(COMMENT(f"End of {self.name} constructor")) return self.instruction_tape
def get_instructions(self, parent): self.parent = parent global IF_BLOCK_COUNTS self.instruction_tape.merge(self.condition.get_instructions(self)) self.instruction_tape.add( JUMPZ(f"else_{IF_BLOCK_COUNTS}", AST_value(VYPaInt(), str(VYPaRegister.Accumulator)))) self.instruction_tape.merge(self.if_body.get_instructions(self)) self.instruction_tape.add(JUMP(f"end_else_if_{IF_BLOCK_COUNTS}")) self.instruction_tape.add(LABEL(f"else_{IF_BLOCK_COUNTS}")) self.instruction_tape.merge(self.else_body.get_instructions(self)) self.instruction_tape.add(LABEL(f"end_else_if_{IF_BLOCK_COUNTS}")) IF_BLOCK_COUNTS += 1 return self.instruction_tape
def get_instructions(self, parent): self.parent = parent global CLASS_INSTANCE_COUNTS self.instruction_tape.merge(self.expression.get_instructions(self)) self.variables["_"] = AST_variable(VYPaInt(), "_") self.stack.push( AST_value(self.expression.type, VYPaRegister.Accumulator)) self.instruction_tape.merge(self.variable.get_instructions(self)) from src.VYPcode.AST.blocks.class_instance import AST_class_instance if hasattr(self.expression, "expression_root") and isinstance( self.expression.expression_root, AST_class_instance): class_instance_variable = AST_variable( VYPaClass(self.expression.type.name), f"instance of {self.expression.type.name} {CLASS_INSTANCE_COUNTS}" ) class_instance_variable.set_size( AST.root.get_class(self.expression.type.name).get_size()) self.variable.variable.parent.add_variable(class_instance_variable) CLASS_INSTANCE_COUNTS += 1 if self.variable.type != self.expression.type: if self.variable.name != "this": Exit(Error.TypesIncompatibility, "Type check error!") if isinstance(self.variable.type, VYPaClass) and self.variable.name != "this": this_offset = 0 class_name = self.expression.type.name self.add_instruction( SET(VYPaRegister.ClassCallReg, self.stack.top())) while self.variable.type.name != class_name: this_offset -= len(AST.root.get_class(class_name).variables) class_name = AST.root.get_class(class_name).predecessor_name self.instruction_tape.add( SET(self.variable, self.stack.get(this_offset, VYPaRegister.ClassCallReg))) else: self.instruction_tape.add(SET(self.variable, self.stack.top())) self.stack.pop() return self.instruction_tape
def get_instructions(self, parent): self.parent = parent self.stack_offset += parent.stack_offset # print is a special function which can be called with multiple parameters # so internally we call PrintInt or PrintString for each parameter... if self.name == "print": self.type = VYPaVoid() if len(self.calling_params) == 0: Exit(Error.SemanticError, "Print called with zero params") for idx, param in enumerate(self.calling_params, 1): self.instruction_tape.merge(param.get_instructions(self)) if param.type == VYPaInt(): function = AST.root.get_function("printInt") elif param.type == VYPaString(): function = AST.root.get_function("printString") else: Exit(Error.SemanticError, "argument of print can be only int or str") self.stack.set(param, 3) self.add_instruction(CALL(self.stack.get(2), function)) if idx != len(self.calling_params): self.stack.pop() else: function = AST.root.get_function(self.name) self.type = function.type for offset, param in enumerate(self.calling_params, 3): if self.name != "stringConcat": # string concat has already merged instructions self.instruction_tape.merge(param.get_instructions(self)) self.stack.set(param, offset) self.check_params(function) self.add_instruction(CALL(self.stack.get(2), function)) self.add_expression_stack_offset() return self.instruction_tape
def get_instructions(self, parent): self.parent = parent self.stack_offset += parent.stack_offset self.instruction_tape.merge(self.left.get_instructions(self)) self.instruction_tape.merge(self.right.get_instructions(self)) if self.left.type == VYPaInt() and self.right.type == VYPaInt(): self.instruction = EQI self.type = VYPaInt() self.add_instruction(self.instruction(self.left, self.right)) elif self.left.type == VYPaString() and self.right.type == VYPaString( ): self.instruction = EQS self.type = VYPaInt() self.add_instruction(self.instruction(self.left, self.right)) elif isinstance(self.left.type, VYPaClass) and isinstance( self.right.type, VYPaClass): self.instruction = EQI self.type = VYPaInt() left_class = AST_expression( AST_class_variable_call(self.left.name, "**runtime_name**")) self.merge_instructions(left_class.get_instructions(self)) self.add_instruction(SET("$6", VYPaRegister.Accumulator)) right_class = AST_expression( AST_class_variable_call(self.right.name, "**runtime_name**")) self.merge_instructions(right_class.get_instructions(self)) self.add_instruction(SET("$7", VYPaRegister.Accumulator)) self.add_instruction(DUMPREGS()) self.add_instruction(DUMPSTACK()) self.add_instruction(DUMPHEAP()) self.add_instruction( self.instruction(AST_value(VYPaInt(), "$6"), AST_value(VYPaInt(), "$7"))) else: Exit(Error.SemanticError, "Types mismatch") pass self.stack.push(AST_value(self.type, str(VYPaRegister.Accumulator))) self.add_expression_stack_offset() return self.instruction_tape
def p_expression_number(t): 'expression : NUMBER' t[0] = AST_value(VYPaInt(), t[1])
def check_types(self): if self.left.type != VYPaInt() or self.right.type != VYPaInt(): Exit(Error.TypesIncompatibility, "Type check error!")
def __init__(self): super().__init__(VYPaVoid(), "printInt", [AST_variable(VYPaInt(), "number")]) block = AST_block() block.add_instruction(WRITEI(self.function.stack.top())) self.add_block(block)
def declare_integer(self, name): self.stack.push(str(0)) return AST_variable(VYPaInt(), name)
def check_types(self): if self.expression.type != VYPaInt(): Exit(Error.TypesIncompatibility, "Type check error!")
def check_types(self): if not ((self.expression.type == VYPaInt() and self.casting_type == VYPaString()) or (isinstance(self.expression.type, VYPaClass) and AST.root.classes.get(self.casting_type.name, False))): Exit(Error.TypesIncompatibility, "Type check error!")
def p_expr_uminus(t): 'expression : MINUS expression %prec UMINUS' t[0] = AST_SUBI(AST_value(VYPaInt(), 0), t[2])
def p_expr_uplus(t): 'expression : PLUS expression %prec UMINUS' t[0] = AST_ADD(AST_value(VYPaInt(), 0), t[2])