PageRenderTime 54ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/scala/jsengine/rewriter/JSRewriter.scala

http://github.com/jankroken/jsengine
Scala | 172 lines | 163 code | 9 blank | 0 comment | 2 complexity | 80a49a68491a176acfce04f70dd92c01 MD5 | raw file
  1. package jsengine.rewriter
  2. import jsengine.ast._
  3. object JSRewriter {
  4. private def rewriteOptionExpression(optExpr: Option[JSBaseExpression]):Option[JSBaseExpression] = {
  5. optExpr match {
  6. case None => None
  7. case Some(expr) => Some(rewriteExpression(expr))
  8. }
  9. }
  10. private def rewriteExpression (expression: JSBaseExpression): JSBaseExpression = {
  11. expression match {
  12. case JSExpression(expressions) => JSExpression(expressions.map(rewriteExpression))
  13. case AssignmentExpression(operator, leftHand, rightHand) => {
  14. def expandAssignment(operator: Operator, leftHand: JSBaseExpression, rightHand: JSBaseExpression): Assign = {
  15. Assign(rewriteExpression(leftHand),
  16. rewriteExpression(BinaryExpression(leftHand,List(BinaryExtension(operator,rightHand)))))
  17. }
  18. operator match {
  19. case Operator("=") => Assign(rewriteExpression(leftHand), rewriteExpression(rightHand))
  20. case Operator("*=") => expandAssignment(Operator("*"),leftHand, rightHand)
  21. case Operator("/=") => expandAssignment(Operator("/"),leftHand, rightHand)
  22. case Operator("%=") => expandAssignment(Operator("%"),leftHand, rightHand)
  23. case Operator("+=") => expandAssignment(Operator("+"),leftHand, rightHand)
  24. case Operator("-=") => expandAssignment(Operator("_"),leftHand, rightHand)
  25. case Operator("<<=") => expandAssignment(Operator("<<"),leftHand, rightHand)
  26. case Operator(">>=") => expandAssignment(Operator(">>"),leftHand, rightHand)
  27. case Operator(">>>=") => expandAssignment(Operator(">>>"),leftHand, rightHand)
  28. case Operator("&=") => expandAssignment(Operator("&"),leftHand, rightHand)
  29. case Operator("^=") => expandAssignment(Operator("^"),leftHand, rightHand)
  30. case Operator("|=") => expandAssignment(Operator("|"),leftHand, rightHand)
  31. }
  32. }
  33. case ConditionalExpression(condition, trueExpression, falseExpression) =>
  34. ConditionalExpression(rewriteExpression(condition),
  35. rewriteExpression(trueExpression),
  36. rewriteExpression(falseExpression))
  37. case OperatorCall(operator: Operator, args: List[JSBaseExpression]) => // only to handle recursion in bottom-up replacement
  38. OperatorCall(operator,args.map(rewriteExpression))
  39. case Lookup(expr,index) => Lookup(rewriteExpression(expr),rewriteExpression(index))
  40. case New(function,args) => New(rewriteExpression(function),args.map(rewriteExpression))
  41. case Call(function,args) => Call(rewriteExpression(function),args.map(rewriteExpression))
  42. case Assign(left,value) => Assign(rewriteExpression(left), rewriteExpression(value))
  43. case BinaryExpression(right,List()) => rewriteExpression(right)
  44. case BinaryExpression(right,BinaryExtension(operator,expr) :: tail) =>
  45. rewriteExpression(BinaryExpression(OperatorCall(operator,
  46. List(rewriteExpression(right),
  47. rewriteExpression(expr))),tail))
  48. case UnaryExpression(List(),expression) => rewriteExpression(expression)
  49. case UnaryExpression(operator :: tail,expression) => OperatorCall(operator, List(rewriteExpression(UnaryExpression(tail,expression))))
  50. case PostfixExpression(expression,operator) => PostfixExpression(rewriteExpression(expression), operator)
  51. case CallExpression(0, function, List()) => rewriteExpression(function)
  52. case CallExpression(n, function, List()) => {
  53. rewriteExpression(CallExpression(n-1,New(function,List()),List()))
  54. }
  55. case CallExpression(newCount, function, ApplyLookup(index) :: tail) => {
  56. rewriteExpression(CallExpression(newCount, Lookup(rewriteExpression(function),rewriteExpression(index)), tail))
  57. }
  58. case CallExpression(newCount, function, ApplyArguments(args) :: tail) => {
  59. if (newCount > 0 ) {
  60. rewriteExpression(CallExpression(newCount-1,New(function,args), tail))
  61. } else {
  62. rewriteExpression(CallExpression(0,Call(function, args),tail))
  63. }
  64. }
  65. case JSArrayLiteral(elements) => JSArrayLiteral(elements.map(rewriteOptionExpression))
  66. case JSFunction(functionName,arguments, source) => {
  67. val functionSource = (List[JSStatement]() /: source) ((x,y) => { x ::: rewriteStatement(y)})
  68. JSFunction(functionName,arguments,functionSource)
  69. }
  70. case JSBoolean(value) => JSBoolean(value)
  71. case JSIdentifier(value) => JSIdentifier(value)
  72. case JSNativeCall(identifier) => JSNativeCall(identifier)
  73. case JSLiteralObject(properties) => {
  74. JSLiteralObject(properties.map({
  75. (property) => {
  76. property match {
  77. case (name, value) => (name, rewriteExpression(value))
  78. }
  79. }
  80. }))
  81. }
  82. case JSNumber(value) => JSNumber(value)
  83. case JSString(value) => JSString(value)
  84. case JSRegexLiteral(value) => JSRegexLiteral(value)
  85. }
  86. }
  87. private def forToWhile(forStatement: ForStatement) : JSStatement = {
  88. forStatement match {
  89. case ForStatement(init,ForSemicolonUpdate(cond,update),body) => {
  90. val whileBody = update match {
  91. case None => body
  92. case Some(statement) => JSBlock(List(body,statement))
  93. }
  94. val whileCond = cond match {
  95. case None => JSBoolean(true)
  96. case Some(condition) => condition
  97. }
  98. val whileStatement = While(whileCond,whileBody)
  99. init match {
  100. case None => whileStatement
  101. case Some(ForInit(initStatement)) => JSBlock(List(initStatement,whileStatement))
  102. }
  103. }
  104. case _ => throw new RuntimeException("should not happen")
  105. }
  106. }
  107. private def rewriteStatement (statement: JSStatement) : List[JSStatement] = {
  108. statement match {
  109. case JSBlock(statements) => List(JSBlock((List[JSStatement]() /: statements) ((x,y) => { x ::: rewriteStatement(y)})))
  110. case VariableDeclarations(declarations) => (List[JSStatement]() /: declarations) ((x,y) => { x ::: rewriteStatement(y)})
  111. case VariableDeclaration(name, None) => Declare(name) :: List()
  112. case VariableDeclaration(name, Some(initialValue)) => Declare(name) :: Assign(name,rewriteExpression(initialValue)) :: List()
  113. case EmptyStatement() => List(EmptyStatement())
  114. case IfStatement(condition, whenTrue, None) => List(IfStatement(rewriteExpression(condition),
  115. JSBlock(rewriteStatement(whenTrue)),
  116. None))
  117. case IfStatement(condition, whenTrue, Some(whenFalse)) => List(IfStatement(rewriteExpression(condition),
  118. JSBlock(rewriteStatement(whenTrue)),
  119. Some(JSBlock(rewriteStatement(whenFalse)))))
  120. case DoWhile (statement, condition) => List(DoWhile(JSBlock(rewriteStatement(statement)),rewriteExpression(condition)))
  121. case While (condition, statement) => List(While(rewriteExpression(condition),JSBlock(rewriteStatement(statement))))
  122. case ForStatement(Some(ForInit(init)), ForInUpdate(expr),body) => List(ForIn(JSBlock(rewriteStatement(init)),rewriteExpression(expr),body))
  123. case forStatement @ ForStatement(init, update:ForSemicolonUpdate,body) => rewriteStatement(forToWhile(forStatement))
  124. case ContinueStatement(label) => List(statement)
  125. case BreakStatement(label) => List(statement)
  126. case ReturnStatement(None) => List(statement)
  127. case ReturnStatement(Some(value)) => List(ReturnStatement(Some(rewriteExpression(value))))
  128. case WithStatement(expr, statement) => List(WithStatement(rewriteExpression(expr),JSBlock(rewriteStatement(statement))))
  129. case SwitchStatement(expr, cases) => {
  130. def rewriteCase(caseClause: CaseClause): CaseClause = {
  131. caseClause match {
  132. case LabeledCaseClause(label,statements) =>
  133. LabeledCaseClause(label,(List[JSStatement]() /: statements) ({(x,y) => { x ::: rewriteStatement(y) }}))
  134. case DefaultClause(statements) =>
  135. DefaultClause((List[JSStatement]() /: statements) ({(x,y) => { x ::: rewriteStatement(y) }}))
  136. }
  137. }
  138. List(SwitchStatement(rewriteExpression(expr),cases.map(rewriteCase)))
  139. }
  140. case LabeledStatement(label, statement) => List(LabeledStatement(label, JSBlock(rewriteStatement(statement))))
  141. case ThrowStatement(expr) => List(ThrowStatement(rewriteExpression(expr)))
  142. case TryStatement(block, TryTail(None,None,Some(finallyBlock))) => {
  143. List(Try(JSBlock(rewriteStatement(block)),None,Some(JSBlock(rewriteStatement(finallyBlock)))))
  144. }
  145. case TryStatement(block, TryTail(Some(id),Some(catchBlock),None)) => {
  146. List(Try(JSBlock(rewriteStatement(block)),Some(Catch(id,JSBlock(rewriteStatement(catchBlock)))),None))
  147. }
  148. case TryStatement(block, TryTail(Some(id),Some(catchBlock),Some(finallyStatement))) => {
  149. List(Try(JSBlock(rewriteStatement(block)),
  150. Some(Catch(id,JSBlock(rewriteStatement(catchBlock)))),
  151. Some(JSBlock(rewriteStatement(finallyStatement)))))
  152. }
  153. case DebuggerStatement() => List(statement)
  154. case expr:JSBaseExpression => List(rewriteExpression(expr))
  155. case unhandledStatement => throw new RuntimeException("Implementation error: missing handling of AST node: "+unhandledStatement)
  156. }
  157. }
  158. def rewriteSource (source: JSSource) : JSSource = {
  159. source match {
  160. case JSSource(statements) => JSSource((List[JSStatement]() /: statements) ((x,y) => { x ::: rewriteStatement(y)}))
  161. }
  162. }
  163. }