def make_offset(self, var_type): self.push_operator(Operation.PLUS) self.make_expression() res = self._operand_stack.pop() res.type = GreaseType(GreaseTypeClass.Pointer, res.type) res_ref = GreaseVar(GreaseType(GreaseTypeClass.Pointer, var_type), res._address, AddressingMethod.Indirect) self._operand_stack.push(res_ref)
def find_type(self, name): struct = self._structs.find_struct(name) if struct is not None: return GreaseType(GreaseTypeClass.Struct, struct, size=struct.size) interface = self._interfaces.find_interface(name) if interface is not None: return GreaseType(GreaseTypeClass.Intererface, interface) raise UndefinedType(name)
def resolve_main(self): main = self.find_function('main') if main is None: raise UndefinedFunction( 'Main is not defined. No entry point for this program.') address = GreaseVar(GreaseType(GreaseTypeClass.Int), main.start, AddressingMethod.Literal) size = GreaseVar(GreaseType(GreaseTypeClass.Int), main.size, AddressingMethod.Literal) self._quads._quads[self._jump_stack.pop()].left_operand = address self._quads._quads[self._jump_stack.pop()].left_operand = size
def push_fn_size(self): self._active_fn.size = self._next_local_address while self._era_stack.peek() is not None: quad = self._quads._quads[self._era_stack.pop()] quad.left_operand = GreaseVar(GreaseType(GreaseTypeClass.Int), self._next_local_address, AddressingMethod.Literal)
def make_addr(self): aux = self._operand_stack.pop() temp = GreaseVar(GreaseType(GreaseTypeClass.Int), self._next_local_address, AddressingMethod.Relative) quad = Quadruple(Operation.ADDR, aux, result=temp) self._quads.push_quad(quad) self.push_operand(temp) self._next_local_address += 1
def p_optional_struct_interfaces(p): '''optional_struct_interfaces : COLON more_interfaces interface_id | empty''' if len(p) > 2: vtable_t = greaser.find_struct('vtable') var_builder.add_type(GreaseType(GreaseTypeClass.Pointer, vtable_t)) vtable = var_builder.build() struct_builder.add_member('vtable', vtable)
def p_const_int(p): '''const_int : CONST_INT''' val = p[1] # Store as 32bit unsigned 2's complement if val < 0: val += 1 << 32 greaser.push_constant(val, GreaseType(GreaseTypeClass.Int))
def fill_jump(self, offset=0): quad_no = self._jump_stack.pop() if quad_no is not None: next_quad = self._quads.next_free_quad address = GreaseVar(GreaseType(GreaseTypeClass.Int), next_quad + offset, AddressingMethod.Literal) self._quads.fill_quad(quad_no, address) else: raise GreaseError('No jumps pending to be resolved')
def make_expression(self): """Exp quad helper: Pops 2 operands from typestack and operand stack, checks type and calls build_and_push_quad""" op = self._operator_stack.pop() rhs = self._operand_stack.pop() if op is Operation.ADDR: self.make_addr() elif op is Operation.DEREF: self.make_deref() elif op in [Operation.U_MINUS, Operation.NOT]: return_type_class = cube.check(rhs, op, None) if return_type_class is None: raise TypeMismatch('{} {}'.format(op, rhs)) tmp_var = GreaseVar(GreaseType(return_type_class), self._next_local_address, AddressingMethod.Relative) self._next_local_address += tmp_var.type.size self._quads.push_quad(Quadruple(op, rhs, result=tmp_var)) self.push_operand(tmp_var) else: lhs = self._operand_stack.pop() return_type_class = cube.check(lhs, op, lhs) if return_type_class is None: raise TypeMismatch('{} {} {}'.format(lhs, op, rhs)) tmp_type = GreaseType(return_type_class) tmp_var = GreaseVar(tmp_type, self._next_local_address, AddressingMethod.Relative) self._next_local_address += tmp_var.type.size # Generate Quadruple and push it to the list quad = Quadruple(op, lhs, rhs, tmp_var) self._quads.push_quad(quad) # push the tmp_var to stack self._operand_stack.push(tmp_var)
def set_arr_add(self): arr = self._agregate_stack.pop() arr_addr = GreaseVar( GreaseType(GreaseTypeClass.Pointer, arr.type.type_data), arr._address, arr.method) self._operand_stack.push(arr_addr) self.make_offset(arr.type.type_data) self.pop_fake_bottom()
def push_substruct(self, name): if self._operator_stack.peek() is Operation.ACCESS: self._operator_stack.pop( ) # This operation can not be executed by VM parent = self._operand_stack.pop() if parent is None: raise UndefinedVariable('Struct does not exist') if self._operator_stack.peek() is Operation.DEREF: self._operand_stack.pop( ) # This operation can not be executed by VM if parent.type.type_class is not GreaseTypeClass.Pointer: raise GreaseError('Expected pointer') parent_addr = GreaseVar(parent.type, parent._address, parent.method) parent_type = parent.type.type_data else: parent_addr = GreaseVar( GreaseType(GreaseTypeClass.Pointer, parent.type), parent._address, parent.method) parent_type = parent.type if parent_type.type_class is not GreaseTypeClass.Struct: raise TypeMismatch('Expression must be struct') var_table = parent_type.type_data.variables var = var_table.find_variable(name) if var is None: raise UndefinedMember(name) offset = GreaseVar(GreaseType(GreaseTypeClass.Int), var._address, AddressingMethod.Literal) parent_addr.type.type_data = var.type self.push_operand(offset) self.push_operand(parent_addr) self.make_offset(var.type) else: var = self.find_variable(name) self.push_operand(var)
def push_dim_stack(self): arr = self._agregate_stack.peek() if len(arr.type.dimens ) > self._dim: #if the next pointer is different from null then t = self._operand_stack.peek() size = GreaseVar(GreaseType(GreaseTypeClass.Int), arr.type.dimens[self._dim].size, AddressingMethod.Literal) offset = GreaseVar(GreaseType(GreaseTypeClass.Int), arr.type.dimens[self._dim].offset, AddressingMethod.Literal) ver = Quadruple(Operation.VER, t, size) self._quads.push_quad(ver) self.push_operator(Operation.TIMES) self.push_operand(offset) self.make_expression() if self._dim > 0: self._operator_stack.push(Operation.PLUS) self.make_expression()
def p_array(p): '''array : OPEN_BRACK basic_type SEMICOLON CONST_INT array_more_dimens CLOSE_BRACK''' dimens = [GreaseDimension(p[4])] + p[5] r = 1 for dimen in dimens: r = r * dimen.size total_size = r for dimen in dimens: dimen.offset = int(r / dimen.size) r = dimen.offset p[0] = GreaseType(GreaseTypeClass.Array, p[2], dimens, total_size)
def make_gosub(self): self.pop_fake_bottom() if self._next_param < len(self._called_fn.param_types): raise UndefinedFunction( 'Invalid function signature. Check argument count.') # Recursive functions dont have their size # calculated yet. Add them to era stack. if self._called_fn is self._active_fn: self._era_stack.push(self._quads.next_free_quad) size = GreaseVar(GreaseType(GreaseTypeClass.Int), self._called_fn.size, AddressingMethod.Literal) # Make ERA era = Quadruple(Operation.ERA, size) self._quads.push_quad(era) for param_quad in self._param_quads: self._quads.push_quad(param_quad) self._param_quads = [] start = GreaseVar(GreaseType(GreaseTypeClass.Int), self._called_fn.start, AddressingMethod.Literal) gosub = Quadruple(Operation.GOSUB, start) self._quads.push_quad(gosub) if self._called_fn.return_type is not None: return_var = GreaseVar(self._called_fn.return_type, self._next_global_address) temp = GreaseVar(return_var.type, self._next_local_address, AddressingMethod.Relative) self._next_local_address += temp.type.size self._quads.push_quad( Quadruple(Operation.ASSIGN, return_var, result=temp)) self.push_operand(temp)
def make_jump(self, to_stack=False): if to_stack: to = self._jump_stack.pop() if to is None: raise GreaseError('Empty jump stack!') address = GreaseVar(GreaseType(GreaseTypeClass.Int), to, AddressingMethod.Literal) quad = Quadruple(Operation.JMP, result=address) else: self._jump_stack.push(self._quads.next_free_quad) quad = Quadruple(Operation.JMP) self._quads.push_quad(quad)
def p_optional_method_declaration(p): '''optional_method_declaration : OPEN_PAREN ID COLON ID CLOSE_PAREN | empty''' if len(p) > 2: try: struct = greaser.find_struct(p[4]) t = GreaseType(GreaseTypeClass.Struct, struct) var_builder.add_type(t) var = var_builder.build() var_builder.reset() fn_builder.add_param(p[2], var) fn_builder.add_struct(struct) except GreaseError as e: e.print(p.lineno(2)) raise
def p_const_real(p): '''const_real : CONST_REAL''' num = struct.pack('>f', p[1]) rep = struct.unpack('>l', num)[0] greaser.push_constant(rep, GreaseType(GreaseTypeClass.Float))
def p_const_str(p): '''const_str : CONST_STR''' str_t = GreaseType(GreaseTypeClass.Array, GreaseType(GreaseTypeClass.Char)) str_t.size = len(p[1]) + 1 # Don't forget null terminator! greaser.push_constant(p[1], str_t)
def p_const_char(p): '''const_char : CONST_CHAR''' val = bytes(p[1], 'utf-8').decode('unicode_escape') greaser.push_constant(ord(val), GreaseType(GreaseTypeClass.Char))
def p_pointer(p): '''pointer : compound_type TIMES''' p[0] = GreaseType(GreaseTypeClass.Pointer, p[1])
def p_true(p): '''true : TRUE''' greaser.push_constant(True, GreaseType(GreaseTypeClass.Bool))
def p_false(p): '''false : FALSE''' greaser.push_constant(False, GreaseType(GreaseTypeClass.Bool))
def basic_type_from_text(name): return GreaseType(type_class_dict.get(name))