Ejemplo n.º 1
0
        private void GetConditions(RuleAction ruleAction)
        {
            foreach (var condition in ruleAction.Conditions)
            {
                var conditionParse = condition.Expression.Parse(ActionSet);

                Element    value1;
                EnumMember compareOperator;
                Element    value2;

                if (conditionParse is V_Compare)
                {
                    value1          = (Element)((Element)conditionParse).ParameterValues[0];
                    compareOperator = (EnumMember)((Element)conditionParse).ParameterValues[1];
                    value2          = (Element)((Element)conditionParse).ParameterValues[2];
                }
                else
                {
                    value1          = (Element)conditionParse;
                    compareOperator = EnumData.GetEnumValue(Operators.Equal);
                    value2          = new V_True();
                }

                Conditions.Add(new Condition(value1, compareOperator, value2));
            }
        }
Ejemplo n.º 2
0
        public void Setup(ActionSet actionSet)
        {
            if (IsSetup)
            {
                return;
            }
            IsSetup = true;

            SkipCount  = Rule.DeltinScript.VarCollection.Assign("continueSkip", Rule.IsGlobal, true);
            TempHolder = Rule.DeltinScript.VarCollection.Assign("continueSkipTemp", Rule.IsGlobal, true);

            A_SkipIf skipAction = Element.Part <A_SkipIf>
                                  (
                // Condition
                Element.Part <V_Compare>(SkipCount.GetVariable(), EnumData.GetEnumValue(Operators.Equal), new V_Number(0)),
                // Number of actions
                new V_Number(3)
                                  );

            Skipper           = new SkipStartMarker(actionSet);
            Skipper.SkipCount = TempHolder.GetVariable();

            IActionList[] actions = ArrayBuilder <IActionList> .Build(
                new ALAction(A_Wait.MinimumWait),
                new ALAction(skipAction),
                new ALAction(TempHolder.SetVariable((Element)SkipCount.GetVariable())[0]),
                new ALAction(SkipCount.SetVariable(0)[0]),
                Skipper
                );

            Rule.Actions.InsertRange(0, actions);
        }
Ejemplo n.º 3
0
 public Element GetArray()
 {
     return(Element.CreateArray(
                // Convert the maps to EnumMembers encased in V_MapVar.
                Maps.Select(m => Element.Part <V_MapVar>(EnumData.GetEnumValue(m)))
                .ToArray()
                ));
 }
Ejemplo n.º 4
0
 public Var(string name, bool isGlobal, Variable variable, int index)
 {
     Name               = name;
     IsGlobal           = isGlobal;
     Variable           = variable;
     VariableAsWorkshop = EnumData.GetEnumValue(Variable);
     Index              = index;
 }
Ejemplo n.º 5
0
        private Rule GetStartRule(DeltinScript deltinScript)
        {
            var condition = new Condition(
                Element.Part <V_CountOf>(Path.GetVariable()),
                Operators.GreaterThan,
                0
                );

            Element eventPlayer    = new V_EventPlayer();
            Element eventPlayerPos = Element.Part <V_PositionOf>(eventPlayer);

            TranslateRule rule = new TranslateRule(deltinScript, Constants.INTERNAL_ELEMENT + "Pathfinder: Move", RuleEvent.OngoingPlayer);

            IfBuilder isBetween = new IfBuilder(rule.ActionSet,
                                                Element.Part <V_And>(
                                                    Element.Part <V_CountOf>(Path.GetVariable()) >= 2,
                                                    IsBetween(eventPlayerPos, NextPosition(eventPlayer), PositionAt(eventPlayer, 1))
                                                    )
                                                );

            isBetween.Setup();
            rule.ActionSet.AddAction(Next());
            isBetween.Finish();

            rule.ActionSet.AddAction(ArrayBuilder <Element> .Build
                                     (
                                         LastUpdate.SetVariable(new V_TotalTimeElapsed()),
                                         DistanceToNext.SetVariable(Element.Part <V_DistanceBetween>(Element.Part <V_PositionOf>(new V_EventPlayer()), NextPosition(new V_EventPlayer()))),
                                         // Element.Part<A_StartFacing>(
                                         //     new V_EventPlayer(),
                                         //     Element.Part<V_DirectionTowards>(
                                         //         new V_EyePosition(),
                                         //         NextPosition()
                                         //     ),
                                         //     new V_Number(700),
                                         //     EnumData.GetEnumValue(Relative.ToWorld),
                                         //     EnumData.GetEnumValue(FacingRev.DirectionAndTurnRate)
                                         // ),

                                         // Move to the next node.
                                         Element.Part <A_StartThrottleInDirection>(
                                             new V_EventPlayer(),
                                             Element.Part <V_DirectionTowards>(
                                                 new V_EyePosition(),
                                                 NextPosition(new V_EventPlayer()) // Because of ThrottleRev this will be reevaluated so 'Start Throttle In Direction' only needs to run once.
                                                 ),
                                             new V_Number(1),
                                             EnumData.GetEnumValue(Relative.ToWorld),
                                             EnumData.GetEnumValue(ThrottleBehavior.ReplaceExistingThrottle),
                                             EnumData.GetEnumValue(ThrottleRev.DirectionAndMagnitude)
                                             )
                                     ));

            var result = rule.GetRule();

            result.Conditions = new Condition[] { condition };
            return(result);
        }
Ejemplo n.º 6
0
        public override void Decompile()
        {
            if (Rule.EventInfo.Event != RuleEvent.Subroutine)
            {
                if (Rule.Disabled)
                {
                    Decompiler.Append("disabled ");
                }
                Decompiler.Append("rule: \"" + Rule.Name + "\"");

                if (Rule.EventInfo.Event != RuleEvent.OngoingGlobal)
                {
                    Decompiler.NewLine();
                    Decompiler.Append("Event." + EnumData.GetEnumValue(Rule.EventInfo.Event).CodeName);
                    // Write the event.
                    if (Rule.EventInfo.Team != Team.All)
                    {
                        Decompiler.NewLine();
                        Decompiler.Append("Team." + EnumData.GetEnumValue(Rule.EventInfo.Team).CodeName);
                    }
                    // Write the player.
                    if (Rule.EventInfo.Player != PlayerSelector.All)
                    {
                        Decompiler.NewLine();
                        Decompiler.Append("Player." + EnumData.GetEnumValue(Rule.EventInfo.Player).CodeName);
                    }
                }

                // Decompile conditions
                foreach (var condition in Rule.Conditions)
                {
                    condition.Decompile(this);
                }
            }
            else
            {
                Decompiler.Append("void " + Rule.EventInfo.SubroutineName + "() \"" + Rule.Name + "\"");
            }

            Decompiler.AddBlock();

            DecompileActions();

            Decompiler.Outdent();
            Decompiler.Append("}");
            Decompiler.NewLine();
            Decompiler.NewLine();
        }
 /// <summary>Throttles the event player to the next node.</summary>
 public void ThrottleEventPlayerToNextNode(ActionSet actionSet)
 {
     // Start throttle to the current node.
     actionSet.AddAction(Element.Part <A_StartThrottleInDirection>(
                             Element.Part <V_EventPlayer>(),
                             Element.Part <V_DirectionTowards>(
                                 Element.Part <V_PositionOf>(Element.Part <V_EventPlayer>()),
                                 // Go to the destination once the final node is reached.
                                 CurrentPositionWithDestination()
                                 ),
                             new V_Number(1),                                                 // Magnitude
                             EnumData.GetEnumValue(Relative.ToWorld),                         // Relative
                             EnumData.GetEnumValue(ThrottleBehavior.ReplaceExistingThrottle), // Throttle Behavior
                             EnumData.GetEnumValue(ThrottleRev.DirectionAndMagnitude)         // Throttle Reevaluation
                             ));
 }
Ejemplo n.º 8
0
        public override object VisitEnum(DeltinScriptParser.EnumContext context)
        {
            string type  = context.PART(0).GetText();
            string value = context.PART(1)?.GetText();

            if (value == null)
            {
                _diagnostics.Error("Expected enum value.", new Location(_file, Range.GetRange(context)));
            }

            else if (EnumData.GetEnumValue(type, value) == null)
            {
                _diagnostics.Error(string.Format(SyntaxErrorException.invalidEnumValue, value, type), new Location(_file, Range.GetRange(context)));
            }

            return(base.VisitEnum(context));
        }
Ejemplo n.º 9
0
        void ExecuteSubroutine(Subroutine subroutine, CallParallel executeOption = CallParallel.NoParallel)
        {
            switch (executeOption)
            {
            case CallParallel.NoParallel:
                ActionSet.AddAction(Element.Part <A_CallSubroutine>(subroutine));
                break;

            case CallParallel.AlreadyRunning_DoNothing:
                ActionSet.AddAction(Element.Part <A_StartRule>(subroutine, EnumData.GetEnumValue(IfAlreadyExecuting.DoNothing)));
                break;

            case CallParallel.AlreadyRunning_RestartRule:
                ActionSet.AddAction(Element.Part <A_StartRule>(subroutine, EnumData.GetEnumValue(IfAlreadyExecuting.RestartRule)));
                break;
            }
        }
Ejemplo n.º 10
0
 public static FuncMethod WorkshopSettingHero(DeltinScript deltinScript) => new FuncMethodBuilder()
 {
     Name          = "WorkshopSettingHero",
     Documentation = "Provides the value of a new hero setting that will appear in the Workshop Settings card as a combo box.",
     Parameters    = new CodeParameter[] {
         new ConstStringParameter("category", "The name of the category in which this setting can be found."),
         new ConstStringParameter("name", "The name of this setting."),
         new ConstHeroParameter("default", "The default value for this setting."),
         new ConstNumberParameter("sortOrder", "The sort order of this setting relative to other settings in the same category. Settings with a higher sort order will come after settings with a lower sort order.")
     },
     DoesReturnValue = true,
     Action          = (actionSet, methodCall) => Element.Part <V_WorkshopSettingHero>(
         new V_CustomString((string)methodCall.AdditionalParameterData[0]),
         new V_CustomString((string)methodCall.AdditionalParameterData[1]),
         EnumData.GetEnumValue(((ConstHeroValueResolver)methodCall.AdditionalParameterData[2]).Hero),
         new V_Number((double)methodCall.AdditionalParameterData[3])
         )
 };
        void ParseConditions(ScopeGroup scope, Node[] expressions)
        {
            foreach (var expr in expressions)
            {
                Element parsedIf = ParseExpression(scope, scope, expr);
                // If the parsed if is a V_Compare, translate it to a condition.
                // Makes "(value1 == value2) == true" to just "value1 == value2"
                if (parsedIf is V_Compare)
                {
                    Element left = (Element)parsedIf.ParameterValues[0];
                    if (!left.ElementData.IsValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(true, left.Name, expr.Location);
                    }

                    Element right = (Element)parsedIf.ParameterValues[2];
                    if (!right.ElementData.IsValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(true, right.Name, expr.Location);
                    }

                    Conditions.Add(
                        new Condition(
                            left,
                            (EnumMember)parsedIf.ParameterValues[1],
                            right
                            )
                        );
                }
                // If not, just do "parsedIf == true"
                else
                {
                    if (!parsedIf.ElementData.IsValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(true, parsedIf.Name, expr.Location);
                    }

                    Conditions.Add(new Condition(
                                       parsedIf, EnumData.GetEnumValue(Operators.Equal), new V_True()
                                       ));
                }
            }
        }
Ejemplo n.º 12
0
        protected Element CreateLine(Line line, Element visibleTo, Element location, Element scale, IWorkshopTree reevaluation)
        {
            Element pos1 = line.Vertex1.ToVector();
            Element pos2 = line.Vertex2.ToVector();

            if (scale != null)
            {
                pos1 = Element.Part <V_Multiply>(pos1, scale);
                pos2 = Element.Part <V_Multiply>(pos2, scale);
            }

            return(Element.Part <A_CreateBeamEffect>(
                       visibleTo,
                       EnumData.GetEnumValue(BeamType.GrappleBeam),
                       Element.Part <V_Add>(location, pos1),
                       Element.Part <V_Add>(location, pos2),
                       EnumData.GetEnumValue(Elements.Color.Red),
                       reevaluation
                       ));
        }
Ejemplo n.º 13
0
        public override IWorkshopTree Get(ActionSet actionSet, IWorkshopTree[] parameterValues, object[] additionalParameterData)
        {
            Element player = (Element)parameterValues[0];

            IndexReference originalHero = actionSet.VarCollection.Assign("isAI_originalHero", actionSet.IsGlobal, true);
            IndexReference isAI         = actionSet.VarCollection.Assign("isAI_originalHero", actionSet.IsGlobal, true);

            actionSet.AddAction(ArrayBuilder <Element> .Build
                                (
                                    originalHero.SetVariable(Element.Part <V_HeroOf>(player)),
                                    Element.Part <A_SkipIf>(Element.Part <V_Compare>(originalHero.GetVariable(), EnumData.GetEnumValue(Operators.NotEqual), new V_Null()), new V_Number(2)),
                                    isAI.SetVariable(new V_False()),
                                    Element.Part <A_Skip>(new V_Number(4)),
                                    Element.Part <A_ForcePlayerHero>(player, EnumData.GetEnumValue(Hero.Ashe)),
                                    isAI.SetVariable(Element.Part <V_Compare>(Element.Part <V_HeroOf>(player), EnumData.GetEnumValue(Operators.NotEqual), EnumData.GetEnumValue(Hero.Ashe))),
                                    Element.Part <A_ForcePlayerHero>(player, originalHero.GetVariable()),
                                    Element.Part <A_StopForcingHero>(player)
                                ));

            return(isAI.GetVariable());
        }
        public void Setup()
        {
            if (IsSetup)
            {
                return;
            }
            IsSetup = true;

            SkipCount  = VarCollection.AssignVar(null, "ContinueSkip", IsGlobal, null);
            TempHolder = VarCollection.AssignVar(null, "ContinueSkip temp holder", IsGlobal, null);

            A_Wait waitAction = A_Wait.MinimumWait;

            waitAction.Comment = "ContinueSkip Wait";

            A_SkipIf skipAction = Element.Part <A_SkipIf>
                                  (
                // Condition
                Element.Part <V_Compare>(SkipCount.GetVariable(), EnumData.GetEnumValue(Operators.Equal), new V_Number(0)),
                // Number of actions
                new V_Number(3)
                                  );

            skipAction.Comment = "ContinueSkip Skipper";

            Element[] actions = ArrayBuilder <Element> .Build(
                waitAction,
                skipAction,
                TempHolder.SetVariable(SkipCount.GetVariable()),
                SkipCount.SetVariable(new V_Number(0)),
                Element.Part <A_Skip>(TempHolder.GetVariable())
                );

            if (actions.Length != ExpectedActionCount)
            {
                throw new Exception($"Expected {ExpectedActionCount} actions for the Continue Skip, got {actions.Length} instead.");
            }

            Actions.InsertRange(0, actions);
        }
Ejemplo n.º 15
0
        // Enumerator Values
        bool EnumeratorValue(out ITTEExpression expr)
        {
            if (Match(Kw("All Teams")))
            {
                expr = new ConstantEnumeratorExpression(EnumData.GetEnumValue(Team.All));
                return(true);
            }
            if (Match(Kw("Team 1")))
            {
                expr = new ConstantEnumeratorExpression(EnumData.GetEnumValue(Team.Team1));
                return(true);
            }
            if (Match(Kw("Team 2")))
            {
                expr = new ConstantEnumeratorExpression(EnumData.GetEnumValue(Team.Team2));
                return(true);
            }
            // TODO: Gamemode, map, button, etc

            expr = null;
            return(false);
        }
Ejemplo n.º 16
0
        public void Setup()
        {
            if (IsSetup)
            {
                return;
            }
            IsSetup = true;

            SkipCount = VarCollection.AssignVar("ContinueSkip", IsGlobal);

            // Add the required wait
            Actions.Insert(0, Element.Part <A_Wait>(new V_Number(Constants.MINIMUM_WAIT)));

            // Add the skip-if
            Actions.Insert(1,
                           Element.Part <A_SkipIf>
                           (
                               Element.Part <V_Compare>(SkipCount.GetVariable(), EnumData.GetEnumValue(Operators.NotEqual), new V_Number(0)),
                               SkipCount.GetVariable()
                           )
                           );
        }
Ejemplo n.º 17
0
        public override object VisitEnum(DeltinScriptParser.EnumContext context)
        {
            string type  = context.ENUM().GetText();
            string value = context.PART()?.GetText();

            if (value == null)
            {
                _diagnostics.Add(new Diagnostic("Expected enum value.", Range.GetRange(context))
                {
                    severity = Diagnostic.Error
                });
            }

            else if (EnumData.GetEnumValue(type, value) == null)
            {
                _diagnostics.Add(new Diagnostic(string.Format(SyntaxErrorException.invalidEnumValue, value, type), Range.GetRange(context))
                {
                    severity = Diagnostic.Error
                });
            }

            return(base.VisitEnum(context));
        }
        private static IWorkshopTree CallSubroutine(DefinedMethod method, MethodCall call, ActionSet callerSet)
        {
            method.SetupSubroutine();

            for (int i = 0; i < method.subroutineInfo.ParameterStores.Length; i++)
            {
                // Normal parameter push.
                if (!method.Attributes.Recursive)
                {
                    callerSet.AddAction(method.subroutineInfo.ParameterStores[i].SetVariable((Element)call.ParameterValues[i]));
                }
                // Recursive parameter push.
                else
                {
                    callerSet.AddAction(((RecursiveIndexReference)method.subroutineInfo.ParameterStores[i]).Push((Element)call.ParameterValues[i]));
                }
            }

            // Store the object the subroutine is executing with.
            if (method.subroutineInfo.ObjectStore != null)
            {
                // Normal
                if (!method.Attributes.Recursive)
                {
                    callerSet.AddAction(method.subroutineInfo.ObjectStore.SetVariable((Element)callerSet.CurrentObject));
                }
                // Recursive: Stack
                else
                {
                    callerSet.AddAction(method.subroutineInfo.ObjectStore.ModifyVariable(Operation.AppendToArray, (Element)callerSet.CurrentObject));
                }
            }

            switch (call.CallParallel)
            {
            // No parallel, call subroutine normally.
            case CallParallel.NoParallel:
                callerSet.AddAction(Element.Part <A_CallSubroutine>(method.subroutineInfo.Subroutine));
                return(method.subroutineInfo.ReturnHandler.GetReturnedValue());

            // Restart the subroutine if it is already running.
            case CallParallel.AlreadyRunning_RestartRule:
                callerSet.AddAction(Element.Part <A_StartRule>(method.subroutineInfo.Subroutine, EnumData.GetEnumValue(IfAlreadyExecuting.RestartRule)));
                return(null);

            // Do nothing if the subroutine is already running.
            case CallParallel.AlreadyRunning_DoNothing:
                callerSet.AddAction(Element.Part <A_StartRule>(method.subroutineInfo.Subroutine, EnumData.GetEnumValue(IfAlreadyExecuting.DoNothing)));
                return(null);

            default: throw new NotImplementedException();
            }
        }
        private void ParseVirtual()
        {
            // Loop through all potential methods.
            DefinedMethod[] options = Array.ConvertAll(Method.Attributes.AllOverrideOptions(), iMethod => (DefinedMethod)iMethod);

            // Create the switch that chooses the overload.
            SwitchBuilder typeSwitch = new SwitchBuilder(BuilderSet);

            // Parse the current overload.
            if (Method.Attributes.Virtual)
            {
                typeSwitch.AddDefault();
            }
            else
            {
                typeSwitch.NextCase(new V_Number(((ClassType)Method.Attributes.ContainingType).Identifier));
            }
            TranslateSegment(BuilderSet, Method);

            foreach (DefinedMethod option in options)
            {
                // The action set for the overload.
                ActionSet optionSet = BuilderSet.New(BuilderSet.IndexAssigner.CreateContained());

                // Add the object variables of the selected method.
                option.Attributes.ContainingType.AddObjectVariablesToAssigner(optionSet.CurrentObject, optionSet.IndexAssigner);

                // Go to next case then parse the block.
                typeSwitch.NextCase(new V_Number(((ClassType)option.Attributes.ContainingType).Identifier));

                // Iterate through every type.
                foreach (CodeType type in BuilderSet.Translate.DeltinScript.Types.AllTypes)
                {
                    // If 'type' does not equal the current virtual option's containing class...
                    if (option.Attributes.ContainingType != type
                        // ...and 'type' implements the containing class...
                        && type.Implements(option.Attributes.ContainingType)
                        // ...and 'type' does not have their own function implementation...
                        && AutoImplemented(option.Attributes.ContainingType, options.Select(o => o.Attributes.ContainingType).ToArray(), type))
                    {
                        // ...then add an additional case for 'type's class identifier.
                        typeSwitch.NextCase(new V_Number(((ClassType)type).Identifier));
                    }
                }

                if (option.subroutineInfo == null)
                {
                    TranslateSegment(optionSet, option);
                }
                else
                {
                    option.SetupSubroutine();
                    BuilderSet.AddAction(Element.Part <A_StartRule>(option.subroutineInfo.Subroutine, EnumData.GetEnumValue(IfAlreadyExecuting.DoNothing)));
                    if (Method.DoesReturnValue)
                    {
                        ReturnHandler.ReturnValue(option.subroutineInfo.ReturnHandler.GetReturnedValue());
                    }
                }

                if (Method.IsSubroutine)
                {
                    option.virtualSubroutineAssigned = Method;
                }
            }

            ClassData classData = BuilderSet.Translate.DeltinScript.GetComponent <ClassData>();

            // Finish the switch.
            typeSwitch.Finish(Element.Part <V_ValueInArray>(classData.ClassIndexes.GetVariable(), BuilderSet.CurrentObject));
        }
Ejemplo n.º 20
0
 public EnumNode(string type, string value, Range range) : base(range)
 {
     Type       = type;
     Value      = value;
     EnumMember = EnumData.GetEnumValue(type, value);
 }
        override public Element Get(TranslateRule context, ScopeGroup scope, MethodNode methodNode, IWorkshopTree[] parameters)
        {
            Element result;

            if (!IsRecursive)
            {
                // Check the method stack if this method was already called.
                // Throw a syntax error if it was.
                if (context.MethodStackNotRecursive.Contains(this))
                {
                    throw SyntaxErrorException.RecursionNotAllowed(methodNode.Location);
                }

                var methodScope = scope.Root().Child();

                // Add the parameter variables to the scope.
                context.AssignParameterVariables(methodScope, Parameters, parameters, methodNode);

                // The variable that stores the return value.
                IndexedVar returns = null;
                if (DoesReturn)
                {
                    returns      = IndexedVar.AssignVar(context.VarCollection, scope, $"{methodNode.Name} return", context.IsGlobal, null);
                    returns.Type = Type;
                }

                // Add the method to the method stack
                context.MethodStackNotRecursive.Add(this);

                Block.RelatedScopeGroup = methodScope;

                // Parse the block of the method
                context.ParseBlock(methodScope, methodScope, Block, true, returns);

                // Take the method scope out of scope.
                methodScope.Out(context);

                // Remove the method from the stack.
                context.MethodStackNotRecursive.Remove(this);

                if (DoesReturn)
                {
                    result = returns.GetVariable();
                }
                else
                {
                    result = new V_Null();
                }
            }
            else
            {
                // Check the method stack if this method was already called. It will be null if it wasn't called.
                MethodStack lastMethod = context.MethodStackRecursive.FirstOrDefault(ms => ms.UserMethod == this);
                if (lastMethod != null)
                {
                    context.ContinueSkip.Setup();

                    // Re-push the paramaters.
                    for (int i = 0; i < lastMethod.ParameterVars.Length; i++)
                    {
                        if (lastMethod.ParameterVars[i] is RecursiveVar)
                        {
                            context.Actions.AddRange
                            (
                                ((RecursiveVar)lastMethod.ParameterVars[i]).InScope((Element)parameters[i])
                            );
                        }
                    }

                    // Add to the continue skip array.
                    context.Actions.AddRange(
                        lastMethod.ContinueSkipArray.SetVariable(
                            Element.Part <V_Append>(lastMethod.ContinueSkipArray.GetVariable(), new V_Number(context.ContinueSkip.GetSkipCount() + 3))
                            )
                        );

                    // Loop back to the start of the method.
                    context.ContinueSkip.SetSkipCount(lastMethod.ActionIndex);
                    context.Actions.Add(Element.Part <A_Loop>());

                    result = lastMethod.Return.GetVariable();
                }
                else
                {
                    var methodScope = scope.Root().Child(true);

                    // Add the parameter variables to the scope.
                    Var[] parameterVars = new Var[Parameters.Length];
                    for (int i = 0; i < parameterVars.Length; i++)
                    {
                        if (parameters[i] is Element)
                        {
                            // Create a new variable using the parameter input.
                            parameterVars[i] = (RecursiveVar)IndexedVar.AssignVar(context.VarCollection, methodScope, Parameters[i].Name, context.IsGlobal, methodNode);
                            ((RecursiveVar)parameterVars[i]).Type = ((Element)parameters[i]).SupportedType?.Type;
                            context.Actions.AddRange
                            (
                                ((RecursiveVar)parameterVars[i]).InScope((Element)parameters[i])
                            );
                        }
                        else if (parameters[i] is EnumMember)
                        {
                            parameterVars[i] = new ElementReferenceVar(Parameters[i].Name, methodScope, methodNode, parameters[i]);
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }
                    }

                    var returns = IndexedVar.AssignInternalVarExt(context.VarCollection, null, $"{methodNode.Name}: return", context.IsGlobal);
                    returns.Type = Type;

                    // Setup the continue skip array.
                    IndexedVar continueSkipArray = IndexedVar.AssignInternalVar(context.VarCollection, null, $"{methodNode.Name} sca", context.IsGlobal);
                    var        stack             = new MethodStack(this, parameterVars, context.ContinueSkip.GetSkipCount(), returns, continueSkipArray);

                    // Add the method to the stack.
                    context.MethodStackRecursive.Add(stack);

                    Block.RelatedScopeGroup = methodScope;

                    // Parse the method block
                    context.ParseBlock(methodScope, methodScope, Block, true, returns);

                    // No return value if the method is being used as an action.
                    result = returns.GetVariable();

                    // Take the method out of scope.
                    //Actions.AddRange(methodScope.RecursiveMethodStackPop());
                    methodScope.Out(context);

                    // Setup the next continue skip.
                    context.ContinueSkip.Setup();
                    context.ContinueSkip.SetSkipCount(Element.Part <V_LastOf>(continueSkipArray.GetVariable()));

                    // Remove the last continue skip.
                    context.Actions.AddRange(
                        continueSkipArray.SetVariable(
                            Element.Part <V_ArraySlice>(
                                continueSkipArray.GetVariable(),
                                new V_Number(0),
                                Element.Part <V_CountOf>(continueSkipArray.GetVariable()) - 1
                                )
                            )
                        );

                    // Loop if the method goes any deeper by checking the length of the continue skip array.
                    context.Actions.Add(
                        Element.Part <A_LoopIf>(
                            Element.Part <V_Compare>(
                                Element.Part <V_CountOf>(continueSkipArray.GetVariable()),
                                EnumData.GetEnumValue(Operators.NotEqual),
                                new V_Number(0)
                                )
                            )
                        );

                    // Reset the continue skip.
                    context.ContinueSkip.ResetSkip();
                    context.Actions.AddRange(continueSkipArray.SetVariable(0));

                    // Remove the method from the stack.
                    context.MethodStackRecursive.Remove(stack);
                }
            }

            return(result);
        }
Ejemplo n.º 22
0
 public static Element Node2(Element segment) => Element.Part <V_RoundToInteger>(Element.Part <V_YOf>(segment), EnumData.GetEnumValue(Rounding.Down));
Ejemplo n.º 23
0
 public static Element Node2Attribute(Element segment) => Element.Part <V_RoundToInteger>(
     (Element.Part <V_YOf>(segment) % 1) * 100,
     EnumData.GetEnumValue(Rounding.Nearest)
     );
Ejemplo n.º 24
0
        protected void CreateLine(ActionSet actionSet, Line line, Element visibleTo, Element location, Element rotation, Element scale, IWorkshopTree reevaluation)
        {
            Vertex  vertex1 = line.Vertex1;
            Vertex  vertex2 = line.Vertex2;
            Element pos1;
            Element pos2;

            bool scaleSet    = false;
            bool rotationSet = false;

            if (scale != null)
            {
                double?constantScale = null;

                // Double constant scale
                if (scale.ConstantSupported <double>())
                {
                    constantScale = (double)scale.GetConstant();
                }

                // Null constant rotation
                else if (scale is V_Null)
                {
                    constantScale = 1;
                }

                if (constantScale == 1)
                {
                    scaleSet = true;
                }

                if (!scaleSet && constantScale != null)
                {
                    vertex1  = vertex1.Scale((double)constantScale);
                    vertex2  = vertex2.Scale((double)constantScale);
                    scaleSet = true;
                }
            }

            if (rotation != null)
            {
                Vertex rotationConstant = null;

                // Vector constant rotation
                if (rotation.ConstantSupported <Vertex>())
                {
                    rotationConstant = (Vertex)rotation.GetConstant();
                }

                // Double constant rotation
                else if (rotation.ConstantSupported <double>())
                {
                    rotationConstant = new Vertex(0, (double)rotation.GetConstant(), 0);
                }

                // Null constant rotation
                else if (rotation is V_Null)
                {
                    rotationConstant = new Vertex(0, 0, 0);
                }

                if (rotationConstant != null && rotationConstant.EqualTo(new Vertex(0, 0, 0)))
                {
                    rotationSet = true;
                }

                if (rotationConstant != null && !rotationSet)
                {
                    vertex1     = vertex1.Rotate(rotationConstant);
                    vertex2     = vertex2.Rotate(rotationConstant);
                    rotationSet = true;
                }
            }

            if (rotation != null && !rotationSet)
            {
                var pos1X = vertex1.X;
                var pos1Y = vertex1.Y;
                var pos1Z = vertex1.Z;
                var pos2X = vertex2.X;
                var pos2Y = vertex2.Y;
                var pos2Z = vertex2.Z;

                var yaw   = Element.Part <V_HorizontalAngleFromDirection>(rotation);
                var pitch = Element.Part <V_VerticalAngleFromDirection>(rotation);

                var cosa = Element.Part <V_CosineFromDegrees>(pitch);
                var sina = Element.Part <V_SineFromDegrees>(pitch);

                var cosb = Element.Part <V_CosineFromDegrees>(yaw);
                var sinb = Element.Part <V_SineFromDegrees>(yaw);

                var Axx = cosa * cosb;
                var Axy = 0 - sina;
                var Axz = cosa * sinb;

                var Ayx = sina * cosb;
                var Ayy = cosa;
                var Ayz = sina * sinb;

                var Azx = -sinb;

                pos1 = Element.Part <V_Vector>(
                    Axx * pos1X +
                    Axy * pos1Y +
                    Axz * pos1Z,
                    Ayx * pos1X +
                    Ayy * pos1Y +
                    Ayz * pos1Z,
                    Azx * pos1X +
                    pos1Z
                    );

                pos2 = Element.Part <V_Vector>(
                    Axx * pos2X +
                    Axy * pos2Y +
                    Axz * pos2Z,
                    Ayx * pos2X +
                    Ayy * pos2Y +
                    Ayz * pos2Z,
                    Azx * pos2X +
                    pos2Z
                    );
            }
            else
            {
                pos1 = vertex1.ToVector();
                pos2 = vertex2.ToVector();
            }

            if (scale != null && !scaleSet)
            {
                pos1 = pos1 * scale;
                pos2 = pos2 * scale;
            }

            actionSet.AddAction(Element.Part <A_CreateBeamEffect>(
                                    visibleTo,
                                    EnumData.GetEnumValue(BeamType.GrappleBeam),
                                    location + pos1,
                                    location + pos2,
                                    EnumData.GetEnumValue(Elements.Color.Red),
                                    reevaluation
                                    ));
        }
        // Calls single-instance methods.
        private IWorkshopTree ParseSubroutine(ActionSet actionSet, MethodCall methodCall)
        {
            if (subroutineInfo == null)
            {
                SetupSubroutine();
            }

            for (int i = 0; i < subroutineInfo.ParameterStores.Length; i++)
            {
                actionSet.AddAction(subroutineInfo.ParameterStores[i].SetVariable((Element)methodCall.ParameterValues[i]));
            }

            if (subroutineInfo.ObjectStore != null)
            {
                actionSet.AddAction(subroutineInfo.ObjectStore.SetVariable(actionSet.CurrentObject));
            }

            switch (methodCall.CallParallel)
            {
            // No parallel, call subroutine normally.
            case CallParallel.NoParallel:
                actionSet.AddAction(Element.Part <A_CallSubroutine>(subroutineInfo.Subroutine));
                return(subroutineInfo.ReturnHandler.GetReturnedValue());

            // Restart the subroutine if it is already running.
            case CallParallel.AlreadyRunning_RestartRule:
                actionSet.AddAction(Element.Part <A_StartRule>(subroutineInfo.Subroutine, EnumData.GetEnumValue(IfAlreadyExecuting.RestartRule)));
                return(null);

            // Do nothing if the subroutine is already running.
            case CallParallel.AlreadyRunning_DoNothing:
                actionSet.AddAction(Element.Part <A_StartRule>(subroutineInfo.Subroutine, EnumData.GetEnumValue(IfAlreadyExecuting.DoNothing)));
                return(null);

            default: throw new NotImplementedException();
            }
        }
Ejemplo n.º 26
0
 public EnumNode(string type, string value, Location location) : base(location)
 {
     Type       = type;
     Value      = value;
     EnumMember = EnumData.GetEnumValue(type, value);
 }
 public override CodeParameter[] Parameters() => new CodeParameter[]
 {
     new VariableParameter("variable", "The variable to manipulate. Player variables will chase the event player's variable. Must be a variable defined on the rule level.", VariableType.Dynamic, new VariableResolveOptions()
     {
         CanBeIndexed = false, FullVariable = true
     }),
     new CodeParameter("destination", "The value that the variable will eventually reach. The type of this value may be either a number or a vector, through the variable’s existing value must be of the same type before the chase begins. Can use number or vector based values."),
     new CodeParameter("rate", "The amount of change that will happen to the variable’s value each second."),
     new CodeParameter("reevaluation", "Specifies which of this action's inputs will be continuously reevaluated. This action will keep asking for and using new values from reevaluated inputs.", ValueGroupType.GetEnumType <RateChaseReevaluation>(), new ExpressionOrWorkshopValue(EnumData.GetEnumValue(RateChaseReevaluation.DestinationAndRate)))
 };
Ejemplo n.º 28
0
 public Element GetArray()
 {
     return(Element.CreateArray(Maps.Select(m => EnumData.GetEnumValue(m)).ToArray()));
 }
Ejemplo n.º 29
0
        private Translate(RuleNode ruleNode, ScopeGroup root, VarCollection varCollection, UserMethod[] userMethods)
        {
            Root          = root;
            VarCollection = varCollection;
            UserMethods   = userMethods;

            Rule     = new Rule(ruleNode.Name, ruleNode.Event, ruleNode.Team, ruleNode.Player);
            IsGlobal = Rule.IsGlobal;

            ContinueSkip = new ContinueSkip(IsGlobal, Actions, varCollection);

            ParseConditions(ruleNode.Conditions);
            ParseBlock(root.Child(), ruleNode.Block, false, null);

            Rule.Actions    = Actions.ToArray();
            Rule.Conditions = Conditions.ToArray();

            // Fufill remaining skips
            foreach (var skip in ReturnSkips)
            {
                skip.ParameterValues = new IWorkshopTree[] { new V_Number(Actions.Count - ReturnSkips.IndexOf(skip)) }
            }
            ;
            ReturnSkips.Clear();
        }

        void ParseConditions(IExpressionNode[] expressions)
        {
            foreach (var expr in expressions)
            {
                Element parsedIf = ParseExpression(Root, expr);
                // If the parsed if is a V_Compare, translate it to a condition.
                // Makes "(value1 == value2) == true" to just "value1 == value2"
                if (parsedIf is V_Compare)
                {
                    Element left = (Element)parsedIf.ParameterValues[0];
                    if (!left.ElementData.IsValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(true, left.Name, ((Node)expr).Range);
                    }

                    Element right = (Element)parsedIf.ParameterValues[2];
                    if (!right.ElementData.IsValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(true, right.Name, ((Node)expr).Range);
                    }

                    Conditions.Add(
                        new Condition(
                            left,
                            (EnumMember)parsedIf.ParameterValues[1],
                            right
                            )
                        );
                }
                // If not, just do "parsedIf == true"
                else
                {
                    if (!parsedIf.ElementData.IsValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(true, parsedIf.Name, ((Node)expr).Range);
                    }

                    Conditions.Add(new Condition(
                                       parsedIf, EnumData.GetEnumValue(Operators.Equal), new V_True()
                                       ));
                }
            }
        }

        Element ParseExpression(ScopeGroup scope, IExpressionNode expression)
        {
            switch (expression)
            {
            // Math and boolean operations.
            case OperationNode operationNode:
            {
                Element left  = ParseExpression(scope, operationNode.Left);
                Element right = ParseExpression(scope, operationNode.Right);

                /*
                 * if (Constants.BoolOperations.Contains(operationNode.Operation))
                 * {
                 *  if (left.ElementData.ValueType != Elements.ValueType.Any && left.ElementData.ValueType != Elements.ValueType.Boolean)
                 *      throw new SyntaxErrorException($"Expected boolean, got {left .ElementData.ValueType.ToString()} instead.", ((Node)operationNode.Left).Range);
                 *
                 *  if (right.ElementData.ValueType != Elements.ValueType.Any && right.ElementData.ValueType != Elements.ValueType.Boolean)
                 *      throw new SyntaxErrorException($"Expected boolean, got {right.ElementData.ValueType.ToString()} instead.", ((Node)operationNode.Right).Range);
                 * }
                 */

                switch (operationNode.Operation)
                {
                // Math: ^, *, %, /, +, -
                case "^":
                    return(Element.Part <V_RaiseToPower>(left, right));

                case "*":
                    return(Element.Part <V_Multiply>(left, right));

                case "%":
                    return(Element.Part <V_Modulo>(left, right));

                case "/":
                    return(Element.Part <V_Divide>(left, right));

                case "+":
                    return(Element.Part <V_Add>(left, right));

                case "-":
                    return(Element.Part <V_Subtract>(left, right));


                // BoolCompare: &, |
                case "&":
                    return(Element.Part <V_And>(left, right));

                case "|":
                    return(Element.Part <V_Or>(left, right));

                // Compare: <, <=, ==, >=, >, !=
                case "<":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.LessThan), right));

                case "<=":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.LessThanOrEqual), right));

                case "==":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.Equal), right));

                case ">=":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.GreaterThanOrEqual), right));

                case ">":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.GreaterThan), right));

                case "!=":
                    return(Element.Part <V_Compare>(left, EnumData.GetEnumValue(Operators.NotEqual), right));
                }

                throw new Exception($"Operation {operationNode.Operation} not implemented.");
            }

            // Number
            case NumberNode numberNode:
                return(new V_Number(numberNode.Value));

            // Bool
            case BooleanNode boolNode:
                if (boolNode.Value)
                {
                    return(new V_True());
                }
                else
                {
                    return(new V_False());
                }

            // Not operation
            case NotNode notNode:
                return(Element.Part <V_Not>(ParseExpression(scope, notNode.Value)));

            // Strings
            case StringNode stringNode:
                Element[] stringFormat = new Element[stringNode.Format?.Length ?? 0];
                for (int i = 0; i < stringFormat.Length; i++)
                {
                    stringFormat[i] = ParseExpression(scope, stringNode.Format[i]);
                }
                return(V_String.ParseString(stringNode.Range, stringNode.Value, stringFormat));

            // Null
            case NullNode nullNode:
                return(new V_Null());

            // TODO check if groups need to be implemented here

            // Methods
            case MethodNode methodNode:
                return(ParseMethod(scope, methodNode, true));

            // Variable
            case VariableNode variableNode:
                return(scope.GetVar(variableNode.Name, variableNode.Range, Diagnostics)
                       .GetVariable(variableNode.Target != null ? ParseExpression(scope, variableNode.Target) : null));

            // Get value in array
            case ValueInArrayNode viaNode:
                return(Element.Part <V_ValueInArray>(ParseExpression(scope, viaNode.Value), ParseExpression(scope, viaNode.Index)));

            // Create array
            case CreateArrayNode createArrayNode:
            {
                Element prev    = null;
                Element current = null;

                for (int i = 0; i < createArrayNode.Values.Length; i++)
                {
                    current = new V_Append()
                    {
                        ParameterValues = new IWorkshopTree[2]
                    };

                    if (prev != null)
                    {
                        current.ParameterValues[0] = prev;
                    }
                    else
                    {
                        current.ParameterValues[0] = new V_EmptyArray();
                    }

                    current.ParameterValues[1] = ParseExpression(scope, createArrayNode.Values[i]);
                    prev = current;
                }

                return(current ?? new V_EmptyArray());
            }

            case EnumNode enumNode:
                return(EnumData.Special(enumNode.EnumMember)
                       ?? throw SyntaxErrorException.EnumCantBeValue(enumNode.Type, enumNode.Range));

                // Seperator
            }

            throw new Exception();
        }

        Element ParseMethod(ScopeGroup scope, MethodNode methodNode, bool needsToBeValue)
        {
            methodNode.RelatedScopeGroup = scope;

            // Get the kind of method the method is (Method (Overwatch), Custom Method, or User Method.)
            var methodType = GetMethodType(UserMethods, methodNode.Name);

            // Throw exception if the method does not exist.
            if (methodType == null)
            {
                throw SyntaxErrorException.NonexistentMethod(methodNode.Name, methodNode.Range);
            }

            Element method;

            switch (methodType)
            {
            case MethodType.Method:
            {
                Type owMethod = Element.GetMethod(methodNode.Name);

                method = (Element)Activator.CreateInstance(owMethod);
                Parameter[] parameterData = owMethod.GetCustomAttributes <Parameter>().ToArray();

                List <IWorkshopTree> parsedParameters = new List <IWorkshopTree>();
                for (int i = 0; i < parameterData.Length; i++)
                {
                    if (methodNode.Parameters.Length > i)
                    {
                        // Parse the parameter.
                        parsedParameters.Add(ParseParameter(scope, methodNode.Parameters[i], methodNode.Name, parameterData[i]));
                    }
                    else
                    {
                        if (parameterData[i].ParameterType == ParameterType.Value && parameterData[i].DefaultType == null)
                        {
                            // Throw exception if there is no default method to fallback on.
                            throw SyntaxErrorException.MissingParameter(parameterData[i].Name, methodNode.Name, methodNode.Range);
                        }
                        else
                        {
                            parsedParameters.Add(parameterData[i].GetDefault());
                        }
                    }
                }

                method.ParameterValues = parsedParameters.ToArray();
                break;
            }

            case MethodType.CustomMethod:
            {
                MethodInfo  customMethod     = CustomMethods.GetCustomMethod(methodNode.Name);
                Parameter[] parameterData    = customMethod.GetCustomAttributes <Parameter>().ToArray();
                object[]    parsedParameters = new Element[parameterData.Length];

                for (int i = 0; i < parameterData.Length; i++)
                {
                    if (methodNode.Parameters.Length > i)
                    {
                        parsedParameters[i] = ParseParameter(scope, methodNode.Parameters[i], methodNode.Name, parameterData[i]);
                    }
                    else
                    {
                        // Throw exception if there is no default method to fallback on.
                        throw SyntaxErrorException.MissingParameter(parameterData[i].Name, methodNode.Name, methodNode.Range);
                    }
                }

                MethodResult result = (MethodResult)customMethod.Invoke(null, new object[] { IsGlobal, VarCollection, parsedParameters });
                switch (result.MethodType)
                {
                case CustomMethodType.Action:
                    if (needsToBeValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(true, methodNode.Name, methodNode.Range);
                    }
                    break;

                case CustomMethodType.MultiAction_Value:
                case CustomMethodType.Value:
                    if (!needsToBeValue)
                    {
                        throw SyntaxErrorException.InvalidMethodType(false, methodNode.Name, methodNode.Range);
                    }
                    break;
                }

                // Some custom methods have extra actions.
                if (result.Elements != null)
                {
                    Actions.AddRange(result.Elements);
                }
                method = result.Result;

                break;
            }

            case MethodType.UserMethod:
            {
                if (!AllowRecursion)
                {
                    UserMethod userMethod = UserMethod.GetUserMethod(UserMethods, methodNode.Name);

                    if (MethodStackNoRecursive.Contains(userMethod))
                    {
                        throw SyntaxErrorException.RecursionNotAllowed(methodNode.Range);
                    }

                    var methodScope = Root.Child();

                    // Add the parameter variables to the scope.
                    DefinedVar[] parameterVars = new DefinedVar[userMethod.Parameters.Length];
                    for (int i = 0; i < parameterVars.Length; i++)
                    {
                        if (methodNode.Parameters.Length > i)
                        {
                            // Create a new variable using the parameter input.
                            parameterVars[i] = VarCollection.AssignDefinedVar(methodScope, IsGlobal, userMethod.Parameters[i].Name, methodNode.Range);
                            Actions.Add(parameterVars[i].SetVariable(ParseExpression(scope, methodNode.Parameters[i])));
                        }
                        else
                        {
                            throw SyntaxErrorException.MissingParameter(userMethod.Parameters[i].Name, methodNode.Name, methodNode.Range);
                        }
                    }

                    var returns = VarCollection.AssignVar($"{methodNode.Name}: return temp value", IsGlobal);

                    MethodStackNoRecursive.Add(userMethod);

                    var userMethodScope = methodScope.Child();
                    userMethod.Block.RelatedScopeGroup = userMethodScope;

                    ParseBlock(userMethodScope, userMethod.Block, true, returns);

                    MethodStackNoRecursive.Remove(userMethod);

                    // No return value if the method is being used as an action.
                    if (needsToBeValue)
                    {
                        method = returns.GetVariable();
                    }
                    else
                    {
                        method = null;
                    }

                    break;
                }
                else
                {
                    UserMethod userMethod = UserMethod.GetUserMethod(UserMethods, methodNode.Name);

                    MethodStack lastMethod = MethodStack.FirstOrDefault(ms => ms.UserMethod == userMethod);
                    if (lastMethod != null)
                    {
                        ContinueSkip.Setup();

                        for (int i = 0; i < lastMethod.ParameterVars.Length; i++)
                        {
                            if (methodNode.Parameters.Length > i)
                            {
                                Actions.Add(lastMethod.ParameterVars[i].Push(ParseExpression(scope, methodNode.Parameters[i])));
                            }
                        }

                        // ?--- Multidimensional Array
                        Actions.Add(
                            Element.Part <A_SetGlobalVariable>(EnumData.GetEnumValue(Variable.B), lastMethod.ContinueSkipArray.GetVariable())
                            );
                        Actions.Add(
                            Element.Part <A_ModifyGlobalVariable>(EnumData.GetEnumValue(Variable.B), EnumData.GetEnumValue(Operation.AppendToArray), new V_Number(ContinueSkip.GetSkipCount() + 4))
                            );
                        Actions.Add(
                            lastMethod.ContinueSkipArray.SetVariable(Element.Part <V_GlobalVariable>(EnumData.GetEnumValue(Variable.B)))
                            );
                        // ?---

                        ContinueSkip.SetSkipCount(lastMethod.ActionIndex);
                        Actions.Add(Element.Part <A_Loop>());

                        if (needsToBeValue)
                        {
                            method = lastMethod.Return.GetVariable();
                        }
                        else
                        {
                            method = null;
                        }
                    }
                    else
                    {
                        var methodScope = Root.Child();

                        // Add the parameter variables to the scope.
                        ParameterVar[] parameterVars = new ParameterVar[userMethod.Parameters.Length];
                        for (int i = 0; i < parameterVars.Length; i++)
                        {
                            if (methodNode.Parameters.Length > i)
                            {
                                // Create a new variable using the parameter input.
                                parameterVars[i] = VarCollection.AssignParameterVar(Actions, methodScope, IsGlobal, userMethod.Parameters[i].Name, methodNode.Range);
                                Actions.Add(parameterVars[i].Push(ParseExpression(scope, methodNode.Parameters[i])));
                            }
                            else
                            {
                                throw SyntaxErrorException.MissingParameter(userMethod.Parameters[i].Name, methodNode.Name, methodNode.Range);
                            }
                        }

                        var returns = VarCollection.AssignVar($"{methodNode.Name}: return temp value", IsGlobal);

                        Var continueSkipArray = VarCollection.AssignVar($"{methodNode.Name}: continue skip temp value", IsGlobal);
                        var stack             = new MethodStack(userMethod, parameterVars, ContinueSkip.GetSkipCount(), returns, continueSkipArray);
                        MethodStack.Add(stack);

                        var userMethodScope = methodScope.Child();
                        userMethod.Block.RelatedScopeGroup = userMethodScope;

                        ParseBlock(userMethodScope, userMethod.Block, true, returns);

                        // No return value if the method is being used as an action.
                        if (needsToBeValue)
                        {
                            method = returns.GetVariable();
                        }
                        else
                        {
                            method = null;
                        }

                        Actions.Add(Element.Part <A_Wait>(new V_Number(Constants.MINIMUM_WAIT)));
                        for (int i = 0; i < parameterVars.Length; i++)
                        {
                            parameterVars[i].Pop();
                        }

                        ContinueSkip.Setup();
                        ContinueSkip.SetSkipCount(Element.Part <V_LastOf>(continueSkipArray.GetVariable()));

                        // ?--- Multidimensional Array
                        Actions.Add(
                            Element.Part <A_SetGlobalVariable>(EnumData.GetEnumValue(Variable.B), continueSkipArray.GetVariable())
                            );
                        Actions.Add(
                            continueSkipArray.SetVariable(
                                Element.Part <V_ArraySlice>(
                                    Element.Part <V_GlobalVariable>(EnumData.GetEnumValue(Variable.B)),
                                    new V_Number(0),
                                    Element.Part <V_Subtract>(
                                        Element.Part <V_CountOf>(Element.Part <V_GlobalVariable>(EnumData.GetEnumValue(Variable.B))),
                                        new V_Number(1)
                                        )
                                    )
                                )
                            );
                        // ?---

                        Actions.Add(
                            Element.Part <A_LoopIf>(
                                Element.Part <V_Compare>(
                                    Element.Part <V_CountOf>(continueSkipArray.GetVariable()),
                                    EnumData.GetEnumValue(Operators.NotEqual),
                                    new V_Number(0)
                                    )
                                )
                            );
                        ContinueSkip.ResetSkip();

                        MethodStack.Remove(stack);
                    }
                    break;
                }
            }

            default: throw new NotImplementedException();
            }

            methodNode.RelatedElement = method;
            return(method);
        }

        IWorkshopTree ParseParameter(ScopeGroup scope, IExpressionNode node, string methodName, Parameter parameterData)
        {
            IWorkshopTree value = null;

            switch (node)
            {
            case EnumNode enumNode:

                /*
                 * if (parameterData.ParameterType != ParameterType.Enum)
                 *  throw SyntaxErrorException.ExpectedType(true, parameterData.ValueType.ToString(), methodName, parameterData.Name, enumNode.Range);
                 *
                 * if (enumNode.Type != parameterData.EnumType.Name)
                 *  throw SyntaxErrorException.ExpectedType(false, parameterData.EnumType.ToString(), methodName, parameterData.Name, enumNode.Range);
                 */

                value = (IWorkshopTree)EnumData.Special(enumNode.EnumMember) ?? (IWorkshopTree)enumNode.EnumMember;

                //if (value == null)
                //  throw SyntaxErrorException.InvalidEnumValue(enumNode.Type, enumNode.Value, enumNode.Range);

                break;

            default:

                if (parameterData.ParameterType != ParameterType.Value)
                {
                    throw SyntaxErrorException.ExpectedType(false, parameterData.EnumType.Name, methodName, parameterData.Name, ((Node)node).Range);
                }

                value = ParseExpression(scope, node);

                Element     element     = value as Element;
                ElementData elementData = element.GetType().GetCustomAttribute <ElementData>();

                if (elementData.ValueType != Elements.ValueType.Any &&
                    !parameterData.ValueType.HasFlag(elementData.ValueType))
                {
                    throw SyntaxErrorException.InvalidType(parameterData.ValueType, elementData.ValueType, ((Node)node).Range);
                }

                break;
            }

            if (value == null)
            {
                throw new Exception("Failed to parse parameter.");
            }

            return(value);
        }
Ejemplo n.º 30
0
        void ParseStatement(ScopeGroup scope, IStatementNode statement, Var returnVar, bool isLast)
        {
            switch (statement)
            {
            // Method
            case MethodNode methodNode:
                Element method = ParseMethod(scope, methodNode, false);
                if (method != null)
                {
                    Actions.Add(method);
                }
                return;

            // Variable set
            case VarSetNode varSetNode:
                ParseVarset(scope, varSetNode);
                return;

            // For
            case ForEachNode forEachNode:
            {
                ContinueSkip.Setup();

                // The action the for loop starts on.
                int forActionStartIndex = Actions.Count() - 1;

                ScopeGroup forGroup = scope.Child();

                // Create the for's temporary variable.
                DefinedVar forTempVar = VarCollection.AssignDefinedVar(
                    scopeGroup: forGroup,
                    name: forEachNode.Variable,
                    isGlobal: IsGlobal,
                    range: forEachNode.Range
                    );

                // Reset the counter.
                Actions.Add(forTempVar.SetVariable(new V_Number(0)));

                // Parse the for's block.
                ParseBlock(forGroup, forEachNode.Block, false, returnVar);

                // Add the for's finishing elements
                Actions.Add(forTempVar.SetVariable(     // Indent the index by 1.
                                Element.Part <V_Add>
                                (
                                    forTempVar.GetVariable(),
                                    new V_Number(1)
                                )
                                ));

                ContinueSkip.SetSkipCount(forActionStartIndex);

                // The target array in the for statement.
                Element forArrayElement = ParseExpression(scope, forEachNode.Array);

                Actions.Add(Element.Part <A_LoopIf>(    // Loop if the for condition is still true.
                                Element.Part <V_Compare>
                                (
                                    forTempVar.GetVariable(),
                                    EnumData.GetEnumValue(Operators.LessThan),
                                    Element.Part <V_CountOf>(forArrayElement)
                                )
                                ));

                ContinueSkip.ResetSkip();
                return;
            }

            // For
            case ForNode forNode:
            {
                ContinueSkip.Setup();

                // The action the for loop starts on.
                int forActionStartIndex = Actions.Count() - 1;

                ScopeGroup forGroup = scope.Child();

                // Set the variable
                if (forNode.VarSetNode != null)
                {
                    ParseVarset(scope, forNode.VarSetNode);
                }
                if (forNode.DefineNode != null)
                {
                    ParseDefine(scope, forNode.DefineNode);
                }

                // Parse the for's block.
                ParseBlock(forGroup, forNode.Block, false, returnVar);

                Element expression = null;
                if (forNode.Expression != null)
                {
                    expression = ParseExpression(forGroup, forNode.Expression);
                }

                // Check the expression
                if (forNode.Expression != null)     // If it has an expression
                {
                    // Parse the statement
                    if (forNode.Statement != null)
                    {
                        ParseStatement(forGroup, forNode.Statement, returnVar, false);
                    }

                    ContinueSkip.SetSkipCount(forActionStartIndex);
                    Actions.Add(Element.Part <A_LoopIf>(expression));
                }
                // If there is no expression but there is a statement, parse the statement.
                else if (forNode.Statement != null)
                {
                    ParseStatement(forGroup, forNode.Statement, returnVar, false);
                    ContinueSkip.SetSkipCount(forActionStartIndex);
                    // Add the loop
                    Actions.Add(Element.Part <A_Loop>());
                }

                ContinueSkip.ResetSkip();
                return;
            }

            // While
            case WhileNode whileNode:
            {
                ContinueSkip.Setup();

                // The action the while loop starts on.
                int whileStartIndex = Actions.Count() - 2;

                ScopeGroup whileGroup = scope.Child();

                ParseBlock(whileGroup, whileNode.Block, false, returnVar);

                ContinueSkip.SetSkipCount(whileStartIndex);

                // Add the loop-if
                Element expression = ParseExpression(scope, whileNode.Expression);
                Actions.Add(Element.Part <A_LoopIf>(expression));

                ContinueSkip.ResetSkip();
                return;
            }

            // If
            case IfNode ifNode:
            {
                A_SkipIf if_SkipIf = new A_SkipIf();
                Actions.Add(if_SkipIf);

                var ifScope = scope.Child();

                // Parse the if body.
                ParseBlock(ifScope, ifNode.IfData.Block, false, returnVar);

                // Determines if the "Skip" action after the if block will be created.
                // Only if there is if-else or else statements.
                bool addIfSkip = ifNode.ElseIfData.Length > 0 || ifNode.ElseBlock != null;

                // Update the initial SkipIf's skip count now that we know the number of actions the if block has.
                // Add one to the body length if a Skip action is going to be added.
                if_SkipIf.ParameterValues = new IWorkshopTree[]
                {
                    Element.Part <V_Not>(ParseExpression(scope, ifNode.IfData.Expression)),
                    new V_Number(Actions.Count - 1 - Actions.IndexOf(if_SkipIf) + (addIfSkip ? 1 : 0))
                };

                // Create the "Skip" action.
                A_Skip if_Skip = new A_Skip();
                if (addIfSkip)
                {
                    Actions.Add(if_Skip);
                }

                // Parse else-ifs
                A_Skip[] elseif_Skips = new A_Skip[ifNode.ElseIfData.Length];     // The ElseIf's skips
                for (int i = 0; i < ifNode.ElseIfData.Length; i++)
                {
                    // Create the SkipIf action for the else if.
                    A_SkipIf elseif_SkipIf = new A_SkipIf();
                    Actions.Add(elseif_SkipIf);

                    // Parse the else-if body.
                    var elseifScope = scope.Child();
                    ParseBlock(elseifScope, ifNode.ElseIfData[i].Block, false, returnVar);

                    // Determines if the "Skip" action after the else-if block will be created.
                    // Only if there is additional if-else or else statements.
                    bool addIfElseSkip = i < ifNode.ElseIfData.Length - 1 || ifNode.ElseBlock != null;

                    // Set the SkipIf's parameters.
                    elseif_SkipIf.ParameterValues = new IWorkshopTree[]
                    {
                        Element.Part <V_Not>(ParseExpression(scope, ifNode.ElseIfData[i].Expression)),
                        new V_Number(Actions.Count - 1 - Actions.IndexOf(elseif_SkipIf) + (addIfElseSkip ? 1 : 0))
                    };

                    // Create the "Skip" action for the else-if.
                    if (addIfElseSkip)
                    {
                        elseif_Skips[i] = new A_Skip();
                        Actions.Add(elseif_Skips[i]);
                    }
                }

                // Parse else body.
                if (ifNode.ElseBlock != null)
                {
                    var elseScope = scope.Child();
                    ParseBlock(elseScope, ifNode.ElseBlock, false, returnVar);
                }

                // Replace dummy skip with real skip now that we know the length of the if, if-else, and else's bodies.
                // Replace if's dummy.
                if_Skip.ParameterValues = new IWorkshopTree[]
                {
                    new V_Number(Actions.Count - 1 - Actions.IndexOf(if_Skip))
                };

                // Replace else-if's dummy.
                for (int i = 0; i < elseif_Skips.Length; i++)
                {
                    if (elseif_Skips[i] != null)
                    {
                        elseif_Skips[i].ParameterValues = new IWorkshopTree[]
                        {
                            new V_Number(Actions.Count - 1 - Actions.IndexOf(elseif_Skips[i]))
                        };
                    }
                }

                return;
            }

            // Return
            case ReturnNode returnNode:

                if (returnNode.Value != null)
                {
                    Element result = ParseExpression(scope, returnNode.Value);
                    if (returnVar != null)
                    {
                        Actions.Add(returnVar.SetVariable(result));
                    }
                }

                if (!isLast)
                {
                    A_Skip returnSkip = new A_Skip();
                    Actions.Add(returnSkip);
                    ReturnSkips.Add(returnSkip);
                }

                return;

            // Define
            case ScopedDefineNode defineNode:
                ParseDefine(scope, defineNode);
                return;
            }
        }