Пример #1
0
        private JST.Statement WithLineCounts(JST.Statement statement, Func<int> nextLine, int currDepth, Set<JST.Identifier> lineCountIds)
        {
            if (statement.Flavor == JST.StatementFlavor.Try)
            {
                var trys = (JST.TryStatement)statement;
                if (trys.Catch != null)
                {
                    var tryBody = WithLineCounts(trys.Body, nextLine, currDepth + 1, lineCountIds);
                    var catchBody = new Seq<JST.Statement>();
                    var saveid = new JST.Identifier(Constants.DebugCurrentLine.Value + "_" + currDepth);
                    lineCountIds.Add(saveid);
                    catchBody.Add(JST.Statement.Assignment(saveid.ToE(), Constants.DebugCurrentLine.ToE())); 
                    foreach (var s in WithLineCounts(trys.Catch.Body, nextLine, currDepth + 1, lineCountIds).Body)
                        catchBody.Add(s);
                    var catchClause = new JST.CatchClause(trys.Catch.Loc, trys.Catch.Name, new JST.Statements(catchBody));
                    var finallyClause = default(JST.FinallyClause);
                    if (trys.Finally != null)
                        finallyClause = new JST.FinallyClause
                            (trys.Finally.Loc, WithLineCounts(trys.Finally.Body, nextLine, currDepth + 1, lineCountIds));
                    return new JST.TryStatement(trys.Loc, tryBody, catchClause, finallyClause);
                }
                // else: fall-through
            }
            // else: fall-through

            return statement.CloneWithSubStatementss
                (statement.SubStatementss.Select(ss => WithLineCounts(ss, nextLine, currDepth, lineCountIds)).ToSeq());
        }
Пример #2
0
        private void TranslateStatement(MethodCompilerEnvironment methCompEnv, Seq<JST.Statement> body, CST.Statement stmnt)
        {
            switch (stmnt.Flavor)
            {
                case CST.StatementFlavor.Expression:
                    {
                        var es = (CST.ExpressionStatement)stmnt;
                        if (env.DebugMode)
                            body.Add(new JST.CommentStatement(es.ToString()));
                        var exp = TranslateExpression(methCompEnv, body, null, true, es.Value);
                        if (exp != null)
                            body.Add(new JST.ExpressionStatement(exp));
                        break;
                    }
                case CST.StatementFlavor.Break:
                    {
                        var bs = (CST.BreakStatement)stmnt;
                        body.Add(new JST.BreakStatement(bs.Label));
                        break;
                    }
                case CST.StatementFlavor.Continue:
                    {
                        var cs = (CST.ContinueStatement)stmnt;
                        body.Add(new JST.ContinueStatement(cs.Label));
                        break;
                    }
                case CST.StatementFlavor.Throw:
                    {
                        var ts = (CST.ThrowStatement)stmnt;
                        if (env.DebugMode)
                            body.Add(new JST.CommentStatement(ts.ToString()));
                        var e = TranslateExpression(methCompEnv, body, null, false, ts.Exception);
                        body.Add(new JST.ThrowStatement(e));
                        break;
                    }
                case CST.StatementFlavor.Rethrow:
                    {
                        var rs = (CST.RethrowStatement)stmnt;
                        if (env.DebugMode)
                            body.Add(new JST.CommentStatement(rs.ToString()));
                        var e = TranslateExpression(methCompEnv, body, null, false, rs.Exception);
                        body.Add(new JST.ThrowStatement(e));
                        break;
                    }
                case CST.StatementFlavor.Return:
                    {
                        var rs = (CST.ReturnStatement)stmnt;
                        if (env.DebugMode)
                            body.Add(new JST.CommentStatement(rs.ToString()));
                        var e = rs.Value == null ? null : TranslateExpression(methCompEnv, body, null, false, rs.Value);
                        body.Add(new JST.ReturnStatement(e));
                        break;
                    }
                case CST.StatementFlavor.IfThenElse:
                    {
                        var ites = (CST.IfThenElseStatement)stmnt;
                        if (env.DebugMode)
                            body.Add(new JST.CommentStatement("condition: " + ites.Condition.ToString()));
                        var cond = TranslateConditionalExpression(methCompEnv, body, ites.Condition);
                        var then = new JST.Statements(TranslateStatements(methCompEnv, ites.Then));
                        var els = ites.Else == null ? default(JST.Statements) : new JST.Statements(TranslateStatements(methCompEnv, ites.Else));
                        body.Add(new JST.IfStatement(cond, then, els));
                        break;
                    }
                case CST.StatementFlavor.Switch:
                    {
                        var ss = (CST.SwitchStatement)stmnt;
                        if (env.DebugMode)
                            body.Add(new JST.CommentStatement("switch: " + ss.Value.ToString()));
                        var v = TranslateExpression(methCompEnv, body, null, false, ss.Value);
                        var cases = new Seq<JST.CaseClause>();
                        var def = default(JST.DefaultClause);
                        foreach (var ssc in ss.Cases)
                        {
                            var actValues = ssc.Values.Where(i => i >= 0).ToList();
                            if (actValues.Count < ssc.Values.Count)
                            {
                                if (def != null)
                                    throw new InvalidOperationException("duplicate default cases");
                                var caseBody = TranslateStatements(methCompEnv, ssc.Body);
                                def = new JST.DefaultClause(new JST.Statements(caseBody), -1);
                            }
                            if (actValues.Count > 0)
                            {
                                for (var i = 0; i < actValues.Count - 1; i++)
                                    cases.Add
                                        (new JST.CaseClause
                                             (new JST.NumericLiteral(ssc.Values[i]), new JST.Statements()));
                                var caseBody = TranslateStatements(methCompEnv, ssc.Body);
                                cases.Add
                                    (new JST.CaseClause
                                         (new JST.NumericLiteral(ssc.Values[ssc.Values.Count - 1]),
                                          new JST.Statements(caseBody)));
                            }
                        }
                        body.Add(new JST.SwitchStatement(v, cases, def));
                        break;
                    }
                case CST.StatementFlavor.DoWhile:
                    {
                        var dws = (CST.DoWhileStatement)stmnt;
                        var whileBody = TranslateStatements(methCompEnv, dws.Body);
                        // NOTE: Not safe to hoist side-effects to body
                        var cond = TranslateConditionalExpression(methCompEnv, null, dws.Condition);
                        body.Add(new JST.DoStatement(new JST.Statements(whileBody), cond));
                        if (env.DebugMode)
                            body.Add(new JST.CommentStatement("condition: " + dws.Condition.ToString()));
                        break;
                    }
                case CST.StatementFlavor.WhileDo:
                    {
                        var wds = (CST.WhileDoStatement)stmnt;
                        if (env.DebugMode)
                            body.Add(new JST.CommentStatement("condition: " + wds.Condition.ToString()));
                        // NOTE: Not safe to hoist side-effects into body
                        var cond = TranslateConditionalExpression(methCompEnv, null, wds.Condition);
                        var doBody = TranslateStatements(methCompEnv, wds.Body);
                        body.Add(new JST.WhileStatement(cond, new JST.Statements(doBody)));
                        break;
                    }
                case CST.StatementFlavor.InitializeObject:
                    {
                        var ios = (CST.InitializeObjectStatement)stmnt;
                        if (env.DebugMode)
                            body.Add(new JST.CommentStatement(ios.ToString()));
                        var ptrType = ios.Address.Type(methCompEnv);
                        if (ios.Address.Flavor == CST.ExpressionFlavor.AddressOf)
                        {
                            var aoe = (CST.AddressOfExpression)ios.Address;
                            var exp = TranslateCellReadWrite
                                (methCompEnv,
                                 body,
                                 true,
                                 aoe.Cell,
                                 lvalue => env.JSTHelpers.DefaultExpressionForType(methCompEnv, ptrType.Arguments[0]));
                            if (exp != null)
                                body.Add(new JST.ExpressionStatement(exp));
                        }
                        else
                        {
                            var ptr = TranslateExpression(methCompEnv, body, null, false, ios.Address);
                            var defval = env.JSTHelpers.DefaultExpressionForType(methCompEnv, ptrType.Arguments[0]);
                            body.Add
                                (new JST.ExpressionStatement(JST.Expression.DotCall(ptr, Constants.PointerWrite, defval)));
                        }
                        break;
                    }
                case CST.StatementFlavor.Try:
                    {
                        var ts = (CST.TryStatement)stmnt;
                        var tryBody = TranslateStatements(methCompEnv, ts.Body);
                        var finallyClause = default(JST.FinallyClause);
                        var exceptionId = default(JST.Identifier);
                        var catchTests = default(Seq<JST.Expression>);
                        var catchBodies = default(Seq<Seq<JST.Statement>>);
                        var nCatches = ts.Handlers.Where(h => h.Flavor == CST.HandlerFlavor.Catch).Count();
                        foreach (var h in ts.Handlers)
                        {
                            switch (h.Flavor)
                            {
                                case CST.HandlerFlavor.Catch:
                                    {
                                        var ch = (CST.TryStatementCatchHandler)h;
                                        var thisBody = TranslateStatements(methCompEnv, ch.Body);
                                        if (exceptionId == null)
                                            exceptionId = ch.ExceptionId;
                                        var type = methCompEnv.ResolveType(ch.Type);
                                        var thisTest = JST.Expression.IsNotNull
                                            (JST.Expression.DotCall
                                                 (rootId.ToE(), Constants.RootIsInst, exceptionId.ToE(), type));
                                        if (catchTests == null)
                                        {
                                            catchTests = new Seq<JST.Expression>();
                                            catchBodies = new Seq<Seq<JST.Statement>>();
                                        }
                                        catchTests.Add(thisTest);
                                        if (!ch.ExceptionId.Equals(exceptionId))
                                        {
                                            var newBody = new Seq<JST.Statement>();
                                            newBody.Add(JST.Statement.Var(ch.ExceptionId, exceptionId.ToE()));
                                            foreach (var s in thisBody)
                                                newBody.Add(s);
                                            catchBodies.Add(newBody);
                                        }
                                        else
                                            catchBodies.Add(thisBody);
                                        break;
                                    }
                                case CST.HandlerFlavor.Finally:
                                    {
                                        var finallyBody = TranslateStatements(methCompEnv, h.Body);
                                        if (finallyClause != null)
                                            throw new InvalidOperationException("more than one finally clause");
                                        finallyClause = new JST.FinallyClause(new JST.Statements(finallyBody));
                                        break;
                                    }
                                case CST.HandlerFlavor.Filter:
                                    throw new InvalidOperationException("filter handler not supported");
                                case CST.HandlerFlavor.Fault:
                                    throw new InvalidOperationException("fault handler not supported");
                                default:
                                    throw new ArgumentOutOfRangeException();
                            }
                        }

                        var catchClause = default(JST.CatchClause);
                        if (exceptionId != null)
                        {
                            var catchIf = default(JST.Statement);
                            for (var i = catchTests.Count - 1; i >= 0; i--)
                            {
                                if (catchIf == null)
                                    catchIf = new JST.IfStatement
                                        (catchTests[i], new JST.Statements(catchBodies[i]), new JST.Statements(new JST.ThrowStatement(exceptionId.ToE())));
                                else
                                    catchIf = new JST.IfStatement(catchTests[i], new JST.Statements(catchBodies[i]), new JST.Statements(catchIf));
                            }
                            catchClause = new JST.CatchClause(exceptionId, new JST.Statements(catchIf));
                        }
                        body.Add(new JST.TryStatement(new JST.Statements(tryBody), catchClause, finallyClause));
                        break;
                    }
                case CST.StatementFlavor.HandlePseudo:
                    {
                        var hs = (CST.HandlePseudoStatement)stmnt;
                        body.Add
                            (JST.Statement.DotCall
                                 (rootId.ToE(), Constants.RootHandle, hs.StateId.ToE(), hs.ExceptionId.ToE()));
                        break;
                    }
                case CST.StatementFlavor.PushTryPseudo:
                    {
                        var pts = (CST.PushTryPseudoStatement)stmnt;
                        body.Add
                            (JST.Statement.Call
                                 (JST.Expression.Dot(pts.StateId.ToE(), Constants.StateTryStack, Constants.push),
                                  new JST.ObjectLiteral(new OrdMap<JST.Identifier, JST.Expression>
                                  {
                                      {
                                          Constants.TryHandlers,
                                          new JST.ArrayLiteral(pts.Handlers.Select(h => HandlerLiteral(methCompEnv, h)).ToSeq())
                                          }
                                  })));
                        break;
                    }
                case CST.StatementFlavor.LeavePseudo:
                    {
                        var ls = (CST.LeavePseudoStatement)stmnt;
                        body.Add
                            (JST.Statement.DotCall
                                 (rootId.ToE(),
                                  Constants.RootLeaveTryCatch,
                                  ls.StateId.ToE(),
                                  new JST.NumericLiteral(ls.PopCount),
                                  new JST.NumericLiteral(ls.TargetId)));
                        break;
                    }
                case CST.StatementFlavor.EndPseudo:
                    {
                        var es = (CST.EndPseudoStatement)stmnt;
                        body.Add
                            (JST.Statement.DotCall(rootId.ToE(), Constants.RootEndFaultFinally, es.StateId.ToE()));
                        break;
                    }
                case CST.StatementFlavor.GotoPseudo:
                    {
                        var gs = (CST.GotoPseudoStatement)stmnt;
                        body.Add
                            (JST.Statement.DotAssignment(gs.StateId.ToE(), Constants.StatePC, new JST.NumericLiteral(gs.TargetId)));
                        break;
                    }
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }