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); } }
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); }