예제 #1
0
        private void ParseAst(JS.AST ast, string sp)
        {
            if (ast == null)
            {
                return;
            }
            if (CheckWorker())
            {
                return;
            }

            //_logView.LogStr("JSM->" + sp + ast.ToString() + "\t\t" + ast.GetType().Name);

            if (ast is JS.FunctionDeclaration)
            {
                JS.Function func = ast as JS.Function;
                ParseAstList(func.func_obj.body.elems, sp + "  ");
            }
            else if (ast is JS.Assign)
            {
                JS.Assign ass = ast as JS.Assign;

                ParseAst(ass.left, sp + "l ");
                ParseAst(ass.right, sp + "r ");
            }
            else if (ast is JS.Binary)
            {
                JS.Binary bin = ast as JS.Binary;

                string[] parts = bin.ToString().Split('.');
                if (parts.Length > 1)
                {
                    if (parts[parts.Length - 2] == "This")
                    {
                        string calledId = parts[parts.Length - 1] + "()";

                        //dup
                        // If we have a method of this name in this file/class
                        if (_addedNodes.ContainsKey(calledId))
                        {
                            // Create an edge.
                            // A definite functional assignment link.
                            AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Aqua);
                        }
                        else
                        {
                            // It's a call to a method outside this class/file.
                            //
                            //_logView.LogStr("skipped assign ref -->" + _methodNodeId + " --------> " + calledId);
                            //
                        }
                    }
                    else if (parts[parts.Length - 2] == "self")
                    {
                        string calledId = parts[parts.Length - 1] + "()";

                        //dup
                        // If we have a method of this name in this file/class
                        if (_addedNodes.ContainsKey(calledId))
                        {
                            // Get the graph node that we're linking to.
                            //Node calledNode = _addedNodes[calledId];

                            // Create an edge.
                            // A definite functional assignment link.
                            AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Aqua);
                        }
                        else
                        {
                            // It's a call to a method outside this class/file.
                            _logView.LogStr("skipped assign ref -->" + _methodNodeId + " --------> " + calledId);
                        }
                    }
                }
            }
            else if (ast is JS.Expression)
            {
                JS.Expression expr = ast as JS.Expression;
                ParseAstList(expr.exprs, sp + "  ");
            }
            else if (ast is JS.FunctionExpression)
            {
                JS.FunctionExpression expr = ast as JS.FunctionExpression;
                ParseAstList(expr.func_obj.body.elems, sp + "  ");
            }
            else if (ast is JS.For)
            {
                JS.For fr = ast as JS.For;
                ParseAst(fr.stms, sp + "  ");
            }
            else if (ast is JS.If)
            {
                JS.If iff = ast as JS.If;
                ParseAst(iff.false_stm, sp + "f  ");
                ParseAst(iff.true_stm, sp + "t  ");
            }
            else if (ast is JS.Block)
            {
                JS.Block block = ast as JS.Block;
                ParseAstList(block.elems, sp + "  ");
            }
            else if (ast is JS.VariableStatement)
            {
                JS.VariableStatement var = ast as JS.VariableStatement;
                //var.
                ParseAstList(var.var_decls, sp + "  ");
            }
            else if (ast is JS.Return)
            {
                JS.Return ret = ast as JS.Return;

                ParseAst(ret.expression, sp + "  ");
            }
            else if (ast is JS.VariableDeclaration)
            {
                JS.VariableDeclaration var = ast as JS.VariableDeclaration;

                Microsoft.JScript.New newval = var.val as Microsoft.JScript.New;

                if (newval != null && newval.exp != null)
                {
                    //_logView.LogStr("new:" + newval.exp.ToString());
                    string[] parts = newval.exp.ToString().Split('.');
                    if (parts.Length > 0)
                    {
                        string calledId = parts[parts.Length - 1] + "()";

                        // If we have a method of this name in this file/class, then
                        // we have a possible constructor link.
                        if (_addedNodes.ContainsKey(calledId))
                        {
                            // Create an edge.
                            AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Green);
                        }
                    }
                }
                else
                {
                    if (var.val != null)
                    {
                        string   valStr = var.val.ToString();
                        string[] parts  = valStr.Split('.');

                        if (parts.Length > 1 && parts[0] == "self")
                        {
                            // dup..

                            string calledId = parts[parts.Length - 1] + "()";

                            // If we have a method of this name in this file/class, then
                            // we have a possible constructor link.
                            if (_addedNodes.ContainsKey(calledId))
                            {
                                // Create an edge.
                                AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Green);
                            }
                        }
                    }
                }

                //ParseAstList(var.var_decls, sp + "  ");
            }
            else if (ast is JS.Call)
            {
                JS.Call  call     = ast as JS.Call;
                string[] parts    = call.ToString().Split(' ');
                string[] bits     = parts[0].Split('.');
                string   calledId = bits[bits.Length - 1] + "()";

                bool methodInThisClass = true;
                if (bits.Length > 1)
                {
                    if ((bits[bits.Length - 2] != "This") &&
                        (bits[bits.Length - 2] != "self"))
                    {
                        methodInThisClass = false;
                    }
                }

                // If we have a method of this name in this file/class
                if (_addedNodes.ContainsKey(calledId))
                {
                    // Create an edge.
                    if (methodInThisClass)
                    {
                        // A definite link.
                        AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Black);
                    }
                    else
                    {
                        // A tentative link.
                        AddEdge(_methodNodeId, calledId, EdgeStyle.NormalArrow, Color.Gray);
                    }
                }
                else
                {
                    // It's a call to a method outside this class/file.
                    //
                    //_logView.LogStr("skipped -------->" + _methodNodeId + " --------> " + parts[0]);
                    //
                }
            }
        }
예제 #2
0
 AST MulExpr(AST parent)
 {
     AST pn = UnaryExpr (parent);
     for (;;) {
         int tt = ts.PeekToken ();
         if (tt == Token.MUL || tt == Token.DIV || tt == Token.MOD) {
             ts.GetToken ();
             decompiler.AddToken (tt);
             pn = new Binary (parent, pn, UnaryExpr (parent), ToJSToken (tt),
                  new Location (ts.SourceName, ts.LineNumber));
             continue;
         }
         break;
     }
     return pn;
 }
예제 #3
0
        AST MemberExprTail(AST parent, bool allow_call_syntax, AST pn)
        {
            int tt;

            while ((tt = ts.GetToken ()) > Token.EOF) {
                if (tt == Token.DOT) {
                    decompiler.AddToken (Token.DOT);
                    MustMatchToken (Token.NAME, "msg.no.name.after.dot");
                    string s = ts.GetString;
                    decompiler.AddName (s);
                    // FIXME: is 'new Identifier' appropriate here?
                    pn = new Binary (parent, pn,
                         new Identifier (parent, ts.GetString, new Location (ts.SourceName, ts.LineNumber)),
                         JSToken.AccessField, new Location (ts.SourceName, ts.LineNumber));
                } else if (tt == Token.LB) {
                    decompiler.AddToken (Token.LB);
                    Binary b = new Binary (parent, pn, JSToken.LeftBracket,
                               new Location (ts.SourceName, ts.LineNumber));
                    b.right = Expr (b, false);
                    pn = b;
                    MustMatchToken (Token.RB, "msg.no.bracket.index");
                    decompiler.AddToken (Token.RB);
                } else if (allow_call_syntax && tt == Token.LP) {
                    /* make a call node */
                    decompiler.AddToken (Token.LP);
                    pn = new Call (parent, pn, new Location (ts.SourceName, ts.LineNumber));

                    /* Add the arguments to pn, if any are supplied. */
                    ArgumentList (parent, (ICallable) pn);
                } else {
                    ts.UnGetToken (tt);
                    break;
                }
            }
            return pn;
        }
예제 #4
0
 AST BitXorExpr(AST parent, bool in_for_init)
 {
     AST pn = BitAndExpr (parent, in_for_init);
     while (ts.MatchToken (Token.BITXOR)) {
         decompiler.AddToken (Token.BITXOR);
         pn = new Binary (parent, pn, BitAndExpr (parent, in_for_init), JSToken.BitwiseXor,
              new Location (ts.SourceName, ts.LineNumber));
     }
     return pn;
 }
예제 #5
0
        AST ShiftExpr(AST parent)
        {
            AST pn = AddExpr (parent);
            for (;;) {
                int tt = ts.PeekToken ();
                if (tt == Token.LSH || tt == Token.URSH || tt == Token.RSH) {
                    ts.GetToken ();
                    decompiler.AddToken (tt);

                    JSToken op = JSToken.LeftShift;
                    if (tt == Token.RSH)
                        op = JSToken.RightShift;
                    else if (tt == Token.URSH)
                        op = JSToken.UnsignedRightShift;

                    pn = new Binary (parent, pn, AddExpr (parent), op,
                         new Location (ts.SourceName, ts.LineNumber));
                    continue;
                }
                break;
            }
            return pn;
        }
예제 #6
0
        internal override void Emit(EmitContext ec)
        {
            if (oper == JSToken.None)
                operand.Emit (ec);
            else {
                ILGenerator ig = ec.ig;
                Type post_prefix = typeof (PostOrPrefixOperator);
                LocalBuilder post_prefix_local = ig.DeclareLocal (post_prefix);
                LocalBuilder tmp_obj = ig.DeclareLocal (typeof (object));

                switch (this.oper) {
                case JSToken.Increment:
                    if (prefix)
                        ig.Emit (OpCodes.Ldc_I4_3);
                    else
                        ig.Emit (OpCodes.Ldc_I4_1);
                    break;
                case JSToken.Decrement:
                    if (prefix)
                        ig.Emit (OpCodes.Ldc_I4_2);
                    else
                        ig.Emit (OpCodes.Ldc_I4_0);
                    break;
                }

                ig.Emit (OpCodes.Newobj, post_prefix.GetConstructor (new Type [] { typeof (int) }));
                ig.Emit (OpCodes.Stloc, post_prefix_local);

                Binary assign = null;
                if (operand is Identifier)
                    ((Identifier) operand).EmitLoad (ec);
                else if (operand is Binary) {
                    Binary binary = operand as Binary;
                    binary.no_effect = false;
                    binary.assign = false;
                    assign = new Binary (binary.parent, binary.left, binary.right, binary.op, binary.location);
                    assign.assign = true;
                    assign.late_bind = true;
                    assign.no_effect = false;
                    if (binary.op == JSToken.LeftBracket || binary.op == JSToken.AccessField) {
                        binary.Emit (ec);
                        ig.Emit (OpCodes.Box, typeof (object));
                    } else
                        throw new NotImplementedException (String.Format ("Unhandled binary op {0}", operand));
                } else {
                    Console.WriteLine ("PostOrPrefixOperator: prefix = {0}, oper = {1}, operand = {2}",
                        prefix, oper, operand.GetType ());
                    throw new NotImplementedException ();
                }

                ig.Emit (OpCodes.Stloc, tmp_obj);
                ig.Emit (OpCodes.Ldloc, post_prefix_local);
                ig.Emit (OpCodes.Ldloca_S, tmp_obj);
                ig.Emit (OpCodes.Call, post_prefix.GetMethod ("EvaluatePostOrPrefix"));

                //
                // if does not appear as a global expression
                //
                if (prefix && !(parent is ScriptBlock)) {
                    ig.Emit (OpCodes.Dup);
                    ig.Emit (OpCodes.Stloc, tmp_obj);
                }

                if (operand is Identifier)
                    ((Identifier) operand).EmitStore (ec);
                else if (operand is Binary)
                    assign.Emit (ec);
                else
                    throw new NotImplementedException ();

                //
                // If value will be used, load the
                // temp var that holded the value
                // before inc/dec was evaluated
                //
                if (!(parent is ScriptBlock || parent is FunctionDeclaration ||
                      parent is FunctionExpression || parent is Block))
                    ig.Emit (OpCodes.Ldloc, tmp_obj);
            }
        }