public ForeachBuilder(ActionSet actionSet, IWorkshopTree array, bool recursive = false) { ActionSet = actionSet; IndexStore = actionSet.VarCollection.Assign("foreachIndex,", actionSet.IsGlobal, !recursive); Recursive = recursive; if (recursive) { RecursiveIndexReference recursiveStore = new RecursiveIndexReference(IndexStore); IndexStore = recursiveStore; actionSet.InitialSet().AddAction(recursiveStore.Reset()); actionSet.AddAction(recursiveStore.Push(0)); actionSet.ReturnHandler.AdditionalPopOnReturn.Add(recursiveStore); } else { actionSet.AddAction(IndexStore.SetVariable(0)); } Array = array; Condition = Element.Compare(IndexStore.GetVariable(), Operator.LessThan, Element.CountOf(Array)); Index = (Element)IndexStore.GetVariable(); IndexValue = Element.ValueInArray(Array, IndexStore.GetVariable()); actionSet.AddAction(Element.While(Condition)); }
public static void Assign(ActionSet actionSet, Var var) { // Get the initial value. IWorkshopTree initialValue = new V_Number(0); if (var.InitialValue != null) { initialValue = var.InitialValue.Parse(actionSet); } // Add the variable to the assigner. actionSet.IndexAssigner.Add(actionSet.VarCollection, var, actionSet.IsGlobal, initialValue); // Set the initial value. if (var.Settable()) { IndexReference reference = (IndexReference)actionSet.IndexAssigner[var]; if (reference is RecursiveIndexReference recursive) { actionSet.InitialSet().AddAction(recursive.Reset()); actionSet.AddAction(recursive.Push((Element)initialValue)); } else { actionSet.AddAction(reference.SetVariable((Element)initialValue)); } } }
/// <summary>Calls the method.</summary> private IWorkshopTree ParseCall(ActionSet actionSet, MethodCall methodCall) { // Create the array used for continuing after a recursive call. continueArray = actionSet.VarCollection.Assign("_" + method.Name + "_recursiveContinue", actionSet.IsGlobal, false); nextContinue = actionSet.VarCollection.Assign("_" + method.Name + "_nextContinue", actionSet.IsGlobal, true); actionSet.InitialSet().AddAction(continueArray.SetVariable(new V_EmptyArray())); ReturnHandler returnHandler = methodCall.ReturnHandler ?? new ReturnHandler(actionSet, method.Name, method.multiplePaths); this.returnHandler = returnHandler; DefinedMethod.AssignParameters(actionSet, method.ParameterVars, methodCall.ParameterValues, true); actionSet.AddAction(Element.Part <A_While>(new V_True())); continueAt = new SkipStartMarker(actionSet); continueAt.SetSkipCount((Element)nextContinue.GetVariable()); actionSet.AddAction(continueAt); method.block.Translate(actionSet); PopParameterStacks(actionSet); // Pop the continueArray. actionSet.AddAction(Element.Part <A_SkipIf>(new V_Compare( Element.Part <V_CountOf>(continueArray.GetVariable()), Operators.Equal, new V_Number(0) ), new V_Number(3))); actionSet.AddAction(nextContinue.SetVariable(Element.Part <V_LastOf>(continueArray.GetVariable()))); actionSet.AddAction(continueArray.ModifyVariable(Operation.RemoveFromArrayByIndex, Element.Part <V_CountOf>(continueArray.GetVariable()) - 1)); actionSet.AddAction(endOfMethod); actionSet.AddAction(new A_End()); actionSet.AddAction(nextContinue.SetVariable(0)); return(returnHandler.GetReturnedValue()); }
// Sets up single-instance methods for methods with the 'rule' attribute. public void SetupSubroutine() { if (subroutineInfo != null || !IsSubroutine) { return; } // Setup the subroutine element. Subroutine subroutine = parseInfo.TranslateInfo.SubroutineCollection.NewSubroutine(Name); // Create the rule. TranslateRule subroutineRule = new TranslateRule(parseInfo.TranslateInfo, subroutine, SubroutineName, subroutineDefaultGlobal); // Setup the return handler. ReturnHandler returnHandler = new ReturnHandler(subroutineRule.ActionSet, Name, multiplePaths || Attributes.Virtual); ActionSet actionSet = subroutineRule.ActionSet.New(returnHandler).New(subroutineRule.ActionSet.IndexAssigner.CreateContained()); // Get the variables that will be used to store the parameters. IndexReference[] parameterStores = new IndexReference[ParameterVars.Length]; for (int i = 0; i < ParameterVars.Length; i++) { // Create the workshop variable the parameter will be stored as. IndexReference indexResult = actionSet.IndexAssigner.AddIndexReference(actionSet.VarCollection, ParameterVars[i], subroutineDefaultGlobal, Attributes.Recursive); parameterStores[i] = indexResult; // Assign virtual variables to the index reference. foreach (Var virtualParameterOption in VirtualVarGroup(i)) { actionSet.IndexAssigner.Add(virtualParameterOption, indexResult); } } // If the subroutine is an object function inside a class, create a variable to store the class object. IndexReference objectStore = null; if (Attributes.ContainingType != null && !Static) { objectStore = actionSet.VarCollection.Assign("_" + Name + "_subroutineStore", true, !Attributes.Recursive); // Set the objectStore as an empty array if the subroutine is recursive. if (Attributes.Recursive) { actionSet.InitialSet().AddAction(objectStore.SetVariable(new V_EmptyArray())); Attributes.ContainingType.AddObjectVariablesToAssigner(Element.Part <V_LastOf>(objectStore.GetVariable()), actionSet.IndexAssigner); actionSet = actionSet.New(Element.Part <V_LastOf>(objectStore.GetVariable())).PackThis(); } else { Attributes.ContainingType.AddObjectVariablesToAssigner(objectStore.GetVariable(), actionSet.IndexAssigner); actionSet = actionSet.New(objectStore.GetVariable()).PackThis(); } } // Set the subroutine info. subroutineInfo = new SubroutineInfo(subroutine, returnHandler, subroutineRule, parameterStores, objectStore); MethodBuilder builder = new MethodBuilder(this, actionSet, returnHandler); builder.BuilderSet = builder.BuilderSet.New(Attributes.Recursive); builder.ParseInner(); // Apply returns. returnHandler.ApplyReturnSkips(); // Pop object array and parameters if recursive. if (Attributes.Recursive) { if (objectStore != null) { actionSet.AddAction(objectStore.ModifyVariable(Operation.RemoveFromArrayByIndex, Element.Part <V_CountOf>(objectStore.GetVariable()) - 1)); } RecursiveStack.PopParameterStacks(actionSet, ParameterVars); } // Add the subroutine. Rule translatedRule = subroutineRule.GetRule(); parseInfo.TranslateInfo.WorkshopRules.Add(translatedRule); var codeLens = new ElementCountCodeLens(DefinedAt.range, parseInfo.TranslateInfo.OptimizeOutput); parseInfo.Script.AddCodeLensRange(codeLens); codeLens.RuleParsed(translatedRule); }