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 __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 __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 get_instructions(self, parent): self.parent = parent self.add_instruction(COMMENT("")) self.add_instruction(COMMENT(f"Start of function {self.name}")) self.add_instruction(LABEL(self.label)) self.stack.allocate(2 + len(self.params)) for variable in self.variables.values(): self.merge_instructions(variable.get_instructions(self)) for statement in self.AST_blocks: self.merge_instructions(statement.get_instructions(self)) if isinstance(self.get_parent(), AST_program ) and self.name == "main" and self.type == VYPaVoid(): self.add_instruction(JUMP("END")) else: from src.VYPcode.AST.blocks.function_return import AST_return if self.type == VYPaVoid(): default_return = AST_return(None) else: default_return = AST_return( AST_value(self.type, self.type.get_default())) default_return.set_parent(self) self.merge_instructions(default_return.get_instructions(self)) self.add_instruction(COMMENT(f"End of function {self.name}")) self.add_instruction(COMMENT("")) return self.instruction_tape
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.variable = self.get_variable(self.name) self.type = self.variable.type self.instruction_tape.add( SET(AST_value(self.type, str(VYPaRegister.Accumulator)), str(self))) 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 __init__(self): super().__init__(VYPaString(), "readString", []) self.add_block(AST_declaration(VYPaString(), ["string"])) reads_block = AST_block() reads_block.add_instruction(READS(VYPaRegister.DestinationReg)) reads_block.stack.set(VYPaRegister.DestinationReg) self.add_block(reads_block) self.add_block(AST_return(AST_value(VYPaString(), self.stack.top())))
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 __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 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 __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 get_instructions(self, parent): self.parent = parent self.class_variable = AST_variable_call(self.class_variable_name) self.instruction_tape.merge(self.class_variable.get_instructions(self)) self.add_instruction( SET(VYPaRegister.ClassCallReg, self.class_variable)) self.variable = AST.root.get_class( self.class_variable.type.name).get_variable(self.name) self.type = self.variable.type self.instruction_tape.add( SET(AST_value(self.type, str(VYPaRegister.Accumulator)), str(self))) return self.instruction_tape
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 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 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.stack_offset += parent.stack_offset this_offset = 0 if self.class_variable_name == "super": this_variable = AST_variable_call("this") self.instruction_tape.merge(this_variable.get_instructions(self)) this_offset += len( AST.root.get_class(this_variable.type.name).variables) class_name = AST.root.get_class( this_variable.type.name).predecessor_name self.class_variable_name = "this" else: this_variable = AST_variable_call(self.class_variable_name) self.instruction_tape.merge(this_variable.get_instructions(self)) class_name = this_variable.type.name function = None while function is None: if AST.root.functions.get(f"{class_name}_{self.name}", None): self.stack.set( self.stack.get(-this_offset, VYPaRegister.Accumulator), 3) function = AST.root.get_function(f"{class_name}_{self.name}") else: this_offset += len(AST.root.get_class(class_name).variables) class_name = AST.root.get_class(class_name).predecessor_name self.type = function.type self.calling_params.insert(0, AST_value(VYPaClass(class_name), None)) for offset, param in enumerate(self.calling_params[1:], 4): 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 = 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 deallocate(self, how_much_variables_to_remove=1): self.instruction_tape.add( SUBI(VYPaRegister.StackPointer, AST_value(VYPaInt, how_much_variables_to_remove), VYPaRegister.StackPointer))
def __str__(self): return str(AST_value(self.type, str(VYPaRegister.Accumulator)))
def __str__(self): return str(AST_value(self.type, self.stack.get()))
def push(self, value): self.instruction_tape.add(SET(self.get(1), value)) self.instruction_tape.add( ADDI(VYPaRegister.StackPointer, AST_value(VYPaInt, 1), VYPaRegister.StackPointer)) return value
def allocate(self, how_much_variables_to_allocate=1): self.instruction_tape.add( ADDI(VYPaRegister.StackPointer, AST_value(VYPaInt, how_much_variables_to_allocate), VYPaRegister.StackPointer))
def pop(self): self.instruction_tape.add( SUBI(VYPaRegister.StackPointer, AST_value(VYPaInt, 1), VYPaRegister.StackPointer)) return self.get(1)
def p_expression_string(t): 'expression : WORD' t[0] = AST_value(VYPaString(), t[1])
def p_expr_uplus(t): 'expression : PLUS expression %prec UMINUS' t[0] = AST_ADD(AST_value(VYPaInt(), 0), t[2])
def p_expr_uminus(t): 'expression : MINUS expression %prec UMINUS' t[0] = AST_SUBI(AST_value(VYPaInt(), 0), t[2])
def p_expression_number(t): 'expression : NUMBER' t[0] = AST_value(VYPaInt(), t[1])