Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * @author Nguyen Hua Phung
- * @version 1.0
- * 23/10/2015
- * This file provides a simple version of code generator
- *
- */
- package mc.codegen
- import mc.utils._
- import java.io.{PrintWriter, File}
- object CodeGenerator extends Utils {
- val libName = "io"
- def init() = List( Symbol("getInt",MType(List(),IntType),CName(libName)),
- Symbol("putInt",MType(List(IntType),VoidType),CName(libName)),
- Symbol("putIntLn",MType(List(IntType),VoidType),CName(libName)),
- Symbol("getFloat",MType(List(),FloatType),CName(libName)),
- Symbol("putFloat",MType(List(FloatType),VoidType),CName(libName)),
- Symbol("putFloatLn",MType(List(FloatType),VoidType),CName(libName)),
- Symbol("putBool",MType(List(BoolType),VoidType),CName(libName)),
- Symbol("putBoolLn",MType(List(BoolType),VoidType),CName(libName)),
- Symbol("putString",MType(List(StringType),VoidType),CName(libName)),
- Symbol("putStringLn",MType(List(StringType),VoidType),CName(libName)),
- Symbol("putLn",MType(List(),VoidType),CName(libName))
- )
- def gen(ast:AST,dir:File) = {
- val gl = init()
- val gc = new CodeGenVisitor(ast,gl,dir)
- gc.visit(ast, null);
- }
- }
- case class ClassType(cname:String) extends Type
- //case class SubContext(emit:Emitter,decl:List[Decl])
- case class SubBody(frame:Frame,sym:List[Symbol])
- class Access(val frame:Frame,val sym:List[Symbol],val isLeft:Boolean,val isFirst:Boolean)
- case class Symbol(val name:String,val typ:Type,val value:Val)
- case class MType(partype:List[Type],rettype:Type) extends Type
- trait Val
- case class Index(value:Int) extends Val
- case class CName(value:String) extends Val
- class CodeGenVisitor(astTree:AST,env:List[Symbol],dir:File) extends BaseVisitor with Utils {
- val className = "MCClass"
- val path = dir.getPath()
- val emit = new Emitter(path+"/"+className+".j")
- override def visitProgram(ast:Program,c:Any) = {
- emit.printout(emit.emitPROLOG(className, "java.lang.Object"))
- val listVarDecl = ast.decl.filter(_.isInstanceOf[VarDecl]).asInstanceOf[List[VarDecl]].map(x=> {
- emit.printout(emit.emitATTRIBUTE(x.variable.name,x.varType,false,null))
- Symbol(x.variable.name,x.varType,null)
- }
- )
- val globalEnv = listVarDecl ++ env
- println(globalEnv)
- genMETHOD(FuncDecl(Id("<init>"),List(),null,Block(List(),List())),listVarDecl,new Frame("<init>",VoidType))
- ast.decl.filter(_.isInstanceOf[FuncDecl]).asInstanceOf[List[FuncDecl]].foldLeft(SubBody(null,globalEnv))(
- (e,x) => visit(x,e).asInstanceOf[SubBody]
- )
- // generate default constructor
- emit.emitEPILOG()
- c
- }
- /** generate code for default constructor
- * @param consdecl the function declaration whose code will be generated by this method
- * @param frame the frame where the initialization happen
- * @param o the referencing environment
- */
- def genInitVar(glenv: List[Symbol]) = {
- }
- def visitStmt(stmt: Stmt, o: Any) = {
- val subctxt = o.asInstanceOf[SubBody]
- val frame = subctxt.frame
- val sym = subctxt.sym
- if(stmt == Break) emit.printout(emit.emitGOTO(frame.getBreakLabel,frame))
- else if(stmt == Continue) emit.printout(emit.emitGOTO(frame.getContinueLabel,frame))
- else if(stmt.isInstanceOf[Expr]) {
- emit.printout(visit(stmt,new Access(frame,sym,false,true)).asInstanceOf[(String,Type)]._1)}
- else visit(stmt,subctxt)
- }
- def genMETHOD(consdecl:FuncDecl,o:Any,frame:Frame) = {
- val isInit = consdecl.returnType == null
- val isMain = consdecl.name.name == "main" && consdecl.param.length == 0 && consdecl.returnType == VoidType
- val returnType = if (isInit) VoidType else consdecl.returnType
- val methodName = if (isInit) "<init>" else consdecl.name.name
- val intype = if (isMain) List(ArrayPointerType(StringType)) else List()
- val mtype = MType(intype,returnType)
- emit.printout(emit.emitMETHOD(methodName, mtype, !isInit, frame))
- frame.enterScope(true);
- val glenv = o.asInstanceOf[List[Symbol]]
- // Generate code for parameter declarations
- if (isInit) emit.printout(emit.emitVAR(frame.getNewIndex,"this",ClassType(className),frame.getStartLabel,frame.getEndLabel,frame))
- if (isMain) emit.printout(emit.emitVAR(frame.getNewIndex,"args",ArrayPointerType(StringType),frame.getStartLabel,frame.getEndLabel,frame))
- // Sinh mã cho params
- val param = consdecl.param.foldLeft(SubBody(frame,List[Symbol]()))(
- (x,y) =>
- y.accept(this,x).asInstanceOf[SubBody]
- )
- val body = consdecl.body.asInstanceOf[Block]
- val loc = body.decl.asInstanceOf[List[VarDecl]].foldLeft(SubBody(frame,List[Symbol]()))(
- (x,y) =>
- y.accept(this,x).asInstanceOf[SubBody]
- )
- emit.printout(emit.emitLABEL(frame.getStartLabel(),frame))
- //Generate code for statements
- if (isInit) {
- emit.printout(emit.emitREADVAR("this",ClassType(className),0,frame)) // .method public <init>()V
- emit.printout(emit.emitINVOKESPECIAL(frame)) // .var 0 is this LMCClass; from Label0 to Label1
- glenv.map(x=>
- x.typ match {
- case IntType | BoolType =>
- emit.printout(
- emit.emitPUSHICONST(0,frame) + emit.emitPUTSTATIC(className + "." + x.name, x.typ, frame)
- )
- case FloatType =>
- emit.printout(
- emit.emitPUSHFCONST("0.0",frame) + emit.emitPUTSTATIC(className + "." + x.name, x.typ, frame)
- )
- case ArrayType(dimen,t) =>
- // iconst_3
- // newarray int
- // putstatic
- emit.printout(
- emit.emitPUSHICONST(dimen.value, frame)
- + emit.emitNEWARRAY(t, frame)
- + emit.emitPUTSTATIC(className + "." + x.name, x.typ, frame)
- )
- if( t != StringType) (0 to dimen.value - 1).map(i =>
- emit.printout(
- emit.emitGETSTATIC(className + "." + x.name, x.typ, frame)
- + emit.emitPUSHICONST(i, frame)
- + (if (t == FloatType) emit.emitPUSHFCONST("0.0", frame) else emit.emitPUSHICONST(0, frame) )
- + emit.emitASTORE(t, frame)
- )
- )
- }
- )
- }
- val env = param.sym ++ loc.sym ++ glenv
- //body.stmt.map(x=>visitStmt(x,SubBody(frame,env)))
- visitStmt(body,SubBody(frame,env))
- emit.printout(emit.emitLABEL(frame.getEndLabel(),frame))
- if (returnType == VoidType) emit.printout(emit.emitRETURN(VoidType,frame));
- emit.printout(emit.emitENDMETHOD(frame));
- frame.exitScope();
- }
- override def visitVarDecl(ast:VarDecl,o:Any) = {
- val subctxt = o.asInstanceOf[SubBody]
- val frame = subctxt.frame
- val listSym = subctxt.sym
- val idx = frame.getNewIndex()
- emit.printout(emit.emitVAR(idx,ast.variable.name,ast.varType,frame.getStartLabel(), frame.getEndLabel(), frame))
- SubBody(frame,Symbol(ast.variable.name,ast.varType,Index(idx))::listSym)
- }
- override def visitFuncDecl(ast:FuncDecl,o:Any) = {
- val subctxt = o.asInstanceOf[SubBody]
- val frame = new Frame(ast.name.name,ast.returnType)
- genMETHOD(ast,subctxt.sym,frame)
- SubBody(null,Symbol(ast.name.name,MType(List(),ast.returnType),CName(className))::subctxt.sym)
- }
- def genArray(local: SubBody )= {
- val lstSym = local.sym
- val frame = local.frame
- lstSym.filter(_.typ.isInstanceOf[ArrayType]).map( x => x.typ match {
- case ArrayType(dimen,t) =>
- emit.printout(
- emit.emitPUSHICONST(dimen.value, frame)
- + emit.emitNEWARRAY(t,frame)
- + emit.emitWRITEVAR(x.name,x.typ,x.value.asInstanceOf[Index].value,frame)
- )
- })
- }
- override def visitBlock(ast: Block, o: Any) = {
- val subctxt = o.asInstanceOf[SubBody]
- val frame = subctxt.frame
- frame.enterScope(false)
- val local = ast.decl.foldLeft(SubBody(frame,List[Symbol]()))(
- (x,y) =>
- y.accept(this,x).asInstanceOf[SubBody]
- )
- val env = local.sym ++ subctxt.sym
- emit.printout(emit.emitLABEL(frame.getStartLabel(),frame))
- genArray(local)
- ast.stmt.map(x=>visitStmt(x,SubBody(frame,env)))
- emit.printout(emit.emitLABEL(frame.getEndLabel(),frame))
- frame.exitScope();
- }
- override def visitIf(ast: If, o: Any) = {
- val subctxt = o.asInstanceOf[SubBody]
- val frame = subctxt.frame
- val exp = ast.expr.accept(this,new Access(frame,subctxt.sym,false,true)).asInstanceOf[(String,Type)]
- emit.printout(exp._1)
- // Xét xem trên stack là 1 hay 0
- // nếu 0 thì nhảy tới lb1 còn 1 thì nhảy tới lb2
- val label1 = frame.getNewLabel()
- emit.printout(emit.emitIFFALSE(label1,frame))
- visitStmt(ast.thenStmt,subctxt)
- if(ast.elseStmt != None) {
- val label2 = frame.getNewLabel()
- emit.emitGOTO(label2,frame)
- emit.printout(emit.emitLABEL(label1,frame))
- visitStmt(ast.elseStmt.get,subctxt)
- emit.printout(emit.emitLABEL(label2,frame))
- }
- else
- emit.printout(emit.emitLABEL(label1,frame))
- }
- override def visitFor(ast: For, o: Any) = {
- // for(a = 3; a < 4 ; a = a +1) {
- // stmt
- //}
- val ctxt = o.asInstanceOf[SubBody]
- val frame = ctxt.frame
- val exp1 = ast.expr1.accept(this,new Access(frame,ctxt.sym,false,true)).asInstanceOf[(String,Type)]
- val exp2 = ast.expr2.accept(this,new Access(frame,ctxt.sym,false,true)).asInstanceOf[(String,Type)]
- val exp3 = ast.expr3.accept(this,new Access(frame,ctxt.sym,false,true)).asInstanceOf[(String,Type)]
- emit.printout(exp1._1)
- frame.enterLoop
- val label = frame.getNewLabel
- val conLabel = frame.getContinueLabel
- val brkLabel = frame.getBreakLabel
- emit.printout(
- emit.emitLABEL(label,frame)
- + exp2._1
- + emit.emitIFFALSE(brkLabel,frame)
- )
- visitStmt(ast.loop,ctxt)
- emit.printout(
- emit.emitLABEL(conLabel,frame)
- + exp3._1
- + emit.emitGOTO(label,frame)
- + emit.emitLABEL(brkLabel,frame)
- )
- frame.exitLoop
- }
- override def visitDowhile(ast: Dowhile, o: Any) = {
- val ctxt = o.asInstanceOf[SubBody]
- val frame = ctxt.frame
- val env = ctxt.sym
- frame.enterLoop()
- val conLabel = frame.getContinueLabel()
- val brkLabel = frame.getBreakLabel()
- emit.printout(emit.emitLABEL(conLabel,frame))
- ast.sl.map(visitStmt(_,ctxt))
- val exp = ast.exp.accept(this,new Access(frame,env,false,true)).asInstanceOf[(String,Type)]
- emit.printout(exp._1)
- emit.printout(emit.emitIFTRUE(conLabel,frame))
- emit.printout(emit.emitLABEL(brkLabel,frame))
- frame.exitLoop()
- }
- override def visitReturn(ast: Return, o: Any) ={
- if(ast.expr != None) {
- val ctxt = o.asInstanceOf[SubBody]
- val frame = ctxt.frame
- val exp = ast.expr.get.accept(this,new Access(frame,ctxt.sym,false,true)).asInstanceOf[(String,Type)]
- emit.printout(
- exp._1
- + emit.emitRETURN(exp._2,frame)
- )
- }
- }
- override def visitCallExpr(ast:CallExpr,o:Any) = {
- println(ast)
- val ctxt = o.asInstanceOf[Access]
- val frame = ctxt.frame
- val nenv = ctxt.sym
- val sym = lookup(ast.method.name,nenv,(x:Symbol)=>x.name).get
- val cname = sym.value.asInstanceOf[CName].value
- val ctype = sym.typ
- val in = ast.params.foldLeft(("",List[Type]()))((y,x)=>
- {
- val (str1,typ1) = visit(x,new Access(frame,nenv,false,true)).asInstanceOf[(String,Type)]
- (y._1 + str1,y._2 :+ typ1)
- }
- )
- (in._1 + emit.emitINVOKESTATIC(cname+"/"+ast.method.name,ctype,frame), ctype.asInstanceOf[MType].rettype)
- }
- override def visitBinaryOp(ast: BinaryOp, o: Any) = {
- val ctxt = o.asInstanceOf[Access]
- val frame = ctxt.frame
- val sym = ctxt.sym
- val left = visit(ast.left, new Access(frame,sym, false, true)).asInstanceOf[(String,Type)]
- val right = visit(ast.right, new Access(frame,sym, false, true)).asInstanceOf[(String,Type)]
- ast.op match {
- case ("*"|"/"|"+"|"-") =>
- if (left._2 == right._2) (left._1 + right._1 + emit.emitNUMOP(ast.op,left._2,frame),left._2)
- else if(left._2 == IntType ) (left._1 + emit.emitI2F(frame) + right._1 + emit.emitNUMOP(ast.op,left._2,frame),right._2)
- else (left._1 + right._1 + emit.emitI2F(frame) + emit.emitNUMOP(ast.op,left._2,frame),left._2)
- case "%" => (left._1 + right._1 + emit.emitMOD(frame), left._2)
- case (">" | "<" | "<=" | ">=" | "==" | "!=") => (left._1 + right._1 + emit.emitREOP(ast.op,frame),BoolType)
- case ("&&") => {
- val label1 = frame.getNewLabel()
- val label2 = frame.getNewLabel
- (left._1 + emit.emitIFFALSE(label1,frame) + right._1 + emit.emitGOTO(label2,frame) +
- emit.emitLABEL(label1,frame) + emit.emitPUSHICONST(0,frame) + emit.emitLABEL(label2,frame), BoolType)
- }
- case ("||") => {
- val label1 = frame.getNewLabel()
- val label2 = frame.getNewLabel
- (left._1 + emit.emitIFGT(label1,frame) + right._1 + emit.emitGOTO(label2,frame) +
- emit.emitLABEL(label1,frame) + emit.emitPUSHICONST(1,frame) + emit.emitLABEL(label2,frame), BoolType)
- }
- case ("=") => {
- val left2 = visit(ast.left, new Access(frame,sym, true, false)).asInstanceOf[(String,Type)]
- if(ast.left.isInstanceOf[ArrayCell]) {
- val left1 = visit(ast.left, new Access(frame,sym, true, true)).asInstanceOf[(String,Type)]
- (left1._1 + right._1 + left2._1, left1._2)
- }
- else (right._1 + left2._1, left._2)
- }
- }
- }
- override def visitUnaryOp(ast: UnaryOp, o: Any) = {
- val ctxt = o.asInstanceOf[Access]
- val frame = ctxt.frame
- val exp = ast.body.accept(this,ctxt).asInstanceOf[(String,Type)]
- ast.op match {
- case "-" => ( exp._1 + emit.emitNEGOP(exp._2,frame), exp._2)
- case "!" => ( exp._1 + emit.emitNOT(exp._2,frame), exp._2)
- }
- }
- override def visitId(ast:Id,o:Any) = {
- val ctxt = o.asInstanceOf[Access]
- val frame = ctxt.frame
- val sym = lookup(ast.name,ctxt.sym,(x:Symbol)=>x.name).get
- val typ = sym.typ
- val idx = sym.value
- if(ctxt.isLeft)
- if(idx != null)(emit.emitWRITEVAR(ast.name, typ, idx.asInstanceOf[Index].value, frame), typ)
- else (emit.emitPUTSTATIC(className + "." + ast.name, typ, frame),typ)
- else
- if(idx != null) (emit.emitREADVAR(ast.name, typ, idx.asInstanceOf[Index].value, frame), typ)
- else (emit.emitGETSTATIC(className + "." + ast.name, typ, frame), typ)
- }
- override def visitArrayCell(ast: ArrayCell, o: Any) = {
- val ctxt = o.asInstanceOf[Access]
- val frame = ctxt.frame
- val isFirst = ctxt.isFirst
- val sym = ctxt.sym
- val arrIdx = ast.idx.accept(this,new Access(frame,sym,false,true)).asInstanceOf[(String,Type)]
- val arr = ast.arr.accept(this,new Access(frame,sym,false,true)).asInstanceOf[(String,Type)]
- val typ = arr._2 match {
- case ArrayType(_,t) => t
- case ArrayPointerType(t) => t
- }
- if(ctxt.isLeft) {
- if(isFirst) (arr._1 + arrIdx._1, typ)
- else (emit.emitASTORE(typ,frame), typ)
- }
- else
- (arr._1 + arrIdx._1 + emit.emitALOAD(typ,frame),typ)
- }
- override def visitIntLiteral(ast:IntLiteral,o:Any) = {
- val ctxt = o.asInstanceOf[Access]
- val frame = ctxt.frame
- (emit.emitPUSHICONST(ast.value, frame),IntType)
- }
- override def visitFloatLiteral(ast:FloatLiteral,o:Any) = {
- val ctxt = o.asInstanceOf[Access]
- val frame = ctxt.frame
- (emit.emitPUSHFCONST(ast.value+"", frame),FloatType)
- }
- override def visitBooleanLiteral(ast:BooleanLiteral,o:Any) = {
- val ctxt = o.asInstanceOf[Access]
- val frame = ctxt.frame
- if(ast.value == true) (emit.emitPUSHICONST(1, frame),IntType)
- else (emit.emitPUSHICONST(0, frame),BoolType)
- }
- override def visitStringLiteral(ast:StringLiteral,o:Any) = {
- val ctxt = o.asInstanceOf[Access]
- val frame = ctxt.frame
- (emit.emitPUSHCONST(ast.value,StringType, frame),StringType)
- }
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- /**
- * @author Dr.Nguyen Hua Phung
- * @version 1.0
- * 28/6/2006
- * This class is used to generate code at a intermediate level
- *
- */
- package mc.codegen
- import java.io.BufferedWriter
- import java.io.FileWriter
- import java.text.DecimalFormat
- import java.util.Iterator
- import mc.utils._
- import mc.checker._
- class Emitter(filename:String) {
- val buff = new StringBuffer()
- val jvm = new JasminCode()
- def getJVMType(inType:Type):String = inType match {
- case IntType => "I"
- case StringType => "Ljava/lang/String;"
- case VoidType => "V"
- case FloatType => "F"
- case BoolType => "Z"
- case ArrayType(_,t) => "[" + getJVMType(t)
- case ArrayPointerType(t) => "["+getJVMType(t)
- case MType(il,o) => "("+il.foldLeft("")(_+getJVMType(_))+")"+getJVMType(o)
- case ClassType(t) => "L"+t+";"
- }
- def getFullType(inType:Type):String = inType match {
- case IntType => "int"
- case StringType => "java/lang/String"
- case VoidType => "void"
- }
- def emitPUSHICONST(i:Int,frame:Frame):String =
- {
- frame.push();
- if (i >= -1 && i <= 5) jvm.emitICONST(i)
- else if (i >= -128 && i <= 127) jvm.emitBIPUSH(i)
- else if (i >= -32768 && i <= 32767) jvm.emitSIPUSH(i)
- else jvm.emitLDC("" + i)
- }
- def emitPUSHICONST(in:String,frame:Frame):String =
- in match {
- case "true" => emitPUSHICONST(1,frame)
- case "false" => emitPUSHICONST(0,frame)
- case _ => emitPUSHICONST(in.toInt,frame)
- }
- def emitPUSHFCONST(in:String,frame:Frame):String =
- {
- val f = in.toFloat;
- frame.push();
- val myFormatter = new DecimalFormat("###0.0###");
- val rst = myFormatter.format(f);
- if (rst.equals("0.0") || rst.equals("1.0") ||rst.equals("2.0"))
- jvm.emitFCONST(rst)
- else
- 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(in:String, typ:Type, frame:Frame) =
- typ match {
- case (IntType) => emitPUSHICONST(in,frame)
- case StringType => {
- frame.push();
- jvm.emitLDC( in);
- }
- case _ => throw IllegalOperandException(in)
- }
- ////////////////////////////////////////////////////////////////
- def emitALOAD(in:Type,frame:Frame) =
- {
- //..., arrayref, index -> ..., value
- frame.pop();
- in match {
- case IntType => jvm.emitIALOAD()
- case BoolType => jvm.emitBALOAD()
- case FloatType => jvm.emitFALOAD()
- case (ArrayPointerType(_)|ClassType(_)|StringType) => jvm.emitAALOAD()
- case _ => throw IllegalOperandException(in.toString);
- }
- }
- def emitASTORE(in:Type,frame:Frame) =
- {
- //..., arrayref, index, value -> ...
- frame.pop();
- frame.pop();
- frame.pop();
- in match {
- case IntType => jvm.emitIASTORE()
- case (ArrayPointerType(_)|ClassType(_)|StringType) => jvm.emitAASTORE()
- case FloatType => jvm.emitFASTORE()
- case BoolType => jvm.emitBASTORE()
- case _ => throw IllegalOperandException(in.toString)
- }
- }
- /** 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(in:Int,varName:String, inType:Type, fromLabel: Int, toLabel: Int,frame:Frame) = jvm.emitVAR(in, varName, getJVMType(inType), fromLabel, toLabel);
- /**
- * generate code to put the value of a variable onto the operand stack.
- * @param name the name entry of the variable.
- */
- def emitREADVAR(name:String,inType:Type,index:Int,frame:Frame) =
- {
- //... -> ..., value
- frame.push();
- inType match {
- case (IntType|BoolType) => jvm.emitILOAD(index)
- case FloatType => jvm.emitFLOAD(index)
- case ArrayType(_,_) => jvm.emitALOAD(index)
- case (ArrayPointerType(_)|ClassType(_)|StringType) => jvm.emitALOAD(index)
- case _ => throw IllegalOperandException(name)
- }
- }
- /* generate the second instruction for array cell access
- *
- */
- def emitREADVAR2(name:String,typ:Type,frame:Frame) =
- {
- //... -> ..., value
- //frame.push();
- typ match {
- case _ => throw 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(name:String,inType:Type,index:Int,frame:Frame) =
- {
- //..., value -> ...
- frame.pop();
- inType match {
- case (IntType ) => jvm.emitISTORE(index)
- case (FloatType ) => jvm.emitFSTORE(index)
- case (BoolType ) => jvm.emitISTORE(index)
- case (ArrayType(_,_)) =>
- frame.pop()
- jvm.emitASTORE(index)
- case (ArrayPointerType(_)|ClassType(_)|StringType) => jvm.emitASTORE(index)
- case _ => throw IllegalOperandException(name)
- }
- }
- /* generate the second instruction for array cell access
- *
- */
- def emitWRITEVAR2(name:String,typ:Type,frame:Frame) =
- {
- //... -> ..., value
- //frame.push();
- typ match {
- case _ => throw 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(lexeme:String, in:Type, isFinal:Boolean, value:String) =
- jvm.emitSTATICFIELD(lexeme,getJVMType(in),false)
- /*
- (kind,isFinal) match {
- case (Static,true) => ".field static final " + lexeme + " " + getJVMType(in) + (if (value == "null") "" else " = " + value + "\n")
- case (Static,false) => ".field static " + lexeme + " " + getJVMType(in) + "\n";
- case (Instance,true) =>".field final " + lexeme + " " + getJVMType(in) + " = " + value + "\n";
- case _ => ".field " + lexeme + " " + getJVMType(in) + "\n";
- }*/
- def emitGETSTATIC( lexeme:String, in:Type,frame:Frame) = {
- frame.push()
- jvm.emitGETSTATIC(lexeme, getJVMType(in))
- }
- def emitPUTSTATIC( lexeme:String, in: Type,frame:Frame) = {
- frame.pop()
- if(in.isInstanceOf[ArrayType]) frame.pop()
- jvm.emitPUTSTATIC(lexeme, getJVMType(in))
- }
- def emitGETFIELD( lexeme:String, in:Type,frame:Frame) = jvm.emitGETFIELD(lexeme, getJVMType(in))
- def emitPUTFIELD( lexeme:String, in: Type,frame:Frame) = {
- frame.pop()
- frame.pop()
- jvm.emitPUTFIELD(lexeme, 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(lexeme:String,in:Type ,frame:Frame) =
- {
- val typ = in.asInstanceOf[MType]
- typ.partype.map(x=>frame.pop)
- if (typ.rettype != VoidType)
- frame.push();
- jvm.emitINVOKESTATIC(lexeme,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(lexeme:String,in:Type ,frame:Frame) =
- {
- val typ = in.asInstanceOf[MType]
- typ.partype.map(x=>frame.pop)
- frame.pop
- if (typ.rettype != VoidType)
- frame.push();
- jvm.emitINVOKESPECIAL(lexeme,getJVMType(in));
- }
- /** generate code to invoke a default special method
- *
- */
- def emitINVOKESPECIAL(frame:Frame) = {
- frame.pop
- 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(lexeme:String,in:Type ,frame:Frame) =
- {
- val typ = in.asInstanceOf[MType]
- typ.partype.map(x=>frame.pop)
- frame.pop
- if (typ.rettype != VoidType)
- frame.push();
- jvm.emitINVOKEVIRTUAL(lexeme,getJVMType(in));
- }
- /**
- * generate ineg, fneg.
- * @param in the type of the operands.
- */
- def emitNEGOP( in:Type,frame:Frame) =
- {
- //..., value -> ..., result
- if (in == IntType)
- jvm.emitINEG()
- else
- jvm.emitFNEG()
- }
- def emitNOT(in:Type,frame:Frame ) =
- {
- val label1 = frame.getNewLabel();
- val label2 = frame.getNewLabel();
- val result = new StringBuffer();
- 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));
- result.toString();
- }
- /**
- * generate iadd, isub, fadd or fsub.
- * @param lexeme the lexeme of the operator.
- * @param in the type of the operands.
- */
- def emitNUMOP(lexeme:String, in:Type,frame:Frame) =
- {
- //..., value1, value2 -> ..., result
- frame.pop();
- if (lexeme.equals("+")) {
- if (in == IntType)
- jvm.emitIADD();
- else
- jvm.emitFADD()
- } else if(lexeme.equals("-"))
- if (in == IntType)
- jvm.emitISUB();
- else
- jvm.emitFSUB();
- else if(lexeme.equals("*"))
- if (in == IntType)
- jvm.emitIMUL();
- else
- jvm.emitFMUL();
- else if (in == IntType)
- jvm.emitIDIV();
- else
- jvm.emitFDIV();
- }
- /**
- * generate imul, idiv, fmul or fdiv.
- * @param lexeme the lexeme of the operator.
- * @param in the type of the operands.
- */
- def emitMULOP(lexeme:String, in:Type,frame:Frame) =
- {
- //TODO \:integer division; %:integer remainder
- //..., value1, value2 -> ..., result
- frame.pop();
- if (lexeme.equals("*")) {
- if (in == IntType)
- jvm.emitIMUL();
- else
- jvm.emitFMUL();
- }
- else if (in == IntType)
- jvm.emitIDIV();
- else
- jvm.emitFDIV();
- }
- def emitDIV(frame:Frame) =
- {
- frame.pop();
- jvm.emitIDIV();
- }
- def emitMOD(frame:Frame) =
- {
- frame.pop();
- jvm.emitIREM();
- }
- /**
- * generate iand.
- */
- def emitANDOP(frame:Frame) =
- {
- frame.pop();
- jvm.emitIAND();
- }
- /**
- * generate ior.
- */
- def emitOROP(frame:Frame) =
- {
- frame.pop();
- jvm.emitIOR();
- }
- def emitREOP( op:String,frame:Frame) =
- {
- //..., value1, value2 -> ..., result
- val result = new StringBuffer();
- val labelF = frame.getNewLabel();
- val labelO = frame.getNewLabel();
- //println(in)
- frame.pop();
- frame.pop();
- op match {
- case ">" => result.append(jvm.emitIFICMPLE(labelF));
- case ">=" => result.append(jvm.emitIFICMPLT(labelF));
- case "<" => result.append(jvm.emitIFICMPGE(labelF));
- case "<=" => result.append(jvm.emitIFICMPGT(labelF));
- case "!=" =>
- result.append(jvm.emitIFICMPEQ(labelF))
- case "==" => result.append(jvm.emitIFICMPNE(labelF))
- }
- result.append(emitPUSHCONST("1", IntType,frame));
- frame.pop()
- result.append(emitGOTO(labelO,frame));
- result.append(emitLABEL(labelF,frame));
- result.append(emitPUSHCONST("0", IntType,frame));
- result.append(emitLABEL(labelO,frame));
- result.toString();
- }
- def emitRELOP( op:String, in:Type,trueLabel:Int,falseLabel:Int,frame:Frame) =
- {
- //..., value1, value2 -> ..., result
- val result = new StringBuffer();
- //val (isFalse,label) = if (trueLabel == CodeGenVisitor.FallThrough) (true,falseLabel) else (false,trueLabel)
- frame.pop();
- frame.pop();
- op match {
- case ">" => {
- result.append(jvm.emitIFICMPLE(falseLabel))
- result.append(jvm.emitGOTO(trueLabel))
- }
- case ">=" => result.append(jvm.emitIFICMPLT(falseLabel))
- case "<" => result.append(jvm.emitIFICMPGE(falseLabel))
- case "<=" => result.append(jvm.emitIFICMPGT(falseLabel))
- case "!=" => result.append(jvm.emitIFICMPEQ(falseLabel))
- case "==" => result.append(jvm.emitIFICMPNE(falseLabel))
- }
- result.append(jvm.emitGOTO(trueLabel))
- result.toString();
- }
- /** 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( lexeme:String, in: Type, isStatic:Boolean,frame:Frame) = jvm.emitMETHOD(lexeme,getJVMType(in),isStatic)
- /** generate the end directive for a function.
- */
- def emitENDMETHOD(frame:Frame) = {
- var buffer = new StringBuffer();
- buffer.append(jvm.emitLIMITSTACK(frame.getMaxOpStackSize()));
- buffer.append(jvm.emitLIMITLOCAL(frame.getMaxIndex()));
- buffer.append(jvm.emitENDMETHOD());
- buffer.toString();
- }
- def getConst(ast:Literal)= ast match {
- case IntLiteral(i) => (i.toString,IntType)
- }
- def emitNEWARRAY(typ : Type , frame: Frame) = {
- frame.push();
- typ match {
- case IntType => jvm.emitNEWARRAY("int")
- case FloatType => jvm.emitNEWARRAY("float")
- case BoolType => jvm.emitNEWARRAY("boolean")
- case StringType => jvm.emitANEWARRAY("java/lang/String")
- }
- }
- /** 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.
- */
- /*public String emitINITARRAY(int index,Type in) throws CompilationException {
- StringBuffer buffer = new StringBuffer();
- ArrayType at = (ArrayType) in;
- ProductType rt = (ProductType) at.getIType();
- int element = 0;
- int dimension = 0;
- while (!(rt.getE1Type() == null && rt.getE2Type() == null)) {
- element = ((RangeType)rt.getE1Type()).getUpper();
- dimension++;
- buffer.append(emitPUSHICONST(element));
- rt = (ProductType) rt.getE2Type();
- }
- if (dimension == 1) {
- buffer.append(emitNEWARRAY(at.getEType()));
- frame.pop();
- buffer.append(jvm.emitASTORE(index));
- }
- else {
- for (int i = 0; i < dimension; i++)
- frame.pop();
- buffer.append(jvm.emitMULTIANEWARRAY(at.getJVMType(), dimension));
- buffer.append(jvm.emitASTORE(index));
- }
- return buffer.toString();
- }*/
- /** generate code to initialize local array variables.
- * @param in the list of symbol entries corresponding to local array variable.
- */
- /* public String emitLISTARRAY(List<SymEntry> in) throws CompilationException {
- StringBuffer result = new StringBuffer();
- for (Iterator<SymEntry> it = in.iterator();it.hasNext();) {
- SymEntry sym = it.next();
- ArrayType at =(ArrayType)sym.getType();
- result.append(emitINITARRAY((Integer)sym.getObject(),at));
- }
- in.clear();
- return result.toString();
- }*/
- /**
- * 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(label:Int,frame:Frame) =
- {
- frame.pop();
- 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(label:Int,frame:Frame) =
- {
- frame.pop();
- jvm.emitIFLE(label);
- }
- def emitIFICMPGT(label:Int,frame:Frame) =
- {
- frame.pop();
- jvm.emitIFICMPGT(label);
- }
- def emitIFICMPLT(label:Int,frame:Frame) =
- {
- frame.pop();
- 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(frame:Frame) =
- {
- frame.push();
- jvm.emitDUP();
- }
- /** generate code to pop the value on the top of the operand stack.
- */
- def emitPOP(frame:Frame) =
- {
- frame.pop();
- jvm.emitPOP();
- }
- /** generate code to exchange an integer on top of stack to a floating-point number.
- */
- def emitI2F(frame:Frame) = 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(in:Type,frame:Frame) =
- {
- in match {
- case (IntType|BoolType ) => frame.pop();jvm.emitIRETURN()
- case (FloatType) => frame.pop();jvm.emitFRETURN()
- case (ArrayType(_,_)|ArrayPointerType(_) ) => frame.pop();jvm.emitARETURN()
- case VoidType => jvm.emitRETURN()
- //case ClassType(_) => frame.pop();jvm.emitARETURN()
- }
- }
- /** generate code that represents a label
- * @param label the label
- * @return code Label<label>:
- */
- def emitLABEL(label:Int,frame:Frame) = jvm.emitLABEL(label)
- /** generate code to jump to a label
- * @param label the label
- * @return code goto Label<label>
- */
- def emitGOTO(label:Int,frame:Frame) = jvm.emitGOTO(label)
- def emitIFEQ(label: Int, frame: Frame) = {
- frame.pop()
- jvm.emitIFEQ(label)
- }
- def emitIFGT(label: Int, frame: Frame) = {
- frame.pop()
- jvm.emitIFGT(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(name:String,parent:String) = {
- val result = new StringBuffer();
- result.append(jvm.emitSOURCE(name + ".java"));
- result.append(jvm.emitCLASS("public " + name));
- result.append(jvm.emitSUPER(if (parent == "") "java/lang/Object" else parent));
- result.toString();
- }
- def emitLIMITSTACK(num:Int) = jvm.emitLIMITSTACK(num)
- def emitLIMITLOCAL(num:Int) = jvm.emitLIMITLOCAL(num)
- def emitEPILOG() = {
- val file = new FileWriter(filename)
- file.write(buff.toString())
- file.close()
- }
- /** print out the code to screen
- * @param in the code to be printed out
- */
- def printout(in:String) = buff.append(in);
- def clearBuff() = buff.setLength(0);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement