def __init__(self): self.tbool = Type.get('bool') self.tchar = Type.get('char') self.tint = Type.get('int') self.tvoid = Type.get('void') self.curfn = None self.in_loop = False
def typeof(self): if (self.__typeof == None): # resolve the field name first btype = self.base.typeof() if btype.isok(): if btype.kind not in ['user', 'class_literal']: signal_type_error( "User-defined class/instance type expected, found {0}". format(str(btype)), self.lines) self.__typeof = Type('error') else: if btype.kind == 'user': # user-defined instance type: acc = 'instance' else: # user-defined class type acc = 'static' baseclass = btype.baseclass j = resolve_field(acc, baseclass, self.fname, Config.current_class) if (j == None): signal_type_error( "No accessible field with name {0} in class {1}". format(self.fname, baseclass.name), self.lines) self.__typeof = Type('error') else: self.field = j self.__typeof = j.type return self.__typeof
def typeof(self): if (self.__typeof == None): # resolve the method name first btype = self.base.typeof() if btype.isok(): if btype.kind not in ['user', 'class_literal']: signal_type_error( "User-defined class/instance type expected, found {0}". format(str(btype)), self.lines) self.__typeof = Type('error') else: if btype.kind == 'user': # user-defined instance type: acc = 'instance' else: # user-defined class type acc = 'static' baseclass = btype.baseclass argtypes = [a.typeof() for a in self.args] if (all([a.isok() for a in argtypes])): j = resolve_method(acc, baseclass, self.mname, argtypes, Config.current_class, self.lines) if (j == None): self.__typeof = Type('error') else: self.method = j self.__typeof = j.rtype else: self.__typeof = Type('error') return self.__typeof
def __init__(self): self.tbool = Type.get('bool') self.tchar = Type.get('char') self.tint = Type.get('int') self.tfloat = Type.get('float') #! added float self.tvoid = Type.get('void') self.curfn = None self.loop_count = 0
def type_spec(self): # TYPESPEC : INTEGER | REAL if self.current_token.type == Token_Type.INTEGER: node = Type(self.current_token) self.eat(Token_Type.INTEGER) elif self.current_token.type == Token_Type.REAL: node = Type(self.current_token) self.eat(Token_Type.REAL) else: raise Exception('Error : unknown type {}'.format(self.current_token.value)) return node
def typeof(self): if (self.__typeof == None): if (Config.current_class.superclass != None): self.current_class = Config.current_class self.__typeof = Type(self.current_class.superclass) else: self.__typeof = Type('error') signal_type_error( "Type error in Super expression: class {0} has no superclass" .format(str(self.current_class)), self.lines) return self.__typeof
def typeof(self): if (self.__typeof == None): arg1type = self.arg1.typeof() arg2type = self.arg2.typeof() self.__typeof = Type('error') if (self.bop in ['add', 'sub', 'mul', 'div']): if (arg1type.isint()) and (arg2type.isint()): self.__typeof = arg1type elif (arg1type.isnumeric()) and (arg2type.isnumeric()): self.__typeof = Type('float') else: if (arg1type.isok() and arg2type.isok()): signal_bop_error('first', self.bop, arg1type, self.arg1, ['int', 'float'], 'int/float') signal_bop_error('second', self.bop, arg2type, self.arg2, ['int', 'float'], 'int/float') elif (self.bop in ['lt', 'leq', 'gt', 'geq']): if ((arg1type.isnumeric()) and (arg2type.isnumeric())): self.__typeof = Type('boolean') else: if (arg1type.isok() and arg2type.isok()): signal_bop_error('first', self.bop, arg1type, self.arg1, ['int', 'float'], 'int/float') signal_bop_error('second', self.bop, arg2type, self.arg2, ['int', 'float'], 'int/float') elif (self.bop in ['and', 'or']): if ((arg1type.isboolean()) and (arg2type.isboolean())): self.__typeof = Type('boolean') else: if (arg1type.isok() and arg2type.isok()): signal_bop_error('first', self.bop, arg1type, self.arg1, ['boolean'], 'boolean') signal_bop_error('second', self.bop, arg2type, self.arg2, ['boolean'], 'boolean') else: # equality/disequality if ((arg1type.isok()) and (arg2type.isok())): if ((arg1type.is_subtype_of(arg2type)) or (arg2type.is_subtype_of(arg1type))): self.__typeof = Type('boolean') else: signal_type_error( 'Type error in arguments of binary {0} expression: compatible types expected, found {1} and {2}' .format(self.bop, str(arg1type), str(arg2type)), self.lines) return self.__typeof
def typeof(self): if (self.__typeof == None): lhstype = self.lhs.typeof() rhstype = self.rhs.typeof() if (lhstype.isok() and rhstype.isok()): if (rhstype.is_subtype_of(lhstype)): self.__typeof = rhstype else: self.__typeof = Type('error') signal_type_error( 'Type error in assign expression: compatible types expected, found {0} and {1}' .format(str(lhstype), str(rhstype)), self.lines) else: self.__typeof = Type('error') return self.__typeof
def typeof(self): if (self.__typeof == None): if (not self.index.typeof().isint()): signal_type_error( "Type error in index of Array Index expression: integer expected, found {0}" .format(str(self.index.typeof())), self.index.lines) mytype = Type('error') if (self.base.typeof().kind != 'array'): signal_type_error( "Type error in base of Array Index expression: array type expected, found {0}" .format(str(self.base.typeof())), self.base.lines) mytype = Type('error') else: mytype = self.base.typeof().basetype self.__typeof = mytype return self.__typeof
def typeof(self): if (self.__typeof == None): # resolve the constructor name first argtypes = [a.typeof() for a in self.args] if (all([a.isok() for a in argtypes])): j = resolve_constructor(Config.current_class, self.classref, argtypes, self.lines) if (j == None): self.__typeof = Type('error') else: self.constructor = j self.__typeof = Type(self.classref) else: # type error in some argument; already signaled before self.__typeof = Type('error') return self.__typeof
def visitFor(self, forNode): #! added Visitfor, how is desugarer called # from: for(VARDEF to END) BLOCK # to: {VARDEF VARDEF1 while (VARDEF.ID < "end"){ BLOCK ASSIGNMENT} # assignment: VARDEF.ID = VARDEF.ID + 1 # vardef1: (int, "end", END) self.visit_children(forNode) endVar = self.makevar("end") initEnd = VarDef(Type.get('int'), endVar, BinaryOp(forNode.end, Operator('-'), IntConst(1))) decrCount = Assignment( VarUse(forNode.start.name), (BinaryOp(VarUse(forNode.start.name), Operator('-'), IntConst(1)))) #initEnd = VarDef(Type.get('int'), endVar, IntConst(1)) endCheck = BinaryOp(VarUse(forNode.start.name), Operator('<'), VarUse(endVar)) incrCount = Assignment( VarUse(forNode.start.name), (BinaryOp(VarUse(forNode.start.name), Operator('+'), IntConst(1)))) return Block([ forNode.start, decrCount, initEnd, While(endCheck, Block([incrCount, forNode.body])) ])
def p_primitive_type_specifier(p): """ primitive_type : INT | CHAR | FLOAT | DOUBLE """ p[0] = Type(p[1])
def typeof(self): if (self.__typeof == None): mytype = Type(self.basetype, len(self.args)) for a in self.args: if (not a.typeof().isok()): # previous error, so mark and pass mytype = Type('error') break if (not a.typeof().isint()): # int arg type expected signal_type_error( "Type error in argument to New Array expression: int expected, found {0}" .format(str(a.typeof())), a.lines) mytype = Type('error') break self.__typeof = mytype return self.__typeof
def p_declaration_aggregate_field(p): """ declaration : opt_field_annotations opt_qualifiers user_defined \ opt_attribute IDENT \ opt_qualifiers variables \ semicolons """ p[0] = create_fields(p[2] + Type("%s %s" % (p[3], p[5])) + p[6], p[1], p[7])
def p_declaration_named_type_field(p): """ declaration : opt_field_annotations opt_qualifiers primitive_type \ opt_qualifiers variables \ semicolons | opt_field_annotations opt_qualifiers IDENT opt_qualifiers \ variables semicolons """ p[0] = create_fields(p[2] + Type(p[3]) + p[4], p[1], p[5])
def p_type_qualifier(p): """ type_qualifier : CONST | VOLATILE | SHORT | LONG | UNSIGNED | SIGNED """ p[0] = Type(p[1])
def typeof(self): if (self.__typeof == None): argtype = self.arg.typeof() if (argtype.isnumeric()): self.__typeof = argtype else: self.__typeof = Type('error') if (argtype.isok()): signal_type_error('Type error in auto expression: int/float expected, found {0}'.format(str(argtype)), self.lines) return self.__typeof
def typecheck(self): global current_method if (self.__typecorrect == None): if (self.expr == None): argtype = Type('void') else: argtype = self.expr.typeof() self.__typecorrect = argtype.is_subtype_of( Config.current_method.rtype) if (argtype.isok() and (not self.__typecorrect)): signal_type_error( "Type error in Return statement: {0} expected, found {1}". format(str(Config.current_method.rtype), str(argtype)), self.lines) return self.__typecorrect
def typeof(self): if (self.__typeof == None): if (self.kind == 'int'): self.__typeof = Type('int') elif (self.kind == 'float'): self.__typeof = Type('float') elif (self.kind == 'string'): self.__typeof = Type('string') elif (self.kind == 'Null'): self.__typeof = Type('null') elif (self.kind == 'True'): self.__typeof = Type('boolean') elif (self.kind == 'False'): self.__typeof = Type('boolean') return self.__typeof
def visitFor(self, node): # from: for(int node.name = node.expr1 to node.expr2) { node.body } # to: # Block wrapper { # Assignment: int node.name = node.expr1; # While type: while ( expression: node.name < node.expr2){ # new block: # Block: node.body; # : node.name = node.name + 1 # } self.visit_children(node) if isinstance(node.ref, str): ref = VarUse(node.ref) initial_assignment = VarDef(Type.get('int'), str(ref), node.expr1).at(node) incrementation = Assignment(ref, BinaryOp(ref, Operator('+'), IntConst(1))).at(node) while_body = Block([node.body, incrementation]).at(node) while_condition = BinaryOp(ref, Operator("<"), node.expr2).at(node) while_statement = While(while_condition, while_body).at(node) while_statement.set_desugared_for(ref) return Block([initial_assignment, while_statement]).at(node)
def typeof(self): if (self.__typeof == None): argtype = self.arg.typeof() self.__typeof = Type('error') if (self.uop == 'uminus'): if (argtype.isnumeric()): self.__typeof = argtype elif (argtype.kind != 'error'): # not already in error signal_type_error( "Type error in unary minus expression: int/float expected, found {0}" .format(str(argtype)), self.arg.lines) elif (self.uop == 'neg'): if (argtype.isboolean()): self.__typeof = argtype elif (argtype.kind != 'error'): # not already in error signal_type_error( "Type error in unary negation expression: boolean expected, found {0}" .format(str(argtype)), self.arg.lines) return self.__typeof
def typeChecking(node): """traverse the AST and add conversion nodes""" if isinstance(node, Identifier): ident = node.getDecl() if isinstance(ident, VarDecl): return ident.type elif isinstance(ident, Function): ''' TODO:this call might be wrong''' return typeChecking(ident) elif isinstance(node, FuncCall): ''' Get corresponding Function Object''' funcObj = node.func_name.getDecl() if len(funcObj.arglist) != len(node.par_list): '''Number of parameter for function call does not match ''' raise InputError("Number of parameter does not match at " + str(node.func_name)) for x in node.par_list: typeChecking(x) return funcObj.getType() elif isinstance(node, ArithExpr): leftType = typeChecking(node.left) rightType = typeChecking(node.right) if leftType.isArray(): leftType = leftType.getBaseType() if rightType.isArray(): rightType = leftType.getBaseType() ''' Return type of result from arith expression ''' if leftType != rightType: if leftType == Type.getIntType(): '''Add ToReal node on left side ''' node.left = ToReal(node.left) else: '''Add ToReal node on right side ''' node.right = ToReal(node.right) return Type.getRealType() if leftType == Type.getIntType(): return Type.getIntType() else: return Type.getRealType() elif isinstance(node, AssignStmt): leftType = typeChecking(node.lvalue) rightType = typeChecking(node.expr) if leftType.isArray(): leftType = leftType.getBaseType() if rightType.isArray(): rightType = leftType.getBaseType() if leftType != rightType: if leftType == Type.getIntType(): '''Add ToInt cast on right side ''' node.expr = ToInt(node.expr) else: '''Add ToReal cast on right side ''' node.expr = ToReal(node.expr) elif isinstance(node, Function): global functionReturnType functionReturnType = node.getType() ''' check the arguments of the function, e.g. array forbidden ''' for a in node.arglist: if len(a.array) != 0: raise InputError("Argument is an array: " + str(node.name)) typeChecking(node.block) elif isinstance(node, VarDecl): accessors = node.getArray() for a in accessors: if Type.getIntType() != typeChecking(a): raise InputError("Invalid array access in VarDecl: " + str(node.name)) elif isinstance(node, LValue): accessors = node.getArrayDeref() decl = node.name.getDecl() if isinstance(decl, VarDecl): if len(node.getArrayDeref()) != len(decl.getArray()): raise InputError("Invalid array access in LValue: " + str(node.name)) for a in accessors: if Type.getRealType() == typeChecking(a): raise InputError("Invalid array access in LValue: " + str(node.name)) else: typeChecking(a) if isinstance(node.name.getDecl(), Function): raise InputError("The function misses its arguments: " + str(node.name)) return decl.type elif isinstance(node, Program): for c in node.children(): typeChecking(c) elif isinstance(node, ReturnStmt): returnType = typeChecking(node.expr) if returnType != functionReturnType: if returnType == Type.getIntType(): node.expr = ToReal(node.expr) else: node.expr = ToInt(node.expr) elif isinstance(node, IntLiteral): return Type.getIntType() elif isinstance(node, FloatLiteral): return Type.getRealType() else: for x in node.children(): typeChecking(x)
def handleType(p): return Type(p[0].value)
def irgen(node, irprogram=None, irfunction=None, jump_dest=None, jump_right=None, negation=False): if isinstance(node, Program): irprogram = IRProgram() for v in node.vars: # TODO use addGlobal(?) # Create IRVariable for globale variables irvar = None if len(v.getArray()) != 0: # create array-type dims = v.getArray() arr_type = v.type.getBaseType() for dim in dims: arr_type = arr_type.getArrayType(dim) irvar = irprogram.getIRVar(v.name.name, arr_type, True) else: irvar = irprogram.getIRVar(v.name.name, v.type, True) irprogram.variables.append(irvar) v.setIRVar(irvar) for f in node.funcs: # TODO use addFunc(?) irprogram.functions.append(irgen(f, irprogram)) return irprogram elif isinstance(node, Function): irfunction = IRFunction(node.name.name, irprogram) for par in node.arglist: irpar = irprogram.getIRVar(par.name.name, par.type) irfunction.addParam(irpar) par.setIRVar(irpar) irgen(node.block, irprogram, irfunction) return irfunction elif isinstance(node, VarDecl): # Edited: node.name to node.name.name if len(node.getArray()) != 0: # create array-type dims = node.getArray() arr_type = node.type.getBaseType() for dim in dims: arr_type = arr_type.getArrayType(dim) irvar = irprogram.getIRVar(node.name.name, arr_type) else: irvar = irprogram.getIRVar(node.name.name, node.type) node.setIRVar(irvar) irfunction.addVar(irvar) elif isinstance(node, Block): for x in node.children(): irgen(x, irprogram, irfunction) elif isinstance(node, Identifier): if node.decl.getIRVar() is not None: return node.decl.getIRVar() else: print( "ERROR Identifier: Cant find IRVariable object to identifier") elif isinstance(node, ToInt): tmp = irgen(node.successor, irprogram, irfunction) virtReg = irprogram.getFreeVirtReg(irfunction, Type.getIntType()) irfunction.addInstr(CR2I(virtReg, tmp)) irfunction.virtRegs[virtReg.name] = virtReg return virtReg elif isinstance(node, ToReal): tmp = irgen(node.successor, irprogram, irfunction) virtReg = irprogram.getFreeVirtReg(irfunction, Type.getRealType()) irfunction.addInstr(CI2R(virtReg, tmp)) irfunction.virtRegs[virtReg.name] = virtReg return virtReg elif isinstance(node, Literal): return ConstValue(node.val, node.type) elif isinstance(node, LValue): decl = node.name.getDecl() derefs = None if isinstance(decl, Identifier): derefs = decl.getArrayDeref() else: derefs = decl.array if len(derefs) != 0: # is array virtReg = irprogram.getFreeVirtReg(irfunction, decl.type.getBaseType()) base = getBase(node, irprogram, irfunction) offset = getOffset(node, irprogram, irfunction) irfunction.addInstr(CLOAD(virtReg, base, offset)) return virtReg else: return irgen(node.name, irprogram, irfunction) elif isinstance(node, ArithExpr): # Evaluate leftern subtree leftReg = irgen(node.left, irprogram, irfunction) # Evaluate rightern subtree rightReg = irgen(node.right, irprogram, irfunction) if rightReg.type != leftReg.type: print("ArithExpr: Subexpressions have different type :'(") destReg = irprogram.getFreeVirtReg(irfunction, rightReg.type) if node.op.val == "+": irfunction.addInstr(CADD(destReg, leftReg, rightReg)) elif node.op.val == "-": irfunction.addInstr(CSUB(destReg, leftReg, rightReg)) elif node.op.val == "*": irfunction.addInstr(CMUL(destReg, leftReg, rightReg)) elif node.op.val == "/": irfunction.addInstr(CDIV(destReg, leftReg, rightReg)) else: print("ArithExpr: Another mysterious error: No valid operand") return destReg elif isinstance(node, FuncCall): virts = [] for p in reversed(node.par_list): virts.append(irgen(p, irprogram, irfunction)) for v in virts: irfunction.addInstr(CPUSH(v)) returnType = node.func_name.getDecl().getType() destReg = irprogram.getFreeVirtReg(irfunction, returnType) irfunction.addInstr(CCALL(destReg, node.func_name.name)) return destReg elif isinstance(node, ReturnStmt): irfunction.addInstr(CRET(irgen(node.expr, irprogram, irfunction))) elif isinstance(node, CondExpr): if node.op.val == "||": l_right_cond = irprogram.genLabel() irgen(node.left, irprogram, irfunction, jump_dest, l_right_cond) irfunction.addInstr(l_right_cond) irgen(node.right, irprogram, irfunction, jump_dest, jump_right) irfunction.addInstr(CBRA(jump_right)) elif node.op.val == "&&": l_right_cond = irprogram.genLabel() irgen(node.left, irprogram, irfunction, l_right_cond, jump_right, True) irfunction.addInstr(l_right_cond) irgen(node.right, irprogram, irfunction, jump_dest, jump_right) irfunction.addInstr(CBRA(jump_right)) # Evaluate rightern subtree else: leftReg = irgen(node.left, irprogram, irfunction) rightReg = irgen(node.right, irprogram, irfunction) if node.op.val == "<=": if negation: irfunction.addInstr(CBGT(jump_right, leftReg, rightReg)) else: irfunction.addInstr(CBLE(jump_dest, leftReg, rightReg)) elif node.op.val == "=": if negation: irfunction.addInstr(CBNE(jump_right, leftReg, rightReg)) else: irfunction.addInstr(CBEQ(jump_dest, leftReg, rightReg)) elif node.op.val == "!=": if negation: irfunction.addInstr(CBEQ(jump_right, leftReg, rightReg)) else: irfunction.addInstr(CBNE(jump_dest, leftReg, rightReg)) elif node.op.val == "<": if negation: irfunction.addInstr(CBGE(jump_right, leftReg, rightReg)) else: irfunction.addInstr(CBLT(jump_dest, leftReg, rightReg)) elif node.op.val == ">": if negation: irfunction.addInstr(CBLE(jump_right, leftReg, rightReg)) else: irfunction.addInstr(CBGT(jump_dest, leftReg, rightReg)) elif node.op.val == ">=": if negation: irfunction.addInstr(CBLT(jump_right, leftReg, rightReg)) else: irfunction.addInstr(CBGE(jump_dest, leftReg, rightReg)) elif isinstance(node, IfStmt): l_then = irprogram.genLabel() l_else = irprogram.genLabel() l_end = irprogram.genLabel() irgen(node.cond, irprogram, irfunction, l_then, l_else) irfunction.addInstr(CBRA(l_else)) irfunction.addInstr(l_then) irgen(node.trueblock, irprogram, irfunction) irfunction.addInstr(CBRA(l_end)) irfunction.addInstr(l_else) irgen(node.falseblock, irprogram, irfunction) irfunction.addInstr(l_end) elif isinstance(node, WhileStmt): l_cond = irprogram.genLabel() l_then = irprogram.genLabel() l_end = irprogram.genLabel() irfunction.addInstr(l_cond) irgen(node.cond, irprogram, irfunction, l_then, l_end) irfunction.addInstr(CBRA(l_end)) irfunction.addInstr(l_then) irgen(node.block, irprogram, irfunction) irfunction.addInstr(CBRA(l_cond)) irfunction.addInstr(l_end) elif isinstance(node, AssignStmt): # get the left side of an assigment src = irgen(node.expr, irprogram, irfunction) decl = node.lvalue.name.getDecl() derefs = decl.array if len(derefs) != 0: # is array base = getBase(node.lvalue, irprogram, irfunction) offset = getOffset(node.lvalue, irprogram, irfunction) irfunction.addInstr(CSTORE(base, offset, src)) else: dest = irgen(node.lvalue, irprogram, irfunction) irfunction.addInstr(CASSGN(dest, src)) else: for x in node.children(): irgen(x, irprogram, irfunction)
def typeof(self): if (self.__typeof == None): self.__typeof = Type(self.classref, literal=True) return self.__typeof
def typeof(self): if (self.__typeof == None): self.current_class = Config.current_class self.__typeof = Type(self.current_class) return self.__typeof