def visit_FuncDef(self, node): if node.args_list_or_empty: arg_types, fun_vars = self.visit(node.args_list_or_empty) else: arg_types, fun_vars = [(), ()] #for convnenience this is a list-pair of: 1)types 2)pairs (name,type) #arg_types are only types without names composing local vars #fun_vars are full description of local variables, that we must add to #the new scope created below if not self.stack.get(node.id.id): # ^ declaration of function must be added to the global scope redefinition_error = False self.stack = self.stack.pushScope("fun " + node.type) for var_desc in fun_vars: var = VariableSymbol(var_desc[0], var_desc[1]) if not self.stack.get( var_desc[0] ): #if the variable name was not used in the current context self.stack.put(var_desc[0], var) #^here we make a use of fun_vars: we just iterate through the collection # creating objects of type VariableSymbol without the need #of any further processing of the elements of that collection else: print "variable redefinition at line:", node.id.lineno, "column:", node.id.column self.error_occured = True redefinition_error = True if not redefinition_error: funcDefVar = FuncSymbol(node.id.id, node.type, arg_types) self.stack.getParentScope().put(node.id.id, funcDefVar) # ^ we are already in the function body scope, so we need to "borrow" the parent scope for this operation self.visit(node.compound_instr) self.stack = self.stack.popScope() else: print "Redefinition of the function", node.id.id, "line:", node.id.lineno, "column:", node.id.column self.error_occured = True
def visit_Declaration(self, node): returnType = ReturnType() res = self.visit(node.inits) for declaration in res if res != None else []: child_name, child_type, line, column =\ declaration[0],declaration[1],declaration[2],declaration[3] # ^ that tuple can mean assigning a variable, which has not 4 but 5 elements if child_type == "id": #if the operation does assigning a variable, we need first check if it was #declared and if it has correct type: assigned_variable_name = declaration[4] var = self.stack.get(assigned_variable_name) if var: if type(var) == VariableSymbol: #get the var's type child_type = var.type else: print "Wrong call of a function", assigned_variable_name, " at line:", line, "column:", column else: print "variable", assigned_variable_name, "has not been declared, line:", line, "column:", column try: table_val = returnType.ttype["="][node.type][child_type] if type(table_val) == tuple: print table_val[1], "at line:", line, "column:", column # ^ here we check if there is no extra msg indicating possible loss of precision if self.stack.get(child_name) is not None: print "Redeclaration of", "'" + child_name + "'", "at line:", line, "column:", column else: var_symbol = VariableSymbol(child_name, node.type) self.stack.put(child_name, var_symbol) except KeyError: print "wrong assignment: type", node.type, "declaration:", child_type, "at line:", line, "column:", column
def visit_FunArg(self, node): if self.symbol_table.current_scope.get(node.arg) is None: self.symbol_table.current_scope.put( node.arg, VariableSymbol(node.arg, node.arg_type)) else: message = "Variable '{}' already declared".format(node.arg) self.log_error(message, node.lineno)
def visit_Assign(self, node): self.visit(node.assign_op) assignments = self.visit(node.expression) if assignments is not None: if isinstance(node.expression, entities.ZerosMatrixInit) \ or isinstance(node.expression, entities.OnesMatrixInit) \ or isinstance(node.expression, entities.EyeMatrixInit): self.table.put(str(node.variable.value), MatrixSymbol(node.assign_op, node.expression, node.expression.columns.value, node.expression.rows.value)) elif isinstance(assignments, entities.MatrixVector): self.table.put(str(node.variable.value), MatrixSymbol(node.assign_op, node.expression, self.elements // self.rows, self.rows)) elif isinstance(assignments, entities.BinaryExpr): self.table.put(str(node.variable.value), BinSymbol(node.assign_op, node.expression)) elif not isinstance(node.variable, entities.ArrayRef): self.table.put(str(node.variable.value), VariableSymbol(node.assign_op, node.expression))
def visit_Assignment(self, node): type = self.visit(node.expression) if isinstance(node.variable, MatrixElement): var = self.symbol_table.get(node.variable.variable) if var is None: print("Error in line " + str(node.line) + ": no matrix with that name") self.errors = True else: self.visit(node.variable) else: var = self.symbol_table.get(node.variable.name) if var is not None: if str(var) != str(type): print("Warning in line " + str(node.line) + ": previously declared variable, type: " + str(var) + " now reassigning with type: " + str(type)) self.symbol_table.put(node.variable.name, VariableSymbol(node.variable.name, type)) self.visit(node.variable)
def visit_Function(self, node): if self.table.get(node.name) is None: fun = FunctionSymbol(node.name, node.type, SymbolTable(self.table, node.name)) self.table.put(node.name, fun) self.actualFun = fun self.table = fun.table numOfParameter = 0 for arg in node.parameters.children: self.visit( arg ) #Wojtku, nie musisz pisac explicite visit_Parameter. Program sam wnioskuje, ktora funkcje odwiedzic, a jak nie to odwiedza defaultowa if self.table.get(arg.name) != None: print "Error: Variable '{}' already declared: line {}".format( arg.name, node.line) varSym = VariableSymbol(arg.name, self.visit(arg)) self.table.put(arg.name, varSym) fun.put(str(numOfParameter), varSym) numOfParameter = numOfParameter + 1 #Zamiast nazywac parametry funkcji bedziemy je numerowac self.visit(node.body) if self.actualFun.returnExists == False: print "Error: Missing return statement in function '{}' returning int: line {}".format( node.name, node.body.endline) self.table = self.table.getParentScope() self.actualFun = None else: print "Error: Redefinition of function '{}': line {}".format( node.name, node.line)
def visit_Arg(self, node): if self.symbol_table.get(node.id) is not None: print("Double argument in function: " + node.id + "in line: " + self.my_str(node.line)) else: self.symbol_table.put(node.id, VariableSymbol(node.id, node.type)) self.current_function.put_arg(node.type)
def visit_For(self, node): self.loop_entry += 1 self.symbol_table = self.symbol_table.pushScope('for') type1 = self.visit(node.range) self.symbol_table.put(node.iter.name, VariableSymbol(node.iter.name, type1)) self.visit(node.for_body) self.symbol_table = self.symbol_table.popScope() self.loop_entry -= 1
def visit_Argument(self, node, tab): if node.id in tab.symbols: print "Error: Duplicated usage of symbol {0}, line {1}".format( node.id, node.line) self.noErrors = False else: tab.put(node.id, VariableSymbol(node.id, node.type, None)) return node.type
def visit_Init(self, node): given_type = self.visit(node.expression) if given_type == self.current_type or (given_type == "int" and self.current_type =="float"): if self.symbol_table.get(node.id) is not None: print("The" + node.id + "was already defined" + "in line: " + self.my_str(node.line)) else: self.symbol_table.put(node.id, VariableSymbol(node.id, self.current_type)) else: print("Forbidden type assignment " + self.my_str(given_type) + " to " + self.my_str(self.current_type)+ "in line: " + self.my_str(node.line))
def visit_For(self, node): self.symbol_table.pushNesting() self.symbol_table.pushScope('for') type = self.visit(node.range) self.symbol_table.put(node.variable.name, VariableSymbol(node.variable.name, type)) self.visit(node.instruction) self.symbol_table.popScope() self.symbol_table.popNesting()
def visit_Arg(self, node): definition = self.table.get(node.idd) if definition is not None: self.errors = True print "Argument {0} is already defined at line {1}. Redefinition at line {2}.".format( node.idd, definition.lineno, node.lineno) else: self.table.put(node.idd, VariableSymbol(node.idd, node.t, node.lineno))
def visit_Init(self, node): initType = self.visit(node.expression) if (initType == self.actType) or (initType == "int" and self.actType == "float") or (initType == "float" and self.actType == "int"): if self.table.get(node.name) is not None: raise MyException("Invalid definition of {} in line: {}. Entity redefined".format(node.name, node.line)) else: self.table.put(node.name, VariableSymbol(node.name, self.actType)) else: raise MyException("Bad assignment of {} to {} in line {}".format(initType, self.actType, node.line))
def visit_Assignment(self, node): print("wisit assignment") r_node = self.visit(node.value) op = node.op if r_node is not None: r_type = r_node.type name = node.ref.name if op == "=": self.symtable.put(name, VariableSymbol(name, r_type, r_node)) else: if self.visit(node.ref) is not None: l_node = self.visit(node.ref) l_type = l_node.type new_type = types[op][l_type][r_type] if new_type is None: print("Line {}: Assignment on different types: '{}' and '{}'".format(node.line, l_type, r_type)) return self.symtable.put(name, VariableSymbol(name, new_type, r_node))
def visit_MatrixAssignment(self, node): var = self.symbol_table.get(node.variable.name) if var is not None: print( "Warning in line " + str(node.line) + ": previously declared variable, now reassigning with type: " + str(Matrix.__name__)) matrix = self.visit(node.expression_list) self.symbol_table.put(node.variable.name, VariableSymbol(node.variable.name, matrix))
def visit_Assign(self, node): type1 = self.visit(node.right) op = node.op if op == '=': self.symbol_table.put(node.left.name, VariableSymbol(node.left.name, type1)) elif op in ['+=', '-=', '*=', '/=']: type2 = self.visit(node.left) if type1 != type2: print("Incompatible types")
def visit_Iterator(self, node): variable = node.name start_node = self.visit(node.start) start_type = start_node.type stop_node = self.visit(node.stop) stop_type = stop_node.type if start_type != 'INTEGER' or stop_type != 'INTEGER': print("Line {}: Range should be defined by integers".format(node.line)) return None else: self.symtable.put(variable.name, VariableSymbol(variable.name, start_type, start_node))
def visit_Init(self, node): initType = self.visit(node.expr) if initType == self.actType or (initType == "int" and self.actType == "float") or ( initType == "float" and self.actType == "int"): if self.table.get(node.name) is not None: self.isValid = False; print "Invalid definition of {} in line: {}. Entity redefined". \ format(node.name, node.line) else: self.table.put(node.name, VariableSymbol(node.name, self.actType)) else: self.isValid = False; print "Bad assignment of {} to {} in line {}".format(initType, self.actType, node.line)
def visit_Init(self, node): initType = self.visit(node.expr) if not typeDiffer(self.actType, initType, node.line): if self.table.get(node.name) is not None: print_message( "Variable '{}' already declared".format(node.name), node.line) else: self.table.put(node.name, VariableSymbol(node.name, self.actType)) else: print_message( "Assignment of {} to {}".format(initType, self.actType), node.line)
def visit_Init(self, node): defined_type = self.visit(node.exp) funSymbol = self.table.getSymbol(node.id) varSymbol = self.table.get(node.id) if isinstance(funSymbol, FunctionSymbol): print "Error: Function identifier '{}' used as a variable: line {}".format( node.id, node.line) elif varSymbol is None: if defined_type == self.actualType or (defined_type == "int" and self.actualType == "float"): self.table.put(node.id, VariableSymbol(node.id, self.actualType)) elif defined_type == "float" and self.actualType == "int": print "warning: float -> int, losing precision in line {}".format( node.line) self.table.put(node.id, VariableSymbol(node.id, self.actualType)) else: print "Error: Assignment of {} to {}: line {}".format( defined_type, self.actualType, node.line) else: print "Error: Variable '{}' already declared: line {}".format( node.id, node.line)
def visit_Assigment(self, node): type2 = self.visit(node.right) op = node.op if isinstance(type2, ErrorType): return ErrorType() if op == '=': if type(node.left) == AST.Variable: self.symbol_table.put(node.left.name, VariableSymbol(node.left.name, type2)) else: #ref type1 = self.visit(node.left) self.symbol_table.put(node.left.var, VariableSymbol(node.left.var, type2)) else: type1 = self.visit(node.left) result_type = _type[op][str(type1)][str(type2)] if result_type is not None: if result_type == 'vector': if isinstance(type1, VectorType) and isinstance(type2, VectorType): if type1.size != type2.size: print(f"Error in line {node.line}") return ErrorType() return result_type else: print(f"Error in line {node.line}. Wrong op with such types") return ErrorType()
def visit_Init(self, node, tab, type): if node.id in tab.symbols: print "Error: Duplicated usage of symbol {0}, line {1}".format(node.id, node.line) value_type = self.visit(node.expression, tab) if not value_type in ttype['='][type]: print "Error: Value of type {0} cannot be assigned to symbol {1} of type {2}, line {3}" \ .format(value_type, node.id, type, node.line) else: if "warn" in ttype['='][type][value_type]: print "Warning: Value of type {0} assigned to symbol {1} of type {2}, line {3}" \ .format(value_type, node.id, type, node.line) tab.put(node.id, VariableSymbol(node.id, type, node.expression))
def visit_ForInstruction(self, node): range_expression = self.visit(node.range_expression) if not isinstance(range_expression, entities.RangeExpression): print("Error: The for condition should be a range, line {}" .format(node.line)) return None self.table.put(str(range_expression.my_id), VariableSymbol('=', range_expression.expression1)) self.is_in_loop = True self.visit(node.braced_expression) self.is_in_loop = False return node
def visit_Init(self, node): expr_type = self.visit(node.expression) declr_type = self.symbol_table.current_scope.current_type definition = self.symbol_table.current_scope.find(node.identifier) if definition is not None and isinstance(definition, FunctionSymbol): message = "Function identifier '{}' used as a variable".format( node.identifier) self.log_error(message, node.lineno) elif self.symbol_table.current_scope.get(node.identifier) is not None: message = "Variable '{}' already declared".format(node.identifier) self.log_error(message, node.lineno) elif not self.ttype.get_type('=', declr_type, expr_type): message = "Assignment of {} to {}".format(expr_type, declr_type) self.log_error(message, node.lineno) else: self.check_precision_loss(declr_type, expr_type, node.lineno) self.symbol_table.current_scope.put( node.identifier, VariableSymbol(node.identifier, declr_type))
def visit_Init(self, node): t = self.visit(node.expression) if t != self.current_type: warning = False if t == "int" and self.current_type == "float": warning = True self.errors = self.errors or not warning print "{0}Initialization to symbol {1}: symbol's type is {2}," \ " tried to assign type {3} at line {4}".format("Warning: " if Warning else "", node.var_name, self.current_type, t, node.lineno) definition = self.table.get(node.var_name) if definition is not None: self.errors = True print "Variable {0} is already defined at line {1}. Redefinition at line {2}.".format( node.var_name, definition.lineno, node.lineno) else: self.table.put( node.var_name, VariableSymbol(node.var_name, self.current_type, node.lineno))
def visit_Argument(self, node): if self.table.get(node.name) is not None: self.isValid = False; print "Argument {} already defined. Line: {}".format(node.name, node.line) else: self.table.put(node.name, VariableSymbol(node.name, node.type))
def visit_Argument(self, node): if self.table.get(node.name) is not None: raise MyException("Argument {} already defined. Line: {}".format(node.name, node.line)) else: self.table.put(node.name, VariableSymbol(node.name, node.type))
def visit_Argument(self, node): if self.table.get(node.name) is not None: print_message("Argument {} is already defined".format(node.name), node.line) else: self.table.put(node.name, VariableSymbol(node.name, node.type))