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;
}
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;
}
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;
}
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);
}
}
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);
}
}
Aggregations