summaryrefslogtreecommitdiff
path: root/examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/optimizer/ClosureAstTransformer.scala
diff options
context:
space:
mode:
Diffstat (limited to 'examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/optimizer/ClosureAstTransformer.scala')
-rw-r--r--examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/optimizer/ClosureAstTransformer.scala397
1 files changed, 0 insertions, 397 deletions
diff --git a/examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/optimizer/ClosureAstTransformer.scala b/examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/optimizer/ClosureAstTransformer.scala
deleted file mode 100644
index af22501..0000000
--- a/examples/scala-js/tools/jvm/src/main/scala/scala/scalajs/tools/optimizer/ClosureAstTransformer.scala
+++ /dev/null
@@ -1,397 +0,0 @@
-package scala.scalajs.tools.optimizer
-
-import scala.scalajs.ir
-import ir.Position
-import ir.Position.NoPosition
-
-import scala.scalajs.tools.javascript.Trees._
-
-import com.google.javascript.rhino._
-import com.google.javascript.jscomp._
-
-import scala.collection.mutable
-import scala.annotation.tailrec
-
-import java.net.URI
-
-class ClosureAstTransformer(val relativizeBaseURI: Option[URI] = None) {
-
- private val inputId = new InputId("Scala.js IR")
-
- private val dummySourceName = new java.net.URI("virtualfile:scala.js-ir")
-
- def transformStat(tree: Tree)(implicit parentPos: Position): Node =
- innerTransformStat(tree, tree.pos orElse parentPos)
-
- private def innerTransformStat(tree: Tree, pos_in: Position): Node = {
- implicit val pos = pos_in
-
- wrapTransform(tree) {
- case VarDef(ident, _, EmptyTree) =>
- new Node(Token.VAR, transformName(ident))
- case VarDef(ident, _, rhs) =>
- val node = transformName(ident)
- node.addChildToFront(transformExpr(rhs))
- new Node(Token.VAR, node)
- case Skip() =>
- new Node(Token.EMPTY)
- case Block(stats) =>
- transformBlock(stats, pos)
- case Labeled(label, body) =>
- new Node(Token.LABEL, transformLabel(label), transformBlock(body))
- case Return(EmptyTree) =>
- new Node(Token.RETURN)
- case Return(expr) =>
- new Node(Token.RETURN, transformExpr(expr))
- case If(cond, thenp, Skip()) =>
- new Node(Token.IF, transformExpr(cond), transformBlock(thenp))
- case If(cond, thenp, elsep) =>
- new Node(Token.IF, transformExpr(cond),
- transformBlock(thenp), transformBlock(elsep))
- case While(cond, body, None) =>
- new Node(Token.WHILE, transformExpr(cond), transformBlock(body))
- case While(cond, body, Some(label)) =>
- val whileNode =
- new Node(Token.WHILE, transformExpr(cond), transformBlock(body))
- new Node(Token.LABEL, transformLabel(label),
- setNodePosition(whileNode, pos))
- case DoWhile(body, cond, None) =>
- new Node(Token.DO, transformBlock(body), transformExpr(cond))
- case DoWhile(body, cond, Some(label)) =>
- val doNode =
- new Node(Token.DO, transformBlock(body), transformExpr(cond))
- new Node(Token.LABEL, transformLabel(label),
- setNodePosition(doNode, pos))
- case Try(block, errVar, handler, EmptyTree) =>
- val catchPos = handler.pos orElse pos
- val catchNode =
- new Node(Token.CATCH, transformName(errVar), transformBlock(handler))
- val blockNode =
- new Node(Token.BLOCK, setNodePosition(catchNode, catchPos))
- new Node(Token.TRY, transformBlock(block),
- setNodePosition(blockNode, catchPos))
- case Try(block, _, EmptyTree, finalizer) =>
- val blockNode = setNodePosition(new Node(Token.BLOCK), pos)
- new Node(Token.TRY, transformBlock(block), blockNode,
- transformBlock(finalizer))
- case Try(block, errVar, handler, finalizer) =>
- val catchPos = handler.pos orElse pos
- val catchNode =
- new Node(Token.CATCH, transformName(errVar), transformBlock(handler))
- val blockNode =
- new Node(Token.BLOCK, setNodePosition(catchNode, catchPos))
- new Node(Token.TRY, transformBlock(block),
- setNodePosition(blockNode, catchPos), transformBlock(finalizer))
- case Throw(expr) =>
- new Node(Token.THROW, transformExpr(expr))
- case Break(None) =>
- new Node(Token.BREAK)
- case Break(Some(label)) =>
- new Node(Token.BREAK, transformLabel(label))
- case Continue(None) =>
- new Node(Token.CONTINUE)
- case Continue(Some(label)) =>
- new Node(Token.CONTINUE, transformLabel(label))
-
- case Switch(selector, cases, default) =>
- val switchNode = new Node(Token.SWITCH, transformExpr(selector))
-
- for ((expr, body) <- cases) {
- val bodyNode = transformBlock(body)
- bodyNode.putBooleanProp(Node.SYNTHETIC_BLOCK_PROP, true)
- val caseNode = new Node(Token.CASE, transformExpr(expr), bodyNode)
- switchNode.addChildToBack(
- setNodePosition(caseNode, expr.pos orElse pos))
- }
-
- if (default != EmptyTree) {
- val bodyNode = transformBlock(default)
- bodyNode.putBooleanProp(Node.SYNTHETIC_BLOCK_PROP, true)
- val caseNode = new Node(Token.DEFAULT_CASE, bodyNode)
- switchNode.addChildToBack(
- setNodePosition(caseNode, default.pos orElse pos))
- }
-
- switchNode
-
- case Debugger() =>
- new Node(Token.DEBUGGER)
- case _ =>
- // We just assume it is an expression
- new Node(Token.EXPR_RESULT, transformExpr(tree))
- }
- }
-
- def transformExpr(tree: Tree)(implicit parentPos: Position): Node =
- innerTransformExpr(tree, tree.pos orElse parentPos)
-
- private def innerTransformExpr(tree: Tree, pos_in: Position): Node = {
- implicit val pos = pos_in
-
- wrapTransform(tree) {
- case Block(exprs) =>
- exprs.map(transformExpr).reduceRight { (expr1, expr2) =>
- setNodePosition(new Node(Token.COMMA, expr1, expr2), pos)
- }
- case If(cond, thenp, elsep) =>
- new Node(Token.HOOK, transformExpr(cond),
- transformExpr(thenp), transformExpr(elsep))
- case Assign(lhs, rhs) =>
- new Node(Token.ASSIGN, transformExpr(lhs), transformExpr(rhs))
- case New(ctor, args) =>
- val node = new Node(Token.NEW, transformExpr(ctor))
- args.foreach(arg => node.addChildToBack(transformExpr(arg)))
- node
- case DotSelect(qualifier, item) =>
- new Node(Token.GETPROP, transformExpr(qualifier), transformString(item))
- case BracketSelect(qualifier, item) =>
- new Node(Token.GETELEM, transformExpr(qualifier), transformExpr(item))
-
- case Apply(fun, args) =>
- val node = new Node(Token.CALL, transformExpr(fun))
- args.foreach(arg => node.addChildToBack(transformExpr(arg)))
-
- // Closure needs to know (from the parser), if the call has a bound
- // `this` or not. Since JSDesugar inserts protects calls if necessary,
- // it is sufficient to check if we have a select as target
- if (!fun.isInstanceOf[DotSelect] &&
- !fun.isInstanceOf[BracketSelect])
- node.putBooleanProp(Node.FREE_CALL, true)
-
- node
-
- case Delete(prop) =>
- new Node(Token.DELPROP, transformExpr(prop))
- case UnaryOp(op, lhs) =>
- mkUnaryOp(op, transformExpr(lhs))
- case BinaryOp(op, lhs, rhs) =>
- mkBinaryOp(op, transformExpr(lhs), transformExpr(rhs))
- case ArrayConstr(items) =>
- val node = new Node(Token.ARRAYLIT)
- items.foreach(i => node.addChildToBack(transformExpr(i)))
- node
-
- case ObjectConstr(fields) =>
- val node = new Node(Token.OBJECTLIT)
-
- for ((name, expr) <- fields) {
- val fldNode = transformStringKey(name)
- fldNode.addChildToBack(transformExpr(expr))
- node.addChildToBack(fldNode)
- }
-
- node
-
- case Undefined() =>
- new Node(Token.VOID, setNodePosition(Node.newNumber(0.0), pos))
- case Null() =>
- new Node(Token.NULL)
- case BooleanLiteral(value) =>
- if (value) new Node(Token.TRUE) else new Node(Token.FALSE)
- case IntLiteral(value) =>
- Node.newNumber(value)
- case DoubleLiteral(value) =>
- Node.newNumber(value)
- case StringLiteral(value) =>
- Node.newString(value)
- case VarRef(ident, _) =>
- transformName(ident)
- case This() =>
- new Node(Token.THIS)
-
- case Function(args, body) =>
- // Note that a Function may also be a statement (when it is named),
- // but Scala.js does not have such an IR node
- val paramList = new Node(Token.PARAM_LIST)
- args.foreach(arg => paramList.addChildToBack(transformParam(arg)))
-
- val emptyName = setNodePosition(Node.newString(Token.NAME, ""), pos)
-
- new Node(Token.FUNCTION, emptyName, paramList, transformBlock(body))
-
- case _ =>
- throw new TransformException(s"Unknown tree of class ${tree.getClass()}")
- }
- }
-
- def transformParam(param: ParamDef)(implicit parentPos: Position): Node =
- transformName(param.name)
-
- def transformName(ident: Ident)(implicit parentPos: Position): Node =
- setNodePosition(Node.newString(Token.NAME, ident.name),
- ident.pos orElse parentPos)
-
- def transformLabel(ident: Ident)(implicit parentPos: Position): Node =
- setNodePosition(Node.newString(Token.LABEL_NAME, ident.name),
- ident.pos orElse parentPos)
-
- def transformString(pName: PropertyName)(implicit parentPos: Position): Node =
- setNodePosition(Node.newString(pName.name), pName.pos orElse parentPos)
-
- def transformStringKey(pName: PropertyName)(
- implicit parentPos: Position): Node = {
- val node = Node.newString(Token.STRING_KEY, pName.name)
-
- if (pName.isInstanceOf[StringLiteral])
- node.setQuotedString()
-
- setNodePosition(node, pName.pos orElse parentPos)
- }
-
- def transformBlock(tree: Tree)(implicit parentPos: Position): Node = {
- val pos = if (tree.pos.isDefined) tree.pos else parentPos
- wrapTransform(tree) {
- case Block(stats) =>
- transformBlock(stats, pos)
- case tree =>
- transformBlock(List(tree), pos)
- } (pos)
- }
-
- def transformBlock(stats: List[Tree], blockPos: Position): Node = {
- @inline def ctorDoc(node: Node) = {
- val b = new JSDocInfoBuilder(false)
- b.recordConstructor()
- b.build(node)
- }
-
- val block = new Node(Token.BLOCK)
-
- // The Rhino IR attaches DocComments to the following nodes (rather than
- // having individual nodes). We preprocess these here.
- @tailrec
- def loop(ts: List[Tree], nextIsCtor: Boolean = false): Unit = ts match {
- case DocComment(text) :: tss if text.startsWith("@constructor") =>
- loop(tss, nextIsCtor = true)
- case DocComment(text) :: tss =>
- loop(tss)
- case t :: tss =>
- val node = transformStat(t)(blockPos)
- if (nextIsCtor) {
- // The @constructor must be propagated through an ExprResult node
- val trg =
- if (node.isExprResult()) node.getChildAtIndex(0)
- else node
-
- trg.setJSDocInfo(ctorDoc(trg))
- }
-
- block.addChildToBack(node)
-
- loop(tss)
- case Nil =>
- }
-
- loop(stats)
-
- block
- }
-
- @inline
- private def wrapTransform(tree: Tree)(body: Tree => Node)(
- implicit pos: Position): Node = {
- try {
- setNodePosition(body(tree), pos)
- } catch {
- case e: TransformException =>
- throw e // pass through
- case e: RuntimeException =>
- throw new TransformException(tree, e)
- }
- }
-
- def setNodePosition(node: Node, pos: ir.Position): node.type = {
- if (pos != ir.Position.NoPosition) {
- attachSourceFile(node, pos.source)
- node.setLineno(pos.line+1)
- node.setCharno(pos.column)
- } else {
- attachSourceFile(node, dummySourceName)
- }
- node
- }
-
- private def attachSourceFile(node: Node, source: URI): node.type = {
- val str = sourceUriToString(source)
-
- node.setInputId(inputId)
- node.setStaticSourceFile(new SourceFile(str))
-
- node
- }
-
- private def sourceUriToString(uri: URI): String = {
- val relURI = relativizeBaseURI.fold(uri)(ir.Utils.relativize(_, uri))
- ir.Utils.fixFileURI(relURI).toASCIIString
- }
-
- // Helpers for IR
- @inline
- private def mkUnaryOp(op: String, lhs: Node): Node = {
- val tok = op match {
- case "!" => Token.NOT
- case "~" => Token.BITNOT
- case "+" => Token.POS
- case "-" => Token.NEG
- case "typeof" => Token.TYPEOF
- case _ => throw new TransformException(s"Unhandled unary op: $op")
- }
-
- new Node(tok, lhs)
- }
-
- @inline
- private def mkBinaryOp(op: String, lhs: Node, rhs: Node): Node = {
- val tok = op match {
- case "|" => Token.BITOR
- case "&" => Token.BITAND
- case "^" => Token.BITXOR
- case "==" => Token.EQ
- case "!=" => Token.NE
- case "<" => Token.LT
- case "<=" => Token.LE
- case ">" => Token.GT
- case ">=" => Token.GE
- case "<<" => Token.LSH
- case ">>" => Token.RSH
- case ">>>" => Token.URSH
- case "+" => Token.ADD
- case "-" => Token.SUB
- case "*" => Token.MUL
- case "/" => Token.DIV
- case "%" => Token.MOD
- case "===" => Token.SHEQ
- case "!==" => Token.SHNE
- case "in" => Token.IN
- case "instanceof" => Token.INSTANCEOF
- case "||" => Token.OR
- case "&&" => Token.AND
- case _ =>
- throw new TransformException(s"Unhandled binary op: $op")
- }
-
- new Node(tok, lhs, rhs)
- }
-
- // Exception wrapper in transforms
-
- class TransformException private (msg: String, e: Throwable)
- extends RuntimeException(msg, e) {
-
- def this(tree: Tree, e: Throwable) =
- this(TransformException.mkMsg(tree), e)
-
- def this(msg: String) = this(msg, null)
- }
-
- object TransformException {
- import ir.Printers._
- import java.io._
-
- private def mkMsg(tree: Tree): String = {
- "Exception while translating Scala.js JS tree to GCC IR at tree:\n" +
- tree.show
- }
- }
-
-}