class CodeGenVisitor(BaseVisitor, Utils): def __init__(self, astTree, env, dir_): #astTree: AST #env: List[Symbol] #dir_: File self.astTree = astTree self.env = env self.className = "MCClass" self.path = dir_ self.emit = Emitter(self.path + "/" + self.className + ".j") def visitProgram(self, ast, c): #ast: Program #c: Any self.emit.printout( self.emit.emitPROLOG(self.className, "java.lang.Object")) e = SubBody(None, self.env) for x in ast.decl: e = self.visit(x, e) # generate default constructor self.genMETHOD(FuncDecl(Id("<init>"), list(), None, Block(list())), c, Frame("<init>", VoidType)) self.emit.emitEPILOG() return c def genMETHOD(self, consdecl, o, frame): #consdecl: FuncDecl #o: Any #frame: Frame isInit = consdecl.returnType is None isMain = consdecl.name.name == "main" and len( consdecl.param) == 0 and type(consdecl.returnType) is VoidType returnType = VoidType() if isInit else consdecl.returnType methodName = "<init>" if isInit else consdecl.name.name intype = [ArrayPointerType(StringType())] if isMain else list() mtype = MType(intype, returnType) self.emit.printout( self.emit.emitMETHOD(methodName, mtype, not isInit, frame)) frame.enterScope(True) glenv = o # Generate code for parameter declarations if isInit: self.emit.printout( self.emit.emitVAR(frame.getNewIndex(), "this", ClassType(self.className), frame.getStartLabel(), frame.getEndLabel(), frame)) if isMain: self.emit.printout( self.emit.emitVAR(frame.getNewIndex(), "args", ArrayPointerType(StringType()), frame.getStartLabel(), frame.getEndLabel(), frame)) body = consdecl.body self.emit.printout(self.emit.emitLABEL(frame.getStartLabel(), frame)) # Generate code for statements if isInit: self.emit.printout( self.emit.emitREADVAR("this", ClassType(self.className), 0, frame)) self.emit.printout(self.emit.emitINVOKESPECIAL(frame)) #list(map(lambda x: self.visit(x, SubBody(frame, glenv)), body.member)) for x in body.member: # TODO: change to visitBody if type(x) is VarDecl: glenv = self.visit(x, SubBody(frame, glenv.sym)) else: self.visit(x, SubBody(frame, glenv.sym)) self.emit.printout(self.emit.emitLABEL(frame.getEndLabel(), frame)) if type(returnType) is VoidType: self.emit.printout(self.emit.emitRETURN(VoidType(), frame)) self.emit.printout(self.emit.emitENDMETHOD(frame)) frame.exitScope() def visitReturn(self, ast, o): ctxt = o frame = ctxt.frame retType = frame.returnType if ast.expr: exprStr, exprType = self.visit( ast.expr, Access(frame, ctxt.sym, False, True)) self.emit.printout(exprStr) if type(exprType) is IntType and type(retType) is FloatType: self.emit.printout(self.emit.emitI2F(frame)) self.emit.printout(self.emit.emitRETURN(retType, frame)) def visitFuncDecl(self, ast, o): #ast: FuncDecl #o: Any subctxt = o frame = Frame(ast.name.name, ast.returnType) self.genMETHOD(ast, subctxt, frame) paramTypes = list(map(lambda x: x.varType, ast.param)) return SubBody(None, [ Symbol(ast.name.name, MType(paramTypes, ast.returnType), CName(self.className)) ] + subctxt.sym) def visitVarDecl(self, ast, o): ctxt = o frame = ctxt.frame varName = ast.variable varType = ast.varType if frame is None: #global self.emit.printout( self.emit.emitATTRIBUTE(varName, varType, False, None)) return SubBody(None, [Symbol(varName, varType, CName(self.className))] + ctxt.sym) else: #local var index = frame.getNewIndex() var = self.emit.emitVAR(index, varName, varType, frame.getStartLabel(), frame.getEndLabel(), frame) self.emit.printout( var) # TODO: Can you move .getLabel() into Emitter? return SubBody(frame, [Symbol(varName, varType, index)] + ctxt.sym) def visitCallExpr(self, ast, o): #ast: CallExpr #o: Any ctxt = o frame = ctxt.frame nenv = ctxt.sym sym = self.lookup(ast.method.name, nenv, lambda x: x.name) cname = sym.value.value ctype = sym.mtype in_ = ("", list()) for x in ast.param: str1, typ1 = self.visit(x, Access(frame, nenv, False, True)) in_ = (in_[0] + str1, in_[1].append(typ1)) self.emit.printout(in_[0]) self.emit.printout( self.emit.emitINVOKESTATIC(cname + "/" + ast.method.name, ctype, frame)) return in_[0], ctype def visitDowhile(self, ast, o): ctxt = o frame = ctxt.frame frame.enterLoop() self.emit.printout(self.emit.emitLABEL(frame.getContinueLabel(), frame)) for st in ast.sl: # TODO: Add updating sym self.visit(st, SubBody(frame, ctxt.sym)) exp, exptyp = self.visit(ast.exp, Access(frame, ctxt.sym, False, False)) self.emit.printout(exp) self.emit.printout( self.emit.emitIFTRUE(frame.getContinueLabel(), frame)) self.emit.printout(self.emit.emitLABEL(frame.getBreakLabel(), frame)) frame.exitLoop() def visitIf(self, ast, o): ctxt = o frame = ctxt.frame elseLabel = frame.getNewLabel() endLabel = frame.getNewLabel() expStr, expType = self.visit(ast.expr, Access(frame, o.sym, False, False)) self.emit.printout(expStr) self.emit.printout(self.emit.emitIFFALSE(elseLabel, frame)) self.visit(ast.thenStmt, o) self.emit.printout(self.emit.emitGOTO(endLabel, frame)) self.emit.printout(self.emit.emitLABEL(elseLabel, frame)) if ast.elseStmt: self.visit(ast.elseStmt, o) # TODO: printout somewhere?? self.emit.printout(self.emit.emitLABEL(endLabel, frame)) def visitFor(self, ast, o): # expr1:Expr # expr2:Expr # expr3:Expr # loop:Stmt ctxt = o frame = ctxt.frame frame.enterLoop() exp1, exp1typ = self.visit(ast.expr1, Access(frame, ctxt.sym, False, False)) self.emit.printout(self.emit.emitLABEL(frame.getContinueLabel(), frame)) exp2, exp2typ = self.visit(ast.expr2, Access(frame, ctxt.sym, False, False)) self.emit.printout(exp2) self.emit.printout(self.emit.emitIFFALSE(frame.getBreakLabel(), frame)) # loop self.visit(ast.loop, ctxt) #TODO: ctxt Correct? #list(map(lambda x: self.visit(x, SubBody(frame, ctxt.sym)), ast.loop)) # from Jim #exp3 exp3, exp3typ = self.visit(ast.expr3, o) self.emit.printout(self.emit.emitGOTO(frame.getContinueLabel(), frame)) self.emit.printout(self.emit.emitLABEL(frame.getBreakLabel(), frame)) frame.exitLoop() # evaluate expr1 # label1 # evaluate expr2 # if false, jump to label 2 # evaluate loop # evaluate expr 3 # goto label1 # label 2 def visitBreak(self, ast, o): frame = o.frame self.emit.printout(self.emit.emitGOTO(frame.getBreakLabel(), frame)) def visitContinue(self, ast, o): frame = o.frame self.emit.printout(self.emit.emitGOTO(frame.getContinueLabel(), frame)) def visitIntLiteral(self, ast, o): #ast: IntLiteral #o: Any ctxt = o frame = ctxt.frame return self.emit.emitPUSHICONST(ast.value, frame), IntType() def visitFloatLiteral(self, ast, o): #ast: FloatLiteral #o: Any ctxt = o frame = ctxt.frame return self.emit.emitPUSHFCONST(str(ast.value), frame), FloatType() def visitBooleanLiteral(self, ast, o): ctxt = o frame = ctxt.frame return self.emit.emitPUSHICONST(str(ast.value).lower(), frame), BoolType() def visitStringLiteral(self, ast, o): ctxt = o frame = ctxt.frame return self.emit.emitPUSHCONST('"' + ast.value + '"', StringType(), frame), BoolType() def visitUnaryOp(self, ast, o): # TODO: [] needed? ctxt = o frame = ctxt.frame operator = ast.op expStr, expType = self.visit(ast.body, o) if operator == '-': return expStr + self.emit.emitNEGOP(expType, frame), expType if operator == '!': return expStr + self.emit.emitNOT(BoolType(), frame), expType def visitBinaryOp(self, ast, o): ctxt = o frame = ctxt.frame if ast.op == "=": return self.visitAssignment(ast, o) if ast.op in ["+", "-", "*", "/"]: operandStr, type_ = self.getOperands(ast.left, ast.right, o) if ast.op == "+" or ast.op == "-": operandStr += self.emit.emitADDOP(ast.op, type_, frame) else: operandStr += self.emit.emitMULOP(ast.op, type_, frame) return operandStr, type_ if ast.op in [">", "<", ">=", "<=", "==", "!="]: leftStr, leftType = self.visit(ast.left, Access(frame, o.sym, False, False)) rightStr, rightType = self.visit( ast.right, Access(frame, o.sym, False, False)) operandStr = leftStr + rightStr if type(leftType) is FloatType and type(rightType) is IntType: operandStr += self.emit.emitI2F(frame) operandStr += self.emit.emitREOP(ast.op, leftType, frame) return operandStr, BoolType() # TODO: with or without brackets?! def visitAssignment(self, ast, o): # a = b (index1 = index2) # iload_2 # dup # always leave value on stack after assignment/expression # istore_1 ctxt = o frame = ctxt.frame #this visit just for type checking _, l_ = self.visit(ast.left, Access(frame, o.sym, True, True)) rightStr, r_ = self.visit(ast.right, Access(frame, o.sym, False, False)) operandStr = rightStr leftType = type(l_) rightType = type(r_) if leftType is not rightType: if leftType is IntType and rightType is FloatType: raise Exception( "Cannot assign float to int.. But didn't we do that in StaticCheck?!" ) elif leftType is FloatType and rightType is IntType: operandStr += self.emit.emitI2F(frame) # else: # raise NotImplementedError("Supporting only Int and Float atm") # cannot use this because it breaks genMETHOD. lol. # duplicate result of assignment so it stays after storing # get store cell leftStr, leftType = self.visit(ast.left, Access(frame, o.sym, True, False)) operandStr += leftStr # TODO: CHECK: deleted "self.emit.emitDUP(frame) + " before leftStr so Code works.. Does it get dup'd elsewhere? self.emit.printout(operandStr) return operandStr, leftType def visitId(self, ast, o): frame = o.frame symbols = o.sym isFirst = o.isFirst isLeft = o.isLeft id_ = self.lookup(ast.name, symbols, lambda x: x.name) type_ = id_.mtype if type(id_.value) is CName: name = self.className + "/" + id_.name if isLeft: if isFirst: #just for type checking, NO emit here x = "", type_ return x # find id in symbols else: return self.emit.emitPUTSTATIC( name, type_, frame), type_ # find id, store else: return self.emit.emitGETSTATIC( name, type_, frame), type_ #find id in symbols, load index else: #local name = id_.name index = id_.value if isLeft: if isFirst: #just for type checking, NO emit here x = "", type_ return x # find id in symbols else: return self.emit.emit( name, type_, index, frame ), type_ # find id, store # TODO: Jim has writeVAR func else: return self.emit.emitREADVAR( name, type_, index, frame), type_ #find id in symbols, load index def getOperands(self, lOp, rOp, o): frame = o.frame lStr, l_ = self.visit(lOp, Access(frame, o.sym, False, False)) rStr, r_ = self.visit(rOp, Access(frame, o.sym, False, False)) lType = type(l_) rType = type(r_) if lType is rType: return lStr + rStr, lType elif lType is FloatType and rType is IntType: return lStr + rStr + self.emit.emitI2F( frame), FloatType #TODO: delete () again (move to Emitter) elif lType is IntType and rType is FloatType: return lStr + self.emit.emitI2F(frame) + rStr, FloatType else: raise Exception("Should never come here")
class Renderer: """rendering the particle system """ def __init__(self): self.t = 0.0 self.t = 0 self.x = 0.0 self.y = 0 self.z = 0 self.scale = 1.0 self.rz = 0.0 #initialise glut glutInit(sys.argv) glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH) self.width = 1000 self.height = 1000 self.aspect = self.width / float(self.height) glutInitWindowSize(1000, 1000) glutCreateWindow("The return of the Bunny") self.init() #initialize GL glutReshapeFunc(self.reshape) glutDisplayFunc(self.display) glutKeyboardFunc(self.keyboard) #glutSpecialFunc(self.glutSpecialKey) # load all the required textures here self.texid_sawblade = glutils.loadTexture('../assets/sawblade.jpg') self.texid_ground = glutils.loadTexture('../assets/ground_tile.jpg') self.texid_slab = glutils.loadTexture('../assets/slab.jpg') self.texid_star = glutils.loadTextureWithTransparency( '../assets/new_spark2.png') self.texid_cube = glutils.loadTexture('../assets/wood.jpg') self.texid_cone = glutils.loadTexture('../assets/blue.jpg') self.texid_sphere = glutils.loadTextureWithTransparency( '../assets/sphere.png') self.texid_bunny = glutils.loadTextureWithTransparency( '../assets/bunny.png') #create an emitter for the particle system self.emitter = Emitter(self.texid_star) self.frame = 0 self.time = 0 self.timebase = 0 glutMainLoop() def keyboard(self, key, x, y): """ Key controls -> Move around the scene, make objects dissapear """ if (key == 'Q'): self.x += 0.3 glutPostRedisplay() elif (key == 'q'): self.x -= 0.3 glutPostRedisplay() elif (key == 'E'): self.y += 0.3 glutPostRedisplay() elif (key == 'e'): self.y -= 0.3 glutPostRedisplay() elif (key == 'Z'): self.z += 0.3 glutPostRedisplay() elif (key == 'z'): self.z -= 0.3 glutPostRedisplay() elif (key == 's'): self.scale -= 0.3 glutPostRedisplay() elif (key == 'S'): self.scale += 0.3 glutPostRedisplay() elif (key == 'y'): #add shpere to the scene globals.obstacles_in_scene[0] = 1 elif (key == 'Y'): #remove shpere from the scene globals.obstacles_in_scene[0] = 0 elif (key == 'u'): #add cone to the scene globals.obstacles_in_scene[1] = 1 elif (key == 'U'): #remove cone from the scene globals.obstacles_in_scene[1] = 0 elif (key == 'i'): #add cube to the scene globals.obstacles_in_scene[2] = 1 elif (key == 'I'): #remove cube from the scene globals.obstacles_in_scene[2] = 0 elif (key == 'o'): #add bunny to the scene globals.obstacles_in_scene[3] = 1 elif (key == 'O'): #remove bunny from the scene globals.obstacles_in_scene[3] = 0 #handles window resize events def reshape(self, w, h): self.width = w self.height = h self.aspect = w / float(h) glViewport(0, 0, w, h) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(-3.0, 10.0, -7, 7, -100.0, 100.0) #gluPerspective(45.0, float(self.width)/float(self.height), 0.1, 100.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() #set initial state def init(self): self.t = 0.0 glClearColor(0, 0, 0, 0) glEnable(GL_DEPTH_TEST) glShadeModel(GL_SMOOTH) lightAmb = [1.0, 1.0, 1.0, 1.0] lightAmb1 = [1.0, 1.0, 0.0, 1.0] lightDifAndSpec = [1.0, 1.0, 1.0, 1.0] globAmb = [2, 2, 2, 1.0] headlightDiffuse = [0.5, 0.5, 0, 1] glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb) glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDifAndSpec) glLightfv(GL_LIGHT0, GL_SPECULAR, lightDifAndSpec) glEnable(GL_LIGHT0) self.sawblade = globals.sawblade self.ground = globals.ground self.slab = globals.slab self.sphere = globals.sphere self.cube = globals.cube self.cone = globals.cone self.bunny = globals.bunny glEnable(GL_LIGHTING) glEnable(GL_TEXTURE_2D) def display(self): # timer to dictate the emission of particles self.t += 10 #incrementing time in each iteration by a constant value of 10 units. if (self.t % 1 == 0): self.emitter.emit() self.frame += 1 self.time = glutGet(GLUT_ELAPSED_TIME) if (self.time - self.timebase > 1000): print "FPS:%4.2f", self.frame * 1000.0 / (self.time - self.timebase) self.timebase = self.time self.frame = 0 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) #variable to rotate the saw blade self.rz += 2.0 glClearColor(0, 0, 0, 0) glPushMatrix() glLoadIdentity() gluLookAt(0, 0, -5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0) glRotatef(self.x, 1, 0, 0) glRotatef(self.y, 0, 1, 0) glRotatef(self.z, 0, 0, 1) glScalef(self.scale, self.scale, self.scale) # texture all the obstacles in the scene glBindTexture(GL_TEXTURE_2D, self.texid_slab) self.slab.draw() glBindTexture(GL_TEXTURE_2D, self.texid_ground) self.ground.draw() glBindTexture(GL_TEXTURE_2D, self.texid_sawblade) glPushMatrix() glTranslatef(self.sawblade.getCentroidX(), self.sawblade.getCentroidY(), self.sawblade.getCentroidZ()) glRotatef(self.rz, 0, 0, 1) glTranslatef(-self.sawblade.getCentroidX(), -self.sawblade.getCentroidY(), -self.sawblade.getCentroidZ()) self.sawblade.draw() glPopMatrix() if (globals.obstacles_in_scene[0] == 1): glBindTexture(GL_TEXTURE_2D, self.texid_sphere) self.sphere.draw() if (globals.obstacles_in_scene[2] == 1): glBindTexture(GL_TEXTURE_2D, self.texid_cube) self.cube.draw() if (globals.obstacles_in_scene[1] == 1): glBindTexture(GL_TEXTURE_2D, self.texid_cone) self.cone.draw() if (globals.obstacles_in_scene[3] == 1): glBindTexture(GL_TEXTURE_2D, self.texid_bunny) self.bunny.draw() glDisable(GL_LIGHTING) #Draw the particles i = 0 while (i < len(globals.all_particles)): status = globals.all_particles[i].draw( ) # Decide if the particle is dead or alive if (status == False): globals.all_particles = numpy.delete(globals.all_particles, i) else: i += 1 glEnable(GL_LIGHTING) glPopMatrix() glutSwapBuffers() time.sleep(0.00005) glutPostRedisplay()