Advertisement
vietanhlehuu

ASS 4 BACKUP 1

Dec 10th, 2017
329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 35.17 KB | None | 0 0
  1. /**
  2. * @author Nguyen Hua Phung
  3. * @version 1.0
  4. * 23/10/2015
  5. * This file provides a simple version of code generator
  6. *
  7. */
  8.  
  9. package mc.codegen
  10.  
  11. import mc.utils._
  12. import java.io.{PrintWriter, File}
  13.  
  14.  
  15. object CodeGenerator extends Utils {
  16. val libName = "io"
  17. def init() = List( Symbol("getInt",MType(List(),IntType),CName(libName)),
  18. Symbol("putInt",MType(List(IntType),VoidType),CName(libName)),
  19. Symbol("putIntLn",MType(List(IntType),VoidType),CName(libName)),
  20. Symbol("getFloat",MType(List(),FloatType),CName(libName)),
  21. Symbol("putFloat",MType(List(FloatType),VoidType),CName(libName)),
  22. Symbol("putFloatLn",MType(List(FloatType),VoidType),CName(libName)),
  23. Symbol("putBool",MType(List(BoolType),VoidType),CName(libName)),
  24. Symbol("putBoolLn",MType(List(BoolType),VoidType),CName(libName)),
  25. Symbol("putString",MType(List(StringType),VoidType),CName(libName)),
  26. Symbol("putStringLn",MType(List(StringType),VoidType),CName(libName)),
  27. Symbol("putLn",MType(List(),VoidType),CName(libName))
  28. )
  29.  
  30.  
  31. def gen(ast:AST,dir:File) = {
  32.  
  33. val gl = init()
  34. val gc = new CodeGenVisitor(ast,gl,dir)
  35. gc.visit(ast, null);
  36. }
  37. }
  38.  
  39.  
  40.  
  41.  
  42. case class ClassType(cname:String) extends Type
  43.  
  44.  
  45.  
  46. //case class SubContext(emit:Emitter,decl:List[Decl])
  47.  
  48. case class SubBody(frame:Frame,sym:List[Symbol])
  49.  
  50. class Access(val frame:Frame,val sym:List[Symbol],val isLeft:Boolean,val isFirst:Boolean)
  51. case class Symbol(val name:String,val typ:Type,val value:Val)
  52. case class MType(partype:List[Type],rettype:Type) extends Type
  53. trait Val
  54. case class Index(value:Int) extends Val
  55. case class CName(value:String) extends Val
  56.  
  57.  
  58.  
  59.  
  60.  
  61. class CodeGenVisitor(astTree:AST,env:List[Symbol],dir:File) extends BaseVisitor with Utils {
  62.  
  63. val className = "MCClass"
  64. val path = dir.getPath()
  65. val emit = new Emitter(path+"/"+className+".j")
  66.  
  67. override def visitProgram(ast:Program,c:Any) = {
  68.  
  69.  
  70. emit.printout(emit.emitPROLOG(className, "java.lang.Object"))
  71. val listVarDecl = ast.decl.filter(_.isInstanceOf[VarDecl]).asInstanceOf[List[VarDecl]].map(x=> {
  72. emit.printout(emit.emitATTRIBUTE(x.variable.name,x.varType,false,null))
  73. Symbol(x.variable.name,x.varType,null)
  74. }
  75. )
  76. val globalEnv = listVarDecl ++ env
  77. println(globalEnv)
  78. genMETHOD(FuncDecl(Id("<init>"),List(),null,Block(List(),List())),listVarDecl,new Frame("<init>",VoidType))
  79.  
  80. ast.decl.filter(_.isInstanceOf[FuncDecl]).asInstanceOf[List[FuncDecl]].foldLeft(SubBody(null,globalEnv))(
  81. (e,x) => visit(x,e).asInstanceOf[SubBody]
  82. )
  83. // generate default constructor
  84. emit.emitEPILOG()
  85. c
  86. }
  87.  
  88.  
  89.  
  90. /** generate code for default constructor
  91.  
  92. * @param consdecl the function declaration whose code will be generated by this method
  93. * @param frame the frame where the initialization happen
  94. * @param o the referencing environment
  95. */
  96. def genInitVar(glenv: List[Symbol]) = {
  97.  
  98. }
  99. def visitStmt(stmt: Stmt, o: Any) = {
  100. val subctxt = o.asInstanceOf[SubBody]
  101. val frame = subctxt.frame
  102. val sym = subctxt.sym
  103. if(stmt == Break) emit.printout(emit.emitGOTO(frame.getBreakLabel,frame))
  104. else if(stmt == Continue) emit.printout(emit.emitGOTO(frame.getContinueLabel,frame))
  105. else if(stmt.isInstanceOf[Expr]) {
  106. emit.printout(visit(stmt,new Access(frame,sym,false,true)).asInstanceOf[(String,Type)]._1)}
  107. else visit(stmt,subctxt)
  108. }
  109. def genMETHOD(consdecl:FuncDecl,o:Any,frame:Frame) = {
  110.  
  111. val isInit = consdecl.returnType == null
  112. val isMain = consdecl.name.name == "main" && consdecl.param.length == 0 && consdecl.returnType == VoidType
  113. val returnType = if (isInit) VoidType else consdecl.returnType
  114. val methodName = if (isInit) "<init>" else consdecl.name.name
  115. val intype = if (isMain) List(ArrayPointerType(StringType)) else List()
  116. val mtype = MType(intype,returnType)
  117.  
  118. emit.printout(emit.emitMETHOD(methodName, mtype, !isInit, frame))
  119.  
  120. frame.enterScope(true);
  121.  
  122. val glenv = o.asInstanceOf[List[Symbol]]
  123.  
  124. // Generate code for parameter declarations
  125. if (isInit) emit.printout(emit.emitVAR(frame.getNewIndex,"this",ClassType(className),frame.getStartLabel,frame.getEndLabel,frame))
  126. if (isMain) emit.printout(emit.emitVAR(frame.getNewIndex,"args",ArrayPointerType(StringType),frame.getStartLabel,frame.getEndLabel,frame))
  127. // Sinh mã cho params
  128. val param = consdecl.param.foldLeft(SubBody(frame,List[Symbol]()))(
  129. (x,y) =>
  130. y.accept(this,x).asInstanceOf[SubBody]
  131. )
  132. val body = consdecl.body.asInstanceOf[Block]
  133. val loc = body.decl.asInstanceOf[List[VarDecl]].foldLeft(SubBody(frame,List[Symbol]()))(
  134. (x,y) =>
  135. y.accept(this,x).asInstanceOf[SubBody]
  136. )
  137. emit.printout(emit.emitLABEL(frame.getStartLabel(),frame))
  138.  
  139. //Generate code for statements
  140. if (isInit) {
  141. emit.printout(emit.emitREADVAR("this",ClassType(className),0,frame)) // .method public <init>()V
  142. emit.printout(emit.emitINVOKESPECIAL(frame)) // .var 0 is this LMCClass; from Label0 to Label1
  143. glenv.map(x=>
  144. x.typ match {
  145. case IntType | BoolType =>
  146. emit.printout(
  147. emit.emitPUSHICONST(0,frame) + emit.emitPUTSTATIC(className + "." + x.name, x.typ, frame)
  148. )
  149. case FloatType =>
  150. emit.printout(
  151. emit.emitPUSHFCONST("0.0",frame) + emit.emitPUTSTATIC(className + "." + x.name, x.typ, frame)
  152. )
  153. case ArrayType(dimen,t) =>
  154. // iconst_3
  155. // newarray int
  156. // putstatic
  157. emit.printout(
  158. emit.emitPUSHICONST(dimen.value, frame)
  159. + emit.emitNEWARRAY(t, frame)
  160. + emit.emitPUTSTATIC(className + "." + x.name, x.typ, frame)
  161. )
  162. if( t != StringType) (0 to dimen.value - 1).map(i =>
  163. emit.printout(
  164. emit.emitGETSTATIC(className + "." + x.name, x.typ, frame)
  165. + emit.emitPUSHICONST(i, frame)
  166. + (if (t == FloatType) emit.emitPUSHFCONST("0.0", frame) else emit.emitPUSHICONST(0, frame) )
  167. + emit.emitASTORE(t, frame)
  168. )
  169. )
  170. }
  171. )
  172.  
  173. }
  174. val env = param.sym ++ loc.sym ++ glenv
  175. //body.stmt.map(x=>visitStmt(x,SubBody(frame,env)))
  176. visitStmt(body,SubBody(frame,env))
  177.  
  178. emit.printout(emit.emitLABEL(frame.getEndLabel(),frame))
  179. if (returnType == VoidType) emit.printout(emit.emitRETURN(VoidType,frame));
  180. emit.printout(emit.emitENDMETHOD(frame));
  181. frame.exitScope();
  182. }
  183. override def visitVarDecl(ast:VarDecl,o:Any) = {
  184. val subctxt = o.asInstanceOf[SubBody]
  185. val frame = subctxt.frame
  186. val listSym = subctxt.sym
  187. val idx = frame.getNewIndex()
  188. emit.printout(emit.emitVAR(idx,ast.variable.name,ast.varType,frame.getStartLabel(), frame.getEndLabel(), frame))
  189. SubBody(frame,Symbol(ast.variable.name,ast.varType,Index(idx))::listSym)
  190. }
  191. override def visitFuncDecl(ast:FuncDecl,o:Any) = {
  192. val subctxt = o.asInstanceOf[SubBody]
  193. val frame = new Frame(ast.name.name,ast.returnType)
  194. genMETHOD(ast,subctxt.sym,frame)
  195. SubBody(null,Symbol(ast.name.name,MType(List(),ast.returnType),CName(className))::subctxt.sym)
  196. }
  197.  
  198. def genArray(local: SubBody )= {
  199. val lstSym = local.sym
  200. val frame = local.frame
  201. lstSym.filter(_.typ.isInstanceOf[ArrayType]).map( x => x.typ match {
  202. case ArrayType(dimen,t) =>
  203. emit.printout(
  204. emit.emitPUSHICONST(dimen.value, frame)
  205. + emit.emitNEWARRAY(t,frame)
  206. + emit.emitWRITEVAR(x.name,x.typ,x.value.asInstanceOf[Index].value,frame)
  207. )
  208. })
  209. }
  210. override def visitBlock(ast: Block, o: Any) = {
  211. val subctxt = o.asInstanceOf[SubBody]
  212. val frame = subctxt.frame
  213. frame.enterScope(false)
  214. val local = ast.decl.foldLeft(SubBody(frame,List[Symbol]()))(
  215. (x,y) =>
  216. y.accept(this,x).asInstanceOf[SubBody]
  217. )
  218. val env = local.sym ++ subctxt.sym
  219. emit.printout(emit.emitLABEL(frame.getStartLabel(),frame))
  220. genArray(local)
  221. ast.stmt.map(x=>visitStmt(x,SubBody(frame,env)))
  222. emit.printout(emit.emitLABEL(frame.getEndLabel(),frame))
  223. frame.exitScope();
  224.  
  225. }
  226. override def visitIf(ast: If, o: Any) = {
  227. val subctxt = o.asInstanceOf[SubBody]
  228. val frame = subctxt.frame
  229. val exp = ast.expr.accept(this,new Access(frame,subctxt.sym,false,true)).asInstanceOf[(String,Type)]
  230. emit.printout(exp._1)
  231. // Xét xem trên stack là 1 hay 0
  232. // nếu 0 thì nhảy tới lb1 còn 1 thì nhảy tới lb2
  233. val label1 = frame.getNewLabel()
  234. emit.printout(emit.emitIFFALSE(label1,frame))
  235. visitStmt(ast.thenStmt,subctxt)
  236.  
  237. if(ast.elseStmt != None) {
  238. val label2 = frame.getNewLabel()
  239. emit.emitGOTO(label2,frame)
  240. emit.printout(emit.emitLABEL(label1,frame))
  241. visitStmt(ast.elseStmt.get,subctxt)
  242. emit.printout(emit.emitLABEL(label2,frame))
  243. }
  244. else
  245. emit.printout(emit.emitLABEL(label1,frame))
  246.  
  247. }
  248. override def visitFor(ast: For, o: Any) = {
  249. // for(a = 3; a < 4 ; a = a +1) {
  250. // stmt
  251. //}
  252. val ctxt = o.asInstanceOf[SubBody]
  253. val frame = ctxt.frame
  254. val exp1 = ast.expr1.accept(this,new Access(frame,ctxt.sym,false,true)).asInstanceOf[(String,Type)]
  255. val exp2 = ast.expr2.accept(this,new Access(frame,ctxt.sym,false,true)).asInstanceOf[(String,Type)]
  256. val exp3 = ast.expr3.accept(this,new Access(frame,ctxt.sym,false,true)).asInstanceOf[(String,Type)]
  257. emit.printout(exp1._1)
  258. frame.enterLoop
  259. val label = frame.getNewLabel
  260. val conLabel = frame.getContinueLabel
  261. val brkLabel = frame.getBreakLabel
  262.  
  263. emit.printout(
  264. emit.emitLABEL(label,frame)
  265. + exp2._1
  266. + emit.emitIFFALSE(brkLabel,frame)
  267. )
  268. visitStmt(ast.loop,ctxt)
  269. emit.printout(
  270. emit.emitLABEL(conLabel,frame)
  271. + exp3._1
  272. + emit.emitGOTO(label,frame)
  273. + emit.emitLABEL(brkLabel,frame)
  274. )
  275. frame.exitLoop
  276.  
  277. }
  278. override def visitDowhile(ast: Dowhile, o: Any) = {
  279. val ctxt = o.asInstanceOf[SubBody]
  280. val frame = ctxt.frame
  281. val env = ctxt.sym
  282. frame.enterLoop()
  283. val conLabel = frame.getContinueLabel()
  284. val brkLabel = frame.getBreakLabel()
  285.  
  286. emit.printout(emit.emitLABEL(conLabel,frame))
  287. ast.sl.map(visitStmt(_,ctxt))
  288. val exp = ast.exp.accept(this,new Access(frame,env,false,true)).asInstanceOf[(String,Type)]
  289. emit.printout(exp._1)
  290. emit.printout(emit.emitIFTRUE(conLabel,frame))
  291. emit.printout(emit.emitLABEL(brkLabel,frame))
  292. frame.exitLoop()
  293.  
  294. }
  295. override def visitReturn(ast: Return, o: Any) ={
  296. if(ast.expr != None) {
  297. val ctxt = o.asInstanceOf[SubBody]
  298. val frame = ctxt.frame
  299. val exp = ast.expr.get.accept(this,new Access(frame,ctxt.sym,false,true)).asInstanceOf[(String,Type)]
  300. emit.printout(
  301. exp._1
  302. + emit.emitRETURN(exp._2,frame)
  303. )
  304.  
  305. }
  306. }
  307. override def visitCallExpr(ast:CallExpr,o:Any) = {
  308. println(ast)
  309. val ctxt = o.asInstanceOf[Access]
  310. val frame = ctxt.frame
  311. val nenv = ctxt.sym
  312. val sym = lookup(ast.method.name,nenv,(x:Symbol)=>x.name).get
  313. val cname = sym.value.asInstanceOf[CName].value
  314. val ctype = sym.typ
  315.  
  316. val in = ast.params.foldLeft(("",List[Type]()))((y,x)=>
  317. {
  318. val (str1,typ1) = visit(x,new Access(frame,nenv,false,true)).asInstanceOf[(String,Type)]
  319. (y._1 + str1,y._2 :+ typ1)
  320. }
  321. )
  322. (in._1 + emit.emitINVOKESTATIC(cname+"/"+ast.method.name,ctype,frame), ctype.asInstanceOf[MType].rettype)
  323. }
  324.  
  325. override def visitBinaryOp(ast: BinaryOp, o: Any) = {
  326. val ctxt = o.asInstanceOf[Access]
  327. val frame = ctxt.frame
  328. val sym = ctxt.sym
  329.  
  330. val left = visit(ast.left, new Access(frame,sym, false, true)).asInstanceOf[(String,Type)]
  331. val right = visit(ast.right, new Access(frame,sym, false, true)).asInstanceOf[(String,Type)]
  332. ast.op match {
  333. case ("*"|"/"|"+"|"-") =>
  334. if (left._2 == right._2) (left._1 + right._1 + emit.emitNUMOP(ast.op,left._2,frame),left._2)
  335. else if(left._2 == IntType ) (left._1 + emit.emitI2F(frame) + right._1 + emit.emitNUMOP(ast.op,left._2,frame),right._2)
  336. else (left._1 + right._1 + emit.emitI2F(frame) + emit.emitNUMOP(ast.op,left._2,frame),left._2)
  337. case "%" => (left._1 + right._1 + emit.emitMOD(frame), left._2)
  338. case (">" | "<" | "<=" | ">=" | "==" | "!=") => (left._1 + right._1 + emit.emitREOP(ast.op,frame),BoolType)
  339. case ("&&") => {
  340. val label1 = frame.getNewLabel()
  341. val label2 = frame.getNewLabel
  342. (left._1 + emit.emitIFFALSE(label1,frame) + right._1 + emit.emitGOTO(label2,frame) +
  343. emit.emitLABEL(label1,frame) + emit.emitPUSHICONST(0,frame) + emit.emitLABEL(label2,frame), BoolType)
  344. }
  345. case ("||") => {
  346. val label1 = frame.getNewLabel()
  347. val label2 = frame.getNewLabel
  348. (left._1 + emit.emitIFGT(label1,frame) + right._1 + emit.emitGOTO(label2,frame) +
  349. emit.emitLABEL(label1,frame) + emit.emitPUSHICONST(1,frame) + emit.emitLABEL(label2,frame), BoolType)
  350. }
  351. case ("=") => {
  352. val left2 = visit(ast.left, new Access(frame,sym, true, false)).asInstanceOf[(String,Type)]
  353. if(ast.left.isInstanceOf[ArrayCell]) {
  354. val left1 = visit(ast.left, new Access(frame,sym, true, true)).asInstanceOf[(String,Type)]
  355. (left1._1 + right._1 + left2._1, left1._2)
  356. }
  357. else (right._1 + left2._1, left._2)
  358. }
  359. }
  360. }
  361. override def visitUnaryOp(ast: UnaryOp, o: Any) = {
  362. val ctxt = o.asInstanceOf[Access]
  363. val frame = ctxt.frame
  364. val exp = ast.body.accept(this,ctxt).asInstanceOf[(String,Type)]
  365. ast.op match {
  366. case "-" => ( exp._1 + emit.emitNEGOP(exp._2,frame), exp._2)
  367. case "!" => ( exp._1 + emit.emitNOT(exp._2,frame), exp._2)
  368. }
  369. }
  370. override def visitId(ast:Id,o:Any) = {
  371. val ctxt = o.asInstanceOf[Access]
  372. val frame = ctxt.frame
  373. val sym = lookup(ast.name,ctxt.sym,(x:Symbol)=>x.name).get
  374. val typ = sym.typ
  375. val idx = sym.value
  376. if(ctxt.isLeft)
  377. if(idx != null)(emit.emitWRITEVAR(ast.name, typ, idx.asInstanceOf[Index].value, frame), typ)
  378. else (emit.emitPUTSTATIC(className + "." + ast.name, typ, frame),typ)
  379. else
  380. if(idx != null) (emit.emitREADVAR(ast.name, typ, idx.asInstanceOf[Index].value, frame), typ)
  381. else (emit.emitGETSTATIC(className + "." + ast.name, typ, frame), typ)
  382.  
  383. }
  384. override def visitArrayCell(ast: ArrayCell, o: Any) = {
  385. val ctxt = o.asInstanceOf[Access]
  386. val frame = ctxt.frame
  387. val isFirst = ctxt.isFirst
  388. val sym = ctxt.sym
  389. val arrIdx = ast.idx.accept(this,new Access(frame,sym,false,true)).asInstanceOf[(String,Type)]
  390. val arr = ast.arr.accept(this,new Access(frame,sym,false,true)).asInstanceOf[(String,Type)]
  391. val typ = arr._2 match {
  392. case ArrayType(_,t) => t
  393. case ArrayPointerType(t) => t
  394. }
  395. if(ctxt.isLeft) {
  396. if(isFirst) (arr._1 + arrIdx._1, typ)
  397. else (emit.emitASTORE(typ,frame), typ)
  398. }
  399. else
  400. (arr._1 + arrIdx._1 + emit.emitALOAD(typ,frame),typ)
  401. }
  402. override def visitIntLiteral(ast:IntLiteral,o:Any) = {
  403. val ctxt = o.asInstanceOf[Access]
  404. val frame = ctxt.frame
  405. (emit.emitPUSHICONST(ast.value, frame),IntType)
  406. }
  407. override def visitFloatLiteral(ast:FloatLiteral,o:Any) = {
  408. val ctxt = o.asInstanceOf[Access]
  409. val frame = ctxt.frame
  410. (emit.emitPUSHFCONST(ast.value+"", frame),FloatType)
  411. }
  412. override def visitBooleanLiteral(ast:BooleanLiteral,o:Any) = {
  413. val ctxt = o.asInstanceOf[Access]
  414. val frame = ctxt.frame
  415. if(ast.value == true) (emit.emitPUSHICONST(1, frame),IntType)
  416. else (emit.emitPUSHICONST(0, frame),BoolType)
  417. }
  418. override def visitStringLiteral(ast:StringLiteral,o:Any) = {
  419. val ctxt = o.asInstanceOf[Access]
  420. val frame = ctxt.frame
  421. (emit.emitPUSHCONST(ast.value,StringType, frame),StringType)
  422. }
  423.  
  424. }
  425. ////////////////////////////////////////////////////////////////////////////////////////////////////
  426. ////////////////////////////////////////////////////////////////////////////////////////////////////
  427. ////////////////////////////////////////////////////////////////////////////////////////////////////
  428. /**
  429. * @author Dr.Nguyen Hua Phung
  430. * @version 1.0
  431. * 28/6/2006
  432. * This class is used to generate code at a intermediate level
  433. *
  434. */
  435. package mc.codegen
  436.  
  437. import java.io.BufferedWriter
  438. import java.io.FileWriter
  439. import java.text.DecimalFormat
  440. import java.util.Iterator
  441.  
  442. import mc.utils._
  443. import mc.checker._
  444.  
  445.  
  446. class Emitter(filename:String) {
  447. val buff = new StringBuffer()
  448.  
  449.  
  450. val jvm = new JasminCode()
  451.  
  452. def getJVMType(inType:Type):String = inType match {
  453. case IntType => "I"
  454. case StringType => "Ljava/lang/String;"
  455. case VoidType => "V"
  456. case FloatType => "F"
  457. case BoolType => "Z"
  458. case ArrayType(_,t) => "[" + getJVMType(t)
  459. case ArrayPointerType(t) => "["+getJVMType(t)
  460. case MType(il,o) => "("+il.foldLeft("")(_+getJVMType(_))+")"+getJVMType(o)
  461. case ClassType(t) => "L"+t+";"
  462. }
  463. def getFullType(inType:Type):String = inType match {
  464. case IntType => "int"
  465. case StringType => "java/lang/String"
  466. case VoidType => "void"
  467. }
  468.  
  469. def emitPUSHICONST(i:Int,frame:Frame):String =
  470. {
  471. frame.push();
  472. if (i >= -1 && i <= 5) jvm.emitICONST(i)
  473. else if (i >= -128 && i <= 127) jvm.emitBIPUSH(i)
  474. else if (i >= -32768 && i <= 32767) jvm.emitSIPUSH(i)
  475. else jvm.emitLDC("" + i)
  476. }
  477.  
  478. def emitPUSHICONST(in:String,frame:Frame):String =
  479. in match {
  480. case "true" => emitPUSHICONST(1,frame)
  481. case "false" => emitPUSHICONST(0,frame)
  482. case _ => emitPUSHICONST(in.toInt,frame)
  483. }
  484.  
  485.  
  486. def emitPUSHFCONST(in:String,frame:Frame):String =
  487. {
  488. val f = in.toFloat;
  489. frame.push();
  490. val myFormatter = new DecimalFormat("###0.0###");
  491. val rst = myFormatter.format(f);
  492. if (rst.equals("0.0") || rst.equals("1.0") ||rst.equals("2.0"))
  493. jvm.emitFCONST(rst)
  494. else
  495. jvm.emitLDC(in);
  496. }
  497. /**
  498. * generate code to push a constant onto the operand stack.
  499. * @param in the lexeme of the constant
  500. * @param typ the type of the constant
  501. */
  502. def emitPUSHCONST(in:String, typ:Type, frame:Frame) =
  503. typ match {
  504. case (IntType) => emitPUSHICONST(in,frame)
  505. case StringType => {
  506. frame.push();
  507. jvm.emitLDC( in);
  508. }
  509. case _ => throw IllegalOperandException(in)
  510. }
  511.  
  512. ////////////////////////////////////////////////////////////////
  513.  
  514.  
  515. def emitALOAD(in:Type,frame:Frame) =
  516. {
  517. //..., arrayref, index -> ..., value
  518. frame.pop();
  519. in match {
  520. case IntType => jvm.emitIALOAD()
  521. case BoolType => jvm.emitBALOAD()
  522. case FloatType => jvm.emitFALOAD()
  523. case (ArrayPointerType(_)|ClassType(_)|StringType) => jvm.emitAALOAD()
  524. case _ => throw IllegalOperandException(in.toString);
  525. }
  526.  
  527. }
  528.  
  529.  
  530. def emitASTORE(in:Type,frame:Frame) =
  531. {
  532. //..., arrayref, index, value -> ...
  533. frame.pop();
  534. frame.pop();
  535. frame.pop();
  536. in match {
  537. case IntType => jvm.emitIASTORE()
  538. case (ArrayPointerType(_)|ClassType(_)|StringType) => jvm.emitAASTORE()
  539. case FloatType => jvm.emitFASTORE()
  540. case BoolType => jvm.emitBASTORE()
  541. case _ => throw IllegalOperandException(in.toString)
  542. }
  543.  
  544. }
  545.  
  546. /** generate the var directive for a local variable.
  547. * @param in the index of the local variable.
  548. * @param varName the name of the local variable.
  549. * @param inType the type of the local variable.
  550. * @param fromLabel the starting label of the scope where the variable is active.
  551. * @param toLabel the ending label of the scope where the variable is active.
  552. */
  553. def emitVAR(in:Int,varName:String, inType:Type, fromLabel: Int, toLabel: Int,frame:Frame) = jvm.emitVAR(in, varName, getJVMType(inType), fromLabel, toLabel);
  554.  
  555.  
  556. /**
  557. * generate code to put the value of a variable onto the operand stack.
  558. * @param name the name entry of the variable.
  559.  
  560. */
  561. def emitREADVAR(name:String,inType:Type,index:Int,frame:Frame) =
  562. {
  563. //... -> ..., value
  564.  
  565. frame.push();
  566. inType match {
  567. case (IntType|BoolType) => jvm.emitILOAD(index)
  568. case FloatType => jvm.emitFLOAD(index)
  569. case ArrayType(_,_) => jvm.emitALOAD(index)
  570. case (ArrayPointerType(_)|ClassType(_)|StringType) => jvm.emitALOAD(index)
  571. case _ => throw IllegalOperandException(name)
  572. }
  573.  
  574.  
  575. }
  576. /* generate the second instruction for array cell access
  577. *
  578. */
  579. def emitREADVAR2(name:String,typ:Type,frame:Frame) =
  580. {
  581. //... -> ..., value
  582.  
  583. //frame.push();
  584. typ match {
  585. case _ => throw IllegalOperandException(name)
  586. }
  587.  
  588.  
  589. }
  590.  
  591. /**
  592. * generate code to pop a value on top of the operand stack and store it to a block-scoped variable.
  593. * @param name the symbol entry of the variable.
  594. */
  595. def emitWRITEVAR(name:String,inType:Type,index:Int,frame:Frame) =
  596. {
  597. //..., value -> ...
  598. frame.pop();
  599. inType match {
  600. case (IntType ) => jvm.emitISTORE(index)
  601.  
  602. case (FloatType ) => jvm.emitFSTORE(index)
  603.  
  604. case (BoolType ) => jvm.emitISTORE(index)
  605.  
  606. case (ArrayType(_,_)) =>
  607. frame.pop()
  608. jvm.emitASTORE(index)
  609.  
  610. case (ArrayPointerType(_)|ClassType(_)|StringType) => jvm.emitASTORE(index)
  611.  
  612. case _ => throw IllegalOperandException(name)
  613. }
  614.  
  615. }
  616. /* generate the second instruction for array cell access
  617. *
  618. */
  619. def emitWRITEVAR2(name:String,typ:Type,frame:Frame) =
  620. {
  621. //... -> ..., value
  622.  
  623. //frame.push();
  624. typ match {
  625.  
  626. case _ => throw IllegalOperandException(name)
  627. }
  628.  
  629.  
  630. }
  631. /** generate the field (static) directive for a class mutable or immutable attribute.
  632. * @param lexeme the name of the attribute.
  633. * @param in the type of the attribute.
  634. * @param isFinal true in case of constant; false otherwise
  635. */
  636. def emitATTRIBUTE(lexeme:String, in:Type, isFinal:Boolean, value:String) =
  637. jvm.emitSTATICFIELD(lexeme,getJVMType(in),false)
  638.  
  639. /*
  640. (kind,isFinal) match {
  641. case (Static,true) => ".field static final " + lexeme + " " + getJVMType(in) + (if (value == "null") "" else " = " + value + "\n")
  642. case (Static,false) => ".field static " + lexeme + " " + getJVMType(in) + "\n";
  643. case (Instance,true) =>".field final " + lexeme + " " + getJVMType(in) + " = " + value + "\n";
  644. case _ => ".field " + lexeme + " " + getJVMType(in) + "\n";
  645. }*/
  646. def emitGETSTATIC( lexeme:String, in:Type,frame:Frame) = {
  647. frame.push()
  648. jvm.emitGETSTATIC(lexeme, getJVMType(in))
  649. }
  650.  
  651. def emitPUTSTATIC( lexeme:String, in: Type,frame:Frame) = {
  652. frame.pop()
  653. if(in.isInstanceOf[ArrayType]) frame.pop()
  654. jvm.emitPUTSTATIC(lexeme, getJVMType(in))
  655. }
  656.  
  657. def emitGETFIELD( lexeme:String, in:Type,frame:Frame) = jvm.emitGETFIELD(lexeme, getJVMType(in))
  658.  
  659.  
  660. def emitPUTFIELD( lexeme:String, in: Type,frame:Frame) = {
  661. frame.pop()
  662. frame.pop()
  663. jvm.emitPUTFIELD(lexeme, getJVMType(in))
  664. }
  665. /** generate code to invoke a static method
  666. * @param lexeme the qualified name of the method(i.e., class-name/method-name)
  667. * @param in the type descriptor of the method.
  668. */
  669. def emitINVOKESTATIC(lexeme:String,in:Type ,frame:Frame) =
  670. {
  671. val typ = in.asInstanceOf[MType]
  672. typ.partype.map(x=>frame.pop)
  673. if (typ.rettype != VoidType)
  674. frame.push();
  675. jvm.emitINVOKESTATIC(lexeme,getJVMType(in));
  676. }
  677. /** generate code to invoke a special method
  678. * @param lexeme the qualified name of the method(i.e., class-name/method-name)
  679. * @param in the type descriptor of the method.
  680. */
  681. def emitINVOKESPECIAL(lexeme:String,in:Type ,frame:Frame) =
  682. {
  683. val typ = in.asInstanceOf[MType]
  684. typ.partype.map(x=>frame.pop)
  685. frame.pop
  686. if (typ.rettype != VoidType)
  687. frame.push();
  688. jvm.emitINVOKESPECIAL(lexeme,getJVMType(in));
  689. }
  690.  
  691. /** generate code to invoke a default special method
  692. *
  693. */
  694. def emitINVOKESPECIAL(frame:Frame) = {
  695. frame.pop
  696. jvm.emitINVOKESPECIAL()
  697. }
  698. /** generate code to invoke a virtual method
  699. * @param lexeme the qualified name of the method(i.e., class-name/method-name)
  700. * @param in the type descriptor of the method.
  701. */
  702. def emitINVOKEVIRTUAL(lexeme:String,in:Type ,frame:Frame) =
  703. {
  704. val typ = in.asInstanceOf[MType]
  705. typ.partype.map(x=>frame.pop)
  706. frame.pop
  707. if (typ.rettype != VoidType)
  708. frame.push();
  709. jvm.emitINVOKEVIRTUAL(lexeme,getJVMType(in));
  710. }
  711. /**
  712. * generate ineg, fneg.
  713. * @param in the type of the operands.
  714. */
  715. def emitNEGOP( in:Type,frame:Frame) =
  716. {
  717. //..., value -> ..., result
  718. if (in == IntType)
  719. jvm.emitINEG()
  720. else
  721. jvm.emitFNEG()
  722. }
  723.  
  724. def emitNOT(in:Type,frame:Frame ) =
  725. {
  726. val label1 = frame.getNewLabel();
  727. val label2 = frame.getNewLabel();
  728. val result = new StringBuffer();
  729. result.append(emitIFTRUE(label1,frame));
  730. result.append(emitPUSHCONST("true", in,frame));
  731. result.append(emitGOTO(label2,frame));
  732. result.append(emitLABEL(label1,frame));
  733. result.append(emitPUSHCONST("false", in,frame));
  734. result.append(emitLABEL(label2,frame));
  735. result.toString();
  736. }
  737.  
  738. /**
  739. * generate iadd, isub, fadd or fsub.
  740. * @param lexeme the lexeme of the operator.
  741. * @param in the type of the operands.
  742. */
  743. def emitNUMOP(lexeme:String, in:Type,frame:Frame) =
  744. {
  745. //..., value1, value2 -> ..., result
  746. frame.pop();
  747. if (lexeme.equals("+")) {
  748. if (in == IntType)
  749. jvm.emitIADD();
  750. else
  751. jvm.emitFADD()
  752. } else if(lexeme.equals("-"))
  753. if (in == IntType)
  754. jvm.emitISUB();
  755. else
  756. jvm.emitFSUB();
  757. else if(lexeme.equals("*"))
  758. if (in == IntType)
  759. jvm.emitIMUL();
  760. else
  761. jvm.emitFMUL();
  762. else if (in == IntType)
  763. jvm.emitIDIV();
  764. else
  765. jvm.emitFDIV();
  766. }
  767. /**
  768. * generate imul, idiv, fmul or fdiv.
  769. * @param lexeme the lexeme of the operator.
  770. * @param in the type of the operands.
  771. */
  772.  
  773. def emitMULOP(lexeme:String, in:Type,frame:Frame) =
  774. {
  775. //TODO \:integer division; %:integer remainder
  776. //..., value1, value2 -> ..., result
  777. frame.pop();
  778. if (lexeme.equals("*")) {
  779. if (in == IntType)
  780. jvm.emitIMUL();
  781. else
  782. jvm.emitFMUL();
  783. }
  784. else if (in == IntType)
  785. jvm.emitIDIV();
  786. else
  787. jvm.emitFDIV();
  788. }
  789.  
  790.  
  791. def emitDIV(frame:Frame) =
  792. {
  793. frame.pop();
  794. jvm.emitIDIV();
  795. }
  796.  
  797.  
  798. def emitMOD(frame:Frame) =
  799. {
  800. frame.pop();
  801. jvm.emitIREM();
  802. }
  803. /**
  804. * generate iand.
  805. */
  806.  
  807. def emitANDOP(frame:Frame) =
  808. {
  809. frame.pop();
  810. jvm.emitIAND();
  811. }
  812. /**
  813. * generate ior.
  814. */
  815. def emitOROP(frame:Frame) =
  816. {
  817. frame.pop();
  818. jvm.emitIOR();
  819. }
  820.  
  821. def emitREOP( op:String,frame:Frame) =
  822. {
  823. //..., value1, value2 -> ..., result
  824. val result = new StringBuffer();
  825. val labelF = frame.getNewLabel();
  826. val labelO = frame.getNewLabel();
  827. //println(in)
  828. frame.pop();
  829. frame.pop();
  830. op match {
  831. case ">" => result.append(jvm.emitIFICMPLE(labelF));
  832.  
  833. case ">=" => result.append(jvm.emitIFICMPLT(labelF));
  834.  
  835. case "<" => result.append(jvm.emitIFICMPGE(labelF));
  836.  
  837. case "<=" => result.append(jvm.emitIFICMPGT(labelF));
  838.  
  839. case "!=" =>
  840. result.append(jvm.emitIFICMPEQ(labelF))
  841.  
  842. case "==" => result.append(jvm.emitIFICMPNE(labelF))
  843.  
  844. }
  845. result.append(emitPUSHCONST("1", IntType,frame));
  846. frame.pop()
  847. result.append(emitGOTO(labelO,frame));
  848. result.append(emitLABEL(labelF,frame));
  849. result.append(emitPUSHCONST("0", IntType,frame));
  850. result.append(emitLABEL(labelO,frame));
  851. result.toString();
  852. }
  853. def emitRELOP( op:String, in:Type,trueLabel:Int,falseLabel:Int,frame:Frame) =
  854. {
  855. //..., value1, value2 -> ..., result
  856. val result = new StringBuffer();
  857. //val (isFalse,label) = if (trueLabel == CodeGenVisitor.FallThrough) (true,falseLabel) else (false,trueLabel)
  858. frame.pop();
  859. frame.pop();
  860. op match {
  861. case ">" => {
  862. result.append(jvm.emitIFICMPLE(falseLabel))
  863. result.append(jvm.emitGOTO(trueLabel))
  864. }
  865.  
  866. case ">=" => result.append(jvm.emitIFICMPLT(falseLabel))
  867.  
  868. case "<" => result.append(jvm.emitIFICMPGE(falseLabel))
  869.  
  870. case "<=" => result.append(jvm.emitIFICMPGT(falseLabel))
  871.  
  872. case "!=" => result.append(jvm.emitIFICMPEQ(falseLabel))
  873. case "==" => result.append(jvm.emitIFICMPNE(falseLabel))
  874.  
  875.  
  876. }
  877. result.append(jvm.emitGOTO(trueLabel))
  878. result.toString();
  879. }
  880. /** generate the method directive for a function.
  881. * @param lexeme the qualified name of the method(i.e., class-name/method-name).
  882. * @param in the type descriptor of the method.
  883. * @param isStatic <code>true</code> if the method is static; <code>false</code> otherwise.
  884. */
  885. def emitMETHOD( lexeme:String, in: Type, isStatic:Boolean,frame:Frame) = jvm.emitMETHOD(lexeme,getJVMType(in),isStatic)
  886. /** generate the end directive for a function.
  887. */
  888. def emitENDMETHOD(frame:Frame) = {
  889. var buffer = new StringBuffer();
  890. buffer.append(jvm.emitLIMITSTACK(frame.getMaxOpStackSize()));
  891. buffer.append(jvm.emitLIMITLOCAL(frame.getMaxIndex()));
  892. buffer.append(jvm.emitENDMETHOD());
  893. buffer.toString();
  894. }
  895.  
  896.  
  897. def getConst(ast:Literal)= ast match {
  898. case IntLiteral(i) => (i.toString,IntType)
  899.  
  900.  
  901. }
  902.  
  903. def emitNEWARRAY(typ : Type , frame: Frame) = {
  904. frame.push();
  905. typ match {
  906. case IntType => jvm.emitNEWARRAY("int")
  907. case FloatType => jvm.emitNEWARRAY("float")
  908. case BoolType => jvm.emitNEWARRAY("boolean")
  909. case StringType => jvm.emitANEWARRAY("java/lang/String")
  910. }
  911. }
  912. /** generate code to initialize a local array variable.<p>
  913. * @param index the index of the local variable.
  914. * @param in the type of the local array variable.
  915. */
  916.  
  917. /*public String emitINITARRAY(int index,Type in) throws CompilationException {
  918. StringBuffer buffer = new StringBuffer();
  919. ArrayType at = (ArrayType) in;
  920. ProductType rt = (ProductType) at.getIType();
  921. int element = 0;
  922. int dimension = 0;
  923. while (!(rt.getE1Type() == null && rt.getE2Type() == null)) {
  924. element = ((RangeType)rt.getE1Type()).getUpper();
  925. dimension++;
  926. buffer.append(emitPUSHICONST(element));
  927. rt = (ProductType) rt.getE2Type();
  928. }
  929. if (dimension == 1) {
  930. buffer.append(emitNEWARRAY(at.getEType()));
  931. frame.pop();
  932. buffer.append(jvm.emitASTORE(index));
  933. }
  934. else {
  935. for (int i = 0; i < dimension; i++)
  936. frame.pop();
  937. buffer.append(jvm.emitMULTIANEWARRAY(at.getJVMType(), dimension));
  938. buffer.append(jvm.emitASTORE(index));
  939. }
  940. return buffer.toString();
  941. }*/
  942. /** generate code to initialize local array variables.
  943. * @param in the list of symbol entries corresponding to local array variable.
  944. */
  945.  
  946. /* public String emitLISTARRAY(List<SymEntry> in) throws CompilationException {
  947. StringBuffer result = new StringBuffer();
  948. for (Iterator<SymEntry> it = in.iterator();it.hasNext();) {
  949. SymEntry sym = it.next();
  950. ArrayType at =(ArrayType)sym.getType();
  951. result.append(emitINITARRAY((Integer)sym.getObject(),at));
  952. }
  953. in.clear();
  954. return result.toString();
  955. }*/
  956. /**
  957. * generate code to jump to label if the value on top of operand stack is true.<p>
  958. * ifgt label
  959. * @param label the label where the execution continues if the value on top of stack is true.
  960. */
  961. def emitIFTRUE(label:Int,frame:Frame) =
  962. {
  963. frame.pop();
  964. jvm.emitIFGT(label);
  965. }
  966. /**
  967. * generate code to jump to label if the value on top of operand stack is false.<p>
  968. * ifle label
  969. * @param label the label where the execution continues if the value on top of stack is false.
  970. */
  971. def emitIFFALSE(label:Int,frame:Frame) =
  972. {
  973. frame.pop();
  974. jvm.emitIFLE(label);
  975. }
  976.  
  977. def emitIFICMPGT(label:Int,frame:Frame) =
  978. {
  979. frame.pop();
  980. jvm.emitIFICMPGT(label);
  981. }
  982.  
  983. def emitIFICMPLT(label:Int,frame:Frame) =
  984. {
  985. frame.pop();
  986. jvm.emitIFICMPLT(label);
  987. }
  988.  
  989. /** generate code to duplicate the value on the top of the operand stack.<p>
  990. * Stack:<p>
  991. * Before: ...,value1<p>
  992. * After: ...,value1,value1<p>
  993. */
  994. def emitDUP(frame:Frame) =
  995. {
  996. frame.push();
  997. jvm.emitDUP();
  998. }
  999. /** generate code to pop the value on the top of the operand stack.
  1000. */
  1001. def emitPOP(frame:Frame) =
  1002. {
  1003. frame.pop();
  1004. jvm.emitPOP();
  1005. }
  1006. /** generate code to exchange an integer on top of stack to a floating-point number.
  1007. */
  1008. def emitI2F(frame:Frame) = jvm.emitI2F()
  1009.  
  1010. /** generate code to return.
  1011. * <ul>
  1012. * <li>ireturn if the type is IntegerType or BooleanType
  1013. * <li>freturn if the type is RealType
  1014. * <li>return if the type is null
  1015. * </ul>
  1016. * @param in the type of the returned expression.
  1017. */
  1018.  
  1019. def emitRETURN(in:Type,frame:Frame) =
  1020. {
  1021. in match {
  1022. case (IntType|BoolType ) => frame.pop();jvm.emitIRETURN()
  1023. case (FloatType) => frame.pop();jvm.emitFRETURN()
  1024. case (ArrayType(_,_)|ArrayPointerType(_) ) => frame.pop();jvm.emitARETURN()
  1025. case VoidType => jvm.emitRETURN()
  1026.  
  1027. //case ClassType(_) => frame.pop();jvm.emitARETURN()
  1028. }
  1029. }
  1030. /** generate code that represents a label
  1031. * @param label the label
  1032. * @return code Label<label>:
  1033. */
  1034. def emitLABEL(label:Int,frame:Frame) = jvm.emitLABEL(label)
  1035.  
  1036. /** generate code to jump to a label
  1037. * @param label the label
  1038. * @return code goto Label<label>
  1039. */
  1040. def emitGOTO(label:Int,frame:Frame) = jvm.emitGOTO(label)
  1041.  
  1042. def emitIFEQ(label: Int, frame: Frame) = {
  1043. frame.pop()
  1044. jvm.emitIFEQ(label)
  1045. }
  1046. def emitIFGT(label: Int, frame: Frame) = {
  1047. frame.pop()
  1048. jvm.emitIFGT(label)
  1049. }
  1050. /** generate some starting directives for a class.<p>
  1051. * .source MPC.CLASSNAME.java<p>
  1052. * .class public MPC.CLASSNAME<p>
  1053. * .super java/lang/Object<p>
  1054. */
  1055. def emitPROLOG(name:String,parent:String) = {
  1056. val result = new StringBuffer();
  1057. result.append(jvm.emitSOURCE(name + ".java"));
  1058. result.append(jvm.emitCLASS("public " + name));
  1059. result.append(jvm.emitSUPER(if (parent == "") "java/lang/Object" else parent));
  1060. result.toString();
  1061. }
  1062.  
  1063. def emitLIMITSTACK(num:Int) = jvm.emitLIMITSTACK(num)
  1064.  
  1065. def emitLIMITLOCAL(num:Int) = jvm.emitLIMITLOCAL(num)
  1066.  
  1067. def emitEPILOG() = {
  1068. val file = new FileWriter(filename)
  1069. file.write(buff.toString())
  1070. file.close()
  1071. }
  1072.  
  1073. /** print out the code to screen
  1074. * @param in the code to be printed out
  1075. */
  1076. def printout(in:String) = buff.append(in);
  1077.  
  1078.  
  1079. def clearBuff() = buff.setLength(0);
  1080.  
  1081. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement