private void AsyncLock() { V_EventPlayer eventPlayer = new V_EventPlayer(); ActionSet.AddAction(Element.Part <A_While>( Element.Part <V_Or>( Element.Part <V_And>( // The subroutine is executing on a global context, new V_Compare(eventPlayer, Operators.Equal, new V_Null()), // ...and the subroutine is running. GlobalRunning.GetVariable() ), // OR Element.Part <V_And>( // The subroutine is executing on a player context, new V_Compare(eventPlayer, Operators.NotEqual, new V_Null()), // ...and the subroutine is running on the player context. PlayerRunning.GetVariable(eventPlayer) ) ) )); // While the above while is running, wait. ActionSet.AddAction(A_Wait.MinimumWait); ActionSet.AddAction(new A_End()); // When it ends, set the context to true. ActionSet.AddAction(PlayerRunning.SetVariable(true, eventPlayer)); // Shouldn't do anything on a global context. ActionSet.AddAction(Element.Part <A_If>(new V_Compare(eventPlayer, Operators.Equal, new V_Null()))); ActionSet.AddAction(GlobalRunning.SetVariable(true)); }
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)); } } }
public void GetClassIndex(int classIdentifier, IndexReference classReference, ActionSet actionSet) { actionSet.AddAction(classReference.SetVariable( Element.IndexOfArrayValue(ClassIndexes.Get(), 0) )); actionSet.AddAction(ClassIndexes.SetVariable( classIdentifier, null, (Element)classReference.GetVariable() )); }
/// <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()); }
private void SetInitialVariables(IndexReference typeObject, ActionSet actionSet) { for (int i = 0; i < objectVariables.Count; i++) { if (objectVariables[i].InitialValue != null) { actionSet.AddAction(typeObject.SetVariable( value: (Element)objectVariables[i].InitialValue.Parse(actionSet), index: i )); } } }
public void ReturnValue(IWorkshopTree value) { if (!MultiplePaths && ValueWasReturned) { throw new Exception("_multiplePaths is set as false and 2 expressions were returned."); } ValueWasReturned = true; // Multiple return paths. if (MultiplePaths) { ActionSet.AddAction(ReturnStore.SetVariable((Element)value)); } // One return path. else { ReturningValue = value; } }
public static void GetClassIndex(IndexReference classReference, ActionSet actionSet, ClassData classData) { // GetClassIndex() is less server load intensive than GetClassIndexWorkaround, // but due to a workshop bug with `Index Of Array Value`, the workaround may // need to be used instead. if (!CLASS_INDEX_WORKAROUND) { // Get the index of the first null value in the class array. actionSet.AddAction(classReference.SetVariable( Element.Part <V_IndexOfArrayValue>( classData.ClassArray.GetVariable(), new V_Null() ) )); // If the index equals -1, use the count of the class array instead. // TODO: Try setting the 1000th index of the class array to null instead. actionSet.AddAction(classReference.SetVariable( Element.TernaryConditional( new V_Compare(classReference.GetVariable(), Operators.Equal, new V_Number(-1)), Element.Part <V_CountOf>(classData.ClassArray.GetVariable()), classReference.GetVariable() ) )); } else { // Get an empty index in the class array to store the new class. Element firstFree = ( Element.Part <V_FirstOf>( Element.Part <V_FilteredArray>( // Sort the taken index array. Element.Part <V_SortedArray>(classData.ClassIndexes.GetVariable(), new V_ArrayElement()), // Filter Element.Part <V_And>( // If the previous index was not taken, use that index. !Element.Part <V_ArrayContains>( classData.ClassIndexes.GetVariable(), new V_ArrayElement() - 1 ), // Make sure the index does not equal 0 so the resulting index is not -1. new V_Compare(new V_ArrayElement(), Operators.NotEqual, new V_Number(0)) ) ) ) - 1 // Subtract 1 to get the previous index ); // If the taken index array has 0 elements, use the length of the class array subtracted by 1. firstFree = Element.TernaryConditional( new V_Compare(Element.Part <V_CountOf>(classData.ClassIndexes.GetVariable()), Operators.NotEqual, new V_Number(0)), firstFree, Element.Part <V_CountOf>(classData.ClassArray.GetVariable()) - 1 ); actionSet.AddAction(classReference.SetVariable(firstFree)); actionSet.AddAction(classReference.SetVariable( Element.TernaryConditional( // If the index equals -1, use the length of the class array instead. new V_Compare(classReference.GetVariable(), Operators.Equal, new V_Number(-1)), Element.Part <V_CountOf>(classData.ClassArray.GetVariable()), classReference.GetVariable() ) )); // Add the selected index to the taken indexes array. actionSet.AddAction( classData.ClassIndexes.SetVariable( Element.Part <V_Append>( classData.ClassIndexes.GetVariable(), classReference.GetVariable() ) ) ); } }
private IWorkshopTree ParseRecursive(ActionSet actionSet, IWorkshopTree[] parameterValues) { // Check the method stack to see if this method was already called. RecursiveMethodStack lastCall = actionSet.Translate.MethodStack.FirstOrDefault(ms => ms.Function == this) as RecursiveMethodStack; // If not, set up the stack and call the method. if (lastCall == null) { // Assign the parameters. AssignParameters(actionSet, ParameterVars, parameterValues, true); // Get the return handler if a value is returned. ReturnHandler returnHandler = new ReturnHandler(actionSet, Name, true); // Set up the condinue skip array. IndexReference continueSkipArray = actionSet.VarCollection.Assign("recursiveContinueArray", actionSet.IsGlobal, false); SkipEndMarker methodStart = new SkipEndMarker(); actionSet.AddAction(methodStart); // Add the method to the stack. var stack = new RecursiveMethodStack(this, returnHandler, continueSkipArray, methodStart); actionSet.Translate.MethodStack.Add(stack); // Parse the method block. block.Translate(actionSet.New(returnHandler)); // Apply the returns. if (returnHandler != null) { returnHandler.ApplyReturnSkips(); } // Pop the recursive parameters // TODO: Make this work with all sub scoped variables somehow for (int i = 0; i < ParameterVars.Length; i++) { var pop = (actionSet.IndexAssigner[ParameterVars[i]] as RecursiveIndexReference)?.Pop(); if (pop != null) { actionSet.AddAction(pop); } } // Setup the continue skip actionSet.ContinueSkip.Setup(actionSet); actionSet.ContinueSkip.SetSkipCount(actionSet, Element.Part <V_LastOf>(continueSkipArray.GetVariable())); // Remove the last recursive continue skip. actionSet.AddAction(continueSkipArray.SetVariable( // Pop Element.Part <V_ArraySlice>( continueSkipArray.GetVariable(), new V_Number(0), Element.Part <V_CountOf>(continueSkipArray.GetVariable()) - 1 ) )); // Loop if there are any values in the continue skip array. actionSet.AddAction(Element.Part <A_LoopIf>( Element.Part <V_CountOf>(continueSkipArray.GetVariable()) > 0 )); // Reset the continue skip. actionSet.ContinueSkip.ResetSkipCount(actionSet); actionSet.AddAction(continueSkipArray.SetVariable(0)); // Remove the method from the stack. actionSet.Translate.MethodStack.Remove(stack); return(returnHandler.GetReturnedValue()); } // If it is, push the parameters to the stack. else { for (int i = 0; i < ParameterVars.Length; i++) { var varReference = actionSet.IndexAssigner[ParameterVars[i]]; if (varReference is RecursiveIndexReference) { actionSet.AddAction(((RecursiveIndexReference)varReference).Push( (Element)parameterValues[i] )); } } // Add to the continue skip array. V_Number skipLength = new V_Number(); actionSet.AddAction(lastCall.ContinueSkipArray.SetVariable( Element.Part <V_Append>(lastCall.ContinueSkipArray.GetVariable(), skipLength) )); actionSet.ContinueSkip.Setup(actionSet); actionSet.ContinueSkip.SetSkipCount(actionSet, lastCall.MethodStart); actionSet.AddAction(new A_Loop()); SkipEndMarker continueAt = new SkipEndMarker(); actionSet.AddAction(continueAt); skipLength.Value = actionSet.ContinueSkip.GetSkipCount(continueAt).Value; return(lastCall.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); }
public void Init(DeltinScript deltinScript) { ClassIndexes = deltinScript.VarCollection.Assign(ClassIndexesTag, true, false); deltinScript.InitialGlobal.ActionSet.AddAction(ClassIndexes.SetVariable(0, null, Constants.MAX_ARRAY_LENGTH)); }