Example #1
0
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")
Example #2
0
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()