Search in sources :

Example 26 with FunctionNode

use of org.mozilla.javascript.ast.FunctionNode in project HL4A by HL4A.

the class Parser method function.

private FunctionNode function(int type) throws IOException {
    int syntheticType = type;
    // line number where source starts
    int baseLineno = ts.lineno;
    // start of "function" kwd
    int functionSourceStart = ts.tokenBeg;
    Name name = null;
    AstNode memberExprNode = null;
    if (matchToken(Token.NAME)) {
        name = createNameNode(true, Token.NAME);
        if (inUseStrictDirective) {
            String id = name.getIdentifier();
            if ("eval".equals(id) || "arguments".equals(id)) {
                reportError("msg.bad.id.strict", id);
            }
        }
        if (!matchToken(Token.LP)) {
            if (compilerEnv.isAllowMemberExprAsFunctionName()) {
                AstNode memberExprHead = name;
                name = null;
                memberExprNode = memberExprTail(false, memberExprHead);
            }
            mustMatchToken(Token.LP, "msg.no.paren.parms");
        }
    } else if (matchToken(Token.LP)) {
    // Anonymous function:  leave name as null
    } else {
        if (compilerEnv.isAllowMemberExprAsFunctionName()) {
            // Note that memberExpr can not start with '(' like
            // in function (1+2).toString(), because 'function (' already
            // processed as anonymous function
            memberExprNode = memberExpr(false);
        }
        mustMatchToken(Token.LP, "msg.no.paren.parms");
    }
    int lpPos = currentToken == Token.LP ? ts.tokenBeg : -1;
    if (memberExprNode != null) {
        syntheticType = FunctionNode.FUNCTION_EXPRESSION;
    }
    if (syntheticType != FunctionNode.FUNCTION_EXPRESSION && name != null && name.length() > 0) {
        // Function statements define a symbol in the enclosing scope
        defineSymbol(Token.FUNCTION, name.getIdentifier());
    }
    FunctionNode fnNode = new FunctionNode(functionSourceStart, name);
    fnNode.setFunctionType(type);
    if (lpPos != -1)
        fnNode.setLp(lpPos - functionSourceStart);
    fnNode.setJsDocNode(getAndResetJsDoc());
    PerFunctionVariables savedVars = new PerFunctionVariables(fnNode);
    try {
        parseFunctionParams(fnNode);
        fnNode.setBody(parseFunctionBody(type, fnNode));
        fnNode.setEncodedSourceBounds(functionSourceStart, ts.tokenEnd);
        fnNode.setLength(ts.tokenEnd - functionSourceStart);
        if (compilerEnv.isStrictMode() && !fnNode.getBody().hasConsistentReturnUsage()) {
            String msg = (name != null && name.length() > 0) ? "msg.no.return.value" : "msg.anon.no.return.value";
            addStrictWarning(msg, name == null ? "" : name.getIdentifier());
        }
    } finally {
        savedVars.restore();
    }
    if (memberExprNode != null) {
        // TODO(stevey): fix missing functionality
        Kit.codeBug();
        // rewrite later
        fnNode.setMemberExprNode(memberExprNode);
    /* old code:
            if (memberExprNode != null) {
                pn = nf.createAssignment(Token.ASSIGN, memberExprNode, pn);
                if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
                    // XXX check JScript behavior: should it be createExprStatement?
                    pn = nf.createExprStatementNoReturn(pn, baseLineno);
                }
            }
            */
    }
    fnNode.setSourceName(sourceURI);
    fnNode.setBaseLineno(baseLineno);
    fnNode.setEndLineno(ts.lineno);
    // at the function boundary when checking for redeclarations.
    if (compilerEnv.isIdeMode()) {
        fnNode.setParentScope(currentScope);
    }
    return fnNode;
}
Also used : FunctionNode(org.mozilla.javascript.ast.FunctionNode) XmlString(org.mozilla.javascript.ast.XmlString) AstNode(org.mozilla.javascript.ast.AstNode) Name(org.mozilla.javascript.ast.Name)

Example 27 with FunctionNode

use of org.mozilla.javascript.ast.FunctionNode in project HL4A by HL4A.

the class Parser method arrowFunction.

private AstNode arrowFunction(AstNode params) throws IOException {
    // line number where source starts
    int baseLineno = ts.lineno;
    // start of "function" kwd
    int functionSourceStart = params != null ? params.getPosition() : -1;
    FunctionNode fnNode = new FunctionNode(functionSourceStart);
    fnNode.setFunctionType(FunctionNode.ARROW_FUNCTION);
    fnNode.setJsDocNode(getAndResetJsDoc());
    // Would prefer not to call createDestructuringAssignment until codegen,
    // but the symbol definitions have to happen now, before body is parsed.
    Map<String, Node> destructuring = new HashMap<String, Node>();
    Set<String> paramNames = new HashSet<String>();
    PerFunctionVariables savedVars = new PerFunctionVariables(fnNode);
    try {
        if (params instanceof ParenthesizedExpression) {
            fnNode.setParens(0, params.getLength());
            AstNode p = ((ParenthesizedExpression) params).getExpression();
            if (!(p instanceof EmptyExpression)) {
                arrowFunctionParams(fnNode, p, destructuring, paramNames);
            }
        } else {
            arrowFunctionParams(fnNode, params, destructuring, paramNames);
        }
        if (!destructuring.isEmpty()) {
            Node destructuringNode = new Node(Token.COMMA);
            // Add assignment helper for each destructuring parameter
            for (Map.Entry<String, Node> param : destructuring.entrySet()) {
                Node assign = createDestructuringAssignment(Token.VAR, param.getValue(), createName(param.getKey()));
                destructuringNode.addChildToBack(assign);
            }
            fnNode.putProp(Node.DESTRUCTURING_PARAMS, destructuringNode);
        }
        fnNode.setBody(parseFunctionBody(FunctionNode.ARROW_FUNCTION, fnNode));
        fnNode.setEncodedSourceBounds(functionSourceStart, ts.tokenEnd);
        fnNode.setLength(ts.tokenEnd - functionSourceStart);
    } finally {
        savedVars.restore();
    }
    if (fnNode.isGenerator()) {
        reportError("msg.arrowfunction.generator");
        return makeErrorNode();
    }
    fnNode.setSourceName(sourceURI);
    fnNode.setBaseLineno(baseLineno);
    fnNode.setEndLineno(ts.lineno);
    return fnNode;
}
Also used : ParenthesizedExpression(org.mozilla.javascript.ast.ParenthesizedExpression) HashMap(java.util.HashMap) ScriptNode(org.mozilla.javascript.ast.ScriptNode) AstNode(org.mozilla.javascript.ast.AstNode) LetNode(org.mozilla.javascript.ast.LetNode) ErrorNode(org.mozilla.javascript.ast.ErrorNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) XmlString(org.mozilla.javascript.ast.XmlString) EmptyExpression(org.mozilla.javascript.ast.EmptyExpression) Map(java.util.Map) HashMap(java.util.HashMap) AstNode(org.mozilla.javascript.ast.AstNode) HashSet(java.util.HashSet)

Example 28 with FunctionNode

use of org.mozilla.javascript.ast.FunctionNode in project HL4A by HL4A.

the class Parser method returnOrYield.

private AstNode returnOrYield(int tt, boolean exprContext) throws IOException {
    if (!insideFunction()) {
        reportError(tt == Token.RETURN ? "msg.bad.return" : "msg.bad.yield");
    }
    consumeToken();
    int lineno = ts.lineno, pos = ts.tokenBeg, end = ts.tokenEnd;
    AstNode e = null;
    // This is ugly, but we don't want to require a semicolon.
    switch(peekTokenOrEOL()) {
        case Token.SEMI:
        case Token.RC:
        case Token.RB:
        case Token.RP:
        case Token.EOF:
        case Token.EOL:
        case Token.ERROR:
        case Token.YIELD:
            break;
        default:
            e = expr();
            end = getNodeEnd(e);
    }
    int before = endFlags;
    AstNode ret;
    if (tt == Token.RETURN) {
        endFlags |= e == null ? Node.END_RETURNS : Node.END_RETURNS_VALUE;
        ret = new ReturnStatement(pos, end - pos, e);
        // see if we need a strict mode warning
        if (nowAllSet(before, endFlags, Node.END_RETURNS | Node.END_RETURNS_VALUE))
            addStrictWarning("msg.return.inconsistent", "", pos, end - pos);
    } else {
        if (!insideFunction())
            reportError("msg.bad.yield");
        endFlags |= Node.END_YIELDS;
        ret = new Yield(pos, end - pos, e);
        setRequiresActivation();
        setIsGenerator();
        if (!exprContext) {
            ret = new ExpressionStatement(ret);
        }
    }
    // see if we are mixing yields and value returns.
    if (insideFunction() && nowAllSet(before, endFlags, Node.END_YIELDS | Node.END_RETURNS_VALUE)) {
        Name name = ((FunctionNode) currentScriptOrFn).getFunctionName();
        if (name == null || name.length() == 0)
            addError("msg.anon.generator.returns", "");
        else
            addError("msg.generator.returns", name.getIdentifier());
    }
    ret.setLineno(lineno);
    return ret;
}
Also used : ExpressionStatement(org.mozilla.javascript.ast.ExpressionStatement) ReturnStatement(org.mozilla.javascript.ast.ReturnStatement) FunctionNode(org.mozilla.javascript.ast.FunctionNode) Yield(org.mozilla.javascript.ast.Yield) AstNode(org.mozilla.javascript.ast.AstNode) Name(org.mozilla.javascript.ast.Name)

Example 29 with FunctionNode

use of org.mozilla.javascript.ast.FunctionNode in project HL4A by HL4A.

the class BodyCodegen method generateEpilogue.

private void generateEpilogue() {
    if (compilerEnv.isGenerateObserverCount())
        addInstructionCount();
    if (isGenerator) {
        // generate locals initialization
        Map<Node, int[]> liveLocals = ((FunctionNode) scriptOrFn).getLiveLocals();
        if (liveLocals != null) {
            List<Node> nodes = ((FunctionNode) scriptOrFn).getResumptionPoints();
            for (int i = 0; i < nodes.size(); i++) {
                Node node = nodes.get(i);
                int[] live = liveLocals.get(node);
                if (live != null) {
                    cfw.markTableSwitchCase(generatorSwitch, getNextGeneratorState(node));
                    generateGetGeneratorLocalsState();
                    for (int j = 0; j < live.length; j++) {
                        cfw.add(ByteCode.DUP);
                        cfw.addLoadConstant(j);
                        cfw.add(ByteCode.AALOAD);
                        cfw.addAStore(live[j]);
                    }
                    cfw.add(ByteCode.POP);
                    cfw.add(ByteCode.GOTO, getTargetLabel(node));
                }
            }
        }
        // generate dispatch tables for finally
        if (finallys != null) {
            for (Node n : finallys.keySet()) {
                if (n.getType() == Token.FINALLY) {
                    FinallyReturnPoint ret = finallys.get(n);
                    // the finally will jump here
                    cfw.markLabel(ret.tableLabel, (short) 1);
                    // start generating a dispatch table
                    int startSwitch = cfw.addTableSwitch(0, ret.jsrPoints.size() - 1);
                    int c = 0;
                    cfw.markTableSwitchDefault(startSwitch);
                    for (int i = 0; i < ret.jsrPoints.size(); i++) {
                        // generate gotos back to the JSR location
                        cfw.markTableSwitchCase(startSwitch, c);
                        cfw.add(ByteCode.GOTO, ret.jsrPoints.get(i).intValue());
                        c++;
                    }
                }
            }
        }
    }
    if (epilogueLabel != -1) {
        cfw.markLabel(epilogueLabel);
    }
    if (hasVarsInRegs) {
        cfw.add(ByteCode.ARETURN);
        return;
    } else if (isGenerator) {
        if (((FunctionNode) scriptOrFn).getResumptionPoints() != null) {
            cfw.markTableSwitchDefault(generatorSwitch);
        }
        // change state for re-entry
        generateSetGeneratorResumptionPoint(GENERATOR_TERMINATE);
        // throw StopIteration
        cfw.addALoad(variableObjectLocal);
        addOptRuntimeInvoke("throwStopIteration", "(Ljava/lang/Object;)V");
        Codegen.pushUndefined(cfw);
        cfw.add(ByteCode.ARETURN);
    } else if (fnCurrent == null) {
        cfw.addALoad(popvLocal);
        cfw.add(ByteCode.ARETURN);
    } else {
        generateActivationExit();
        cfw.add(ByteCode.ARETURN);
        // Generate catch block to catch all and rethrow to call exit code
        // under exception propagation as well.
        int finallyHandler = cfw.acquireLabel();
        cfw.markHandler(finallyHandler);
        short exceptionObject = getNewWordLocal();
        cfw.addAStore(exceptionObject);
        // Duplicate generateActivationExit() in the catch block since it
        // takes less space then full-featured ByteCode.JSR/ByteCode.RET
        generateActivationExit();
        cfw.addALoad(exceptionObject);
        releaseWordLocal(exceptionObject);
        // rethrow
        cfw.add(ByteCode.ATHROW);
        // mark the handler
        cfw.addExceptionHandler(enterAreaStartLabel, epilogueLabel, finallyHandler, // catch any
        null);
    }
}
Also used : ScriptNode(org.mozilla.javascript.ast.ScriptNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode)

Example 30 with FunctionNode

use of org.mozilla.javascript.ast.FunctionNode in project HL4A by HL4A.

the class BodyCodegen method initOptFunctions_r.

private static void initOptFunctions_r(ScriptNode scriptOrFn) {
    for (int i = 0, N = scriptOrFn.getFunctionCount(); i != N; ++i) {
        FunctionNode fn = scriptOrFn.getFunctionNode(i);
        new OptFunctionNode(fn);
        initOptFunctions_r(fn);
    }
}
Also used : FunctionNode(org.mozilla.javascript.ast.FunctionNode)

Aggregations

FunctionNode (org.mozilla.javascript.ast.FunctionNode)32 ScriptNode (org.mozilla.javascript.ast.ScriptNode)20 AstNode (org.mozilla.javascript.ast.AstNode)8 Name (org.mozilla.javascript.ast.Name)7 LetNode (org.mozilla.javascript.ast.LetNode)6 Jump (org.mozilla.javascript.ast.Jump)4 Scope (org.mozilla.javascript.ast.Scope)4 XmlString (org.mozilla.javascript.ast.XmlString)3 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 Iterator (java.util.Iterator)2 Map (java.util.Map)2 AstRoot (org.mozilla.javascript.ast.AstRoot)2 ErrorNode (org.mozilla.javascript.ast.ErrorNode)2 Block (org.mozilla.javascript.ast.Block)1 Comment (org.mozilla.javascript.ast.Comment)1 EmptyExpression (org.mozilla.javascript.ast.EmptyExpression)1 ExpressionStatement (org.mozilla.javascript.ast.ExpressionStatement)1 ObjectProperty (org.mozilla.javascript.ast.ObjectProperty)1 ParenthesizedExpression (org.mozilla.javascript.ast.ParenthesizedExpression)1