Пример #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);
     }
 }
 private static Node addBeforeCurrent(Node parent, Node previous, Node current, Node toAdd)
 {
     if (previous == null) {
         if (!(current == parent.FirstChild))
             Context.CodeBug ();
         parent.addChildToFront (toAdd);
     }
     else {
         if (!(current == previous.Next))
             Context.CodeBug ();
         parent.addChildAfter (toAdd, previous);
     }
     return toAdd;
 }
Пример #3
0
        /// <summary> Statement leaf nodes.</summary>

        internal Node CreateSwitch (Node expr, int lineno)
        {
            //
            // The switch will be rewritten from:
            //
            // switch (expr) {
            //   case test1: statements1;
            //   ...
            //   default: statementsDefault;
            //   ...
            //   case testN: statementsN;
            // }
            //
            // to:
            //
            // {
            //     switch (expr) {
            //       case test1: goto label1;
            //       ...
            //       case testN: goto labelN;
            //     }
            //     goto labelDefault;
            //   label1:
            //     statements1;
            //   ...
            //   labelDefault:
            //     statementsDefault;
            //   ...
            //   labelN:
            //     statementsN;
            //   breakLabel:
            // }
            //
            // where inside switch each "break;" without label will be replaced
            // by "goto breakLabel".
            //
            // If the original switch does not have the default label, then
            // the transformed code would contain after the switch instead of
            //     goto labelDefault;
            // the following goto:
            //     goto breakLabel;
            //

            Node.Jump switchNode = new Node.Jump (Token.SWITCH, expr, lineno);
            Node block = new Node (Token.BLOCK, switchNode);
            return block;
        }
 private static Node replaceCurrent(Node parent, Node previous, Node current, Node replacement)
 {
     if (previous == null) {
         if (!(current == parent.FirstChild))
             Context.CodeBug ();
         parent.replaceChild (current, replacement);
     }
     else if (previous.next == current) {
         // Check cachedPrev.next == current is necessary due to possible
         // tree mutations
         parent.replaceChildAfter (previous, replacement);
     }
     else {
         parent.replaceChild (current, replacement);
     }
     return replacement;
 }
Пример #5
0
        /// <summary> If caseExpression argument is null it indicate default label.</summary>
        internal void addSwitchCase(Node switchBlock, Node caseExpression, Node statements)
        {
            if (switchBlock.Type != Token.BLOCK)
                throw Context.CodeBug ();
            Node.Jump switchNode = (Node.Jump)switchBlock.FirstChild;
            if (switchNode.Type != Token.SWITCH)
                throw Context.CodeBug ();

            Node gotoTarget = Node.newTarget ();
            if (caseExpression != null) {
                Node.Jump caseNode = new Node.Jump (Token.CASE, caseExpression);
                caseNode.target = gotoTarget;
                switchNode.addChildToBack (caseNode);
            }
            else {
                switchNode.Default = gotoTarget;
            }
            switchBlock.addChildToBack (gotoTarget);
            switchBlock.addChildToBack (statements);
        }
Пример #6
0
 protected internal virtual void visitCall (Node node, ScriptOrFnNode tree)
 {
 }
Пример #7
0
 public Node(int nodeType, Node child)
 {
     Type = nodeType;
     first = last = child;
     child.next = null;
 }
Пример #8
0
 internal Jump(int Type, Node child)
     : base(Type, child)
 {
 }
Пример #9
0
 private static void generatePrintIds(Node n, ObjToIntMap map)
 {
     if (Token.printTrees) {
         map.put (n, map.size ());
         for (Node cursor = n.FirstChild; cursor != null; cursor = cursor.Next) {
             generatePrintIds (cursor, map);
         }
     }
 }
Пример #10
0
 public void replaceChildAfter(Node prevChild, Node newChild)
 {
     Node child = prevChild.next;
     newChild.next = child.next;
     prevChild.next = newChild;
     if (child == last)
         last = newChild;
     child.next = null;
 }
Пример #11
0
 public void removeChild(Node child)
 {
     Node prev = getChildBefore (child);
     if (prev == null)
         first = first.next;
     else
         prev.next = child.next;
     if (child == last)
         last = prev;
     child.next = null;
 }
Пример #12
0
        void VisitExpression (Node node, int contextFlags)
        {
            if (VisitExpressionOptimized (node, contextFlags))
                return;

            int type = node.Type;
            Node child = node.FirstChild;
            int savedStackDepth = itsStackDepth;
            switch (type) {


                case Token.FUNCTION: {
                        int fnIndex = node.getExistingIntProp (Node.FUNCTION_PROP);
                        FunctionNode fn = scriptOrFn.getFunctionNode (fnIndex);

                        // See comments in visitStatement for Token.FUNCTION case					
                        switch (fn.FunctionType) {
                            case FunctionNode.FUNCTION_EXPRESSION:
                                addIndexOp (Icode_CLOSURE_EXPR, fnIndex);
                                break;
                            default:
                                throw Context.CodeBug ();
                        }

                        stackChange (1);
                    }
                    break;


                case Token.LOCAL_LOAD: {
                        int localIndex = getLocalBlockRef (node);
                        addIndexOp (Token.LOCAL_LOAD, localIndex);
                        stackChange (1);
                    }
                    break;


                case Token.COMMA: {
                        Node lastChild = node.LastChild;
                        while (child != lastChild) {
                            VisitExpression (child, 0);
                            addIcode (Icode_POP);
                            stackChange (-1);
                            child = child.Next;
                        }
                        // Preserve tail context flag if any
                        VisitExpression (child, contextFlags & ECF_TAIL);
                    }
                    break;


                case Token.USE_STACK:
                    // Indicates that stack was modified externally,
                    // like placed catch object
                    stackChange (1);
                    break;


                case Token.REF_CALL:
                case Token.CALL:
                case Token.NEW: {
                        if (type == Token.NEW) {
                            VisitExpression (child, 0);
                        }
                        else {
                            generateCallFunAndThis (child);
                        }
                        int argCount = 0;
                        while ((child = child.Next) != null) {
                            VisitExpression (child, 0);
                            ++argCount;
                        }
                        int callType = node.getIntProp (Node.SPECIALCALL_PROP, Node.NON_SPECIALCALL);
                        if (callType != Node.NON_SPECIALCALL) {
                            // embed line number and source filename
                            addIndexOp (Icode_CALLSPECIAL, argCount);
                            addUint8 (callType);
                            addUint8 (type == Token.NEW ? 1 : 0);
                            addUint16 (itsLineNumber & 0xFFFF);
                        }
                        else {
                            if (type == Token.CALL) {
                                if ((contextFlags & ECF_TAIL) != 0) {
                                    type = Icode_TAIL_CALL;
                                }
                            }
                            addIndexOp (type, argCount);
                        }
                        // adjust stack
                        if (type == Token.NEW) {
                            // new: f, args -> result
                            stackChange (-argCount);
                        }
                        else {
                            // call: f, thisObj, args -> result
                            // ref_call: f, thisObj, args -> ref
                            stackChange (-1 - argCount);
                        }
                        if (argCount > itsData.itsMaxCalleeArgs) {
                            itsData.itsMaxCalleeArgs = argCount;
                        }
                    }
                    break;


                case Token.AND:
                case Token.OR: {
                        VisitExpression (child, 0);
                        addIcode (Icode_DUP);
                        stackChange (1);
                        int afterSecondJumpStart = itsICodeTop;
                        int jump = (type == Token.AND) ? Token.IFNE : Token.IFEQ;
                        addGotoOp (jump);
                        stackChange (-1);
                        addIcode (Icode_POP);
                        stackChange (-1);
                        child = child.Next;
                        // Preserve tail context flag if any
                        VisitExpression (child, contextFlags & ECF_TAIL);
                        resolveForwardGoto (afterSecondJumpStart);
                    }
                    break;


                case Token.HOOK: {
                        Node ifThen = child.Next;
                        Node ifElse = ifThen.Next;
                        VisitExpression (child, 0);
                        int elseJumpStart = itsICodeTop;
                        addGotoOp (Token.IFNE);
                        ;
                        stackChange (-1);
                        // Preserve tail context flag if any
                        VisitExpression (ifThen, contextFlags & ECF_TAIL);
                        int afterElseJumpStart = itsICodeTop;
                        addGotoOp (Token.GOTO);
                        resolveForwardGoto (elseJumpStart);
                        itsStackDepth = savedStackDepth;
                        // Preserve tail context flag if any
                        VisitExpression (ifElse, contextFlags & ECF_TAIL);
                        resolveForwardGoto (afterElseJumpStart);
                    }
                    break;


                case Token.GETPROP:
                    VisitExpression (child, 0);
                    child = child.Next;
                    addStringOp (Token.GETPROP, child.String);
                    break;


                case Token.ADD:
                case Token.GETELEM:
                case Token.DELPROP:
                case Token.BITAND:
                case Token.BITOR:
                case Token.BITXOR:
                case Token.LSH:
                case Token.RSH:
                case Token.URSH:
                case Token.SUB:
                case Token.MOD:
                case Token.DIV:
                case Token.MUL:
                case Token.EQ:
                case Token.NE:
                case Token.SHEQ:
                case Token.SHNE:
                case Token.IN:
                case Token.INSTANCEOF:
                case Token.LE:
                case Token.LT:
                case Token.GE:
                case Token.GT:
                    VisitExpression (child, 0);
                    VisitExpression (child.Next, 0);
                    addToken (type);
                    stackChange (-1);
                    break;


                case Token.POS:
                case Token.NEG:
                case Token.NOT:
                case Token.BITNOT:
                case Token.TYPEOF:
                case Token.VOID:
                    VisitExpression (child, 0);
                    if (type == Token.VOID) {
                        addIcode (Icode_POP);
                        addIcode (Icode_UNDEF);
                    }
                    else {
                        addToken (type);
                    }
                    break;


                case Token.GET_REF:
                case Token.DEL_REF:
                    VisitExpression (child, 0);
                    addToken (type);
                    break;


                case Token.SETPROP:
                case Token.SETPROP_OP:
                case Token.SETPROP_GETTER:
                case Token.SETPROP_SETTER: 
                    {
                        VisitExpression (child, 0);
                        child = child.Next;
                        string property = child.String;
                        child = child.Next;
                        if (type == Token.SETPROP_OP) {
                            addIcode (Icode_DUP);
                            stackChange (1);
                            addStringOp (Token.GETPROP, property);
                            // Compensate for the following USE_STACK
                            stackChange (-1);
                        }
                        VisitExpression (child, 0);
                        addStringOp ((type == Token.SETPROP_OP) ? Token.SETPROP : type, property);
                        stackChange (-1);
                    }
                    break;


                case Token.SETELEM:
                case Token.SETELEM_OP:
                    VisitExpression (child, 0);
                    child = child.Next;
                    VisitExpression (child, 0);
                    child = child.Next;
                    if (type == Token.SETELEM_OP) {
                        addIcode (Icode_DUP2);
                        stackChange (2);
                        addToken (Token.GETELEM);
                        stackChange (-1);
                        // Compensate for the following USE_STACK
                        stackChange (-1);
                    }
                    VisitExpression (child, 0);
                    addToken (Token.SETELEM);
                    stackChange (-2);
                    break;


                case Token.SET_REF:
                case Token.SET_REF_OP:
                    VisitExpression (child, 0);
                    child = child.Next;
                    if (type == Token.SET_REF_OP) {
                        addIcode (Icode_DUP);
                        stackChange (1);
                        addToken (Token.GET_REF);
                        // Compensate for the following USE_STACK
                        stackChange (-1);
                    }
                    VisitExpression (child, 0);
                    addToken (Token.SET_REF);
                    stackChange (-1);
                    break;


                case Token.SETNAME: {
                        string name = child.String;
                        VisitExpression (child, 0);
                        child = child.Next;
                        VisitExpression (child, 0);
                        addStringOp (Token.SETNAME, name);
                        stackChange (-1);
                    }
                    break;


                case Token.TYPEOFNAME: {
                        string name = node.String;
                        int index = -1;
                        // use typeofname if an activation frame exists
                        // since the vars all exist there instead of in jregs
                        if (itsInFunctionFlag && !itsData.itsNeedsActivation)
                            index = scriptOrFn.getParamOrVarIndex (name);
                        if (index == -1) {
                            addStringOp (Icode_TYPEOFNAME, name);
                            stackChange (1);
                        }
                        else {
                            addVarOp (Token.GETVAR, index);
                            stackChange (1);
                            addToken (Token.TYPEOF);
                        }
                    }
                    break;


                case Token.BINDNAME:
                case Token.NAME:
                case Token.STRING:
                    addStringOp (type, node.String);
                    stackChange (1);
                    break;


                case Token.INC:
                case Token.DEC:
                    VisitIncDec (node, child);
                    break;


                case Token.NUMBER: {
                        double num = node.Double;
                        int inum = (int)num;
                        if (inum == num) {
                            if (inum == 0) {
                                addIcode (Icode_ZERO);
                                // Check for negative zero
                                if (1.0 / num < 0.0) {
                                    addToken (Token.NEG);
                                }
                            }
                            else if (inum == 1) {
                                addIcode (Icode_ONE);
                            }
                            else if ((short)inum == inum) {
                                addIcode (Icode_SHORTNUMBER);
                                // write short as uin16 bit pattern
                                addUint16 (inum & 0xFFFF);
                            }
                            else {
                                addIcode (Icode_INTNUMBER);
                                addInt (inum);
                            }
                        }
                        else {
                            int index = GetDoubleIndex (num);
                            addIndexOp (Token.NUMBER, index);
                        }
                        stackChange (1);
                    }
                    break;


                case Token.GETVAR: {
                        if (itsData.itsNeedsActivation)
                            Context.CodeBug ();
                        string name = node.String;
                        int index = scriptOrFn.getParamOrVarIndex (name);
                        addVarOp (Token.GETVAR, index);
                        stackChange (1);
                    }
                    break;


                case Token.SETVAR: {
                        if (itsData.itsNeedsActivation)
                            Context.CodeBug ();
                        string name = child.String;
                        child = child.Next;
                        VisitExpression (child, 0);
                        int index = scriptOrFn.getParamOrVarIndex (name);
                        addVarOp (Token.SETVAR, index);
                    }
                    break;



                case Token.NULL:
                case Token.THIS:
                case Token.THISFN:
                case Token.FALSE:
                case Token.TRUE:
                    addToken (type);
                    stackChange (1);
                    break;


                case Token.ENUM_NEXT:
                case Token.ENUM_ID:
                    addIndexOp (type, getLocalBlockRef (node));
                    stackChange (1);
                    break;


                case Token.REGEXP: {
                        int index = node.getExistingIntProp (Node.REGEXP_PROP);
                        addIndexOp (Token.REGEXP, index);
                        stackChange (1);
                    }
                    break;


                case Token.ARRAYLIT:
                case Token.OBJECTLIT:
                    VisitLiteral (node, child);
                    break;


                case Token.REF_SPECIAL:
                    VisitExpression (child, 0);
                    addStringOp (type, (string)node.getProp (Node.NAME_PROP));
                    break;


                case Token.REF_MEMBER:
                case Token.REF_NS_MEMBER:
                case Token.REF_NAME:
                case Token.REF_NS_NAME: {
                        int memberTypeFlags = node.getIntProp (Node.MEMBER_TYPE_PROP, 0);
                        // generate possible target, possible namespace and member
                        int childCount = 0;
                        do {
                            VisitExpression (child, 0);
                            ++childCount;
                            child = child.Next;
                        }
                        while (child != null);
                        addIndexOp (type, memberTypeFlags);
                        stackChange (1 - childCount);
                    }
                    break;


                case Token.DOTQUERY: {
                        int queryPC;
                        updateLineNumber (node);
                        VisitExpression (child, 0);
                        addIcode (Icode_ENTERDQ);
                        stackChange (-1);
                        queryPC = itsICodeTop;
                        VisitExpression (child.Next, 0);
                        addBackwardGoto (Icode_LEAVEDQ, queryPC);
                    }
                    break;


                case Token.DEFAULTNAMESPACE:
                case Token.ESCXMLATTR:
                case Token.ESCXMLTEXT:
                    VisitExpression (child, 0);
                    addToken (type);
                    break;

                default:
                    throw badTree (node);

            }
            //if (savedStackDepth + 1 != itsStackDepth) {
            //    EcmaScriptHelper.CodeBug();
            //}
        }
Пример #13
0
        bool VisitExpressionOptimized (Node node, int contextFlags)
        {
            return false;
#if FALKSE
            if (node.Type == Token.ADD) {
                Node next = node.Next;
                if (next == null)
                    return false;
                switch (next.Type) { 
                    case Token.NAME:
                    case Token.STRING:
                        return true;
                }
            }
            return false;
#endif
        }
Пример #14
0
        void VisitStatement (Node node)
        {
            int type = node.Type;
            Node child = node.FirstChild;
            switch (type) {


                case Token.FUNCTION: {
                        int fnIndex = node.getExistingIntProp (Node.FUNCTION_PROP);
                        int fnType = scriptOrFn.getFunctionNode (fnIndex).FunctionType;
                        // Only function expressions or function expression
                        // statements needs closure code creating new function
                        // object on stack as function statements are initialized
                        // at script/function start
                        // In addition function expression can not present here
                        // at statement level, they must only present as expressions.
                        if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) {
                            addIndexOp (Icode_CLOSURE_STMT, fnIndex);
                        }
                        else {
                            if (fnType != FunctionNode.FUNCTION_STATEMENT) {
                                throw Context.CodeBug ();
                            }
                        }
                    }
                    break;


                case Token.SCRIPT:
                case Token.LABEL:
                case Token.LOOP:
                case Token.BLOCK:
                case Token.EMPTY:
                case Token.WITH:
                    updateLineNumber (node);
                    while (child != null) {
                        VisitStatement (child);
                        child = child.Next;
                    }
                    break;


                case Token.ENTERWITH:
                    VisitExpression (child, 0);
                    addToken (Token.ENTERWITH);
                    stackChange (-1);
                    break;


                case Token.LEAVEWITH:
                    addToken (Token.LEAVEWITH);
                    break;


                case Token.LOCAL_BLOCK: {
                        int local = allocLocal ();
                        node.putIntProp (Node.LOCAL_PROP, local);
                        updateLineNumber (node);
                        while (child != null) {
                            VisitStatement (child);
                            child = child.Next;
                        }
                        addIndexOp (Icode_LOCAL_CLEAR, local);
                        releaseLocal (local);
                    }
                    break;

                case Token.DEBUGGER:
                    updateLineNumber (node);
                    addIcode (Icode_DEBUGGER);
                    break;

                case Token.SWITCH:
                    updateLineNumber (node); {
                        // See comments in IRFactory.createSwitch() for description
                        // of SWITCH node
                        Node switchNode = (Node.Jump)node;
                        VisitExpression (child, 0);
                        for (Node.Jump caseNode = (Node.Jump)child.Next; caseNode != null; caseNode = (Node.Jump)caseNode.Next) {
                            if (caseNode.Type != Token.CASE)
                                throw badTree (caseNode);
                            Node test = caseNode.FirstChild;
                            addIcode (Icode_DUP);
                            stackChange (1);
                            VisitExpression (test, 0);
                            addToken (Token.SHEQ);
                            stackChange (-1);
                            // If true, Icode_IFEQ_POP will jump and remove case
                            // value from stack
                            addGoto (caseNode.target, Icode_IFEQ_POP);
                            stackChange (-1);
                        }
                        addIcode (Icode_POP);
                        stackChange (-1);
                    }
                    break;


                case Token.TARGET:
                    markTargetLabel (node);
                    break;


                case Token.IFEQ:
                case Token.IFNE: {
                        Node target = ((Node.Jump)node).target;
                        VisitExpression (child, 0);
                        addGoto (target, type);
                        stackChange (-1);
                    }
                    break;


                case Token.GOTO: {
                        Node target = ((Node.Jump)node).target;
                        addGoto (target, type);
                    }
                    break;


                case Token.JSR: {
                        Node target = ((Node.Jump)node).target;
                        addGoto (target, Icode_GOSUB);
                    }
                    break;


                case Token.FINALLY: {
                        // Account for incomming GOTOSUB address
                        stackChange (1);
                        int finallyRegister = getLocalBlockRef (node);
                        addIndexOp (Icode_STARTSUB, finallyRegister);
                        stackChange (-1);
                        while (child != null) {
                            VisitStatement (child);
                            child = child.Next;
                        }
                        addIndexOp (Icode_RETSUB, finallyRegister);
                    }
                    break;


                case Token.EXPR_VOID:
                case Token.EXPR_RESULT:
                    updateLineNumber (node);
                    VisitExpression (child, 0);
                    addIcode ((type == Token.EXPR_VOID) ? Icode_POP : Icode_POP_RESULT);
                    stackChange (-1);
                    break;


                case Token.TRY: {
                        Node.Jump tryNode = (Node.Jump)node;
                        int exceptionObjectLocal = getLocalBlockRef (tryNode);
                        int scopeLocal = allocLocal ();

                        addIndexOp (Icode_SCOPE_SAVE, scopeLocal);

                        int tryStart = itsICodeTop;
                        while (child != null) {
                            VisitStatement (child);
                            child = child.Next;
                        }

                        Node catchTarget = tryNode.target;
                        if (catchTarget != null) {
                            int catchStartPC = itsLabelTable [getTargetLabel (catchTarget)];
                            addExceptionHandler (tryStart, catchStartPC, catchStartPC, false, exceptionObjectLocal, scopeLocal);
                        }
                        Node finallyTarget = tryNode.Finally;
                        if (finallyTarget != null) {
                            int finallyStartPC = itsLabelTable [getTargetLabel (finallyTarget)];
                            addExceptionHandler (tryStart, finallyStartPC, finallyStartPC, true, exceptionObjectLocal, scopeLocal);
                        }

                        addIndexOp (Icode_LOCAL_CLEAR, scopeLocal);
                        releaseLocal (scopeLocal);
                    }
                    break;


                case Token.CATCH_SCOPE: {
                        int localIndex = getLocalBlockRef (node);
                        int scopeIndex = node.getExistingIntProp (Node.CATCH_SCOPE_PROP);
                        string name = child.String;
                        child = child.Next;
                        VisitExpression (child, 0); // load expression object
                        addStringPrefix (name);
                        addIndexPrefix (localIndex);
                        addToken (Token.CATCH_SCOPE);
                        addUint8 (scopeIndex != 0 ? 1 : 0);
                        stackChange (-1);
                    }
                    break;


                case Token.THROW:
                    updateLineNumber (node);
                    VisitExpression (child, 0);
                    addToken (Token.THROW);
                    addUint16 (itsLineNumber & 0xFFFF);
                    stackChange (-1);
                    break;


                case Token.RETHROW:
                    updateLineNumber (node);
                    addIndexOp (Token.RETHROW, getLocalBlockRef (node));
                    break;


                case Token.RETURN:
                    updateLineNumber (node);
                    if (child != null) {
                        VisitExpression (child, ECF_TAIL);
                        addToken (Token.RETURN);
                        stackChange (-1);
                    }
                    else {
                        addIcode (Icode_RETUNDEF);
                    }
                    break;


                case Token.RETURN_RESULT:
                    updateLineNumber (node);
                    addToken (Token.RETURN_RESULT);
                    break;


                case Token.ENUM_INIT_KEYS:
                case Token.ENUM_INIT_VALUES:
                    VisitExpression (child, 0);
                    addIndexOp (type, getLocalBlockRef (node));
                    stackChange (-1);
                    break;


                default:
                    throw badTree (node);

            }

            if (itsStackDepth != 0) {
                throw Context.CodeBug ();
            }
        }
Пример #15
0
 ApplicationException badTree (Node node)
 {
     throw new ApplicationException (node.ToString ());
 }
Пример #16
0
 public void addChildToFront(Node child)
 {
     child.next = first;
     first = child;
     if (last == null) {
         last = child;
     }
 }
Пример #17
0
 public Node getChildBefore(Node child)
 {
     if (child == first)
         return null;
     Node n = first;
     while (n.next != child) {
         n = n.next;
         if (n == null)
             throw new ApplicationException ("node is not a child");
     }
     return n;
 }
Пример #18
0
 public Node(int nodeType, Node child, int line)
     : this(nodeType, child)
 {
     lineno = line;
 }
Пример #19
0
 public void replaceChild(Node child, Node newChild)
 {
     newChild.next = child.next;
     if (child == first) {
         first = newChild;
     }
     else {
         Node prev = getChildBefore (child);
         prev.next = newChild;
     }
     if (child == last)
         last = newChild;
     child.next = null;
 }
Пример #20
0
 public Node(int nodeType, Node left, Node mid, Node right, int line)
     : this(nodeType, left, mid, right)
 {
     lineno = line;
 }
Пример #21
0
 private static void appendPrintId(Node n, ObjToIntMap printIds, System.Text.StringBuilder sb)
 {
     if (Token.printTrees) {
         if (n != null) {
             int id = printIds.Get (n, -1);
             sb.Append ('#');
             if (id != -1) {
                 sb.Append (id + 1);
             }
             else {
                 sb.Append ("<not_available>");
             }
         }
     }
 }
Пример #22
0
 /// <summary> Add 'child' after 'node'.</summary>
 public void addChildAfter(Node newChild, Node node)
 {
     if (newChild.next != null)
         throw new ApplicationException ("newChild had siblings in addChildAfter");
     newChild.next = node.next;
     node.next = newChild;
     if (last == node)
         last = newChild;
 }
Пример #23
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);
             }
         }
     }
 }
Пример #24
0
 /// <summary> Add 'child' before 'node'.</summary>
 public void addChildBefore(Node newChild, Node node)
 {
     if (newChild.next != null)
         throw new ApplicationException ("newChild had siblings in addChildBefore");
     if (first == node) {
         newChild.next = first;
         first = newChild;
         return;
     }
     Node prev = getChildBefore (node);
     addChildAfter (newChild, prev);
 }
Пример #25
0
 internal Jump(int Type, Node child, int lineno)
     : base(Type, child, lineno)
 {
 }
Пример #26
0
 public void addChildrenToBack(Node children)
 {
     if (last != null) {
         last.next = children;
     }
     last = children.LastSibling;
     if (first == null) {
         first = children;
     }
 }
Пример #27
0
 public Node(int nodeType, Node left, Node right)
 {
     Type = nodeType;
     first = left;
     last = right;
     left.next = right;
     right.next = null;
 }
Пример #28
0
 public void addChildrenToFront(Node children)
 {
     Node lastSib = children.LastSibling;
     lastSib.next = first;
     first = children;
     if (last == null) {
         last = lastSib;
     }
 }
Пример #29
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:
                    ;
                }
            }
        }
Пример #30
0
 public void addChildToBack(Node child)
 {
     child.next = null;
     if (last == null) {
         first = last = child;
         return;
     }
     last.next = child;
     last = child;
 }