org.mozilla.javascript.ast.FunctionNode Java Examples

The following examples show how to use org.mozilla.javascript.ast.FunctionNode. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: CodeGenerator.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
private void generateNestedFunctions()
{
    int functionCount = scriptOrFn.getFunctionCount();
    if (functionCount == 0) return;

    InterpreterData[] array = new InterpreterData[functionCount];
    for (int i = 0; i != functionCount; i++) {
        FunctionNode fn = scriptOrFn.getFunctionNode(i);
        CodeGenerator gen = new CodeGenerator();
        gen.compilerEnv = compilerEnv;
        gen.scriptOrFn = fn;
        gen.itsData = new InterpreterData(itsData);
        gen.generateFunctionICode();
        array[i] = gen.itsData;
    }
    itsData.itsNestedFunctions = array;
}
 
Example #2
Source File: ConstraintGenUtil.java    From SJS with Apache License 2.0 6 votes vote down vote up
@Override
public boolean visit(AstNode node) {
	if (node instanceof PropertyGet){
		PropertyGet pg = (PropertyGet)node;
		AstNode target = pg.getTarget();
		String propName = pg.getProperty().getIdentifier();
		if (target instanceof KeywordLiteral && ConstraintGenUtil.isThis(target)){
			if (node.getParent() instanceof Assignment){
				Assignment a = (Assignment)node.getParent();
				if (a.getLeft() == node){
					writtenProperties.add(propName);
				} else {
					readProperties.add(propName);
				}
			} else {
				readProperties.add(propName);
			}
			readProperties.removeAll(writtenProperties); // if something is read and written, it should only be in the written set
		}
	} else if (node instanceof FunctionNode) {
	    // don't recurse into nested function body
	    return false;
	}
	return true;
}
 
Example #3
Source File: ConstraintVisitor.java    From SJS with Apache License 2.0 6 votes vote down vote up
/**
 * For a function definition (FunctionNode), create constraints equating its
 * parameters to param(.) variables, and equate the type of the function name
 * to the type of the entire function definition.
 */
private void createFunctionNodeConstraints(FunctionNode node, ITypeTerm funTerm){
	// if the function has a name, equate the types of the function node and the function name
	Name funName = node.getFunctionName();
	if (funName != null){
		ITypeTerm nameTerm = findOrCreateNameDeclarationTerm(funName);
		addSubTypeConstraint(funTerm, nameTerm, node.getLineno(), null);
	}

	// for a function f with params v1, v2, ... generate param(|f|,i) = |v_i|
	for (int i=0; i < node.getParamCount(); i++){
		AstNode param = node.getParams().get(i);
		if (param instanceof Name){
			Name name = (Name)param;
			ITypeTerm nameVar = findOrCreateNameDeclarationTerm(name);
			ITypeTerm paramVar = findOrCreateFunctionParamTerm(funTerm, i, node.getParamCount(), node.getLineno());
			addTypeEqualityConstraint(paramVar, nameVar, param.getLineno(), null);
		} else {
			error("createFunctionNodeConstraints: unexpected parameter type", node);
		}
	}

}
 
Example #4
Source File: ConstraintVisitor.java    From SJS with Apache License 2.0 6 votes vote down vote up
/**
 * generate constraints for return statements
 */
private void processReturnStatement(ReturnStatement rs) throws Error {
	FunctionNode fun = ConstraintGenUtil.findEnclosingFunction(rs);
	FunctionTerm.FunctionKind funType =
			ConstraintGenUtil.isConstructor(fun) ? FunctionTerm.FunctionKind.Constructor :
			(ConstraintGenUtil.isMethod(fun) ? FunctionTerm.FunctionKind.Method : FunctionTerm.FunctionKind.Function);

	ITypeTerm funTerm = findOrCreateFunctionTerm(fun, funType);
	ITypeTerm returnTerm = findOrCreateFunctionReturnTerm(funTerm, fun.getParamCount(), rs.getLineno(), null);
	AstNode exp = rs.getReturnValue();
	if (exp != null){
		ITypeTerm expTerm = processExpression(exp);
		addSubTypeConstraint(expTerm, returnTerm, rs.getLineno(),
				(solution) -> subtypeError("bad return value " + shortSrc(exp),
						solution.typeOfTerm(expTerm), solution.typeOfTerm(returnTerm), locationOf(rs)));
	} else {
		ITypeTerm voidTerm = findOrCreateTypeTerm(new VoidType(), rs.getLineno());
		addTypeEqualityConstraint(voidTerm, returnTerm, rs.getLineno(),
				(solution) -> genericTypeError("missing return value", locationOf(rs))
						.withNote("expected " + describeTypeOf(returnTerm, solution)));
	}
}
 
Example #5
Source File: ConstraintFactory.java    From SJS with Apache License 2.0 6 votes vote down vote up
/**
 * Find or create a term representing a FunctionNode (function definition). The
 * created FunctionTerm provides methods for accessing the terms corresponding to the
 * function's parameters and return type. The boolean flag isMethod indicates whether
 * the function is a method.
 */
public FunctionTerm findOrCreateFunctionTerm(FunctionNode fun, FunctionTerm.FunctionKind funType) {
    if (!functionTerms.containsKey(fun)){
        FunctionTerm var = new FunctionTerm(fun, funType);
        var.setReturnVariable(this.findOrCreateFunctionReturnTerm(var, fun.getParamCount()));
        List<AstNode> params = fun.getParams();
        List<NameDeclarationTerm> paramVars = new ArrayList<NameDeclarationTerm>();
        for (int i=0; i < params.size(); i++){
            AstNode param = params.get(i);
            if (param instanceof Name){
                NameDeclarationTerm paramCV = this.findOrCreateNameDeclarationTerm((Name)param);
                paramVars.add(paramCV);
            } else {
                throw new Error("unimplemented case in findOrCreateFunctionVariable");
            }
        }
        var.setParamVariables(paramVars);
        functionTerms.put(fun, var);
    }
    return functionTerms.get(fun);
}
 
Example #6
Source File: Bug708801Test.java    From rhino-android with Apache License 2.0 6 votes vote down vote up
/**
 * Checks every variable {@code v} in {@code source} is marked as a
 * number-variable iff {@code numbers} contains {@code v}
 */
protected void assertNumberVars(CharSequence source, String... numbers) {
    // wrap source in function
    ScriptNode tree = compile("function f(o, fn){" + source + "}");

    FunctionNode fnode = tree.getFunctionNode(0);
    assertNotNull(fnode);
    OptFunctionNode opt = OptFunctionNode.get(fnode);
    assertNotNull(opt);
    assertSame(fnode, opt.fnode);

    for (int i = 0, c = fnode.getParamCount(); i < c; ++i) {
        assertTrue(opt.isParameter(i));
        assertFalse(opt.isNumberVar(i));
    }

    Set<String> set = new HashSet<String>(asList(numbers));
    for (int i = fnode.getParamCount(), c = fnode.getParamAndVarCount(); i < c; ++i) {
        assertFalse(opt.isParameter(i));
        String name = fnode.getParamOrVarName(i);
        String msg = format("{%s -> number? = %b}", name, opt.isNumberVar(i));
        assertEquals(msg, set.contains(name), opt.isNumberVar(i));
    }
}
 
Example #7
Source File: Bug782363Test.java    From rhino-android with Apache License 2.0 6 votes vote down vote up
/**
 * Checks every variable {@code v} in {@code source} is marked as a
 * number-variable iff {@code numbers} contains {@code v}
 */
protected void assertNumberVars(CharSequence source, String... numbers) {
    // wrap source in function
    ScriptNode tree = compile("function f(){" + source + "}");

    FunctionNode fnode = tree.getFunctionNode(0);
    assertNotNull(fnode);
    OptFunctionNode opt = OptFunctionNode.get(fnode);
    assertNotNull(opt);
    assertSame(fnode, opt.fnode);

    for (int i = 0, c = fnode.getParamCount(); i < c; ++i) {
        assertTrue(opt.isParameter(i));
        assertFalse(opt.isNumberVar(i));
    }

    Set<String> set = new HashSet<String>(asList(numbers));
    for (int i = fnode.getParamCount(), c = fnode.getParamAndVarCount(); i < c; ++i) {
        assertFalse(opt.isParameter(i));
        String name = fnode.getParamOrVarName(i);
        String msg = format("{%s -> number? = %b}", name, opt.isNumberVar(i));
        assertEquals(msg, set.contains(name), opt.isNumberVar(i));
    }
}
 
Example #8
Source File: CodeGenerator.java    From JsDroidCmd with Mozilla Public License 2.0 6 votes vote down vote up
private void generateNestedFunctions()
{
    int functionCount = scriptOrFn.getFunctionCount();
    if (functionCount == 0) return;

    InterpreterData[] array = new InterpreterData[functionCount];
    for (int i = 0; i != functionCount; i++) {
        FunctionNode fn = scriptOrFn.getFunctionNode(i);
        CodeGenerator gen = new CodeGenerator();
        gen.compilerEnv = compilerEnv;
        gen.scriptOrFn = fn;
        gen.itsData = new InterpreterData(itsData);
        gen.generateFunctionICode();
        array[i] = gen.itsData;
    }
    itsData.itsNestedFunctions = array;
}
 
Example #9
Source File: CodeGenerator.java    From JsDroidCmd with Mozilla Public License 2.0 6 votes vote down vote up
private void generateFunctionICode()
{
    itsInFunctionFlag = true;

    FunctionNode theFunction = (FunctionNode)scriptOrFn;

    itsData.itsFunctionType = theFunction.getFunctionType();
    itsData.itsNeedsActivation = theFunction.requiresActivation();
    if (theFunction.getFunctionName() != null) {
        itsData.itsName = theFunction.getName();
    }
    if (theFunction.isGenerator()) {
      addIcode(Icode_GENERATOR);
      addUint16(theFunction.getBaseLineno() & 0xFFFF);
    }
    if (theFunction.isInStrictMode()) {
        itsData.isStrict = true;
    }

    generateICodeFromTree(theFunction.getLastChild());
}
 
Example #10
Source File: NodeTransformer.java    From JsDroidCmd with Mozilla Public License 2.0 6 votes vote down vote up
private void transformCompilationUnit(ScriptNode tree, boolean inStrictMode)
{
    loops = new ObjArray();
    loopEnds = new ObjArray();

    // to save against upchecks if no finally blocks are used.
    hasFinally = false;

    // Flatten all only if we are not using scope objects for block scope
    boolean createScopeObjects = tree.getType() != Token.FUNCTION ||
                              ((FunctionNode)tree).requiresActivation();
    tree.flattenSymbolTable(!createScopeObjects);

    //uncomment to print tree before transformation
    if (Token.printTrees) System.out.println(tree.toStringTree(tree));
    transformCompilationUnit_r(tree, tree, tree, createScopeObjects,
                               inStrictMode);
}
 
Example #11
Source File: Parser.java    From JsDroidCmd with Mozilla Public License 2.0 6 votes vote down vote up
PerFunctionVariables(FunctionNode fnNode) {
    savedCurrentScriptOrFn = Parser.this.currentScriptOrFn;
    Parser.this.currentScriptOrFn = fnNode;

    savedCurrentScope = Parser.this.currentScope;
    Parser.this.currentScope = fnNode;

    savedLabelSet = Parser.this.labelSet;
    Parser.this.labelSet = null;

    savedLoopSet = Parser.this.loopSet;
    Parser.this.loopSet = null;

    savedLoopAndSwitchSet = Parser.this.loopAndSwitchSet;
    Parser.this.loopAndSwitchSet = null;

    savedEndFlags = Parser.this.endFlags;
    Parser.this.endFlags = 0;

    savedInForInit = Parser.this.inForInit;
    Parser.this.inForInit = false;
}
 
Example #12
Source File: CodeGenerator.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
private void generateFunctionICode()
{
    itsInFunctionFlag = true;

    FunctionNode theFunction = (FunctionNode)scriptOrFn;

    itsData.itsFunctionType = theFunction.getFunctionType();
    itsData.itsNeedsActivation = theFunction.requiresActivation();
    if (theFunction.getFunctionName() != null) {
        itsData.itsName = theFunction.getName();
    }
    if (theFunction.isGenerator()) {
      addIcode(Icode_GENERATOR);
      addUint16(theFunction.getBaseLineno() & 0xFFFF);
    }

    generateICodeFromTree(theFunction.getLastChild());
}
 
Example #13
Source File: NodeTransformer.java    From astor with GNU General Public License v2.0 6 votes vote down vote up
private void transformCompilationUnit(ScriptNode tree)
{
    loops = new ObjArray();
    loopEnds = new ObjArray();

    // to save against upchecks if no finally blocks are used.
    hasFinally = false;

    // Flatten all only if we are not using scope objects for block scope
    boolean createScopeObjects = tree.getType() != Token.FUNCTION ||
                              ((FunctionNode)tree).requiresActivation();
    tree.flattenSymbolTable(!createScopeObjects);

    //uncomment to print tree before transformation
    if (Token.printTrees) System.out.println(tree.toStringTree(tree));
    boolean inStrictMode = tree instanceof AstRoot &&
                           ((AstRoot)tree).isInStrictMode();
    transformCompilationUnit_r(tree, tree, tree, createScopeObjects,
                               inStrictMode);
}
 
Example #14
Source File: Parser.java    From JsDroidCmd with Mozilla Public License 2.0 6 votes vote down vote up
protected void checkActivationName(String name, int token) {
    if (!insideFunction()) {
        return;
    }
    boolean activation = false;
    if ("arguments".equals(name) &&
        // An arrow function not generate arguments. So it not need activation.
        ((FunctionNode)currentScriptOrFn).getFunctionType() != FunctionNode.ARROW_FUNCTION) {
        activation = true;
    } else if (compilerEnv.getActivationNames() != null
            && compilerEnv.getActivationNames().contains(name)) {
        activation = true;
    } else if ("length".equals(name)) {
        if (token == Token.GETPROP
            && compilerEnv.getLanguageVersion() == Context.VERSION_1_2)
        {
            // Use of "length" in 1.2 requires an activation object.
            activation = true;
        }
    }
    if (activation) {
        setRequiresActivation();
    }
}
 
Example #15
Source File: NodeTransformer.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
public final void transform(ScriptNode tree)
{
    transformCompilationUnit(tree);
    for (int i = 0; i != tree.getFunctionCount(); ++i) {
        FunctionNode fn = tree.getFunctionNode(i);
        transform(fn);
    }
}
 
Example #16
Source File: IRFactory.java    From JsDroidCmd with Mozilla Public License 2.0 5 votes vote down vote up
Node decompileFunctionHeader(FunctionNode fn) {
    Node mexpr = null;
    if (fn.getFunctionName() != null) {
        decompiler.addName(fn.getName());
    } else if (fn.getMemberExprNode() != null) {
        mexpr = transform(fn.getMemberExprNode());
    }
    boolean isArrow = fn.getFunctionType() == FunctionNode.ARROW_FUNCTION;
    boolean noParen = isArrow && fn.getLp() == -1;
    if (!noParen) {
        decompiler.addToken(Token.LP);
    }
    List<AstNode> params = fn.getParams();
    for (int i = 0; i < params.size(); i++) {
        decompile(params.get(i));
        if (i < params.size() - 1) {
            decompiler.addToken(Token.COMMA);
        }
    }
    if (!noParen) {
        decompiler.addToken(Token.RP);
    }
    if (isArrow) {
        decompiler.addToken(Token.ARROW);
    }
    if (!fn.isExpressionClosure()) {
        decompiler.addEOL(Token.LC);
    }
    return mexpr;
}
 
Example #17
Source File: Decompiler.java    From JsDroidCmd with Mozilla Public License 2.0 5 votes vote down vote up
int markFunctionStart(int functionType)
{
    int savedOffset = getCurrentOffset();
    if (functionType != FunctionNode.ARROW_FUNCTION) {
        addToken(Token.FUNCTION);
        append((char)functionType);
    }
    return savedOffset;
}
 
Example #18
Source File: ConstraintGenUtil.java    From SJS with Apache License 2.0 5 votes vote down vote up
/**
 * find the function definition that immediately surrounds a given AST node.
 * Returns null if there is no surrounding function.
 *
 */
public static FunctionNode findEnclosingFunction(AstNode node) {
	AstNode current = node;
	while (current != null && !(current instanceof FunctionNode)){
		current = current.getParent();
	}
	FunctionNode fun = (FunctionNode)current;
	return fun;
}
 
Example #19
Source File: ConstraintGenUtil.java    From SJS with Apache License 2.0 5 votes vote down vote up
/**
 * Finds the declaration of the called function. Assumes that the call's target
 * is a Name, which is passed as the second parameter.
 *
 */
static FunctionNode findFunDecl(FunctionCall fc, Name funName){
	List<FunctionNode> funsFound = findFunDecl2(fc, new ArrayList<FunctionNode>());
	for (int i=0; i < funsFound.size(); i++){
		FunctionNode fun = funsFound.get(i);
		if (funName.getIdentifier().equals(fun.getName())){
			return fun;
		}
	}
	return null;
}
 
Example #20
Source File: ConstraintGenUtil.java    From SJS with Apache License 2.0 5 votes vote down vote up
@Override
public boolean visit(AstNode node) {
	if (isThis(node)){
		AstNode current = node;
		while (!(current instanceof FunctionNode)){
			current = current.getParent();
		}
		if (current == this.fun){
			refersToThis = true;
		}
	}
	return true;
}
 
Example #21
Source File: Parser.java    From JsDroidCmd with Mozilla Public License 2.0 5 votes vote down vote up
private void arrowFunctionParams(FunctionNode fnNode, AstNode params, Map<String, Node> destructuring, Set<String> paramNames) {
    if (params instanceof ArrayLiteral || params instanceof ObjectLiteral) {
        markDestructuring(params);
        fnNode.addParam(params);
        String pname = currentScriptOrFn.getNextTempName();
        defineSymbol(Token.LP, pname, false);
        destructuring.put(pname, params);
    } else if (params instanceof InfixExpression && params.getType() == Token.COMMA) {
        arrowFunctionParams(fnNode, ((InfixExpression)params).getLeft(), destructuring, paramNames);
        arrowFunctionParams(fnNode, ((InfixExpression)params).getRight(), destructuring, paramNames);
    } else if (params instanceof Name) {
        fnNode.addParam(params);
        String paramName = ((Name)params).getIdentifier();
        defineSymbol(Token.LP, paramName);

        if (this.inUseStrictDirective) {
            if ("eval".equals(paramName) ||
                "arguments".equals(paramName))
                {
                    reportError("msg.bad.id.strict", paramName);
                }
            if (paramNames.contains(paramName))
                addError("msg.dup.param.strict", paramName);
            paramNames.add(paramName);
        }
    } else {
        reportError("msg.no.parm", params.getPosition(), params.getLength());
        fnNode.addParam(makeErrorNode());
    }
}
 
Example #22
Source File: NodeTransformer.java    From JsDroidCmd with Mozilla Public License 2.0 5 votes vote down vote up
public final void transform(ScriptNode tree, boolean inStrictMode)
{
    inStrictMode = inStrictMode || tree.isInStrictMode();
    transformCompilationUnit(tree, inStrictMode);
    for (int i = 0; i != tree.getFunctionCount(); ++i) {
        FunctionNode fn = tree.getFunctionNode(i);
        transform(fn, inStrictMode);
    }
}
 
Example #23
Source File: Node.java    From JsDroidCmd with Mozilla Public License 2.0 5 votes vote down vote up
private static void toStringTreeHelper(ScriptNode treeTop, Node n,
                                       ObjToIntMap printIds,
                                       int level, StringBuilder sb)
{
    if (Token.printTrees) {
        if (printIds == null) {
            printIds = new ObjToIntMap();
            generatePrintIds(treeTop, printIds);
        }
        for (int i = 0; i != level; ++i) {
            sb.append("    ");
        }
        n.toString(printIds, sb);
        sb.append('\n');
        for (Node cursor = n.getFirstChild(); cursor != null;
             cursor = cursor.getNext())
        {
            if (cursor.getType() == Token.FUNCTION) {
                int fnIndex = cursor.getExistingIntProp(Node.FUNCTION_PROP);
                FunctionNode fn = treeTop.getFunctionNode(fnIndex);
                toStringTreeHelper(fn, fn, null, level + 1, sb);
            } else {
                toStringTreeHelper(treeTop, cursor, printIds, level+1, sb);
            }
        }
    }
}
 
Example #24
Source File: Parser.java    From JsDroidCmd with Mozilla Public License 2.0 5 votes vote down vote up
private ObjectProperty methodDefinition(int pos, AstNode propName, int entryKind)
    throws IOException
{
    FunctionNode fn = function(FunctionNode.FUNCTION_EXPRESSION);
    // We've already parsed the function name, so fn should be anonymous.
    Name name = fn.getFunctionName();
    if (name != null && name.length() != 0) {
        reportError("msg.bad.prop");
    }
    ObjectProperty pn = new ObjectProperty(pos);
    switch (entryKind) {
    case GET_ENTRY:
        pn.setIsGetterMethod();
        fn.setFunctionIsGetterMethod();
        break;
    case SET_ENTRY:
        pn.setIsSetterMethod();
        fn.setFunctionIsSetterMethod();
        break;
    case METHOD_ENTRY:
        pn.setIsNormalMethod();
        fn.setFunctionIsNormalMethod();
        break;
    }
    int end = getNodeEnd(fn);
    pn.setLeft(propName);
    pn.setRight(fn);
    pn.setLength(end - pos);
    return pn;
}
 
Example #25
Source File: Node.java    From astor with GNU General Public License v2.0 5 votes vote down vote up
private static void toStringTreeHelper(ScriptNode treeTop, Node n,
                                       ObjToIntMap printIds,
                                       int level, StringBuffer sb)
{
    if (Token.printTrees) {
        if (printIds == null) {
            printIds = new ObjToIntMap();
            generatePrintIds(treeTop, printIds);
        }
        for (int i = 0; i != level; ++i) {
            sb.append("    ");
        }
        n.toString(printIds, sb);
        sb.append('\n');
        for (Node cursor = n.getFirstChild(); cursor != null;
             cursor = cursor.getNext())
        {
            if (cursor.getType() == Token.FUNCTION) {
                int fnIndex = cursor.getExistingIntProp(Node.FUNCTION_PROP);
                FunctionNode fn = treeTop.getFunctionNode(fnIndex);
                toStringTreeHelper(fn, fn, null, level + 1, sb);
            } else {
                toStringTreeHelper(treeTop, cursor, printIds, level+1, sb);
            }
        }
    }
}
 
Example #26
Source File: ConstraintGenUtil.java    From SJS with Apache License 2.0 4 votes vote down vote up
/**
 * For a {@link FunctionNode} representing a constructor, if the constructor C is
 * followed by a sequence of assignments of the form C.prototype.a = ...;, return
 * a set of all the properties written on the prototype.  If the assignments do not
 * fit that form, return the empty set.
 * @param consNode
 * @return
 */
public static Set<String> getWrittenPrototypeProps(FunctionNode consNode) {
    Set<String> result = HashSetFactory.make();
    AstNode parent = consNode.getParent();
    boolean found = false;
    for (Node child: parent) {
        if (child instanceof EmptyStatement) {
            continue;
        }
        if (child.equals(consNode)) {
            found = true;
        } else if (found) {
            // looking for a statement of the form C.prototype.a = ...;
            boolean foundAssign = false;
            if (child instanceof ExpressionStatement) {
                AstNode expression = ((ExpressionStatement)child).getExpression();
                if (expression instanceof Assignment) {
                    Assignment assign = (Assignment) expression;
                    AstNode lhs = assign.getLeft();
                    if (lhs instanceof PropertyGet) {
                        PropertyGet pg = (PropertyGet) lhs;
                        AstNode pgTarget = pg.getTarget();
                        if (pgTarget instanceof PropertyGet) {
                            PropertyGet basePG = (PropertyGet) pgTarget;
                            if (basePG.getProperty().getIdentifier().equals("prototype")) {
                                // BINGO
                                result.add(pg.getProperty().getIdentifier());
                                foundAssign = true;
                            }
                        }
                    }
                }
            }
            if (!foundAssign) {
                // stop looking for more assignments
                break;
            }
        }
    }
    return result;
}
 
Example #27
Source File: ConstraintGenUtil.java    From SJS with Apache License 2.0 4 votes vote down vote up
public static boolean isMethodAssignedInObjectLiteral(FunctionNode n){
	return (n.getParent() instanceof ObjectProperty && n.getParent().getParent() instanceof ObjectLiteral);
}
 
Example #28
Source File: ConstraintVisitor.java    From SJS with Apache License 2.0 4 votes vote down vote up
/**
 * This method generates constraints for all relevant AstNodes. It delegates its work to various
 * processXXX() methods that handle AstNodes of type XXX.
 */
@Override
public boolean visit(AstNode node) {
	if (node instanceof VariableInitializer){
		processVariableInitializer(node);
	} else if (node instanceof ReturnStatement){
		processReturnStatement((ReturnStatement)node);
	} else if (node instanceof ExpressionStatement){
		processExpressionStatement((ExpressionStatement)node);
	} else if (node instanceof ForLoop){
		processForLoop((ForLoop)node);
	} else if (node instanceof ForInLoop){
		processForInLoop((ForInLoop)node);
	}else if (node instanceof WhileLoop){
		processWhileLoop((WhileLoop)node);
	} else if (node instanceof DoLoop){
		processDoLoop((DoLoop)node);
	} else if (node instanceof NewExpression){
		processNewExpression((NewExpression)node);
	} else if (node instanceof FunctionCall){
		processFunctionCall((FunctionCall)node);
	} else if (node instanceof ElementGet){
		processElementGet((ElementGet)node);
	} else if (node instanceof FunctionNode){
		processFunctionNode((FunctionNode)node);
	} else if (node instanceof IfStatement){
		processIfStatement((IfStatement)node);
	} else if (node instanceof KeywordLiteral){
		processKeywordLiteral((KeywordLiteral)node);
	} else if (node instanceof SwitchStatement){
		processSwitchStatement((SwitchStatement)node);
	} else if (node instanceof SwitchCase){
		processSwitchCase((SwitchCase)node);
	} else if ((node instanceof AstRoot) || //AstRoot: no constraints need to be generated
		(node instanceof BreakStatement) || //BreakStatement: no constraints need to be generated
		(node instanceof VariableDeclaration) || //VariableDeclaration: we generate constraints for its constituent VariableInitializer nodes
		(node instanceof Name) || //Name: generate constraints for complex expressions that refer to names
		(node instanceof NumberLiteral) || //NumberLiteral: generate constraints for complex expressions that refer to names
		(node instanceof StringLiteral) || //StringLiteral: generate constraints for complex expressions that refer to names
		(node instanceof Assignment) || // Assignment is a special case of InfixExpression
		(node instanceof ArrayLiteral) ||
		(node instanceof UnaryExpression) ||
		(node instanceof InfixExpression) ||
		(node instanceof ConditionalExpression) ||
		(node instanceof ParenthesizedExpression) ||
		(node instanceof EmptyExpression) ||
		(node instanceof ObjectLiteral) ||
		(node instanceof EmptyStatement) ||
		(node instanceof ContinueStatement) ||
		(node instanceof Scope) ||
		(node instanceof Block)){ // // occurs in programs with for loops -- nothing to be done here?
		/* nothing */
	} else {
		error("unsupported node " + node.toSource().trim() + " of type: " + node.getClass().getName(), node);
	}
	return true;
}
 
Example #29
Source File: IRFactory.java    From JsDroidCmd with Mozilla Public License 2.0 4 votes vote down vote up
private Node transformGenExpr(GeneratorExpression node) {
    Node pn;
    
    FunctionNode fn = new FunctionNode();
    fn.setSourceName(currentScriptOrFn.getNextTempName());
    fn.setIsGenerator();
    fn.setFunctionType(FunctionNode.FUNCTION_EXPRESSION);
    fn.setRequiresActivation();
  
    int functionType = fn.getFunctionType();
    int start = decompiler.markFunctionStart(functionType);
    Node mexpr = decompileFunctionHeader(fn);
    int index = currentScriptOrFn.addFunction(fn);

    PerFunctionVariables savedVars = new PerFunctionVariables(fn);
    try {
        // If we start needing to record much more codegen metadata during
        // function parsing, we should lump it all into a helper class.
        Node destructuring = (Node)fn.getProp(Node.DESTRUCTURING_PARAMS);
        fn.removeProp(Node.DESTRUCTURING_PARAMS);

        int lineno = node.lineno;
        ++nestingOfFunction;  // only for body, not params
        Node body = genExprTransformHelper(node);

        if (!fn.isExpressionClosure()) {
            decompiler.addToken(Token.RC);
        }
        fn.setEncodedSourceBounds(start, decompiler.markFunctionEnd(start));

        if (functionType != FunctionNode.FUNCTION_EXPRESSION && !fn.isExpressionClosure()) {
            // Add EOL only if function is not part of expression
            // since it gets SEMI + EOL from Statement in that case
            decompiler.addToken(Token.EOL);
        }

        if (destructuring != null) {
            body.addChildToFront(new Node(Token.EXPR_VOID,
                                          destructuring, lineno));
        }

        int syntheticType = fn.getFunctionType();
        pn = initFunction(fn, index, body, syntheticType);
        if (mexpr != null) {
            pn = createAssignment(Token.ASSIGN, mexpr, pn);
            if (syntheticType != FunctionNode.FUNCTION_EXPRESSION) {
                pn = createExprStatementNoReturn(pn, fn.getLineno());
            }
        }
    } finally {
        --nestingOfFunction;
        savedVars.restore();
    }
   
    Node call = createCallOrNew(Token.CALL, pn);
    call.setLineno(node.getLineno());
    decompiler.addToken(Token.LP);
    decompiler.addToken(Token.RP);
    return call;
}
 
Example #30
Source File: ConstraintVisitor.java    From SJS with Apache License 2.0 4 votes vote down vote up
/**
 * assignment to the "prototype" property
 */
private void processAssignToPrototype(Assignment a, AstNode left, AstNode right, ITypeTerm expTerm) throws Error {
	PropertyGet pg = (PropertyGet)left;
	AstNode base = pg.getTarget();
	ITypeTerm pgTerm = findOrCreateExpressionTerm(pg);
	if (base instanceof Name){
		Name name = (Name)base;
		if (!validRHSForAssignToPrototype(right)) {
			error(
					"expression "
							+ right.toSource()
							+ " cannot be assigned to a constructor prototype (line "
							+ right.getLineno() + ")", a);
		}
		// can only write to prototype immediately after declaration of
		// constructor of the same name
		AstNode parent = a.getParent();
		if (!(parent instanceof ExpressionStatement)) {
			error(
					"assignment to prototype property not allowed here (line "
							+ a.getLineno() + ")", a);
			return;
		}
		Node prev = getPredecessorNode(parent);
		if (!(prev instanceof FunctionNode)) {
			error(
					"assignment to prototype property only allowed after constructor declaration (line "
							+ a.getLineno() + ")", a);
			return;
		}
		FunctionNode fn = (FunctionNode) prev;
		String functionName = fn.getName();
		String identifier = name.getIdentifier();
		if (!functionName.equals(identifier)) {
			error(
					"can only assign to prototype of function "
							+ functionName + " here (line " + a.getLineno()
							+ ")", a);
			return;
		}
		ITypeTerm baseTerm = findOrCreateExpressionTerm(base); // make term for expression
		ITypeTerm nameTerm = findOrCreateNameDeclarationTerm(name); // find unique representative for referenced Name
		addTypeEqualityConstraint(baseTerm, nameTerm, a.getLineno(), null); // equate them
		ITypeTerm protoTerm = findOrCreateProtoTerm(baseTerm, pg.getLineno());
		ITypeTerm rightTerm = processExpression(right);
		addTypeEqualityConstraint(pgTerm, protoTerm, a.getLineno(), null);
		addTypeEqualityConstraint(rightTerm, protoTerm, a.getLineno(), null);
		addTypeEqualityConstraint(expTerm, protoTerm, a.getLineno(), null);
	} else {
		error("processAssignToPrototype: unsupported case for receiver expression: " + base.getClass().getName(), base);
	}
}