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));
        }
Пример #2
0
 public virtual IWorkshopTree GetReturnedValue()
 {
     if (_multiplePaths)
     {
         return(_returnStore.GetVariable());
     }
     else
     {
         return(_returningValue);
     }
 }
 public IWorkshopTree GetReturnedValue()
 {
     if (MultiplePaths)
     {
         return(ReturnStore.GetVariable());
     }
     else
     {
         return(ReturningValue);
     }
 }
Пример #4
0
 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());
        }
        // Sets up single-instance methods for methods with the 'rule' attribute.
        public void SetupSubroutine()
        {
            if (!IsSubroutine)
            {
                throw new Exception(Name + " does not have the subroutine attribute.");
            }

            // Setup the subroutine element.
            Subroutine subroutine = parseInfo.TranslateInfo.SubroutineCollection.NewSubroutine(Name);

            // Create the rule.
            TranslateRule subroutineRule = new TranslateRule(parseInfo.TranslateInfo, SubroutineName, subroutine);

            // Setup the return handler.
            ReturnHandler returnHandler = new ReturnHandler(subroutineRule.ActionSet, Name, multiplePaths);
            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++)
            {
                parameterStores[i] = actionSet.IndexAssigner.Add(actionSet.VarCollection, ParameterVars[i], true, null, Attributes.Recursive) as IndexReference;
            }

            // 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, true);
                Attributes.ContainingType.AddObjectVariablesToAssigner(objectStore.GetVariable(), actionSet.IndexAssigner);
            }

            // Set the subroutine info.
            subroutineInfo = new SubroutineInfo(subroutine, returnHandler, subroutineRule, parameterStores, objectStore);

            // Parse the block.
            block.Translate(actionSet);

            // Apply returns.
            returnHandler.ApplyReturnSkips();

            // Add the subroutine.
            parseInfo.TranslateInfo.WorkshopRules.Add(subroutineRule.GetRule());
        }
Пример #7
0
        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());
            }
        }
Пример #9
0
        // 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);
        }