/*
 * Copyright 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev.js;

import com.google.gwt.dev.jjs.HasSourceInfo;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.js.ast.HasName;
import com.google.gwt.dev.js.ast.JsArrayAccess;
import com.google.gwt.dev.js.ast.JsArrayLiteral;
import com.google.gwt.dev.js.ast.JsBinaryOperation;
import com.google.gwt.dev.js.ast.JsBinaryOperator;
import com.google.gwt.dev.js.ast.JsBlock;
import com.google.gwt.dev.js.ast.JsBooleanLiteral;
import com.google.gwt.dev.js.ast.JsBreak;
import com.google.gwt.dev.js.ast.JsCase;
import com.google.gwt.dev.js.ast.JsCatch;
import com.google.gwt.dev.js.ast.JsConditional;
import com.google.gwt.dev.js.ast.JsContinue;
import com.google.gwt.dev.js.ast.JsDebugger;
import com.google.gwt.dev.js.ast.JsDefault;
import com.google.gwt.dev.js.ast.JsDoWhile;
import com.google.gwt.dev.js.ast.JsEmpty;
import com.google.gwt.dev.js.ast.JsExprStmt;
import com.google.gwt.dev.js.ast.JsExpression;
import com.google.gwt.dev.js.ast.JsFor;
import com.google.gwt.dev.js.ast.JsForIn;
import com.google.gwt.dev.js.ast.JsFunction;
import com.google.gwt.dev.js.ast.JsIf;
import com.google.gwt.dev.js.ast.JsInvocation;
import com.google.gwt.dev.js.ast.JsLabel;
import com.google.gwt.dev.js.ast.JsName;
import com.google.gwt.dev.js.ast.JsNameOf;
import com.google.gwt.dev.js.ast.JsNameRef;
import com.google.gwt.dev.js.ast.JsNew;
import com.google.gwt.dev.js.ast.JsNode;
import com.google.gwt.dev.js.ast.JsNullLiteral;
import com.google.gwt.dev.js.ast.JsNumberLiteral;
import com.google.gwt.dev.js.ast.JsNumericEntry;
import com.google.gwt.dev.js.ast.JsObjectLiteral;
import com.google.gwt.dev.js.ast.JsParameter;
import com.google.gwt.dev.js.ast.JsPostfixOperation;
import com.google.gwt.dev.js.ast.JsPrefixOperation;
import com.google.gwt.dev.js.ast.JsProgram;
import com.google.gwt.dev.js.ast.JsProgramFragment;
import com.google.gwt.dev.js.ast.JsPropertyInitializer;
import com.google.gwt.dev.js.ast.JsRegExp;
import com.google.gwt.dev.js.ast.JsReturn;
import com.google.gwt.dev.js.ast.JsSeedIdOf;
import com.google.gwt.dev.js.ast.JsStatement;
import com.google.gwt.dev.js.ast.JsStringLiteral;
import com.google.gwt.dev.js.ast.JsSwitch;
import com.google.gwt.dev.js.ast.JsSwitchMember;
import com.google.gwt.dev.js.ast.JsThisRef;
import com.google.gwt.dev.js.ast.JsThrow;
import com.google.gwt.dev.js.ast.JsTry;
import com.google.gwt.dev.js.ast.JsUnaryOperator;
import com.google.gwt.dev.js.ast.JsVars;
import com.google.gwt.dev.js.ast.JsVars.JsVar;
import com.google.gwt.dev.js.ast.JsWhile;
import com.google.gwt.dev.js.ast.NodeKind;
import com.google.gwt.thirdparty.guava.common.base.Preconditions;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import com.google.gwt.thirdparty.javascript.jscomp.AstValidator;
import com.google.gwt.thirdparty.javascript.rhino.IR;
import com.google.gwt.thirdparty.javascript.rhino.InputId;
import com.google.gwt.thirdparty.javascript.rhino.Node;
import com.google.gwt.thirdparty.javascript.rhino.Token;
import com.google.gwt.thirdparty.javascript.rhino.jstype.SimpleSourceFile;
import com.google.gwt.thirdparty.javascript.rhino.jstype.StaticSourceFile;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Translate a GWT JS AST to a Closure Compiler AST.
 */
public class ClosureJsAstTranslator {
  private static String getStringValue(double value) {
    long longValue = (long) value;

    // Return "1" instead of "1.0"
    if (longValue == value) {
      return Long.toString(longValue);
    } else {
      return Double.toString(value);
    }
  }

  private final Map<String, StaticSourceFile> sourceCache = new HashMap<String, StaticSourceFile>();

  private final boolean validate;
  private final Set<String> globalVars = Sets.newHashSet();
  private final Set<String> externalProperties = Sets.newHashSet();

  private final Set<String> externalVars = Sets.newHashSet();

  private final JsProgram program;

  ClosureJsAstTranslator(boolean validate, JsProgram program) {
    this.program = program;
    this.validate = validate;
  }

  public Node translate(JsProgramFragment fragment, InputId inputId, String source) {
    Node script = IR.script();
    script.putBooleanProp(Node.SYNTHETIC_BLOCK_PROP, true);
    script.setInputId(inputId);
    script.putProp(Node.SOURCENAME_PROP, source);
    script.setStaticSourceFile(getClosureSourceFile(source));
    for (JsStatement s : fragment.getGlobalBlock().getStatements()) {
      script.addChildToBack(transform(s));
    }
    // Validate the structural integrity of the AST.
    if (validate) {
      new AstValidator().validateScript(script);
    }
    return script;
  }

  Set<String> getExternalPropertyReferences() {
    return externalProperties;
  }

  Set<String> getExternalVariableReferences() {
    return externalVars;
  }

  Set<String> getGlobalVariableNames() {
    return globalVars;
  }

  private Node applyOriginalName(Node n, JsNode x) {
    /*
     * if (x instanceof HasSymbol) { Symbol symbol = ((HasSymbol)x).getSymbol(); if (symbol != null)
     * { String originalName = symbol.getOriginalSymbolName(); n.putProp(Node.ORIGINALNAME_PROP,
     * originalName); } }
     */
    return n;
  }

  private Node applySourceInfo(Node n, HasSourceInfo srcNode) {
    if (n != null && srcNode != null) {
      SourceInfo info = srcNode.getSourceInfo();
      if (info != null && info.getFileName() != null) {
        n.setStaticSourceFile(getClosureSourceFile(info.getFileName()));
        n.setLineno(info.getStartLine());
        n.setCharno(0);
      }
    }
    return n;
  }

  private StaticSourceFile getClosureSourceFile(String source) {
    StaticSourceFile closureSourceFile = sourceCache.get(source);
    if (closureSourceFile == null) {
      closureSourceFile = new SimpleSourceFile(source, false);
      sourceCache.put(source, closureSourceFile);
    }
    return closureSourceFile;
  }

  private String getName(JsName name) {
    return name.getShortIdent();
  }

  private String getName(JsNameRef name) {
    return name.getShortIdent();
  }

  private Node getNameNodeFor(HasName hasName) {
    Node n = IR.name(getName(hasName.getName()));
    applyOriginalName(n, (JsNode) hasName);
    return applySourceInfo(n, (HasSourceInfo) hasName);
  }

  private int getTokenForOp(JsBinaryOperator op) {
    switch (op) {
      case MUL:
        return Token.MUL;
      case DIV:
        return Token.DIV;
      case MOD:
        return Token.MOD;
      case ADD:
        return Token.ADD;
      case SUB:
        return Token.SUB;
      case SHL:
        return Token.LSH;
      case SHR:
        return Token.RSH;
      case SHRU:
        return Token.URSH;
      case LT:
        return Token.LT;
      case LTE:
        return Token.LE;
      case GT:
        return Token.GT;
      case GTE:
        return Token.GE;
      case INSTANCEOF:
        return Token.INSTANCEOF;
      case INOP:
        return Token.IN;
      case EQ:
        return Token.EQ;
      case NEQ:
        return Token.NE;
      case REF_EQ:
        return Token.SHEQ;
      case REF_NEQ:
        return Token.SHNE;
      case BIT_AND:
        return Token.BITAND;
      case BIT_XOR:
        return Token.BITXOR;
      case BIT_OR:
        return Token.BITOR;
      case AND:
        return Token.AND;
      case OR:
        return Token.OR;
      case ASG:
        return Token.ASSIGN;
      case ASG_ADD:
        return Token.ASSIGN_ADD;
      case ASG_SUB:
        return Token.ASSIGN_SUB;
      case ASG_MUL:
        return Token.ASSIGN_MUL;
      case ASG_DIV:
        return Token.ASSIGN_DIV;
      case ASG_MOD:
        return Token.ASSIGN_MOD;
      case ASG_SHL:
        return Token.ASSIGN_LSH;
      case ASG_SHR:
        return Token.ASSIGN_RSH;
      case ASG_SHRU:
        return Token.ASSIGN_URSH;
      case ASG_BIT_AND:
        return Token.ASSIGN_BITAND;
      case ASG_BIT_OR:
        return Token.ASSIGN_BITOR;
      case ASG_BIT_XOR:
        return Token.ASSIGN_BITXOR;
      case COMMA:
        return Token.COMMA;
    }
    return 0;
  }

  private int getTokenForOp(JsUnaryOperator op) {
    switch (op) {
      case BIT_NOT:
        return Token.BITNOT;
      case DEC:
        return Token.DEC;
      case DELETE:
        return Token.DELPROP;
      case INC:
        return Token.INC;
      case NEG:
        return Token.NEG;
      case POS:
        return Token.POS;
      case NOT:
        return Token.NOT;
      case TYPEOF:
        return Token.TYPEOF;
      case VOID:
        return Token.VOID;
    }
    throw new IllegalStateException();
  }

  private Node transform(JsArrayAccess x) {
    Node n = IR.getelem(transform(x.getArrayExpr()), transform(x.getIndexExpr()));
    return applySourceInfo(n, x);
  }

  private Node transform(JsArrayLiteral x) {
    Node n = IR.arraylit();
    for (Object element : x.getExpressions()) {
      JsExpression arg = (JsExpression) element;
      n.addChildToBack(transform(arg));
    }
    return applySourceInfo(n, x);
  }

  private Node transform(JsBinaryOperation x) {
    JsBinaryOperator op = x.getOperator();
    Node n = new Node(getTokenForOp(op), transform(x.getArg1()), transform(x.getArg2()));
    return applySourceInfo(n, x);
  }

  private Node transform(JsBlock x) {
    Node n = IR.block();
    for (JsStatement s : x.getStatements()) {
      n.addChildToBack(transform(s));
    }
    return applySourceInfo(n, x);
  }

  private Node transform(JsBooleanLiteral x) {
    Node n = x.getValue() ? IR.trueNode() : IR.falseNode();
    return applySourceInfo(n, x);
  }

  private Node transform(JsBreak x) {
    Node n;
    JsNameRef label = x.getLabel();
    if (label == null) {
      n = IR.breakNode();
    } else {
      n = IR.breakNode(transformLabel(label));
    }

    return applySourceInfo(n, x);
  }

  private Node transform(JsCase x) {
    Node expr = transform(x.getCaseExpr());
    Node body = IR.block();
    body.putBooleanProp(Node.SYNTHETIC_BLOCK_PROP, true);
    applySourceInfo(body, x);

    for (Object element : x.getStmts()) {
      JsStatement stmt = (JsStatement) element;
      body.addChildToBack(transform(stmt));
    }

    Node n = IR.caseNode(expr, body);
    return applySourceInfo(n, x);
  }

  private Node transform(JsCatch x) {
    Node n = IR.catchNode(transformName(x.getParameter().getName()), transform(x.getBody()));
    Preconditions.checkState(x.getCondition() == null);
    return applySourceInfo(n, x);
  }

  private Node transform(JsConditional x) {
    Node n =
        IR.hook(transform(x.getTestExpression()), transform(x.getThenExpression()), transform(x
            .getElseExpression()));
    return applySourceInfo(n, x);
  }

  private Node transform(JsContinue x) {
    Node n;
    JsNameRef label = x.getLabel();
    if (label == null) {
      n = IR.continueNode();
    } else {
      n = IR.continueNode(transformLabel(label));
    }

    return applySourceInfo(n, x);
  }

  private Node transform(JsDebugger x) {
    Node n = new Node(Token.DEBUGGER);
    return applySourceInfo(n, x);
  }

  private Node transform(JsDefault x) {
    Node body = IR.block();
    body.putBooleanProp(Node.SYNTHETIC_BLOCK_PROP, true);
    applySourceInfo(body, x);

    for (Object element : x.getStmts()) {
      JsStatement stmt = (JsStatement) element;
      body.addChildToBack(transform(stmt));
    }
    Node n = IR.defaultCase(body);
    return applySourceInfo(n, x);
  }

  private Node transform(JsDoWhile x) {
    Node n = IR.doNode(transformBody(x.getBody(), x), transform(x.getCondition()));
    return applySourceInfo(n, x);
  }

  private Node transform(JsEmpty x) {
    return IR.empty();
  }

  private Node transform(JsExpression x) {
    assert x != null;
    switch (x.getKind()) {
      case ARRAY:
        return transform((JsArrayLiteral) x);
      case ARRAY_ACCESS:
        return transform((JsArrayAccess) x);
      case BINARY_OP:
        return transform((JsBinaryOperation) x);
      case CONDITIONAL:
        return transform((JsConditional) x);
      case INVOKE:
        return transform((JsInvocation) x);
      case FUNCTION:
        return transform((JsFunction) x);
      case OBJECT:
        return transform((JsObjectLiteral) x);
      case BOOLEAN:
        return transform((JsBooleanLiteral) x);
      case NULL:
        return transform((JsNullLiteral) x);
      case NUMBER:
        if (x instanceof JsNumericEntry) {
          return transform((JsNumericEntry) x);
        }
        return transform((JsNumberLiteral) x);
      case REGEXP:
        return transform((JsRegExp) x);
      case STRING:
        return transform((JsStringLiteral) x);
      case THIS:
        return transform((JsThisRef) x);
      case NAME_OF:
        return transform((JsNameOf) x);
      case SEED_ID_OF:
        return transform((JsSeedIdOf) x);
      case NAME_REF:
        return transform((JsNameRef) x);
      case NEW:
        return transform((JsNew) x);
      case POSTFIX_OP:
        return transform((JsPostfixOperation) x);
      case PREFIX_OP:
        return transform((JsPrefixOperation) x);
      default:
        throw new IllegalStateException("Unexpected expression type: "
            + x.getClass().getSimpleName());
    }
  }

  private Node transform(JsExprStmt x) {
    // The GWT JS AST doesn't produce function declarations, instead
    // they are expressions statements:
    Node expr = transform(x.getExpression());
    if (!expr.isFunction()) {
      return IR.exprResult(expr);
    } else {
      return expr;
    }
  }

  private Node transform(JsFor x) {
    // The init expressions or var decl.
    //
    Node init;
    if (x.getInitExpr() != null) {
      init = transform(x.getInitExpr());
    } else if (x.getInitVars() != null) {
      init = transform(x.getInitVars());
    } else {
      init = IR.empty();
    }

    // The loop test.
    //
    Node cond;
    if (x.getCondition() != null) {
      cond = transform(x.getCondition());
    } else {
      cond = IR.empty();
    }

    // The incr expression.
    //
    Node incr;
    if (x.getIncrExpr() != null) {
      incr = transform(x.getIncrExpr());
    } else {
      incr = IR.empty();
    }

    Node body = transformBody(x.getBody(), x);
    Node n = IR.forNode(init, cond, incr, body);
    return applySourceInfo(n, x);
  }

  private Node transform(JsForIn x) {
    Node valueExpr;
    if (x.getIterVarName() != null) {
      valueExpr = new Node(Token.VAR, transformName(x.getIterVarName()));
    } else {
      // Just a name ref.
      //
      valueExpr = transform(x.getIterExpr());
    }

    Node n = IR.forIn(valueExpr, transform(x.getObjExpr()), transformBody(x.getBody(), x));
    return applySourceInfo(n, x);
  }

  private Node transform(JsFunction x) {
    Node name;
    if (x.getName() != null) {
      name = getNameNodeFor(x);
    } else {
      name = IR.name("");
    }
    applySourceInfo(name, x);

    Node params = IR.paramList();
    for (Object element : x.getParameters()) {
      JsParameter param = (JsParameter) element;
      params.addChildToBack(transform(param));
    }
    applySourceInfo(params, x);

    Node n = IR.function(name, params, transform(x.getBody()));
    if (name.getString().isEmpty()) {
      n.putProp(Node.ORIGINALNAME_PROP, "");
    } else {
      applyOriginalName(n, x);
    }

    /*
     * if (x.isConstructor()) { JSDocInfoBuilder builder = new JSDocInfoBuilder(false);
     * builder.recordConstructor(); n.setJSDocInfo(builder.build(n)); }
     */

    return applySourceInfo(n, x);
  }

  private Node transform(JsIf x) {
    Node n = IR.ifNode(transform(x.getIfExpr()), transformBody(x.getThenStmt(), x));
    if (x.getElseStmt() != null) {
      n.addChildToBack(transformBody(x.getElseStmt(), x));
    }
    return applySourceInfo(n, x);
  }

  private Node transform(JsInvocation x) {
    Node n = IR.call(transform(x.getQualifier()));
    for (Object element : x.getArguments()) {
      JsExpression arg = (JsExpression) element;
      n.addChildToBack(transform(arg));
    }
    return applySourceInfo(n, x);
  }

  private Node transform(JsLabel x) {
    Node n = IR.label(transformLabel(x.getName()), transform(x.getStmt()));

    return applySourceInfo(n, x);
  }

  private Node transform(JsNameOf x) {
    Node n = transformName(x.getName().getShortIdent(), x);
    applyOriginalName(n, x);
    return applySourceInfo(n, x);
  }

  private Node transform(JsNameRef x) {
    Node n;
    JsName name = x.getName();
    boolean isExternal = name == null || !name.isObfuscatable();
    if (x.getQualifier() != null) {
      n = IR.getprop(transform(x.getQualifier()), transformNameAsString(x.getShortIdent(), x));
      if (isExternal) {
        this.externalProperties.add(x.getShortIdent());
      }
    } else {
      n = transformName(x.getShortIdent(), x);
      if (isExternal) {
        this.externalVars.add(x.getShortIdent());
      } else if (name.getEnclosing() == program.getScope()) {
        this.globalVars.add(x.getShortIdent());
      }
    }
    applyOriginalName(n, x);
    return applySourceInfo(n, x);
  }

  private Node transform(JsNew x) {
    Node n = IR.newNode(transform(x.getConstructorExpression()));
    for (Object element : x.getArguments()) {
      JsExpression arg = (JsExpression) element;
      n.addChildToBack(transform(arg));
    }
    return applySourceInfo(n, x);
  }

  private Node transform(JsNullLiteral x) {
    return IR.nullNode();
  }

  private Node transform(JsNumericEntry x) {
    return IR.number(x.getValue());
  }
  
  private Node transform(JsNumberLiteral x) {
    return IR.number(x.getValue());
  }

  private Node transform(JsObjectLiteral x) {
    Node n = IR.objectlit();

    for (Object element : x.getPropertyInitializers()) {
      JsPropertyInitializer propInit = (JsPropertyInitializer) element;
      Node key;
      if (propInit.getLabelExpr().getKind() == NodeKind.NUMBER) {
        key = transformNumberAsString((JsNumberLiteral) propInit.getLabelExpr());
        key.putBooleanProp(Node.QUOTED_PROP, true);
      } else if (propInit.getLabelExpr().getKind() == NodeKind.NAME_REF) {
        key =
            transformNameAsString(((JsNameRef) propInit.getLabelExpr()).getShortIdent(), propInit
                .getLabelExpr());
      } else {
        key = transform(propInit.getLabelExpr());
      }
      Preconditions.checkState(key.isString(), key);
      n.addChildToBack(IR.propdef(key, transform(propInit.getValueExpr())));
    }
    return applySourceInfo(n, x);
  }

  private Node transform(JsParameter x) {
    return getNameNodeFor(x);
  }

  private Node transform(JsPostfixOperation x) {
    Node n = new Node(getTokenForOp(x.getOperator()), transform(x.getArg()));
    n.putBooleanProp(Node.INCRDECR_PROP, true);
    return applySourceInfo(n, x);
  }

  private Node transform(JsPrefixOperation x) {
    Node n = new Node(getTokenForOp(x.getOperator()), transform(x.getArg()));
    return applySourceInfo(n, x);
  }

  private Node transform(JsRegExp x) {
    String flags = x.getFlags();
    Node n =
        IR.regexp(Node.newString(x.getPattern()), Node.newString(flags != null ? x.getFlags() : ""));
    return applySourceInfo(n, x);
  }

  private Node transform(JsReturn x) {
    Node n = IR.returnNode();
    JsExpression result = x.getExpr();
    if (result != null) {
      n.addChildToBack(transform(x.getExpr()));
    }
    return applySourceInfo(n, x);
  }

  private Node transform(JsSeedIdOf x) {
    Node n = Node.newNumber(x.getSeedId());
    return applySourceInfo(n, x);
  }

  private Node transform(JsStatement x) {
    switch (x.getKind()) {
      case BLOCK:
        return transform((JsBlock) x);
      case BREAK:
        return transform((JsBreak) x);
      case CONTINUE:
        return transform((JsContinue) x);
      case DEBUGGER:
        return transform((JsDebugger) x);
      case DO:
        return transform((JsDoWhile) x);
      case EMPTY:
        return transform((JsEmpty) x);
      case EXPR_STMT:
        return transform((JsExprStmt) x);
      case FOR:
        return transform((JsFor) x);
      case FOR_IN:
        return transform((JsForIn) x);
      case IF:
        return transform((JsIf) x);
      case LABEL:
        return transform((JsLabel) x);
      case RETURN:
        return transform((JsReturn) x);
      case SWITCH:
        return transform((JsSwitch) x);
      case THROW:
        return transform((JsThrow) x);
      case TRY:
        return transform((JsTry) x);
      case VARS:
        return transform((JsVars) x);
      case WHILE:
        return transform((JsWhile) x);
      default:
        throw new IllegalStateException("Unexpected statement type: "
            + x.getClass().getSimpleName());
    }
  }

  private Node transform(JsStringLiteral x) {
    return IR.string(x.getValue());
  }

  private Node transform(JsSwitch x) {
    Node n = IR.switchNode(transform(x.getExpr()));
    for (JsSwitchMember member : x.getCases()) {
      n.addChildToBack(transform(member));
    }
    return applySourceInfo(n, x);
  }

  private Node transform(JsSwitchMember x) {
    switch (x.getKind()) {
      case CASE:
        return transform((JsCase) x);
      case DEFAULT:
        return transform((JsDefault) x);
      default:
        throw new IllegalStateException("Unexpected switch member type: "
            + x.getClass().getSimpleName());
    }
  }

  private Node transform(JsThisRef x) {
    Node n = new Node(Token.THIS);
    return applySourceInfo(n, x);
  }

  private Node transform(JsThrow x) {
    Node n = IR.throwNode(transform(x.getExpr()));
    return applySourceInfo(n, x);
  }

  private Node transform(JsTry x) {
    Node n = new Node(Token.TRY, transform(x.getTryBlock()));

    Node catches = new Node(Token.BLOCK);
    for (JsCatch catchBlock : x.getCatches()) {
      catches.addChildToBack(transform(catchBlock));
    }
    n.addChildToBack(catches);

    JsBlock finallyBlock = x.getFinallyBlock();
    if (finallyBlock != null) {
      n.addChildToBack(transform(finallyBlock));
    }

    return applySourceInfo(n, x);
  }

  private Node transform(JsVar x) {
    Node n = getNameNodeFor(x);
    JsExpression initExpr = x.getInitExpr();
    if (initExpr != null) {
      n.addChildToBack(transform(initExpr));
    }
    return applySourceInfo(n, x);
  }

  private Node transform(JsVars x) {
    Node n = new Node(Token.VAR);
    for (JsVar var : x) {
      n.addChildToBack(transform(var));
    }
    return applySourceInfo(n, x);
  }

  private Node transform(JsWhile x) {
    Node n =
        IR.forNode(IR.empty(), transform(x.getCondition()), IR.empty(), transformBody(x.getBody(),
            x));
    return applySourceInfo(n, x);
  }

  private Node transformBody(JsStatement x, HasSourceInfo parent) {
    Node n = transform(x);
    if (!n.isBlock()) {
      Node stmt = n;
      n = IR.block();
      if (!stmt.isEmpty()) {
        n.addChildToBack(stmt);
      }
      applySourceInfo(n, parent);
    }
    return n;
  }

  private Node transformLabel(JsName label) {
    Node n = IR.labelName(getName(label));
    return applySourceInfo(n, label.getStaticRef());
  }

  private Node transformLabel(JsNameRef label) {
    Node n = IR.labelName(getName(label));
    return applySourceInfo(n, label);
  }

  private Node transformName(JsName name) {
    Node n = IR.name(getName(name));
    return applySourceInfo(n, name.getStaticRef());
  }

  private Node transformName(String name, HasSourceInfo info) {
    Node n = IR.name(name);
    return applySourceInfo(n, info);
  }

  private Node transformNameAsString(String name, HasSourceInfo info) {
    Node n = IR.string(name);
    return applySourceInfo(n, info);
  }

  private Node transformNumberAsString(JsNumberLiteral literalNode) {
    Node irNode = Node.newString(getStringValue(literalNode.getValue()));
    return irNode;
  }
}
