Example #1
0
class Emitter():
    def __init__(self, filename):
        self.filename = filename
        self.buff = list()
        self.jvm = JasminCode()

    def getJVMType(self, inType):
        typeIn = type(inType)
        if typeIn is IntType:
            return "I"
        elif typeIn is FloatType:
            return "F"
        elif typeIn is StringType:
            return "Ljava/lang/String;"
        elif typeIn is BoolType:
            return "Z"
        elif typeIn is VoidType:
            return "V"
        elif typeIn is ArrayPointerType:
            return "[" + self.getJVMType(inType.eleType)
        elif typeIn is MType:
            return "(" + "".join(
                list(map(lambda x: self.getJVMType(x),
                         inType.partype))) + ")" + self.getJVMType(
                             inType.rettype)
        elif typeIn is cgen.ClassType:
            return "L" + inType.cname + ";"

    def getFullType(inType):
        typeIn = type(inType)
        if typeIn is IntType:
            return "int"
        elif typeIn is StringType:
            return "java/lang/String"
        elif typeIn is VoidType:
            return "void"

    def emitPUSHICONST(self, in_, frame):
        #in: Int or Sring
        #frame: Frame

        frame.push()
        if type(in_) is int:
            i = in_
            if i >= -1 and i <= 5:
                return self.jvm.emitICONST(i)
            elif i >= -128 and i <= 127:
                return self.jvm.emitBIPUSH(i)
            elif i >= -32768 and i <= 32767:
                return self.jvm.emitSIPUSH(i)
        elif type(in_) is str:
            if in_ == "true":
                return self.emitPUSHICONST(1, frame)
            elif in_ == "false":
                return self.emitPUSHICONST(0, frame)
            else:
                return self.emitPUSHICONST(int(in_), frame)

    def emitPUSHFCONST(self, in_, frame):
        #in_: String
        #frame: Frame

        f = float(in_)
        frame.push()
        rst = "{0:.4f}".format(f)
        if rst == "0.0" or rst == "1.0" or rst == "2.0":
            return self.jvm.emitFCONST(rst)
        else:
            return self.jvm.emitLDC(in_)

    ''' 
    *    generate code to push a constant onto the operand stack.
    *    @param in the lexeme of the constant
    *    @param typ the type of the constant
    '''

    def emitPUSHCONST(self, in_, typ, frame):
        #in_: String
        #typ: Type
        #frame: Frame

        if type(typ) is IntType:
            return self.emitPUSHICONST(in_, frame)
        elif type(typ) is StringType:
            frame.push()
            return self.jvm.emitLDC(in_)
        else:
            raise IllegalOperandException(in_)

    ##############################################################

    def emitALOAD(self, in_, frame):
        #in_: Type
        #frame: Frame
        #..., arrayref, index, value -> ...

        frame.pop()
        if type(in_) is IntType:
            return self.jvm.emitIALOAD()
        elif type(in_) is ArrayPointerType or type(
                in_) is cgen.ClassType or type(in_) is StringType:
            return self.jvm.emitAALOAD()
        else:
            raise IllegalOperandException(str(in_))

    def emitASTORE(self, in_, frame):
        #in_: Type
        #frame: Frame
        #..., arrayref, index, value -> ...

        frame.pop()
        frame.pop()
        frame.pop()
        if type(in_) is IntType:
            return self.jvm.emitIASTORE()
        elif type(in_) is ArrayPointerType or type(in_) is ClassType or type(
                in_) is StringType:
            return self.jvm.emitAASTORE()
        else:
            raise IllegalOperandException(str(in_))

    '''    generate the var directive for a local variable.
    *   @param in the index of the local variable.
    *   @param varName the name of the local variable.
    *   @param inType the type of the local variable.
    *   @param fromLabel the starting label of the scope where the variable is active.
    *   @param toLabel the ending label  of the scope where the variable is active.
    '''

    def emitVAR(self, in_, varName, inType, fromLabel, toLabel, frame):
        #in_: Int
        #varName: String
        #inType: Type
        #fromLabel: Int
        #toLabel: Int
        #frame: Frame

        return self.jvm.emitVAR(in_, varName, self.getJVMType(inType),
                                fromLabel, toLabel)

    def emitREADVAR(self, name, inType, index, frame):
        #name: String
        #inType: Type
        #index: Int
        #frame: Frame
        #... -> ..., value

        frame.push()
        if type(inType) is IntType:
            return self.jvm.emitILOAD(index)
        elif type(inType) is ArrayPointerType or type(
                inType) is cgen.ClassType or type(inType) is StringType:
            return self.jvm.emitALOAD(index)
        else:
            raise IllegalOperandException(name)

    ''' generate the second instruction for array cell access
    *
    '''

    def emitREADVAR2(self, name, typ, frame):
        #name: String
        #typ: Type
        #frame: Frame
        #... -> ..., value

        #frame.push()
        raise IllegalOperandException(name)

    '''
    *   generate code to pop a value on top of the operand stack and store it to a block-scoped variable.
    *   @param name the symbol entry of the variable.
    '''

    def emitWRITEVAR(self, name, inType, index, frame):
        #name: String
        #inType: Type
        #index: Int
        #frame: Frame
        #..., value -> ...

        frame.pop()

        if type(inType) is IntType:
            return self.jvm.emitISTORE(index)
        elif type(inType) is ArrayPointerType or type(
                inType) is cgen.ClassType or type(inType) is StringType:
            return self.jvm.emitASTORE(index)
        else:
            raise IllegalOperandException(name)

    ''' generate the second instruction for array cell access
    *
    '''

    def emitWRITEVAR2(self, name, typ, frame):
        #name: String
        #typ: Type
        #frame: Frame
        #..., value -> ...

        #frame.push()
        raise IllegalOperandException(name)

    ''' generate the field (static) directive for a class mutable or immutable attribute.
    *   @param lexeme the name of the attribute.
    *   @param in the type of the attribute.
    *   @param isFinal true in case of constant; false otherwise
    '''

    def emitATTRIBUTE(self, lexeme, in_, isFinal, value):
        #lexeme: String
        #in_: Type
        #isFinal: Boolean
        #value: String

        return self.jvm.emitSTATICFIELD(lexeme, self.getJVMType(in_), false)

    def emitGETSTATIC(self, lexeme, in_, frame):
        #lexeme: String
        #in_: Type
        #frame: Frame

        frame.push()
        return self.jvm.emitGETSTATIC(lexeme, self.getJVMType(in_))

    def emitPUTSTATIC(self, lexeme, in_, frame):
        #lexeme: String
        #in_: Type
        #frame: Frame

        frame.pop()
        return self.jvm.emitPUTSTATIC(lexeme, self.getJVMType(in_))

    def emitGETFIELD(self, lexeme, in_, frame):
        #lexeme: String
        #in_: Type
        #frame: Frame

        return self.jvm.emitGETFIELD(lexeme, self.getJVMType(in_))

    def emitPUTFIELD(self, lexeme, in_, frame):
        #lexeme: String
        #in_: Type
        #frame: Frame

        frame.pop()
        frame.pop()
        return self.jvm.emitPUTFIELD(lexeme, self.getJVMType(in_))

    ''' generate code to invoke a static method
    *   @param lexeme the qualified name of the method(i.e., class-name/method-name)
    *   @param in the type descriptor of the method.
    '''

    def emitINVOKESTATIC(self, lexeme, in_, frame):
        #lexeme: String
        #in_: Type
        #frame: Frame

        typ = in_
        list(map(lambda x: frame.pop(), typ.partype))
        if not type(typ.rettype) is VoidType:
            frame.push()
        return self.jvm.emitINVOKESTATIC(lexeme, self.getJVMType(in_))

    ''' generate code to invoke a special method
    *   @param lexeme the qualified name of the method(i.e., class-name/method-name)
    *   @param in the type descriptor of the method.
    '''

    def emitINVOKESPECIAL(self, frame, lexeme=None, in_=None):
        #lexeme: String
        #in_: Type
        #frame: Frame

        if not lexeme is None and not in_ is None:
            typ = in_
            list(map(lambda x: frame.pop(), typ.partype))
            frame.pop()
            if not type(typ.rettype) is VoidType:
                frame.push()
            return self.jvm.emitINVOKESPECIAL(lexeme, self.getJVMType(in_))
        elif lexeme is None and in_ is None:
            frame.pop()
            return self.jvm.emitINVOKESPECIAL()

    ''' generate code to invoke a virtual method
    * @param lexeme the qualified name of the method(i.e., class-name/method-name)
    * @param in the type descriptor of the method.
    '''

    def emitINVOKEVIRTUAL(self, lexeme, in_, frame):
        #lexeme: String
        #in_: Type
        #frame: Frame

        typ = in_
        list(map(lambda x: frame.pop(), typ.partype))
        frame.pop()
        if not type(typ) is VoidType:
            frame.push()
        return self.jvm.emitINVOKEVIRTUAL(lexeme, self.getJVMType(in_))

    '''
    *   generate ineg, fneg.
    *   @param in the type of the operands.
    '''

    def emitNEGOP(self, in_, frame):
        #in_: Type
        #frame: Frame
        #..., value -> ..., result

        if type(in_) is IntType:
            return self.jvm.emitINEG()
        else:
            return self.jvm.emitFNEG()

    def emitNOT(self, in_, frame):
        #in_: Type
        #frame: Frame

        label1 = frame.getNewLabel()
        label2 = frame.getNewLabel()
        result = list()
        result.append(emitIFTRUE(label1, frame))
        result.append(emitPUSHCONST("true", in_, frame))
        result.append(emitGOTO(label2, frame))
        result.append(emitLABEL(label1, frame))
        result.append(emitPUSHCONST("false", in_, frame))
        result.append(emitLABEL(label2, frame))
        return ''.join(result)

    '''
    *   generate iadd, isub, fadd or fsub.
    *   @param lexeme the lexeme of the operator.
    *   @param in the type of the operands.
    '''

    def emitADDOP(self, lexeme, in_, frame):
        #lexeme: String
        #in_: Type
        #frame: Frame
        #..., value1, value2 -> ..., result

        frame.pop()
        if lexeme == "+":
            if type(in_) is IntType:
                return self.jvm.emitIADD()
            else:
                return self.jvm.emitFADD()
        else:
            if type(in_) is IntType:
                return self.jvm.emitISUB()
            else:
                return self.jvm.emitFSUB()

    '''
    *   generate imul, idiv, fmul or fdiv.
    *   @param lexeme the lexeme of the operator.
    *   @param in the type of the operands.
    '''

    def emitMULOP(self, lexeme, in_, frame):
        #lexeme: String
        #in_: Type
        #frame: Frame
        #..., value1, value2 -> ..., result

        frame.pop()
        if lexeme == "*":
            if type(in_) is IntType:
                return self.jvm.emitIMUL()
            else:
                return self.jvm.emitFMUL()
        else:
            if type(in_) is IntType:
                return self.jvm.emitIDIV()
            else:
                return self.jvm.emitFDIV()

    def emitDIV(self, frame):
        #frame: Frame

        frame.pop()
        return self.jvm.emitIDIV()

    def emitMOD(self, frame):
        #frame: Frame

        frame.pop()
        return self.jvm.emitIREM()

    '''
    *   generate iand
    '''

    def emitANDOP(self, frame):
        #frame: Frame

        frame.pop()
        return self.jvm.emitIAND()

    '''
    *   generate ior
    '''

    def emitOROP(self, frame):
        #frame: Frame

        frame.pop()
        return self.jvm.emitIOR()

    def emitREOP(self, op, in_, frame):
        #op: String
        #in_: Type
        #frame: Frame
        #..., value1, value2 -> ..., result

        result = list()
        labelF = frame.getNewLabel()
        labelO = frame.getNewLabel()

        frame.pop()
        frame.pop()
        if op == ">":
            result.append(self.jvm.emitIFICMPLE(labelF))
        elif op == ">=":
            result.append(self.jvm.emitIFICMPLT(labelF))
        elif op == "<":
            result.append(self.jvm.emitIFICMPGE(labelF))
        elif op == "<=":
            result.append(self.jvm.emitIFICMPGT(labelF))
        elif op == "!=":
            result.append(self.jvm.emitIFICMPEQ(labelF))
        elif op == "==":
            result.append(self.jvm.emitIFICMPNE(labelF))
        result.append(self.emitPUSHCONST("1", IntType(), frame))
        frame.pop()
        result.append(self.emitGOTO(labelO, frame))
        result.append(self.emitLABEL(labelF, frame))
        result.append(self.emitPUSHCONST("0", IntType(), frame))
        result.append(self.emitLABEL(labelO, frame))
        return ''.join(result)

    def emitRELOP(self, op, in_, trueLabel, falseLabel, frame):
        #op: String
        #in_: Type
        #trueLabel: Int
        #falseLabel: Int
        #frame: Frame
        #..., value1, value2 -> ..., result

        result = list()

        frame.pop()
        frame.pop()
        if op == ">":
            result.append(self.jvm.emitIFICMPLE(falseLabel))
            result.append(self.emitGOTO(trueLabel))
        elif op == ">=":
            result.append(self.jvm.emitIFICMPLT(falseLabel))
        elif op == "<":
            result.append(self.jvm.emitIFICMPGE(falseLabel))
        elif op == "<=":
            result.append(self.jvm.emitIFICMPGT(falseLabel))
        elif op == "!=":
            result.append(self.jvm.emitIFICMPEQ(falseLabel))
        elif op == "==":
            result.append(self.jvm.emitIFICMPNE(falseLabel))
        result.append(self.jvm.emitGOTO(trueLabel))
        return ''.join(result)

    '''   generate the method directive for a function.
    *   @param lexeme the qualified name of the method(i.e., class-name/method-name).
    *   @param in the type descriptor of the method.
    *   @param isStatic <code>true</code> if the method is static; <code>false</code> otherwise.
    '''

    def emitMETHOD(self, lexeme, in_, isStatic, frame):
        #lexeme: String
        #in_: Type
        #isStatic: Boolean
        #frame: Frame

        return self.jvm.emitMETHOD(lexeme, self.getJVMType(in_), isStatic)

    '''   generate the end directive for a function.
    '''

    def emitENDMETHOD(self, frame):
        #frame: Frame

        buffer = list()
        buffer.append(self.jvm.emitLIMITSTACK(frame.getMaxOpStackSize()))
        buffer.append(self.jvm.emitLIMITLOCAL(frame.getMaxIndex()))
        buffer.append(self.jvm.emitENDMETHOD())
        return ''.join(buffer)

    def getConst(self, ast):
        #ast: Literal
        if type(ast) is IntLiteral:
            return (str(ast.value), IntType())

    '''   generate code to initialize a local array variable.<p>
    *   @param index the index of the local variable.
    *   @param in the type of the local array variable.
    '''
    '''   generate code to initialize local array variables.
    *   @param in the list of symbol entries corresponding to local array variable.    
    '''
    '''   generate code to jump to label if the value on top of operand stack is true.<p>
    *   ifgt label
    *   @param label the label where the execution continues if the value on top of stack is true.
    '''

    def emitIFTRUE(self, label, frame):
        #label: Int
        #frame: Frame

        frame.pop()
        return self.jvm.emitIFGT(label)

    '''
    *   generate code to jump to label if the value on top of operand stack is false.<p>
    *   ifle label
    *   @param label the label where the execution continues if the value on top of stack is false.
    '''

    def emitIFFALSE(self, label, frame):
        #label: Int
        #frame: Frame

        frame.pop()
        return self.jvm.emitIFLE(label)

    def emitIFICMPGT(self, label, frame):
        #label: Int
        #frame: Frame

        frame.pop()
        return self.jvm.emitIFICMPGT(label)

    def emitIFICMPLT(self, label, frame):
        #label: Int
        #frame: Frame

        frame.pop()
        return self.jvm.emitIFICMPLT(label)

    '''   generate code to duplicate the value on the top of the operand stack.<p>
    *   Stack:<p>
    *   Before: ...,value1<p>
    *   After:  ...,value1,value1<p>
    '''

    def emitDUP(self, frame):
        #frame: Frame

        frame.push()
        return self.jvm.emitDUP()

    def emitPOP(self, frame):
        #frame: Frame

        frame.pop()
        return self.jvm.emitPOP()

    '''   generate code to exchange an integer on top of stack to a floating-point number.
    '''

    def emitI2F(self, frame):
        #frame: Frame

        return self.jvm.emitI2F()

    ''' generate code to return.
    *   <ul>
    *   <li>ireturn if the type is IntegerType or BooleanType
    *   <li>freturn if the type is RealType
    *   <li>return if the type is null
    *   </ul>
    *   @param in the type of the returned expression.
    '''

    def emitRETURN(self, in_, frame):
        #in_: Type
        #frame: Frame

        if type(in_) is IntType:
            frame.pop()
            return self.jvm.emitIRETURN()
        elif type(in_) is VoidType:
            return self.jvm.emitRETURN()

    ''' generate code that represents a label	
    *   @param label the label
    *   @return code Label<label>:
    '''

    def emitLABEL(self, label, frame):
        #label: Int
        #frame: Frame

        return self.jvm.emitLABEL(label)

    ''' generate code to jump to a label	
    *   @param label the label
    *   @return code goto Label<label>
    '''

    def emitGOTO(self, label, frame):
        #label: Int
        #frame: Frame

        return self.jvm.emitGOTO(label)

    ''' generate some starting directives for a class.<p>
    *   .source MPC.CLASSNAME.java<p>
    *   .class public MPC.CLASSNAME<p>
    *   .super java/lang/Object<p>
    '''

    def emitPROLOG(self, name, parent):
        #name: String
        #parent: String

        result = list()
        result.append(self.jvm.emitSOURCE(name + ".java"))
        result.append(self.jvm.emitCLASS("public " + name))
        result.append(
            self.jvm.emitSUPER("java/land/Object" if parent == "" else parent))
        return ''.join(result)

    def emitLIMITSTACK(self, num):
        #num: Int

        return self.jvm.emitLIMITSTACK(num)

    def emitLIMITLOCAL(self, num):
        #num: Int

        return self.jvm.emitLIMITLOCAL(num)

    def emitEPILOG(self):
        file = open(self.filename, "w")
        file.write(''.join(self.buff))
        file.close()

    ''' print out the code to screen
    *   @param in the code to be printed out
    '''

    def printout(self, in_):
        #in_: String

        self.buff.append(in_)

    def clearBuff(self):
        self.buff.clear()
Example #2
0
class Emitter():
	def __init__(self, filename):
		self.filename = filename
		self.buff = list()
		self.jvm = JasminCode()

	def getJVMType(self, inType):
		typeIn = type(inType)
		if typeIn is IntType:
			return "I"
		elif typeIn is FloatType:
			return "F"
		elif typeIn is BoolType:
			return "Z"
		elif typeIn is cgen.StringType:
			return "Ljava/lang/String;"
		elif typeIn is VoidType:
			return "V"
		elif typeIn is cgen.ArrayPointerType:
			return "[" + self.getJVMType(inType.eleType)
		elif typeIn is MType:
			return "(" + "".join(list(map(lambda x: self.getJVMType(x), inType.partype))) + ")" + self.getJVMType(inType.rettype)
		elif typeIn is cgen.ClassType:
			return "L" + inType.cname + ";"
		else:
			raise IllegalOperandException(str(inType))

	# def getFullType(inType):
		# typeIn = type(inType)
		# if typeIn is IntType:
			# return "int"
		# elif typeIn is cgen.StringType:
			# return "java/lang/String"
		# elif typeIn is VoidType:
			# return "void"

	def emitPUSHICONST(self, in_, frame):
		#in: Int or Sring
		#frame: Frame
		if type(in_) is int:
			frame.push();
			i = in_
			if i >= -1 and i <=5:
				return self.jvm.emitICONST(i)
			elif i >= -128 and i <= 127:
				return self.jvm.emitBIPUSH(i)
			elif i >= -32768 and i <= 32767:
				return self.jvm.emitSIPUSH(i)
			else:
				return self.jvm.emitLDC(str(i))
		elif type(in_) is str:
			if in_.lower() == "true":
				return self.emitPUSHICONST(1, frame)
			elif in_.lower() == "false":
				return self.emitPUSHICONST(0, frame)
			else:
				return self.emitPUSHICONST(int(in_), frame)

	def emitPUSHFCONST(self, in_, frame):
		#in_: String
		#frame: Frame
		f = float(in_)
		frame.push()
		if f in (0.0, 1.0, 2.0):
			rst = "{0:.1f}".format(f)
			return self.jvm.emitFCONST(rst)
		else:
			return self.jvm.emitLDC(in_)

	# generate code to push a constant onto the operand stack.
	# @param in_: the lexeme (String) of the constant
	# @param typ: the type of the constant
	def emitPUSHCONST(self, in_, typ, frame):
		#in_: String
		#typ: Type
		#frame: Frame
		if type(typ) is IntType:
			return self.emitPUSHICONST(in_, frame)
		elif type(typ) is StringType:
			frame.push()
			return self.jvm.emitLDC('"' + in_ + '"')
		else:
			raise IllegalOperandException(in_)


	################################################################
	#	Unary Operators
	################################################################

	# generate ineg, fneg.
	# @param in_: the type of the operands.
	# ..., value -> ..., result
	def emitNEGOP(self, in_, frame):
		if type(in_) is IntType:
			return self.jvm.emitINEG()
		else:
			return self.jvm.emitFNEG()

	def emitNOT(self, frame):
		label1 = frame.getNewLabel()
		label2 = frame.getNewLabel()
		result = list()
		result.append(self.emitIFTRUE(label1, frame))
		result.append(self.emitPUSHICONST("true", frame))
		result.append(self.emitGOTO(label2, frame))
		result.append(self.emitLABEL(label1, frame))
		result.append(self.emitPUSHICONST("false", frame))
		result.append(self.emitLABEL(label2, frame))
		return ''.join(result)

	################################################################
	## Binary Operators
	################################################################

	# generate iadd, isub, fadd or fsub.
	# @param lexeme: the lexeme (String) of the operator.
	# @param in_: the type of the operands.
	# ..., value1, value2 -> result
	def emitADDOP(self, lexeme, in_, frame):
		frame.pop()
		if lexeme == "+":
			if type(in_) is IntType:
				return self.jvm.emitIADD()
			else:
				return self.jvm.emitFADD()
		else:
			if type(in_) is IntType:
				return self.jvm.emitISUB()
			else:
				return self.jvm.emitFSUB()

	# generate imul, idiv, fmul or fdiv.
	# @param lexeme: the lexeme (String) of the operator.
	# @param in_: the type of the operands.
	# ..., value1, value2 -> result
	def emitMULOP(self, lexeme, in_, frame):
		frame.pop()
		if lexeme == "*":
			if type(in_) is IntType:
				return self.jvm.emitIMUL()
			else:
				return self.jvm.emitFMUL()
		else:
			if type(in_) is IntType:
				return self.jvm.emitIDIV()
			else:
				return self.jvm.emitFDIV()

	def emitDIV(self, frame):
		#frame: Frame
		frame.pop()
		return self.jvm.emitIDIV()

	def emitMOD(self, frame):
		#frame: Frame
		frame.pop()
		return self.jvm.emitIREM()

	def emitANDOP(self, frame):
		#frame: Frame
		frame.pop()
		return self.jvm.emitIAND()

	def emitOROP(self, frame):
		#frame: Frame
		frame.pop()
		return self.jvm.emitIOR()

	def emitREOP(self, op, in_, frame):
		#op: String
		#in_: Type
		#frame: Frame
		#..., value1, value2 -> ..., result
		result = list()
		labelFalse = frame.getNewLabel()
		labelOut = frame.getNewLabel()
		frame.pop()
		frame.pop()

		if type(in_) is IntType:
			if op == ">":
				result.append(self.jvm.emitIFICMPLE(labelFalse))
			elif op == ">=":
				result.append(self.jvm.emitIFICMPLT(labelFalse))
			elif op == "<":
				result.append(self.jvm.emitIFICMPGE(labelFalse))
			elif op == "<=":
				result.append(self.jvm.emitIFICMPGT(labelFalse))
			elif op == "<>":
				result.append(self.jvm.emitIFICMPEQ(labelFalse))
			elif op == "=":
				result.append(self.jvm.emitIFICMPNE(labelFalse))
		else:
			result.append(self.jvm.emitFCMPL())
			if op == ">":
				result.append(self.jvm.emitIFLE(labelFalse))
			elif op == ">=":
				result.append(self.jvm.emitIFLT(labelFalse))
			elif op == "<":
				result.append(self.jvm.emitIFGE(labelFalse))
			elif op == "<=":
				result.append(self.jvm.emitIFGT(labelFalse))
			elif op == "<>":
				result.append(self.jvm.emitIFEQ(labelFalse))
			elif op == "=":
				result.append(self.jvm.emitIFNE(labelFalse))

		result.append(self.emitPUSHCONST("1", IntType(), frame))
		result.append(self.emitGOTO(labelOut, frame))
		result.append(self.emitLABEL(labelFalse, frame))
		result.append(self.emitPUSHCONST("0", IntType(), frame))
		result.append(self.emitLABEL(labelOut, frame))
		frame.pop() # only "1" or "0"

		return ''.join(result)

	# def emitRELOP(self, op, in_, trueLabel, falseLabel, frame):
		# #op: String
		# #in_: Type
		# #trueLabel: Int
		# #falseLabel: Int
		# #frame: Frame
		# #..., value1, value2 -> ..., result
		# result = list()

		# frame.pop()
		# frame.pop()
		# if op == ">":
			# result.append(self.jvm.emitIFICMPLE(falseLabel))
		# elif op == ">=":
			# result.append(self.jvm.emitIFICMPLT(falseLabel))
		# elif op == "<":
			# result.append(self.jvm.emitIFICMPGE(falseLabel))
		# elif op == "<=":
			# result.append(self.jvm.emitIFICMPGT(falseLabel))
		# elif op == "<>":
			# result.append(self.jvm.emitIFICMPEQ(falseLabel))
		# elif op == "=":
			# result.append(self.jvm.emitIFICMPNE(falseLabel))
		# result.append(self.jvm.emitGOTO(trueLabel))
		# return ''.join(result)

	################################################################
	## Labeling and Jumping
	################################################################

	# generate code to jump to label if the value on top of operand stack is true
	# ifgt label
	# @param label: the label (Int) where the execution continues if the value on top of stack is true
	def emitIFTRUE(self, label, frame):
		frame.pop()
		return self.jvm.emitIFGT(label)

	# generate code to jump to label if the value on top of operand stack is false
	# ifle label
	# @param label: the label (Int) where the execution continues if the value on top of stack is false
	def emitIFFALSE(self, label, frame):
		frame.pop()
		return self.jvm.emitIFLE(label)

	# ..., value1, value2 -> ...
	# generate code to jump to label if value1 > value2
	# label: Int
	def emitIFICMPGT(self, label, frame):
		frame.pop()
		frame.pop()
		return self.jvm.emitIFICMPGT(label)

	# ..., value1, value2 -> ...
	# generate code to jump to label if value1 < value2
	# label: Int
	def emitIFICMPLT(self, label, frame):
		frame.pop()
		frame.pop()
		return self.jvm.emitIFICMPLT(label)

	# @return code goto Label<label>
	# @param label: Int
	def emitGOTO(self, label, frame):
		return self.jvm.emitGOTO(str(label))

	# @return code Label<label>
	# @param label: Int
	def emitLABEL(self, label, frame):
		return self.jvm.emitLABEL(label)

	################################################################
	## No Arrays
	################################################################

	# def emitALOAD(self, in_, frame):
		# #in_: Type
		# #frame: Frame
		# #..., arrayref, index, value -> ...
		
		# frame.pop()
		# if type(in_) is IntType:
			# return self.jvm.emitIALOAD()
		# elif type(in_) is cgen.ArrayPointerType or type(in_) is cgen.ClassType or type(in_) is StringType:
			# return self.jvm.emitAALOAD()
		# else:
			# raise IllegalOperandException(str(in_))

	# def emitASTORE(self, in_, frame):
		# #in_: Type
		# #frame: Frame
		# #..., arrayref, index, value -> ...
		
		# frame.pop()
		# frame.pop()
		# frame.pop()
		# if type(in_) is IntType:
			# return self.jvm.emitIASTORE()
		# elif type(in_) is cgen.ArrayPointerType or type(in_) is cgen.ClassType or type(in_) is StringType:
			# return self.jvm.emitAASTORE()
		# else:
			# raise IllegalOperandException(str(in_))

	################################################################
	## Declarations
	################################################################

	# generate the var directive for a local variable.
	# @param in_: Int the index of the local variable.
	# @param varName: String the name of the local variable.
	# @param inType: Type the type of the local variable.
	# @param fromLabel: Int the starting label of the scope where the variable is active.
	# @param toLabel: Int the ending label of the scope where the variable is active.
	def emitVAR(self, in_, varName, inType, fromLabel, toLabel, frame):
		return self.jvm.emitVAR(in_, varName, self.getJVMType(inType), fromLabel, toLabel)

	# generate the field (static) directive for a class mutable or immutable attribute.
	# @param lexeme: the name of the attribute.
	# @param in_: the type of the attribute.
	# @param isFinal: true in case of constant, false otherwise
	def emitATTRIBUTE(self, lexeme, in_, isFinal, value):
		return self.jvm.emitSTATICFIELD(lexeme, self.getJVMType(in_), False)

	# iload, fload, aload
	# push a value to stack
	def emitREADVAR(self, name, inType, index, frame):
		frame.push()
		if type(inType) in (IntType, BoolType):
			return self.jvm.emitILOAD(index)
		elif type(inType) is FloatType:
			return self.jvm.emitFLOAD(index)
		elif type(inType) is cgen.ArrayPointerType or type(inType) is cgen.ClassType or type(inType) is StringType:
			return self.jvm.emitALOAD(index)
		else:
			raise IllegalOperandException(name)

	# istore, fstore, astore
	# pop a value from stack
	def emitWRITEVAR(self, name, inType, index, frame):
		frame.pop()
		if type(inType) in (IntType, BoolType):
			return self.jvm.emitISTORE(index)
		elif type(inType) is FloatType:
			return self.jvm.emitFSTORE(index)
		elif type(inType) is cgen.ArrayPointerType or type(inType) is cgen.ClassType or type(inType) is StringType:
			return self.jvm.emitASTORE(index)
		else:
			raise IllegalOperandException(name)

	# getstatic
	# push a value to stack
	def emitGETSTATIC(self, lexeme, in_, frame):
		frame.push()
		return self.jvm.emitGETSTATIC(lexeme, self.getJVMType(in_))

	# putstatic
	# pop a value from stack
	def emitPUTSTATIC(self, lexeme, in_, frame):
		frame.pop()
		return self.jvm.emitPUTSTATIC(lexeme, self.getJVMType(in_))

	# def emitGETFIELD(self, lexeme, in_, frame):
		# frame.push()
		# return self.jvm.emitGETFIELD(lexeme, self.getJVMType(in_))

	# def emitPUTFIELD(self, lexeme, in_, frame):
		# frame.pop()
		# return self.jvm.emitPUTFIELD(lexeme, self.getJVMType(in_))

	################################################################
	## Functions
	################################################################

	# generate code to invoke a static method
	# @param lexeme the qualified name of the method(i.e., class-name/method-name)
	# @param in_ the type descriptor of the method.
	def emitINVOKESTATIC(self, lexeme, in_, frame):
		mtype = in_
		list(map(lambda x: frame.pop(), mtype.partype))
		if not type(mtype.rettype) is VoidType:
			frame.push()
		return self.jvm.emitINVOKESTATIC(lexeme, self.getJVMType(in_))

	# return, ireturn, freturn
	def emitRETURN(self, in_, frame):
		if type(in_) in (IntType, BoolType):
			frame.pop()
			return self.jvm.emitIRETURN()
		elif type(in_) is FloatType:
			frame.pop()
			return self.jvm.emitFRETURN()
		elif type(in_) is StringType:
			frame.pop()
			return self.jvm.emitARETURN()
		elif type(in_) is VoidType:
			return self.jvm.emitRETURN()
		else:
			raise IllegalOperandException(str(in_))

	# remove the last occurrence of "ele" in the list "buff"
	def reversedremove(self, ele):
		if ele in self.buff:
			del self.buff[-self.buff[::-1].index(ele) - 1]

################################################################################################################################

	''' generate code to invoke a special method
	*	@param lexeme the qualified name of the method(i.e., class-name/method-name)
	*	@param in the type descriptor of the method.
	'''
	def emitINVOKESPECIAL(self, frame, lexeme=None, in_=None):
		#lexeme: String
		#in_: Type
		#frame: Frame

		if not lexeme is None and not in_ is None:
			typ = in_
			list(map(lambda x: frame.pop(), typ.partype))
			frame.pop()
			if not type(typ.rettype) is VoidType:
				frame.push()
			return self.jvm.emitINVOKESPECIAL(lexeme, self.getJVMType(in_))
		elif lexeme is None and in_ is None:
			frame.pop()
			return self.jvm.emitINVOKESPECIAL()

	''' generate code to invoke a virtual method
	* @param lexeme the qualified name of the method(i.e., class-name/method-name)
	* @param in the type descriptor of the method.
	'''
	def emitINVOKEVIRTUAL(self, lexeme, in_, frame):
		#lexeme: String
		#in_: Type
		#frame: Frame

		typ = in_
		list(map(lambda x: frame.pop(), typ.partype))
		frame.pop()
		if not type(typ) is VoidType:
			frame.push()
		return self.jvm.emitINVOKEVIRTUAL(lexeme, self.getJVMType(in_))


	'''	  generate the method directive for a function.
	*	@param lexeme the qualified name of the method(i.e., class-name/method-name).
	*	@param in the type descriptor of the method.
	*	@param isStatic <code>true</code> if the method is static; <code>false</code> otherwise.
	'''

	def emitMETHOD(self, lexeme, in_, isStatic, frame):
		#lexeme: String
		#in_: Type
		#isStatic: Boolean
		#frame: Frame

		return self.jvm.emitMETHOD(lexeme, self.getJVMType(in_), isStatic)

	'''	  generate the end directive for a function.
	'''
	def emitENDMETHOD(self, frame):
		#frame: Frame

		buffer = list()
		buffer.append(self.jvm.emitLIMITSTACK(frame.getMaxOpStackSize()))
		buffer.append(self.jvm.emitLIMITLOCAL(frame.getMaxIndex()))
		buffer.append(self.jvm.emitENDMETHOD())
		return ''.join(buffer)

	def getConst(self, ast):
		#ast: Literal
		if type(ast) is IntLiteral:
			return (str(ast.value), IntType())

	'''	  generate code to initialize a local array variable.<p>
	*	@param index the index of the local variable.
	*	@param in the type of the local array variable.
	'''

	'''	  generate code to initialize local array variables.
	*	@param in the list of symbol entries corresponding to local array variable.	   
	'''

	'''	  generate code to duplicate the value on the top of the operand stack.<p>
	*	Stack:<p>
	*	Before: ...,value1<p>
	*	After:	...,value1,value1<p>
	'''
	def emitDUP(self, frame):
		#frame: Frame

		frame.push()
		return self.jvm.emitDUP()

	def emitPOP(self, frame):
		#frame: Frame

		frame.pop()
		return self.jvm.emitPOP()

	'''	  generate code to exchange an integer on top of stack to a floating-point number.
	'''
	def emitI2F(self, frame):
		#frame: Frame

		return self.jvm.emitI2F()

	''' generate some starting directives for a class.<p>
	*	.source MPC.CLASSNAME.java<p>
	*	.class public MPC.CLASSNAME<p>
	*	.super java/lang/Object<p>
	'''
	def emitPROLOG(self, name, parent):
		#name: String
		#parent: String

		result = list()
		result.append(self.jvm.emitSOURCE(name + ".java"))
		result.append(self.jvm.emitCLASS("public " + name))
		result.append(self.jvm.emitSUPER("java/land/Object" if parent == "" else parent))
		return ''.join(result)

	def emitLIMITSTACK(self, num):
		#num: Int
		return self.jvm.emitLIMITSTACK(num)

	def emitLIMITLOCAL(self, num):
		#num: Int
		return self.jvm.emitLIMITLOCAL(num)

	def emitEPILOG(self):
		file = open(self.filename, "w")
		file.write(''.join(self.buff))
		file.close()

	def printout(self, in_):
		self.buff.append(in_)

	def clearBuff(self):
		self.buff.clear()