public JsFunction mapFunction(Node fnNode) throws JsParserException { int nodeType = fnNode.getType(); assert nodeType == TokenStream.FUNCTION : "Expected function node, got: " + TokenStream.tokenToName(nodeType); Node fromFnNameNode = fnNode.getFirstChild(); Node fromParamNode = fnNode.getFirstChild().getNext().getFirstChild(); Node fromBodyNode = fnNode.getFirstChild().getNext().getNext(); JsFunction toFn = scopeContext.enterFunction(); // Decide the function's name, if any. // String fnNameIdent = fromFnNameNode.getString(); if (fnNameIdent != null && fnNameIdent.length() > 0) { scopeContext.globalNameFor(fnNameIdent); } while (fromParamNode != null) { String fromParamName = fromParamNode.getString(); JsName name = scopeContext.localNameFor(fromParamName); toFn.getParameters().add(new JsParameter(name)); fromParamNode = fromParamNode.getNext(); } // Map the function's body. // JsBlock toBody = mapBlock(fromBodyNode); toFn.setBody(toBody); scopeContext.exitFunction(); return toFn; }
private JsStatement mapDoOrWhileStatement(boolean isWhile, Node ifNode) throws JsParserException { // Pull out the pieces we want to map. // Node fromTestExpr; Node fromBody; if (isWhile) { fromTestExpr = ifNode.getFirstChild(); fromBody = ifNode.getFirstChild().getNext(); } else { fromBody = ifNode.getFirstChild(); fromTestExpr = ifNode.getFirstChild().getNext(); } // Map the test expression. // JsExpression toTestExpr = mapExpression(fromTestExpr); // Map the body block. // JsStatement toBody = mapStatement(fromBody); // Create and attach the "while" or "do" statement we're mapping to. // if (isWhile) { return new JsWhile(toTestExpr, toBody); } else { return new JsDoWhile(toTestExpr, toBody); } }
private JsIf mapIfStatement(Node ifNode) throws JsParserException { // Pull out the pieces we want to map. // Node fromTestExpr = ifNode.getFirstChild(); Node fromThenBlock = ifNode.getFirstChild().getNext(); Node fromElseBlock = ifNode.getFirstChild().getNext().getNext(); // Create the "if" statement we're mapping to. // JsIf toIf = new JsIf(); // Map the test expression. // JsExpression toTestExpr = mapExpression(fromTestExpr); toIf.setIfExpression(toTestExpr); // Map the "then" block. // toIf.setThenStatement(mapStatement(fromThenBlock)); // Map the "else" block. // if (fromElseBlock != null) { toIf.setElseStatement(mapStatement(fromElseBlock)); } return toIf; }
private JsExpression mapUnaryVariant(Node unOp) throws JsParserException { switch (unOp.getIntDatum()) { case TokenStream.SUB: return mapPrefixOperation(JsUnaryOperator.NEG, unOp); case TokenStream.NOT: return mapPrefixOperation(JsUnaryOperator.NOT, unOp); case TokenStream.BITNOT: return mapPrefixOperation(JsUnaryOperator.BIT_NOT, unOp); case TokenStream.TYPEOF: return mapPrefixOperation(JsUnaryOperator.TYPEOF, unOp); case TokenStream.ADD: if (!isJsNumber(unOp.getFirstChild())) { return mapPrefixOperation(JsUnaryOperator.POS, unOp); } else { // Pretend we didn't see it. return mapExpression(unOp.getFirstChild()); } case TokenStream.VOID: return mapPrefixOperation(JsUnaryOperator.VOID, unOp); default: throw createParserException("Unknown unary operator variant: " + unOp.getIntDatum(), unOp); } }
private JsTry mapTryStatement(Node tryNode) throws JsParserException { JsTry toTry = new JsTry(); // Map the "try" body. // Node fromTryBody = tryNode.getFirstChild(); toTry.setTryBlock(mapBlock(fromTryBody)); // Map zero or more catch blocks. // Node fromCatchNodes = fromTryBody.getNext(); Node fromCatchNode = fromCatchNodes.getFirstChild(); while (fromCatchNode != null) { assert (fromCatchNode.getType() == TokenStream.CATCH); // Map the catch variable. // Node fromCatchVarName = fromCatchNode.getFirstChild(); JsCatch catchBlock = scopeContext.enterCatch(fromCatchVarName.getString()); // Pre-advance to the next catch block, if any. // We do this here to decide whether or not this is the last one. // fromCatchNode = fromCatchNode.getNext(); // Map the condition, with a little fixup based on whether or not // this is the last catch block. // Node fromCondition = fromCatchVarName.getNext(); JsExpression toCondition = mapExpression(fromCondition); catchBlock.setCondition(toCondition); if (fromCatchNode == null) { if (toCondition instanceof JsBooleanLiteral) { if (((JsBooleanLiteral) toCondition).getValue()) { // Actually, this is an unconditional catch block. // Indicate that by nulling the condition. // catchBlock.setCondition(null); } } } // Map the catch body. // Node fromCatchBody = fromCondition.getNext(); catchBlock.setBody(mapBlock(fromCatchBody)); // Attach it. // toTry.getCatches().add(catchBlock); scopeContext.exitCatch(); } Node fromFinallyNode = fromCatchNodes.getNext(); if (fromFinallyNode != null) { toTry.setFinallyBlock(mapBlock(fromFinallyNode)); } return toTry; }
private JsLabel mapLabel(Node labelNode) throws JsParserException { String fromName = labelNode.getFirstChild().getString(); JsName toName = scopeContext.enterLabel(fromName); Node fromStmt = labelNode.getFirstChild().getNext(); JsLabel toLabel = new JsLabel(toName); toLabel.setStatement(mapStatement(fromStmt)); scopeContext.exitLabel(); return toLabel; }
private JsSwitch mapSwitchStatement(Node switchNode) throws JsParserException { JsSwitch toSwitch = new JsSwitch(); // The switch expression. // Node fromSwitchExpr = switchNode.getFirstChild(); toSwitch.setExpression(mapExpression(fromSwitchExpr)); // The members. // Node fromMember = fromSwitchExpr.getNext(); while (fromMember != null) { if (fromMember.getType() == TokenStream.CASE) { JsCase toCase = new JsCase(); // Set the case expression. In JS, this can be any expression. // Node fromCaseExpr = fromMember.getFirstChild(); toCase.setCaseExpression(mapExpression(fromCaseExpr)); // Set the case statements. // Node fromCaseBlock = fromCaseExpr.getNext(); mapStatements(toCase.getStatements(), fromCaseBlock); // Attach the case to the switch. // toSwitch.getCases().add(toCase); } else { // This should be the only default statement. // If more than one is present, we keep the last one. // assert (fromMember.getType() == TokenStream.DEFAULT); JsDefault toDefault = new JsDefault(); // Set the default statements. // Node fromDefaultBlock = fromMember.getFirstChild(); mapStatements(toDefault.getStatements(), fromDefaultBlock); // Attach the default to the switch. // toSwitch.getCases().add(toDefault); } fromMember = fromMember.getNext(); } return toSwitch; }
private JsExpression mapObjectLit(Node objLitNode) throws JsParserException { JsObjectLiteral toLit = new JsObjectLiteral(); Node fromPropInit = objLitNode.getFirstChild(); while (fromPropInit != null) { Node fromLabelExpr = fromPropInit; JsExpression toLabelExpr = mapExpression(fromLabelExpr); // Advance to the initializer expression. // fromPropInit = fromPropInit.getNext(); Node fromValueExpr = fromPropInit; if (fromValueExpr == null) { throw createParserException("Expected an init expression for: " + toLabelExpr, objLitNode); } JsExpression toValueExpr = mapExpression(fromValueExpr); JsPropertyInitializer toPropInit = new JsPropertyInitializer(toLabelExpr, toValueExpr); toLit.getPropertyInitializers().add(toPropInit); // Begin the next property initializer, if there is one. // fromPropInit = fromPropInit.getNext(); } return toLit; }
private JsThrow mapThrowStatement(Node throwNode) throws JsParserException { // Create, map, and attach. // Node fromExpr = throwNode.getFirstChild(); JsThrow toThrow = new JsThrow(mapExpression(fromExpr)); return toThrow; }
private JsArrayLiteral mapArrayLit(Node node) throws JsParserException { JsArrayLiteral toLit = new JsArrayLiteral(); Node from = node.getFirstChild(); while (from != null) { toLit.getExpressions().add(mapExpression(from)); from = from.getNext(); } return toLit; }
private JsArrayAccess mapGetElem(Node getElemNode) throws JsParserException { Node from1 = getElemNode.getFirstChild(); Node from2 = from1.getNext(); JsExpression to1 = mapExpression(from1); JsExpression to2 = mapExpression(from2); return new JsArrayAccess(to1, to2); }
private JsExpression mapBinaryOperation(JsBinaryOperator op, Node node) throws JsParserException { Node from1 = node.getFirstChild(); Node from2 = from1.getNext(); JsExpression to1 = mapExpression(from1); JsExpression to2 = mapExpression(from2); return new JsBinaryOperation(op, to1, to2); }
private JsReturn mapReturn(Node returnNode) throws JsParserException { JsReturn toReturn = new JsReturn(); Node from = returnNode.getFirstChild(); if (from != null) { JsExpression to = mapExpression(from); toReturn.setExpression(to); } return toReturn; }
private JsExpression mapSetProp(Node getPropNode) throws JsParserException { // Reuse the get prop code. // JsNameRef lhs = mapGetProp(getPropNode); // Map the RHS. // Node fromRhs = getPropNode.getFirstChild().getNext().getNext(); JsExpression toRhs = mapExpression(fromRhs); return new JsBinaryOperation(JsBinaryOperator.ASG, lhs, toRhs); }
private JsExpression mapDeleteProp(Node node) throws JsParserException { Node from = node.getFirstChild(); JsExpression to = mapExpression(from); if (to instanceof JsNameRef) { return new JsPrefixOperation(JsUnaryOperator.DELETE, to); } else if (to instanceof JsArrayAccess) { return new JsPrefixOperation(JsUnaryOperator.DELETE, to); } else { throw createParserException( "'delete' can only operate on property names and array elements", from); } }
private JsExpression mapSetElem(Node setElemNode) throws JsParserException { // Reuse the get elem code. // JsArrayAccess lhs = mapGetElem(setElemNode); // Map the RHS. // Node fromRhs = setElemNode.getFirstChild().getNext().getNext(); JsExpression toRhs = mapExpression(fromRhs); return new JsBinaryOperation(JsBinaryOperator.ASG, lhs, toRhs); }
private JsNode mapRegExp(Node regExpNode) { JsRegExp toRegExp = new JsRegExp(); Node fromPattern = regExpNode.getFirstChild(); toRegExp.setPattern(fromPattern.getString()); Node fromFlags = fromPattern.getNext(); if (fromFlags != null) { toRegExp.setFlags(fromFlags.getString()); } return toRegExp; }
private void mapStatements(List<JsStatement> stmts, Node nodeStmts) throws JsParserException { Node curr = nodeStmts.getFirstChild(); while (curr != null) { JsStatement stmt = mapStatement(curr); if (stmt != null) { stmts.add(stmt); } else { // When mapStatement() returns null, we just ignore it. // } curr = curr.getNext(); } }
private JsExpression mapConditional(Node condNode) throws JsParserException { JsConditional toCond = new JsConditional(); Node fromTest = condNode.getFirstChild(); toCond.setTestExpression(mapExpression(fromTest)); Node fromThen = fromTest.getNext(); toCond.setThenExpression(mapExpression(fromThen)); Node fromElse = fromThen.getNext(); toCond.setElseExpression(mapExpression(fromElse)); return toCond; }
private JsVars mapVar(Node varNode) throws JsParserException { JsVars toVars = new JsVars(); Node fromVar = varNode.getFirstChild(); while (fromVar != null) { // Use a conservative name allocation strategy that allocates all names // from the function's scope, even the names of properties in field // literals. // String fromName = fromVar.getString(); JsName toName = scopeContext.localNameFor(fromName); JsVars.JsVar toVar = new JsVars.JsVar(toName); Node fromInit = fromVar.getFirstChild(); if (fromInit != null) { JsExpression toInit = mapExpression(fromInit); toVar.setInitExpression(toInit); } toVars.add(toVar); fromVar = fromVar.getNext(); } return toVars; }
private JsInvocation mapCall(Node callNode) throws JsParserException { // Map the target expression. // Node from = callNode.getFirstChild(); JsExpression qualifier = mapExpression(from); // Iterate over and map the arguments. // List<JsExpression> arguments = new SmartList<JsExpression>(); from = from.getNext(); while (from != null) { arguments.add(mapExpression(from)); from = from.getNext(); } return new JsInvocation(qualifier, arguments); }
private JsNew mapNew(Node newNode) throws JsParserException { // Map the constructor expression, which is often just the name of // some lambda. // Node fromCtorExpr = newNode.getFirstChild(); JsNew newExpr = new JsNew(mapExpression(fromCtorExpr)); // Iterate over and map the arguments. // List<JsExpression> args = newExpr.getArguments(); Node fromArg = fromCtorExpr.getNext(); while (fromArg != null) { args.add(mapExpression(fromArg)); fromArg = fromArg.getNext(); } return newExpr; }
private JsNameRef mapGetProp(Node getPropNode) throws JsParserException { Node from1 = getPropNode.getFirstChild(); Node from2 = from1.getNext(); JsExpression toQualifier = mapExpression(from1); JsNameRef toNameRef; if (from2 != null) { toNameRef = mapAsPropertyNameRef(from2); } else { // Special properties don't have a second expression. // Object obj = getPropNode.getProp(Node.SPECIAL_PROP_PROP); assert (obj instanceof String); toNameRef = scopeContext.referenceFor((String) obj); } toNameRef.setQualifier(toQualifier); return toNameRef; }
@Nullable private JsNameRef getTargetLabel(@NotNull Node statementWithLabel) { int type = statementWithLabel.getType(); if (type != TokenStream.BREAK && type != TokenStream.CONTINUE) { String tokenTypeName = TokenStream.tokenToName(statementWithLabel.getType()); throw new AssertionError("Unexpected node type with label: " + tokenTypeName); } Node label = statementWithLabel.getFirstChild(); if (label == null) return null; String identifier = label.getString(); assert identifier != null : "If label exists identifier should not be null"; JsName labelName = scopeContext.labelFor(identifier); assert labelName != null : "Unknown label name: " + identifier; return labelName.makeRef(); }
private JsStatement mapForStatement(Node forNode) throws JsParserException { Node fromInit = forNode.getFirstChild(); Node fromTest = fromInit.getNext(); Node fromIncr = fromTest.getNext(); Node fromBody = fromIncr.getNext(); if (fromBody == null) { // This could be a "for...in" structure. // We could based on the different child layout. // Node fromIter = forNode.getFirstChild(); Node fromObjExpr = fromIter.getNext(); fromBody = fromObjExpr.getNext(); JsForIn toForIn; if (fromIter.getType() == TokenStream.VAR) { // A named iterator var. // Node fromIterVarName = fromIter.getFirstChild(); String fromName = fromIterVarName.getString(); JsName toName = scopeContext.localNameFor(fromName); toForIn = new JsForIn(toName); Node fromIterInit = fromIterVarName.getFirstChild(); if (fromIterInit != null) { // That has an initializer expression (useful only for side effects). // toForIn.setIterExpression(mapOptionalExpression(fromIterInit)); } } else { // An unnamed iterator var. // toForIn = new JsForIn(); toForIn.setIterExpression(mapExpression(fromIter)); } toForIn.setObjectExpression(mapExpression(fromObjExpr)); // The body stmt. // JsStatement bodyStmt = mapStatement(fromBody); if (bodyStmt != null) { toForIn.setBody(bodyStmt); } else { toForIn.setBody(JsEmpty.INSTANCE$); } return toForIn; } else { // Regular ol' for loop. // JsFor toFor; // The first item is either an expression or a JsVars. JsNode init = map(fromInit); JsExpression condition = mapOptionalExpression(fromTest); JsExpression increment = mapOptionalExpression(fromIncr); assert (init != null); if (init instanceof JsVars) { toFor = new JsFor((JsVars) init, condition, increment); } else { assert (init instanceof JsExpression); toFor = new JsFor((JsExpression) init, condition, increment); } JsStatement bodyStmt = mapStatement(fromBody); if (bodyStmt != null) { toFor.setBody(bodyStmt); } else { toFor.setBody(JsEmpty.INSTANCE$); } return toFor; } }
private JsStatement mapExpressionStatement(Node node) throws JsParserException { JsExpression expr = mapExpression(node.getFirstChild()); return expr.makeStmt(); }
private JsExpression mapPrefixOperation(JsUnaryOperator op, Node node) throws JsParserException { Node from = node.getFirstChild(); JsExpression to = mapExpression(from); return new JsPrefixOperation(op, to); }