def function_return(self): return_value = self._operand.pop() if return_value is None: raise BigError("Error on retrun data") check_data = cube.compare_types(Operator.RETURN, return_value.type_var, self.active_function.return_type) if check_data: result = FluffyVariable( None, type_var=self.active_function.return_type, addr=address.set_addr(kind=self.active_function.return_type)) quadruple = QuadruplePack(Operator.RETURN, l_value=return_value, r_value=None, result=result) self._quadruple.add(quadruple) else: raise BigError.mismatch_operator( "Return type {} does't correspond to the return type of function {} " .format(return_value.type_var, self.active_function.return_type))
def eval_dim(self): """ Function to evaluate the expression for each dimension. Generates the quadruple of VER (Verification of dimension) and the multiplication of the expression times the m value """ exp = self._operand.pop() dim = self._top_dim() if exp.type_var != Types.INT: raise BigError.invalid_value( "The value of the array {} is not an Integer".format( exp.id_var)) if exp is not None: dimS = FluffyVariable(None, Types.INT, addr=dim.size) dimM = self.add_constants(dim.m, Types.INT) # m dim self._operand.pop() dimInf = self.add_constants(0, Types.INT) # Dimension inferior self._operand.pop() tem = FluffyVariable(None, exp.type_var, addr=address.set_addr(exp.type_var)) # Validate dim and generate VER self._quadruple.add(QuadruplePack(Operator.VER, exp, dimInf, dimS)) self._quadruple.add(QuadruplePack(Operator.TIMES, exp, dimM, tem)) # x m self._operand.append(tem) else: raise BigError("Error in array expression")
def function_validate_params(self, empty_params=False): fun = self.find_function(self.active_function.id) if empty_params: if self.active_function.params_size != 0: raise BigError.no_empty_params( "The function {} required {} parameters, {} given".format( fun.id_function, self.active_function.params_size, self._count_params + 1)) argument = self._operand.pop() if self._count_params + 1 > self.active_function.params_size: raise BigError.no_empty_params( "The function {} required {} parameters, {} given".format( fun.id_function, self.active_function.params_size, self._count_params + 1)) if argument.type_var != fun.params[self._count_params].type_var: raise BigError.mismatch_params( "The parameter {} doesn't match the type of parameter in function" .format(self._count_params)) param = FluffyVariable(None, None, addr=self._count_params) self._quadruple.add( QuadruplePack(Operator.PARAM, argument, None, param)) self._count_params += 1
def add_local_variable(self, instance): if instance.id_var in self._global_variable: raise BigError.redefined_variable(instance.id_var) if instance.id_var in self._local_variable: raise BigError.redefined_variable(instance.id_var) instance.addr = address.set_addr(instance.type_var) self._local_variable[instance.id_var] = instance
def create_assignation(self): expression = self._operand.pop() variable = self._operand.pop() if variable is None or expression is None: raise BigError('None Value to assign') comparison = cube.compare_types(Operator.EQUAL, expression.type_var, variable.type_var) if comparison: q = QuadruplePack(Operator.EQUAL, expression, None, variable) self._quadruple.add(q) else: raise BigError.mismatch_assignation( "The expression has type {} and expression has type {} they're incompatible" .format(expression.type_var.name, variable.type_var.name))
def _check_top(self): # len(self._operator)> 0 r_operand = self._operand.pop() r_type = r_operand.type_var l_operand = self._operand.pop() l_type = l_operand.type_var oper = self._operator.pop() check_types = cube.compare_types(oper, l_type, r_type) if check_types: val_result = address.set_addr(check_types) result = FluffyVariable(None, type_var=check_types, addr=val_result) # Generate Quadruple quadruple = QuadruplePack(oper, l_operand, r_operand, result) # Push _quadruple to list self._quadruple.add(quadruple) # Add result position of _quadruple to the operand list self._operand.append(result) else: raise BigError.mismatch_operator("{} {} {} ".format( l_type.name, oper.name, r_type.name))
def make_special_function_input(self): exp = self._operand.pop() if exp is None: raise BigError("No given value to save input") self._quadruple.add(QuadruplePack(SpecialFunction.INPUT, result=exp))
def jump_false(self): # if len(self._operand) == 0: self._jumps.append(self._quadruple.index) result = self._operand.pop() if result is None: print(self._operand) raise BigError("The stack is empty") if result.type_var != Types.BOOLEAN: raise BigError.mismatch_operator( "The operation doesn't return a boolean value") # Generate GotoFalse, return to fill the address self._quadruple.add(QuadruplePack(Operator.GOTOF, result, None, None))
def find_function_call(self, _id): self.active_function_call = self.find_function(_id) if self.active_function_call is None: raise BigError.undefined_function( "The function {} is not declared".format(_id)) self._count_params = 0
def find_variable(self, id_var): if id_var in self._local_variable: return self._local_variable.get(id_var) elif id_var in self._global_variable: return self._global_variable.get(id_var) else: raise BigError.undefined_variable( 'The variable {} doest exist'.format(id_var))
def add_function(self, instance): if instance.id_function in self._functions: raise BigError.redefined_function(' This one -> {} <- '.format( instance.id_function)) self._functions[instance.id_function] = instance self.function_validate(instance.id_function) self.active_function.start_position = self._quadruple.index
def _fill(self, line=0): actual_quadruple = self._jumps.pop() if actual_quadruple is None: raise BigError("Error, pending quadruples") else: available_quadruple = self._quadruple.index + line address_quadruple = FluffyVariable(None, None, addr=available_quadruple) self._quadruple.fill(actual_quadruple, address_quadruple)
def set_addr(self, kind, g_var=False): if kind not in self.local_address: raise BigError("Error type not defined") # Global variable if g_var: actual_value = self.global_address[kind] self.global_address[kind] += 1 # Local variables else: actual_value = self.local_address[kind] self.local_address[kind] += 1 return actual_value
def function_validate(self, fn_name): self.active_function.clear() self._count_params = 0 find = self.find_function(fn_name) if find is None: raise BigError.undefined_function( "The Function in the assignation doesn't see to be declared -> {} <-" .format(fn_name)) self.active_function.id = find.id_function self.active_function.params_size = len(find.params) self.active_function.return_type = self.text_to_type(find.return_type) self.active_function.size = find.size
def make_special_function(self, action_name, expected_type=None): """ Generic function for crating almost all special function :param action_name: :param expected_type: :return: None, Insert quadruple in stack """ action_name = self.text_to_special_operator(action_name) exp = self._operand.pop() if exp is None: raise BigError("Error getting value for function") if expected_type is not None: if exp.type_var not in expected_type: print(action_name) raise BigError.invalid_type( "Function {} only accepts expression of type {} ".format( action_name.name, [item.name for item in expected_type])) q = QuadruplePack(action_name, None, None, exp) self._quadruple.add(q)
def make_special_function_circle(self, expected_type=None): radius = self._operand.pop() angle = self._operand.pop() if expected_type is not None: if radius.type_var not in expected_type or angle.type_var not in expected_type: raise BigError.invalid_type( "Function {} only accepts expression of type {} ".format( SpecialFunction.STARTPOSITION.name, [item.name for item in expected_type])) self._quadruple.add( QuadruplePack(SpecialFunction.CIRCLE, None, radius, angle)) pass
def make_special_function_go(self, expected_type=None): """ Make quadruple to move to an x,y position :param expected_type: :return: """ x = self._operand.pop() y = self._operand.pop() if expected_type is not None: if x.type_var not in expected_type or y.type_var not in expected_type: raise BigError.invalid_type( "Function {} only accepts expression of type {} ".format( SpecialFunction.STARTPOSITION.name, [item.name for item in expected_type])) self._quadruple.add(QuadruplePack(SpecialFunction.GO, None, x, y))
def make_special_function_start_point(self, expected_type=None): """ Make quadruple for start point, define the starting point of the pencil :param expected_type: :return: """ x = self._operand.pop() y = self._operand.pop() if expected_type is not None: if x.type_var not in expected_type or y.type_var not in expected_type: raise BigError.invalid_type( "Function {} only accepts expression of type {} ".format( SpecialFunction.STARTPOSITION.name, [item.name for item in expected_type])) self._quadruple.add( QuadruplePack(SpecialFunction.STARTPOSITION, None, x, y))
def make_special_function_square(self, expected_type=None): """ Make quadruple for square, accept 1, 2 parameters :param expected_type: :return: """ p1 = self._operand.pop() p2 = self._operand.pop() if expected_type is not None: if p1.type_var not in expected_type or p2.type_var not in expected_type: raise BigError.invalid_type( "Function {} only accepts expression of type {} ".format( SpecialFunction.STARTPOSITION.name, [item.name for item in expected_type])) self._quadruple.add(QuadruplePack(SpecialFunction.SQUARE, None, p1, p2))
def make_special_function_screen_size(self, expected_type=None): """ Make quadruple for start screen size (x and y), define the starting point of the pencil :param sizes: :return: """ exp1 = self._operand.pop() exp2 = self._operand.pop() if expected_type is not None: if exp1.type_var not in expected_type or exp2.type_var not in expected_type: raise BigError.invalid_type( "Function {} only accepts expression of type {} ".format( SpecialFunction.STARTPOSITION.name, [item.name for item in expected_type])) self._quadruple.add( QuadruplePack(SpecialFunction.SCREENSIZES, result=exp1)) self._quadruple.add( QuadruplePack(SpecialFunction.SCREENSIZES, result=exp2))
def text_to_operator(op): op = match_operators.get(op) for e in list(Operator): if op == e.name: return e raise BigError("Operator {} is not a valid one".format(op))
def text_to_type(tp): for t in list(Types): if tp.upper() == t.name: return t raise BigError("Type {} is not a valid one".format(tp))
def text_to_special_operator(op): for e in list(SpecialFunction): if op.upper() == e.name: return e raise BigError("Operator {} is not a valid one".format(op))
def find_function(self, id_fun): if id_fun not in self._functions: raise BigError.undefined_function(id_fun) return self._functions[id_fun]
def get_addr(self, kind, g_var=False): if kind not in self.local_address: raise BigError("Error type not defined") if g_var: return self.global_address[kind] return self.local_address[kind]