예제 #1
0
        public IdContainer ExtractCommand(Command Command, NCExpressionRunBefores[] RunBefores)
        {
            var State = Command.State;
            var Code  = Command.Code;

            if (Command.Type == CommandType.For)
            {
                var Scope = CreateScopeForCommand(Command);
                if (Command.Expressions[0] != null)
                {
                    var Init = new Command(Scope, Code, CommandType.Expression);
                    Init.Expressions = new List <ExpressionNode>()
                    {
                        Command.Expressions[0]
                    };
                    Scope.Children.Add(Init);
                    if (!ProcessContainer(Init))
                    {
                        return(null);
                    }
                }

                var While = new Command(Scope, Code, CommandType.While);
                While.Expressions = new List <ExpressionNode>()
                {
                    Command.Expressions[1]
                };
                Scope.Children.Add(While);

                var WhileScope = new CodeScopeNode(While, Code);
                While.Children.Add(WhileScope);
                WhileScope.Children.Add(Command.Children[0]);
                Command.Children[0].Parent = WhileScope;

                var Loop = new Command(WhileScope, Code, CommandType.Expression);
                Loop.Expressions = new List <ExpressionNode>()
                {
                    Command.Expressions[2]
                };
                WhileScope.Children.Add(Loop);
                if (!ProcessContainer(Loop))
                {
                    return(null);
                }

                if (!ProcessContainer(WhileScope))
                {
                    return(null);
                }
                if (!ProcessContainer(While))
                {
                    return(null);
                }
                if (!ProcessContainer(Scope))
                {
                    return(null);
                }
                return(Scope);
            }

            else if (Command.Type == CommandType.While || Command.Type == CommandType.DoWhile)
            {
                var Cycle = new Command(Command.Parent, Code, CommandType.Cycle);
                Command.Parent.ReplaceChild(Command, Cycle);
                CopyIdentifiers(Cycle, Command);

                var CycleScope = new CodeScopeNode(Cycle, Code);
                Cycle.Children.Add(CycleScope);

                var If = new Command(CycleScope, Code, CommandType.If);
                CycleScope.Children.Add(If);

                var Condition = NCExpressions.Negate(If.GetPlugin(), Command.Expressions[0], Code);
                If.Expressions = new List <ExpressionNode>()
                {
                    Condition
                };
                if (Condition == null)
                {
                    return(null);
                }

                var Then = new Command(If, Code, CommandType.Break);
                Then.Label = Cycle.BreakLabel;
                If.Children.Add(Then);

                if (!ProcessContainer(Then))
                {
                    return(null);
                }
                if (!ProcessContainer(If))
                {
                    return(null);
                }

                if (Command.Type == CommandType.While)
                {
                    CycleScope.Children.Add(Command.Children[0]);
                }
                else
                {
                    CycleScope.Children.Insert(0, Command.Children[0]);
                }
                Command.Children[0].Parent = CycleScope;

                if (!ProcessContainer(CycleScope))
                {
                    return(null);
                }
                if (!ProcessContainer(Cycle))
                {
                    return(null);
                }
                return(Cycle);
            }

            else if (Command.Type == CommandType.If)
            {
                var Scope = CreateScopeForCommand(Command);
                if (Command.Expressions.Count == 1)
                {
                    var FreeScopeCount = RunBefores[0].NeededRunBefores.Length;
                    if (!AddFreeScopes(Scope, FreeScopeCount, Code))
                    {
                        return(null);
                    }

                    Scope.Children.Add(Command);
                    Command.Parent = Scope;

                    if (!ProcessContainer(Command, true))
                    {
                        return(null);
                    }
                }
                else
                {
                    var Label     = State.AutoLabel;
                    var LabelComm = new Command(Scope, Code, CommandType.Label);
                    LabelComm.Label = Label;

                    for (var i = 0; i < Command.Expressions.Count; i++)
                    {
                        var If = new Command(Scope, Code, CommandType.If);
                        If.Expressions = new List <ExpressionNode>()
                        {
                            Command.Expressions[i]
                        };
                        Scope.Children.Add(If);

                        if (i == Command.Expressions.Count - 1)
                        {
                            If.Children.Add(Command.Children[i]);
                            Command.Children[i].Parent = If;

                            for (var j = i + 1; j < Command.Children.Count; j++)
                            {
                                If.Children.Add(Command.Children[j]);
                                Command.Children[j].Parent = If;
                            }
                        }
                        else
                        {
                            var ThenScope = new CodeScopeNode(If, Code);
                            If.Children.Add(ThenScope);

                            ThenScope.Children.Add(Command.Children[i]);
                            Command.Children[i].Parent = ThenScope;

                            var Goto = new Command(ThenScope, Code, CommandType.Goto);
                            Goto.JumpTo = LabelComm;
                            Goto.Label  = Label;
                            ThenScope.Children.Add(Goto);

                            if (!ProcessContainer(Goto))
                            {
                                return(null);
                            }
                            if (!ProcessContainer(ThenScope))
                            {
                                return(null);
                            }
                        }

                        if (!ProcessContainer(If))
                        {
                            return(null);
                        }
                    }

                    Scope.Children.Add(LabelComm);

                    if (!ProcessContainer(LabelComm))
                    {
                        return(null);
                    }
                }

                if (!ProcessContainer(Scope))
                {
                    return(null);
                }
                return(Scope);
            }

            else
            {
                if (RunBefores.Length != 1)
                {
                    throw new ApplicationException();
                }

                var Scope          = CreateScopeForCommand(Command);
                var FreeScopeCount = RunBefores[0].NeededRunBefores.Length;
                if (!AddFreeScopes(Scope, FreeScopeCount, Code))
                {
                    return(null);
                }

                Scope.Children.Add(Command);
                Command.Parent = Scope;

                if (!ProcessContainer(Command, true))
                {
                    return(null);
                }
                if (!ProcessContainer(Scope))
                {
                    return(null);
                }
                return(Scope);
            }
        }
예제 #2
0
        IdContainer ProcessCommand(Command Command, bool NoExtract = false)
        {
            var State           = Command.State;
            var GlobalContainer = State.GlobalContainer;
            var Code            = Command.Code;

            if (!NoExtract && Command.Expressions != null && Command.Expressions.Count > 0)
            {
                var RunBefores = NCExpressions.GetCommandRunBefores(Command);
                if (!RunBefores.TrueForAll(x => x.NeededRunBefores.Length == 0))
                {
                    return(ExtractCommand(Command, RunBefores));
                }
            }

            if (Command.Type == CommandType.Try)
            {
                var NCData = Command.Data.GetOrCreate <NCCommandData>();
                if (NCData.FinallyJump != null && !InitializeFinallyJump(Command, Code))
                {
                    return(null);
                }

                var TryScope = Command.Children[0] as CodeScopeNode;
                var CatchVar = GetCatchVariable(Command);
                if (CatchVar == null)
                {
                    return(null);
                }

                var Pos = NCData.FinallyJump != null ? 1 : 0;
                if (!EnterTryBlock(TryScope, Pos, Code, CatchVar, Command.CatchLabel))
                {
                    return(null);
                }

                if (!LeaveTryBlock(TryScope, Code))
                {
                    return(null);
                }

                if (Command.CatchScope == null)
                {
                    if (!FinallyRethrow(Command, Command.FinallyScope, Code))
                    {
                        return(null);
                    }
                }

                if (Command.FinallyScope != null && NCData.FinallyJump != null)
                {
                    if (!FinallyJump(Command.FinallyScope, NCData.FinallyJump, Command.Code))
                    {
                        return(null);
                    }
                }
            }

            else if (Command.Type == CommandType.Throw || Command.Type == CommandType.Rethrow)
            {
                var NewPlugin = Command.GetPlugin();
                if (!NewPlugin.Begin())
                {
                    return(null);
                }

                ExpressionNode Node;
                if (Command.Expressions != null && Command.Expressions.Count > 0)
                {
                    Node = Command.Expressions[0];
                }
                else
                {
                    var TryComm  = Command.GetParent(CommandType.Try);
                    var CatchVar = GetCatchVariable(TryComm);

                    Node = NewPlugin.NewNode(new IdExpressionNode(CatchVar, Command.Code));
                    if (Node == null)
                    {
                        return(null);
                    }

                    Command.Expressions = new List <ExpressionNode>()
                    {
                        null
                    };
                }

                Node = NCExpressions.Throw(NewPlugin, Node, Code);
                if (Node == null)
                {
                    return(null);
                }

                Command.Expressions[0] = Node;
                Command.Type           = CommandType.Expression;
            }

            else if (Commands.IsJumpCommand(Command.Type))
            {
                var TryComms = new AutoAllocatedList <Command>();
                Command.ForEachJumpedOver <Command>(x =>
                {
                    if (x.Type == CommandType.Try && x.FinallyScope != null)
                    {
                        TryComms.Add(x);
                    }
                });

                if (TryComms.Count > 0)
                {
                    var NewScope = new CodeScopeNode(Command.Parent, Code);
                    Command.Parent.ReplaceChild(Command, NewScope);

                    var LastLabel = Command.Label;
                    if (Command.Type == CommandType.Return)
                    {
                        if (!SetFinallyReturn(NewScope, Command.Expressions[0], Code))
                        {
                            return(null);
                        }

                        var FS     = Command.FunctionScope;
                        var FSData = FS.Data.Get <NCFuncScopeData>();
                        LastLabel = FSData.FinallyReturnLabel;
                    }

                    for (var i = 0; i < TryComms.Count - 1; i++)
                    {
                        var Label = TryComms[i + 1].FinallyLabel;
                        if (!SetFinallyJump(TryComms[i], NewScope, Label, Code))
                        {
                            return(null);
                        }
                    }

                    var Last = TryComms[TryComms.Count - 1];
                    if (!SetFinallyJump(Last, NewScope, LastLabel, Code))
                    {
                        return(null);
                    }
                    if (!CreateJump(NewScope, TryComms[0].FinallyLabel, Code))
                    {
                        return(null);
                    }
                    Command.FunctionScope.NeverSkippedLabels.Add(Command.Label);
                    return(NewScope);
                }
            }

            return(Command);
        }