Exemplo n.º 1
0
        public void GenerateScope(Subroutine sub, Scope scope)
        {
            // TODO should not rely on block order
            BasicBlock first_block = null;
            var exps = new List<Expression>();

            CurrentScope = scope;

            for (int i = 0; i < sub.BasicBlocks.Count; ++i)
            {
                var block = sub.BasicBlocks[i];
                if (block == null || block.Dead != 0) // TODO enumeration
                    continue;

                if (block.Scope > scope.Id)
                {
                    int scopeId = block.Scope;

                    // if scope has no blocks on its own, still needs to
                    // insert inner scopes, so it can't just test whether this
                    // block's scope is directly inside the current scope, but
                    // it must handle the case when a scope is entirely
                    // composed by blocks in inner scopes
                    if (Scopes[scopeId].FirstBlockFor != -1)
                        scopeId = Scopes[scopeId].FirstBlockFor;

                    if (sub.Scopes[scopeId].Outer == scope.Id &&
                        !Scopes[scopeId].Used)
                    {
                        Scopes[scopeId].Used = true;

                        if (Scopes[scopeId].Body != null)
                        {
                            if (first_block != null)
                                exps.Add(Expression.Label(Scopes[scopeId].Start));

                            exps.AddRange(Scopes[scopeId].Body);
                        }

                        if (first_block == null)
                        {
                            first_block = Scopes[block.Scope].FirstBlock;
                            Scopes[block.Scope].FirstBlockFor = scope.Id;
                        }
                    }
                }
                else if (block.Scope == scope.Id)
                {
                    if (first_block == null)
                        first_block = block;
                    else
                        exps.Add(Expression.Label(BlockLabels[block]));

                    GenerateBlock(sub, block, exps);
                }
            }

            List<Expression> body = null;

            if ((scope.Flags & Scope.SCOPE_EVAL) != 0)
            {
                exps.Insert(0,
                    Expression.Call(
                        Expression.Field(Runtime, "CallStack"),
                        typeof(Stack<StackFrame>).GetMethod("Push"),
                        Expression.New(
                            typeof(StackFrame).GetConstructor(new Type[] {
                                    typeof(string), typeof(string),
                                    typeof(int), typeof(P5Code),
                                    typeof(Opcode.ContextValues),
                                    typeof(bool)}),
                            Expression.Constant(sub.LexicalStates[scope.LexicalState].Package),
                            Expression.Constant(scope.Start.File),
                            Expression.Constant(scope.Start.Line),
                            Expression.Constant(null, typeof(P5Code)),
                            Expression.Constant((Opcode.ContextValues)scope.Context),
                            Expression.Constant(true)
                            )));

                var except = new List<Expression>();
                var ex = Expression.Variable(typeof(P5Exception));
                for (int j = scope.Opcodes.Count - 1; j >= 0; --j)
                    GenerateOpcodes(sub, scope.Opcodes[j], except);
                except.Add(
                    Expression.Call(
                        Runtime,
                        typeof(Runtime).GetMethod("SetException"),
                        ex));
                GenerateBlock(sub, scope.Exception, except);

                var block = Expression.TryCatchFinally(
                    Expression.Block(typeof(IP5Any), exps),
                    Expression.Call(
                        Expression.Field(Runtime, "CallStack"),
                        typeof(Stack<StackFrame>).GetMethod("Pop")),
                    Expression.Catch(
                        ex,
                        Expression.Block(typeof(IP5Any), except))
                    );

                body = new List<Expression>();
                body.Add(block);
            }
            else if (scope.Opcodes.Count > 0)
            {
                var fault = new List<Expression>();
                for (int j = scope.Opcodes.Count - 1; j >= 0; --j)
                    GenerateOpcodes(sub, scope.Opcodes[j], fault);
                fault.Add(Expression.Rethrow(typeof(IP5Any)));

                var block = Expression.TryCatch(
                    Expression.Block(typeof(IP5Any), exps),
                    Expression.Catch(
                        typeof(System.Exception),
                        Expression.Block(typeof(IP5Any), fault)));

                body = new List<Expression>();
                body.Add(block);
            }
            else if (first_block != null)
                body = exps;

            if (first_block != null)
                Scopes[scope.Id].Start = BlockLabels[first_block];

            Scopes[scope.Id].FirstBlock = first_block;

            if ((scope.Flags & Scope.SCOPE_VALUE) != 0)
                ValueBlocks[first_block] = Expression.Block(
                    typeof(IP5Any), body);
            else
                Scopes[scope.Id].Body = body;
        }
Exemplo n.º 2
0
        public static Scope ReadScope(BinaryReader reader, Subroutine[] subs,
                                      Subroutine sub)
        {
            var scope = new Scope();

            scope.Outer = reader.ReadInt32();
            scope.Id = reader.ReadInt32();
            scope.Flags = reader.ReadInt32();
            scope.Context = reader.ReadInt32();
            ReadPos(reader, out scope.Start);
            ReadPos(reader, out scope.End);
            scope.LexicalState = reader.ReadInt32();
            int exc_idx = reader.ReadInt32();
            if (exc_idx >= 0)
                scope.Exception = sub.BasicBlocks[exc_idx];

            int leave_count = reader.ReadInt32();

            scope.Opcodes = new List<List<Opcode>>(leave_count);

            for (int i = 0; i < leave_count; ++i)
            {
                int op_count = reader.ReadInt32();
                scope.Opcodes.Add(new List<Opcode>(op_count));

                for (int j = 0; j < op_count; ++j)
                    scope.Opcodes[i].Add(ReadOpcode(reader, subs, sub));
            }

            return scope;
        }