Esempio n. 1
0
 /// <summary> Script (for associating file/url names with toplevel scripts.)</summary>
 internal void initScript (ScriptOrFnNode scriptNode, Node body)
 {
     Node children = body.FirstChild;
     if (children != null) {
         scriptNode.addChildrenToBack (children);
     }
 }
Esempio n. 2
0
 private static void toStringTreeHelper(ScriptOrFnNode treeTop, Node n, ObjToIntMap printIds, int level, System.Text.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.FirstChild; cursor != null; cursor = cursor.Next)
         {
             if (cursor.Type == 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);
             }
         }
     }
 }
Esempio n. 3
0
 public void transform (ScriptOrFnNode tree)
 {
     transformCompilationUnit (tree);
     for (int i = 0; i != tree.FunctionCount; ++i) {
         FunctionNode fn = tree.getFunctionNode (i);
         transform (fn);
     }
 }
Esempio n. 4
0
 public void transform(ScriptOrFnNode tree)
 {
     transformCompilationUnit(tree);
     for (int i = 0; i != tree.FunctionCount; ++i)
     {
         FunctionNode fn = tree.getFunctionNode(i);
         transform(fn);
     }
 }
Esempio n. 5
0
 public string toStringTree(ScriptOrFnNode treeTop)
 {
     if (Token.printTrees)
     {
         System.Text.StringBuilder sb = new System.Text.StringBuilder();
         toStringTreeHelper(treeTop, this, null, 0, sb);
         return(sb.ToString());
     }
     return(null);
 }
Esempio n. 6
0
        private void transformCompilationUnit(ScriptOrFnNode tree)
        {
            loops    = new ObjArray();
            loopEnds = new ObjArray();
            // to save against upchecks if no finally blocks are used.
            hasFinally = false;

            try {
                transformCompilationUnit_r(tree, tree);
            } catch (Helpers.StackOverflowVerifierException) {
                throw Context.ReportRuntimeError(
                          ScriptRuntime.GetMessage("mag.too.deep.parser.recursion"));
            }
        }
Esempio n. 7
0
 private void transformCompilationUnit (ScriptOrFnNode tree)
 {
     loops = new ObjArray ();
     loopEnds = new ObjArray ();
     // to save against upchecks if no finally blocks are used.
     hasFinally = false;
     
     try {
         transformCompilationUnit_r (tree, tree);
     } catch (Helpers.StackOverflowVerifierException) {
         throw Context.ReportRuntimeError (
             ScriptRuntime.GetMessage ("mag.too.deep.parser.recursion"));
     }
 }
Esempio n. 8
0
 protected internal virtual void visitCall (Node node, ScriptOrFnNode tree)
 {
 }
Esempio n. 9
0
 private static void toStringTreeHelper(ScriptOrFnNode treeTop, Node n, ObjToIntMap printIds, int level, System.Text.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.FirstChild; cursor != null; cursor = cursor.Next) {
             if (cursor.Type == 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);
             }
         }
     }
 }
Esempio n. 10
0
 public string toStringTree(ScriptOrFnNode treeTop)
 {
     if (Token.printTrees) {
         System.Text.StringBuilder sb = new System.Text.StringBuilder ();
         toStringTreeHelper (treeTop, this, null, 0, sb);
         return sb.ToString ();
     }
     return null;
 }
Esempio n. 11
0
 protected internal virtual void visitCall(Node node, ScriptOrFnNode tree)
 {
 }
Esempio n. 12
0
        public virtual object Compile (CompilerEnvirons compilerEnv, ScriptOrFnNode tree, string encodedSource, bool returnFunction)
        {
            this.compilerEnv = compilerEnv;
            new NodeTransformer ().transform (tree);

            if (Token.printTrees) {
                System.Console.Out.WriteLine (tree.toStringTree (tree));
            }

            if (returnFunction) {
                tree = tree.getFunctionNode (0);
            }

            scriptOrFn = tree;
            itsData = new InterpreterData (compilerEnv.LanguageVersion, scriptOrFn.SourceName, encodedSource);
            itsData.topLevel = true;

            if (returnFunction) {
                generateFunctionICode ();
            }
            else {
                generateICodeFromTree (scriptOrFn);
            }

            return itsData;
        }
Esempio n. 13
0
        Node function (int functionType)
        {
            using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier (1024)) {
                int syntheticType = functionType;
                int baseLineno = ts.Lineno; // line number where source starts

                int functionSourceStart = decompiler.MarkFunctionStart (functionType);
                string name;
                Node memberExprNode = null;
                
                int tt = peekToken ();                
                if (tt == Token.NAME) {
                    consumeToken ();    
                    name = ts.String;
                    decompiler.AddName (name);
                    if (!matchToken (Token.LP)) {
                        if (compilerEnv.isAllowMemberExprAsFunctionName ()) {
                            // Extension to ECMA: if 'function <name>' does not follow
                            // by '(', assume <name> starts memberExpr
                            Node memberExprHead = nf.CreateName (name);
                            name = "";
                            memberExprNode = memberExprTail (false, memberExprHead);
                        }
                        mustMatchToken (Token.LP, "msg.no.paren.parms");
                    }
                }
                else if (matchToken (Token.LP)) {
                    // Anonymous function
                    name = "";
                }
                else {
                    name = "";
                    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");
                }

                if (memberExprNode != null) {
                    syntheticType = FunctionNode.FUNCTION_EXPRESSION;
                }

                bool nested = insideFunction ();

                FunctionNode fnNode = nf.CreateFunction (name);
                if (nested || nestingOfWith > 0) {
                    // 1. Nested functions are not affected by the dynamic scope flag
                    // as dynamic scope is already a parent of their scope.
                    // 2. Functions defined under the with statement also immune to
                    // this setup, in which case dynamic scope is ignored in favor
                    // of with object.
                    fnNode.itsIgnoreDynamicScope = true;
                }

                int functionIndex = currentScriptOrFn.addFunction (fnNode);

                int functionSourceEnd;

                ScriptOrFnNode savedScriptOrFn = currentScriptOrFn;
                currentScriptOrFn = fnNode;
                int savedNestingOfWith = nestingOfWith;
                nestingOfWith = 0;
                Hashtable savedLabelSet = labelSet;
                labelSet = null;
                ObjArray savedLoopSet = loopSet;
                loopSet = null;
                ObjArray savedLoopAndSwitchSet = loopAndSwitchSet;
                loopAndSwitchSet = null;

                Node body;
                try {
                    decompiler.AddToken (Token.LP);
                    if (!matchToken (Token.RP)) {
                        bool first = true;
                        do {
                            if (!first)
                                decompiler.AddToken (Token.COMMA);
                            first = false;
                            mustMatchToken (Token.NAME, "msg.no.parm");
                            string s = ts.String;
                            if (fnNode.hasParamOrVar (s)) {
                                AddWarning ("msg.dup.parms", s);
                            }
                            fnNode.addParam (s);
                            decompiler.AddName (s);
                        }
                        while (matchToken (Token.COMMA));

                        mustMatchToken (Token.RP, "msg.no.paren.after.parms");
                    }
                    decompiler.AddToken (Token.RP);

                    mustMatchToken (Token.LC, "msg.no.brace.body");
                    decompiler.AddEol (Token.LC);
                    body = parseFunctionBody ();
                    mustMatchToken (Token.RC, "msg.no.brace.after.body");

                    decompiler.AddToken (Token.RC);
                    functionSourceEnd = decompiler.MarkFunctionEnd (functionSourceStart);
                    if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
                        if (compilerEnv.LanguageVersion >= Context.Versions.JS1_2) {
                            // function f() {} function g() {} is not allowed in 1.2
                            // or later but for compatibility with old scripts
                            // the check is done only if language is
                            // explicitly set.
                            //  TODO: warning needed if version == VERSION_DEFAULT ?
                            tt = peekTokenOrEOL ();
                            if (tt == Token.FUNCTION) {
                                ReportError ("msg.no.semi.stmt");
                            }
                        }
                        // Add EOL only if function is not part of expression
                        // since it gets SEMI + EOL from Statement in that case
                        decompiler.AddToken (Token.EOL);
                    }
                }
                finally {
                    loopAndSwitchSet = savedLoopAndSwitchSet;
                    loopSet = savedLoopSet;
                    labelSet = savedLabelSet;
                    nestingOfWith = savedNestingOfWith;
                    currentScriptOrFn = savedScriptOrFn;
                }

                fnNode.setEncodedSourceBounds (functionSourceStart, functionSourceEnd);
                fnNode.SourceName = sourceURI;
                fnNode.BaseLineno = baseLineno;
                fnNode.EndLineno = ts.Lineno;

                Node pn = nf.initFunction (fnNode, functionIndex, body, syntheticType);
                if (memberExprNode != null) {
                    pn = nf.CreateAssignment (Token.ASSIGN, memberExprNode, pn, false);
                    if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
                        // TOOD: check JScript behavior: should it be createExprStatement?
                        pn = nf.CreateExprStatementNoReturn (pn, baseLineno);
                    }
                }
                return pn;
            }
        }
Esempio n. 14
0
        ScriptOrFnNode Parse ()
        {
            this.decompiler = CreateDecompiler (compilerEnv);
            this.nf = new NodeFactory (this);
            currentScriptOrFn = nf.CreateScript ();
            int sourceStartOffset = decompiler.CurrentOffset;
            this.encodedSource = null;
            decompiler.AddToken (Token.SCRIPT);

            this.currentFlaggedToken = Token.EOF;
            this.syntaxErrorCount = 0;

            int baseLineno = ts.Lineno; // line number where source starts

            /* so we have something to add nodes to until
            * we've collected all the source */
            Node pn = nf.CreateLeaf (Token.BLOCK);

            for (; ; ) {
                int tt = peekToken ();

                if (tt <= Token.EOF) {
                    break;
                }

                Node n;
                if (tt == Token.FUNCTION) {
                    consumeToken ();
                    try {
                        n = function (calledByCompileFunction ? FunctionNode.FUNCTION_EXPRESSION : FunctionNode.FUNCTION_STATEMENT);
                    }
                    catch (ParserException) {
                        break;
                    }
                }
                else {
                    n = statement ();
                }
                nf.addChildToBack (pn, n);
            }

            if (this.syntaxErrorCount != 0) {
                string msg = Convert.ToString (this.syntaxErrorCount);
                msg = ScriptRuntime.GetMessage ("msg.got.syntax.errors", msg);
                throw errorReporter.RuntimeError (msg, sourceURI, baseLineno, null, 0);
            }

            currentScriptOrFn.SourceName = sourceURI;
            currentScriptOrFn.BaseLineno = baseLineno;
            currentScriptOrFn.EndLineno = ts.Lineno;

            int sourceEndOffset = decompiler.CurrentOffset;
            currentScriptOrFn.setEncodedSourceBounds (sourceStartOffset, sourceEndOffset);

            nf.initScript (currentScriptOrFn, pn);

            if (compilerEnv.isGeneratingSource ()) {
                encodedSource = decompiler.EncodedSource;
            }
            this.decompiler = null; // It helps GC

            return currentScriptOrFn;
        }
Esempio n. 15
0
        private void transformCompilationUnit_r(ScriptOrFnNode tree, Node parent)
        {
            Node node = null;

            using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier(1024)) {
                for (; ;)
                {
                    Node previous = null;
                    if (node == null)
                    {
                        node = parent.FirstChild;
                    }
                    else
                    {
                        previous = node;
                        node     = node.Next;
                    }
                    if (node == null)
                    {
                        break;
                    }

                    int type = node.Type;

                    switch (type)
                    {
                    case Token.LABEL:
                    case Token.SWITCH:
                    case Token.LOOP:
                        loops.push(node);
                        loopEnds.push(((Node.Jump)node).target);
                        break;


                    case Token.WITH: {
                        loops.push(node);
                        Node leave = node.Next;
                        if (leave.Type != Token.LEAVEWITH)
                        {
                            Context.CodeBug();
                        }
                        loopEnds.push(leave);
                        break;
                    }


                    case Token.TRY: {
                        Node.Jump jump          = (Node.Jump)node;
                        Node      finallytarget = jump.Finally;
                        if (finallytarget != null)
                        {
                            hasFinally = true;
                            loops.push(node);
                            loopEnds.push(finallytarget);
                        }
                        break;
                    }


                    case Token.TARGET:
                    case Token.LEAVEWITH:
                        if (!loopEnds.Empty && loopEnds.peek() == node)
                        {
                            loopEnds.pop();
                            loops.pop();
                        }
                        break;


                    case Token.RETURN: {
                        /* If we didn't support try/finally, it wouldn't be
                         * necessary to put LEAVEWITH nodes here... but as
                         * we do need a series of JSR FINALLY nodes before
                         * each RETURN, we need to ensure that each finally
                         * block gets the correct scope... which could mean
                         * that some LEAVEWITH nodes are necessary.
                         */
                        if (!hasFinally)
                        {
                            break;         // skip the whole mess.
                        }
                        Node unwindBlock = null;
                        for (int i = loops.size() - 1; i >= 0; i--)
                        {
                            Node n        = (Node)loops.Get(i);
                            int  elemtype = n.Type;
                            if (elemtype == Token.TRY || elemtype == Token.WITH)
                            {
                                Node unwind;
                                if (elemtype == Token.TRY)
                                {
                                    Node.Jump jsrnode   = new Node.Jump(Token.JSR);
                                    Node      jsrtarget = ((Node.Jump)n).Finally;
                                    jsrnode.target = jsrtarget;
                                    unwind         = jsrnode;
                                }
                                else
                                {
                                    unwind = new Node(Token.LEAVEWITH);
                                }
                                if (unwindBlock == null)
                                {
                                    unwindBlock = new Node(Token.BLOCK, node.Lineno);
                                }
                                unwindBlock.addChildToBack(unwind);
                            }
                        }
                        if (unwindBlock != null)
                        {
                            Node returnNode = node;
                            Node returnExpr = returnNode.FirstChild;
                            node = replaceCurrent(parent, previous, node, unwindBlock);
                            if (returnExpr == null)
                            {
                                unwindBlock.addChildToBack(returnNode);
                            }
                            else
                            {
                                Node store = new Node(Token.EXPR_RESULT, returnExpr);
                                unwindBlock.addChildToFront(store);
                                returnNode = new Node(Token.RETURN_RESULT);
                                unwindBlock.addChildToBack(returnNode);
                                // transform return expression
                                transformCompilationUnit_r(tree, store);
                            }
                            // skip transformCompilationUnit_r to avoid infinite loop

                            goto siblingLoop;
                        }
                        break;
                    }


                    case Token.BREAK:
                    case Token.CONTINUE: {
                        Node.Jump jump          = (Node.Jump)node;
                        Node.Jump jumpStatement = jump.JumpStatement;
                        if (jumpStatement == null)
                        {
                            Context.CodeBug();
                        }

                        for (int i = loops.size(); ;)
                        {
                            if (i == 0)
                            {
                                // Parser/IRFactory ensure that break/continue
                                // always has a jump statement associated with it
                                // which should be found
                                throw Context.CodeBug();
                            }
                            --i;
                            Node n = (Node)loops.Get(i);
                            if (n == jumpStatement)
                            {
                                break;
                            }

                            int elemtype = n.Type;
                            if (elemtype == Token.WITH)
                            {
                                Node leave = new Node(Token.LEAVEWITH);
                                previous = addBeforeCurrent(parent, previous, node, leave);
                            }
                            else if (elemtype == Token.TRY)
                            {
                                Node.Jump tryNode    = (Node.Jump)n;
                                Node.Jump jsrFinally = new Node.Jump(Token.JSR);
                                jsrFinally.target = tryNode.Finally;
                                previous          = addBeforeCurrent(parent, previous, node, jsrFinally);
                            }
                        }

                        if (type == Token.BREAK)
                        {
                            jump.target = jumpStatement.target;
                        }
                        else
                        {
                            jump.target = jumpStatement.Continue;
                        }
                        jump.Type = Token.GOTO;

                        break;
                    }


                    case Token.CALL:
                        visitCall(node, tree);
                        break;


                    case Token.NEW:
                        visitNew(node, tree);
                        break;


                    case Token.VAR: {
                        Node result = new Node(Token.BLOCK);
                        for (Node cursor = node.FirstChild; cursor != null;)
                        {
                            // Move cursor to next before createAssignment get chance
                            // to change n.next
                            Node n = cursor;
                            if (n.Type != Token.NAME)
                            {
                                Context.CodeBug();
                            }
                            cursor = cursor.Next;
                            if (!n.hasChildren())
                            {
                                continue;
                            }
                            Node init = n.FirstChild;
                            n.removeChild(init);
                            n.Type = Token.BINDNAME;
                            n      = new Node(Token.SETNAME, n, init);
                            Node pop = new Node(Token.EXPR_VOID, n, node.Lineno);
                            result.addChildToBack(pop);
                        }
                        node = replaceCurrent(parent, previous, node, result);
                        break;
                    }


                    case Token.NAME:
                    case Token.SETNAME:
                    case Token.DELPROP: {
                        // Turn name to var for faster access if possible
                        if (tree.Type != Token.FUNCTION || ((FunctionNode)tree).RequiresActivation)
                        {
                            break;
                        }
                        Node nameSource;
                        if (type == Token.NAME)
                        {
                            nameSource = node;
                        }
                        else
                        {
                            nameSource = node.FirstChild;
                            if (nameSource.Type != Token.BINDNAME)
                            {
                                if (type == Token.DELPROP)
                                {
                                    break;
                                }
                                throw Context.CodeBug();
                            }
                        }
                        string name = nameSource.String;
                        if (tree.hasParamOrVar(name))
                        {
                            if (type == Token.NAME)
                            {
                                node.Type = Token.GETVAR;
                            }
                            else if (type == Token.SETNAME)
                            {
                                node.Type       = Token.SETVAR;
                                nameSource.Type = Token.STRING;
                            }
                            else if (type == Token.DELPROP)
                            {
                                // Local variables are by definition permanent
                                Node n = new Node(Token.FALSE);
                                node = replaceCurrent(parent, previous, node, n);
                            }
                            else
                            {
                                throw Context.CodeBug();
                            }
                        }
                        break;
                    }
                    }

                    transformCompilationUnit_r(tree, node);

siblingLoop:
                    ;
                }
            }
        }
Esempio n. 16
0
        private void transformCompilationUnit_r (ScriptOrFnNode tree, Node parent)
        {
            Node node = null;

            using (Helpers.StackOverflowVerifier sov = new Helpers.StackOverflowVerifier (1024)) {
                for (; ; ) {
                    Node previous = null;
                    if (node == null) {
                        node = parent.FirstChild;
                    }
                    else {
                        previous = node;
                        node = node.Next;
                    }
                    if (node == null) {
                        break;
                    }

                    int type = node.Type;

                    switch (type) {


                        case Token.LABEL:
                        case Token.SWITCH:
                        case Token.LOOP:
                            loops.push (node);
                            loopEnds.push (((Node.Jump)node).target);
                            break;


                        case Token.WITH: {
                                loops.push (node);
                                Node leave = node.Next;
                                if (leave.Type != Token.LEAVEWITH) {
                                    Context.CodeBug ();
                                }
                                loopEnds.push (leave);
                                break;
                            }


                        case Token.TRY: {
                                Node.Jump jump = (Node.Jump)node;
                                Node finallytarget = jump.Finally;
                                if (finallytarget != null) {
                                    hasFinally = true;
                                    loops.push (node);
                                    loopEnds.push (finallytarget);
                                }
                                break;
                            }


                        case Token.TARGET:
                        case Token.LEAVEWITH:
                            if (!loopEnds.Empty && loopEnds.peek () == node) {
                                loopEnds.pop ();
                                loops.pop ();
                            }
                            break;


                        case Token.RETURN: {
                                /* If we didn't support try/finally, it wouldn't be
                                * necessary to put LEAVEWITH nodes here... but as
                                * we do need a series of JSR FINALLY nodes before
                                * each RETURN, we need to ensure that each finally
                                * block gets the correct scope... which could mean
                                * that some LEAVEWITH nodes are necessary.
                                */
                                if (!hasFinally)
                                    break; // skip the whole mess.
                                Node unwindBlock = null;
                                for (int i = loops.size () - 1; i >= 0; i--) {
                                    Node n = (Node)loops.Get (i);
                                    int elemtype = n.Type;
                                    if (elemtype == Token.TRY || elemtype == Token.WITH) {
                                        Node unwind;
                                        if (elemtype == Token.TRY) {
                                            Node.Jump jsrnode = new Node.Jump (Token.JSR);
                                            Node jsrtarget = ((Node.Jump)n).Finally;
                                            jsrnode.target = jsrtarget;
                                            unwind = jsrnode;
                                        }
                                        else {
                                            unwind = new Node (Token.LEAVEWITH);
                                        }
                                        if (unwindBlock == null) {
                                            unwindBlock = new Node (Token.BLOCK, node.Lineno);
                                        }
                                        unwindBlock.addChildToBack (unwind);
                                    }
                                }
                                if (unwindBlock != null) {
                                    Node returnNode = node;
                                    Node returnExpr = returnNode.FirstChild;
                                    node = replaceCurrent (parent, previous, node, unwindBlock);
                                    if (returnExpr == null) {
                                        unwindBlock.addChildToBack (returnNode);
                                    }
                                    else {
                                        Node store = new Node (Token.EXPR_RESULT, returnExpr);
                                        unwindBlock.addChildToFront (store);
                                        returnNode = new Node (Token.RETURN_RESULT);
                                        unwindBlock.addChildToBack (returnNode);
                                        // transform return expression
                                        transformCompilationUnit_r (tree, store);
                                    }
                                    // skip transformCompilationUnit_r to avoid infinite loop

                                    goto siblingLoop;
                                }
                                break;
                            }


                        case Token.BREAK:
                        case Token.CONTINUE: {
                                Node.Jump jump = (Node.Jump)node;
                                Node.Jump jumpStatement = jump.JumpStatement;
                                if (jumpStatement == null)
                                    Context.CodeBug ();

                                for (int i = loops.size (); ; ) {
                                    if (i == 0) {
                                        // Parser/IRFactory ensure that break/continue
                                        // always has a jump statement associated with it
                                        // which should be found
                                        throw Context.CodeBug ();
                                    }
                                    --i;
                                    Node n = (Node)loops.Get (i);
                                    if (n == jumpStatement) {
                                        break;
                                    }

                                    int elemtype = n.Type;
                                    if (elemtype == Token.WITH) {
                                        Node leave = new Node (Token.LEAVEWITH);
                                        previous = addBeforeCurrent (parent, previous, node, leave);
                                    }
                                    else if (elemtype == Token.TRY) {
                                        Node.Jump tryNode = (Node.Jump)n;
                                        Node.Jump jsrFinally = new Node.Jump (Token.JSR);
                                        jsrFinally.target = tryNode.Finally;
                                        previous = addBeforeCurrent (parent, previous, node, jsrFinally);
                                    }
                                }

                                if (type == Token.BREAK) {
                                    jump.target = jumpStatement.target;
                                }
                                else {
                                    jump.target = jumpStatement.Continue;
                                }
                                jump.Type = Token.GOTO;

                                break;
                            }


                        case Token.CALL:
                            visitCall (node, tree);
                            break;


                        case Token.NEW:
                            visitNew (node, tree);
                            break;


                        case Token.CONST:
                        case Token.VAR: {
                                Node result = new Node (Token.BLOCK);
                                for (Node cursor = node.FirstChild; cursor != null; ) {
                                    // Move cursor to next before createAssignment get chance
                                    // to change n.next
                                    Node n = cursor;
                                    if (n.Type != Token.NAME)
                                        Context.CodeBug ();
                                    cursor = cursor.Next;
                                    if (!n.hasChildren ())
                                        continue;
                                    Node init = n.FirstChild;
                                    n.removeChild (init);
                                    n.Type = Token.BINDNAME;
                                    n = new Node ((node.Type == Token.VAR) ? Token.SETNAME : Token.SETNAME_CONST, n, init);
                                    Node pop = new Node (Token.EXPR_VOID, n, node.Lineno);
                                    result.addChildToBack (pop);
                                }
                                node = replaceCurrent (parent, previous, node, result);
                                break;
                            }


                        case Token.NAME:
                        case Token.SETNAME:
                        case Token.DELPROP: {
                                // Turn name to var for faster access if possible
                                if (tree.Type != Token.FUNCTION || ((FunctionNode)tree).RequiresActivation) {
                                    break;
                                }
                                Node nameSource;
                                if (type == Token.NAME) {
                                    nameSource = node;
                                }
                                else {
                                    nameSource = node.FirstChild;
                                    if (nameSource.Type != Token.BINDNAME) {
                                        if (type == Token.DELPROP) {
                                            break;
                                        }
                                        throw Context.CodeBug ();
                                    }
                                }
                                string name = nameSource.String;
                                if (tree.hasParamOrVar (name)) {
                                    if (type == Token.NAME) {
                                        node.Type = Token.GETVAR;
                                    }
                                    else if (type == Token.SETNAME) {
                                        node.Type = Token.SETVAR;
                                        nameSource.Type = Token.STRING;
                                    }
                                    else if (type == Token.DELPROP) {
                                        // Local variables are by definition permanent
                                        Node n = new Node (Token.FALSE);
                                        node = replaceCurrent (parent, previous, node, n);
                                    }
                                    else {
                                        throw Context.CodeBug ();
                                    }
                                }
                                break;
                            }
                    }

                    transformCompilationUnit_r (tree, node);

                siblingLoop:
                    ;
                }
            }
        }
Esempio n. 17
0
        private void toString(ObjToIntMap printIds, System.Text.StringBuilder sb)
        {
            if (Token.printTrees)
            {
                sb.Append(Token.name(this.Type));
                if (this is StringNode)
                {
                    sb.Append(' ');
                    sb.Append(String);
                }
                else if (this is ScriptOrFnNode)
                {
                    ScriptOrFnNode sof = (ScriptOrFnNode)this;
                    if (this is FunctionNode)
                    {
                        FunctionNode fn = (FunctionNode)this;
                        sb.Append(' ');
                        sb.Append(fn.FunctionName);
                    }
                    sb.Append(" [source name: ");
                    sb.Append(sof.SourceName);
                    sb.Append("] [encoded source length: ");
                    sb.Append(sof.EncodedSourceEnd - sof.EncodedSourceStart);
                    sb.Append("] [base line: ");
                    sb.Append(sof.BaseLineno);
                    sb.Append("] [end line: ");
                    sb.Append(sof.EndLineno);
                    sb.Append(']');
                }
                else if (this is Jump)
                {
                    Jump jump = (Jump)this;
                    if (this.Type == Token.BREAK || this.Type == Token.CONTINUE)
                    {
                        sb.Append(" [label: ");
                        appendPrintId(jump.JumpStatement, printIds, sb);
                        sb.Append(']');
                    }
                    else if (this.Type == Token.TRY)
                    {
                        Node catchNode     = jump.target;
                        Node finallyTarget = jump.Finally;
                        if (catchNode != null)
                        {
                            sb.Append(" [catch: ");
                            appendPrintId(catchNode, printIds, sb);
                            sb.Append(']');
                        }
                        if (finallyTarget != null)
                        {
                            sb.Append(" [finally: ");
                            appendPrintId(finallyTarget, printIds, sb);
                            sb.Append(']');
                        }
                    }
                    else if (this.Type == Token.LABEL || this.Type == Token.LOOP || this.Type == Token.SWITCH)
                    {
                        sb.Append(" [break: ");
                        appendPrintId(jump.target, printIds, sb);
                        sb.Append(']');
                        if (this.Type == Token.LOOP)
                        {
                            sb.Append(" [continue: ");
                            appendPrintId(jump.Continue, printIds, sb);
                            sb.Append(']');
                        }
                    }
                    else
                    {
                        sb.Append(" [target: ");
                        appendPrintId(jump.target, printIds, sb);
                        sb.Append(']');
                    }
                }
                else if (this.Type == Token.NUMBER)
                {
                    sb.Append(' ');
                    sb.Append(Double);
                }
                else if (this.Type == Token.TARGET)
                {
                    sb.Append(' ');
                    appendPrintId(this, printIds, sb);
                }
                if (lineno != -1)
                {
                    sb.Append(' ');
                    sb.Append(lineno);
                }

                for (PropListItem x = propListHead; x != null; x = x.next)
                {
                    int Type = x.Type;
                    sb.Append(" [");
                    sb.Append(propToString(Type));
                    sb.Append(": ");
                    string value;
                    switch (Type)
                    {
                    case TARGETBLOCK_PROP:      // can't add this as it recurses
                        value = "target block property";
                        break;

                    case LOCAL_BLOCK_PROP:      // can't add this as it is dull
                        value = "last local block";
                        break;

                    case ISNUMBER_PROP:
                        switch (x.intValue)
                        {
                        case BOTH:
                            value = "both";
                            break;

                        case RIGHT:
                            value = "right";
                            break;

                        case LEFT:
                            value = "left";
                            break;

                        default:
                            throw Context.CodeBug();
                        }
                        break;

                    case SPECIALCALL_PROP:
                        switch (x.intValue)
                        {
                        case SPECIALCALL_EVAL:
                            value = "eval";
                            break;

                        case SPECIALCALL_WITH:
                            value = "with";
                            break;

                        default:
                            // NON_SPECIALCALL should not be stored
                            throw Context.CodeBug();
                        }
                        break;

                    default:
                        object obj = x.objectValue;
                        if (obj != null)
                        {
                            value = obj.ToString();
                        }
                        else
                        {
                            value = Convert.ToString(x.intValue);
                        }
                        break;
                    }
                    sb.Append(value);
                    sb.Append(']');
                }
            }
        }