public Var[] AssignParameterVariables(ScopeGroup methodScope, ParameterBase[] parameters, IWorkshopTree[] values, Node methodNode)
        {
            Var[] parameterVars = new Var[values.Length];
            for (int i = 0; i < values.Length; i++)
            {
                if (values[i] is Element)
                {
                    // Create a new variable using the parameter.
                    if (!parameters[i].Extended)
                    {
                        parameterVars[i] = IndexedVar.AssignVar(VarCollection, methodScope, parameters[i].Name, IsGlobal, methodNode);
                    }
                    else
                    {
                        parameterVars[i] = IndexedVar.AssignVarExt(VarCollection, methodScope, parameters[i].Name, IsGlobal, methodNode);
                    }

                    ((IndexedVar)parameterVars[i]).Type = ((Element)values[i]).SupportedType?.Type;
                    Actions.AddRange(((IndexedVar)parameterVars[i]).SetVariable((Element)values[i]));
                }
                else if (values[i] is EnumMember)
                {
                    parameterVars[i] = new ElementReferenceVar(parameters[i].Name, methodScope, methodNode, values[i]);
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            return(parameterVars);
        }
Exemplo n.º 2
0
        override public void GetSource(TranslateRule context, Element element, Location location)
        {
            IndexedVar supportedType = context.ParserData.ClassArray.CreateChild(null, Name + " root", new Element[] { element }, null);

            supportedType.Type    = this;
            element.SupportedType = supportedType;
        }
        void ParseDefine(ScopeGroup getter, ScopeGroup scope, DefineNode defineNode)
        {
            IndexedVar var;

            if (!defineNode.Extended)
            {
                var = IndexedVar.AssignVar(VarCollection, scope, defineNode.VariableName, IsGlobal, defineNode);
            }
            else
            {
                var = IndexedVar.AssignVarExt(VarCollection, scope, defineNode.VariableName, IsGlobal, defineNode);
            }

            // Set the defined variable if the variable is defined like "define var = 1"
            Element[] inScopeActions = var.InScope(defineNode.Value != null ? ParseExpression(getter, scope, defineNode.Value) : null);
            if (inScopeActions != null)
            {
                Actions.AddRange(inScopeActions);
            }

            if (defineNode.Type != null)
            {
                var.Type = ParserData.GetDefinedType(defineNode.Type, defineNode.Location);
            }
        }
        public ScopeGroup GetRootScope(IndexedVar var, ParsingData parseData, Element target = null)
        {
            if (target == null)
            {
                target = new V_EventPlayer();
            }

            IndexedVar root = GetRoot(var, parseData, target);

            root.DefaultTarget = target;

            ScopeGroup typeScope = new ScopeGroup(parseData.VarCollection);

            typeScope.This = root;

            for (int i = 0; i < DefinedVars.Length; i++)
            {
                IndexedVar newVar = root.CreateChild(typeScope, DefinedVars[i].VariableName, Element.IntToElement(i), DefinedVars[i]);
                newVar.DefaultTarget = target;
                if (DefinedVars[i].Type != null)
                {
                    newVar.Type = parseData.GetDefinedType(DefinedVars[i].Type, DefinedVars[i].Location);
                }
                newVar.AccessLevel = DefinedVars[i].AccessLevel;
            }

            for (int i = 0; i < MethodNodes.Length; i++)
            {
                UserMethod method = new UserMethod(typeScope, MethodNodes[i]);
                method.RegisterParameters(parseData);
                method.AccessLevel = MethodNodes[i].AccessLevel;
            }

            return(typeScope);
        }
        public ScopeGroup GetRootScope(IndexedVar var, ParsingData parseData)
        {
            ScopeGroup typeScope = new ScopeGroup(parseData.VarCollection);

            typeScope.This = var;

            for (int i = 0; i < DefinedVars.Length; i++)
            {
                IndexedVar newVar = var.CreateChild(typeScope, DefinedVars[i].VariableName, new int[] { i }, DefinedVars[i]);
                if (DefinedVars[i].Type != null)
                {
                    newVar.Type = parseData.GetDefinedType(DefinedVars[i].Type, DefinedVars[i].Location);
                }
                newVar.AccessLevel = DefinedVars[i].AccessLevel;
            }

            for (int i = 0; i < MethodNodes.Length; i++)
            {
                UserMethod method = new UserMethod(typeScope, MethodNodes[i]);
                method.RegisterParameters(parseData);
                method.AccessLevel = MethodNodes[i].AccessLevel;
            }

            return(typeScope);
        }
 public MethodStack(UserMethod userMethod, Var[] parameterVars, int actionIndex, IndexedVar @return, IndexedVar continueSkipArray)
 {
     UserMethod        = userMethod;
     ParameterVars     = parameterVars;
     ActionIndex       = actionIndex;
     Return            = @return;
     ContinueSkipArray = continueSkipArray;
 }
Exemplo n.º 7
0
 override protected IndexedVar GetRoot(IndexedVar req, ParsingData context, Element target)
 {
     if (req.Name == Name + " root")
     {
         return(req);
     }
     return(context.ClassArray.CreateChild(null, Name + " root", new Element[] { req.GetVariable(target) }, null));
 }
Exemplo n.º 8
0
        public static IndexedVar AssignVar(VarCollection collection, ScopeGroup scope, string name, bool isGlobal, Node node)
        {
            WorkshopVariable assignedVariable = collection.Assign(name, isGlobal);
            IndexedVar       var = CreateVar(collection.WorkshopArrayBuilder, scope, name, isGlobal, assignedVariable, null, node);

            collection.AllVars.Add(var);
            return(var);
        }
Exemplo n.º 9
0
        public VarCollection(Variable global, Variable player, Variable builder)
        {
            Global = global;
            Player = player;

            IndexedVar tempArrayBuilderVar = AssignVar(null, "Multidimensional Array Builder", true, null);

            WorkshopArrayBuilder             = new WorkshopArrayBuilder(builder, tempArrayBuilderVar);
            tempArrayBuilderVar.ArrayBuilder = WorkshopArrayBuilder;
        }
        override public Element New(CreateObjectNode node, ScopeGroup getter, ScopeGroup scope, TranslateRule context)
        {
            IndexedVar store = context.VarCollection.AssignVar(scope, Name + " store", context.IsGlobal, null);

            store.Type = this;
            ScopeGroup typeScope = GetRootScope(store, context.ParserData);

            SetupNew(getter, scope, store, typeScope, context, node);

            return(store.GetVariable());
        }
Exemplo n.º 11
0
        override public void GetSource(TranslateRule context, Element element, Location location)
        {
            ElementOrigin origin = ElementOrigin.GetElementOrigin(element);

            if (origin == null)
            {
                throw new SyntaxErrorException("Could not get the type source.", location);
            }

            IndexedVar typeVar = origin.OriginVar(context.VarCollection, null, Name + " origin");

            typeVar.Type          = this;
            element.SupportedType = typeVar;
        }
Exemplo n.º 12
0
        private void Set(bool isGlobal, IndexedVar var)
        {
            if (var.Index.Length != 1)
            {
                throw new Exception();
            }

            if (isGlobal)
            {
                GlobalCollection[var.CollectionIndex] = var;
            }
            else
            {
                PlayerCollection[var.CollectionIndex] = var;
            }
        }
 override protected IndexedVar GetRoot(IndexedVar req, ParsingData context, Element target)
 {
     if (req.Name == Name + " root")
     {
         return(req);
     }
     return(new IndexedVar(
                null,
                Name + " root",
                true,
                Variable.C,
                new Element[] { req.GetVariable(target) },
                context.VarCollection.WorkshopArrayBuilder,
                null
                ));
 }
Exemplo n.º 14
0
        public VarCollection(int[] reservedGlobalIDs, string[] reservedGlobalNames, int[] reservedPlayerIDs, string[] reservedPlayerNames)
        {
            ReservedGlobalIDs   = reservedGlobalIDs;
            ReservedPlayerIDs   = reservedPlayerIDs;
            ReservedGlobalNames = reservedGlobalNames;
            ReservedPlayerNames = reservedPlayerNames;

            Global = Assign("_extendedGlobalCollection", true);
            Player = Assign("_extendedPlayerCollection", false);
            var builder = Assign("_arrayBuilder", true);

            IndexedVar tempArrayBuilderVar = IndexedVar.AssignInternalVar(this, null, "_arrayBuilderStore", true);

            WorkshopArrayBuilder             = new WorkshopArrayBuilder(builder, tempArrayBuilderVar);
            tempArrayBuilderVar.ArrayBuilder = WorkshopArrayBuilder;
        }
Exemplo n.º 15
0
        public static IndexedVar AssignVarExt(VarCollection collection, ScopeGroup scope, string name, bool isGlobal, Node node)
        {
            int        index = collection.NextFreeExtended(isGlobal);
            IndexedVar var   = CreateVar(
                collection.WorkshopArrayBuilder,
                scope,
                name,
                isGlobal,
                collection.UseVariable(isGlobal),
                new Element[] { new V_Number(index) },
                node
                );

            collection.AllVars.Add(var);
            collection.UseExtendedCollection(isGlobal)[index] = var;
            return(var);
        }
        override public Element New(CreateObjectNode node, ScopeGroup getter, ScopeGroup scope, TranslateRule context)
        {
            // Get the index to store the class.
            IndexedVar index = context.VarCollection.AssignVar(scope, "New " + Name + " class index", context.IsGlobal, null); // Assigns the index variable.

            // Get the index of the next free spot in the class array.
            context.Actions.AddRange(
                index.SetVariable(
                    Element.Part <V_IndexOfArrayValue>(
                        WorkshopArrayBuilder.GetVariable(true, null, Variable.C),
                        new V_Null()
                        )
                    )
                );
            // Set the index to the count of the class array if the index equals -1.
            context.Actions.AddRange(
                index.SetVariable(
                    Element.TernaryConditional(
                        new V_Compare(index.GetVariable(), Operators.Equal, new V_Number(-1)),
                        Element.Part <V_CountOf>(
                            WorkshopArrayBuilder.GetVariable(true, null, Variable.C)
                            ),
                        index.GetVariable()
                        )
                    )
                );
            // The direct reference to the class variable.
            IndexedVar store = new IndexedVar(
                scope,
                Name + " root",
                true,
                Variable.C,
                new Element[] { index.GetVariable() },
                context.VarCollection.WorkshopArrayBuilder,
                null
                );

            store.Index[0].SupportedType = store;
            store.Type = this;

            ScopeGroup typeScope = GetRootScope(store, context.ParserData);

            SetupNew(getter, scope, store, typeScope, context, node);

            return(index.GetVariable());
        }
Exemplo n.º 17
0
        protected void SetupNew(ScopeGroup getter, ScopeGroup scope, IndexedVar store, ScopeGroup typeScope, TranslateRule context, CreateObjectNode node)
        {
            // Set the default variables in the struct
            for (int i = 0; i < DefinedVars.Length; i++)
            {
                if (DefinedVars[i].Value != null)
                {
                    context.Actions.AddRange(
                        store.SetVariable(context.ParseExpression(typeScope, typeScope, DefinedVars[i].Value), null, i)
                        );
                }
            }

            Constructor constructor = Constructors.FirstOrDefault(c => c.Parameters.Length == node.Parameters.Length);

            if (constructor == null)
            {
                throw SyntaxErrorException.NotAConstructor(TypeKind, Name, node.Parameters.Length, node.Location);
            }

            if (context.MethodStackNotRecursive.Contains(constructor))
            {
                throw new SyntaxErrorException("Constructors cannot be recursive.", node.Location);
            }
            context.MethodStackNotRecursive.Add(constructor);

            ScopeGroup constructorScope = typeScope.Child();

            IWorkshopTree[] parameters = context.ParseParameters(
                getter,
                scope,
                constructor.Parameters,
                node.Parameters,
                node.TypeName,
                node.Location
                );

            context.AssignParameterVariables(constructorScope, constructor.Parameters, parameters, node);
            if (constructor.BlockNode != null)
            {
                context.ParseBlock(constructorScope, constructorScope, constructor.BlockNode, true, null);
            }
            constructorScope.Out(context);
            context.MethodStackNotRecursive.Remove(constructor);
        }
Exemplo n.º 18
0
        // Get This was an Australian radio comedy show which aired on Triple M and was hosted
        // by Tony Martin and Ed Kavalee, with contributions from panel operator, Richard Marsland.
        // A different guest co-host was featured nearly every day on the show and included music played throughout.
        // On the 15 October 2007 episode, the Get This team announced that Triple M/Austereo would not be renewing the show for 2008.
        // The final broadcast was on 23 November 2007. During its lifetime and since its cancellation, Get This developed a strong cult following.
        public IndexedVar GetThis(Location errorLocation)
        {
            ScopeGroup check = this;
            IndexedVar @this = null;

            while (check != null && @this == null)
            {
                @this = check.This;
                check = check.Parent;
            }

            if (errorLocation != null && @this == null)
            {
                throw SyntaxErrorException.ThisCantBeUsed(errorLocation);
            }

            return(@this);
        }
        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);
        }
Exemplo n.º 20
0
        public static IndexedVar AssignVar(VarCollection collection, ScopeGroup scope, string name, bool isGlobal, WorkshopVariable variable, Node node)
        {
            string workshopName = variable.Name;

            if (workshopName == null)
            {
                workshopName = collection.WorkshopNameFromCodeName(isGlobal, name);
            }

            int id = variable.ID;

            if (id == -1)
            {
                id = collection.NextFree(isGlobal);
            }
            else
            {
                WorkshopVariable assigned = collection.FromID(isGlobal, variable.ID);
                if (assigned != null)
                {
                    throw new SyntaxErrorException("Variable ID '" + variable.ID + "' has already been assigned by '" + assigned.Name + "'.", node.Location);
                }
            }

            WorkshopVariable use = new WorkshopVariable(isGlobal, id, workshopName);

            IndexedVar var = CreateVar(
                collection.WorkshopArrayBuilder,
                scope,
                name,
                isGlobal,
                use,
                null,
                node
                );

            collection.AllVars.Add(var);
            collection.UseCollection(isGlobal)[id] = use;
            return(var);
        }
Exemplo n.º 21
0
        private void GetObjects(RulesetNode rulesetNode, string file, TranslateRule globalTranslate, TranslateRule playerTranslate)
        {
            string absolute = new Uri(file).AbsolutePath;

            // Get the defined types
            foreach (var definedType in rulesetNode.DefinedTypes)
            {
                try
                {
                    if (DefinedTypes.Any(type => type.Name == definedType.Name))
                    {
                        throw SyntaxErrorException.NameAlreadyDefined(definedType.Location);
                    }
                    DefinedTypes.Add(DefinedType.GetDefinedType(definedType));
                }
                catch (SyntaxErrorException ex)
                {
                    Diagnostics.Error(ex);
                }
            }

            // Get the user methods.
            for (int i = 0; i < rulesetNode.UserMethods.Length; i++)
            {
                try
                {
                    UserMethods.Add(UserMethod.CreateUserMethod(Root, rulesetNode.UserMethods[i]));
                }
                catch (SyntaxErrorException ex)
                {
                    Diagnostics.Error(ex);
                }
            }

            // Get the rules
            RuleNodes.AddRange(rulesetNode.Rules);

            List <string> importedFiles = new List <string>();

            foreach (ImportObjectNode importObject in rulesetNode.ObjectImports)
            {
                try
                {
                    Importer importer = new Importer(Diagnostics, importedFiles, importObject.File, file, importObject.Location);
                    if (!importer.AlreadyImported)
                    {
                        importedFiles.Add(importer.ResultingPath);
                        switch (importer.FileType)
                        {
                        case ".obj":
                            importer.FileData.Update();
                            string content  = importer.FileData.Content;
                            Model  newModel = Model.ImportObj(content);
                            new ModelVar(importObject.Name, Root, importObject, newModel);
                            break;

                        case ".pathmap":
                            PathMap pathMap = PathMap.ImportFromXML(importer.ResultingPath);
                            new PathMapVar(this, importObject.Name, Root, importObject, pathMap);
                            break;
                        }
                    }
                }
                catch (SyntaxErrorException ex)
                {
                    Diagnostics.Error(ex);
                }
            }

            // Get the variables
            foreach (var definedVar in rulesetNode.DefinedVars)
            {
                try
                {
                    IndexedVar var;

                    if (!definedVar.Extended)
                    {
                        if (definedVar.OverrideID == -1)
                        {
                            var = IndexedVar.AssignVar(VarCollection, Root, definedVar.VariableName, definedVar.IsGlobal, definedVar);
                        }
                        else
                        {
                            var = IndexedVar.AssignVar(
                                VarCollection,
                                Root,
                                definedVar.VariableName,
                                definedVar.IsGlobal,
                                new WorkshopVariable(definedVar.IsGlobal, definedVar.OverrideID, VarCollection.WorkshopNameFromCodeName(definedVar.IsGlobal, definedVar.VariableName)),
                                definedVar
                                );
                        }
                    }
                    else
                    {
                        var = IndexedVar.AssignVarExt(VarCollection, Root, definedVar.VariableName, definedVar.IsGlobal, definedVar);
                    }


                    if (definedVar.Type != null)
                    {
                        var.Type = GetDefinedType(definedVar.Type, definedVar.Location);
                    }
                }
                catch (SyntaxErrorException ex)
                {
                    Diagnostics.Error(ex);
                }
            }
        }
Exemplo n.º 22
0
        private ParsingData(string file, string content)
        {
            Rule initialGlobalValues = new Rule(Constants.INTERNAL_ELEMENT + "Initial Global Values");
            Rule initialPlayerValues = new Rule(Constants.INTERNAL_ELEMENT + "Initial Player Values", RuleEvent.OngoingPlayer, Team.All, PlayerSelector.All);

            globalTranslate = new TranslateRule(initialGlobalValues, Root, this);
            playerTranslate = new TranslateRule(initialPlayerValues, Root, this);

            GetRulesets(content, file, true, null);

            VarCollection = new VarCollection(ReservedGlobalIDs.ToArray(), ReservedGlobalNames.ToArray(), ReservedPlayerIDs.ToArray(), ReservedPlayerNames.ToArray());
            Root          = new ScopeGroup(VarCollection);
            ClassIndexes  = IndexedVar.AssignInternalVar(VarCollection, null, "_classIndexes", true);
            ClassArray    = IndexedVar.AssignInternalVar(VarCollection, null, "_classArray", true);

            if (!Diagnostics.ContainsErrors())
            {
                foreach (var ruleset in Rulesets)
                {
                    GetObjects(ruleset.Value, ruleset.Key, globalTranslate, playerTranslate);
                }
            }

            foreach (var type in DefinedTypes)
            {
                try
                {
                    type.RegisterParameters(this);
                }
                catch (SyntaxErrorException ex)
                {
                    Diagnostics.Error(ex);
                }
            }
            foreach (var method in UserMethods)
            {
                try
                {
                    method.RegisterParameters(this);
                }
                catch (SyntaxErrorException ex)
                {
                    Diagnostics.Error(ex);
                }
            }

            if (!Diagnostics.ContainsErrors())
            {
                // Parse the rules.
                Rules = new List <Rule>();

                for (int i = 0; i < RuleNodes.Count; i++)
                {
                    try
                    {
                        var result = TranslateRule.GetRule(RuleNodes[i], Root, this);
                        Rules.Add(result);
                    }
                    catch (SyntaxErrorException ex)
                    {
                        Diagnostics.Error(ex);
                    }
                }

                foreach (var definedVar in VarCollection.AllVars)
                {
                    try
                    {
                        if (definedVar is IndexedVar && definedVar.IsDefinedVar && definedVar.Scope == Root)
                        {
                            Node value = ((IDefine)definedVar.Node).Value;
                            if (value != null)
                            {
                                if (((IndexedVar)definedVar).IsGlobal)
                                {
                                    globalTranslate.Actions.AddRange(((IndexedVar)definedVar).SetVariable(globalTranslate.ParseExpression(Root, Root, value)));
                                }
                                else
                                {
                                    playerTranslate.Actions.AddRange(((IndexedVar)definedVar).SetVariable(playerTranslate.ParseExpression(Root, Root, value)));
                                }
                            }
                        }
                    }
                    catch (SyntaxErrorException ex)
                    {
                        Diagnostics.Error(ex);
                    }
                }

                globalTranslate.Finish();
                playerTranslate.Finish();

                // Add the player initial values rule if it was used.
                if (initialPlayerValues.Actions.Length > 0)
                {
                    Rules.Insert(0, initialPlayerValues);
                }

                // Add the global initial values rule if it was used.
                if (initialGlobalValues.Actions.Length > 0)
                {
                    Rules.Insert(0, initialGlobalValues);
                }

                foreach (Rule rule in AdditionalRules)
                {
                    if (rule.Actions.Length > 0)
                    {
                        Rules.Add(rule);
                    }
                }
            }

            Success = !Diagnostics.ContainsErrors();
        }
 override protected IndexedVar GetRoot(IndexedVar req, ParsingData context, Element target)
 {
     return(req);
 }
        public void ParseBlock(ScopeGroup getter, ScopeGroup scopeGroup, BlockNode blockNode, bool fulfillReturns, IndexedVar returnVar)
        {
            if (scopeGroup == null)
            {
                throw new ArgumentNullException(nameof(scopeGroup));
            }

            blockNode.RelatedScopeGroup = scopeGroup;

            int returnSkipStart = ReturnSkips.Count;

            for (int i = 0; i < blockNode.Statements.Length; i++)
            {
                ParseStatement(getter, scopeGroup, blockNode.Statements[i], returnVar);
            }

            if (fulfillReturns)
            {
                FulfillReturns(returnSkipStart);
            }
        }
 abstract protected IndexedVar GetRoot(IndexedVar req, ParsingData context, Element target);
        void ParseVarset(ScopeGroup getter, ScopeGroup scope, VarSetNode varSetNode)
        {
            var varSetData = new ParseExpressionTree(this, getter, scope, varSetNode.Variable);

            if (!(varSetData.ResultingVariable is IndexedVar))
            {
                throw SyntaxErrorException.VariableIsReadonly(varSetData.ResultingVariable.Name, varSetNode.Location);
            }

            IndexedVar variable = (IndexedVar)varSetData.ResultingVariable;

            Element[] index = varSetData.VariableIndex;

            Element value = null;

            if (varSetNode.Value != null)
            {
                value = ParseExpression(getter, scope, varSetNode.Value);
            }

            Element initialVar = variable.GetVariable(varSetData.Target);

            Operation?operation = null;

            switch (varSetNode.Operation)
            {
            case "+=":
                operation = Operation.Add;
                break;

            case "-=":
                operation = Operation.Subtract;
                break;

            case "*=":
                operation = Operation.Multiply;
                break;

            case "/=":
                operation = Operation.Divide;
                break;

            case "^=":
                operation = Operation.RaiseToPower;
                break;

            case "%=":
                operation = Operation.Modulo;
                break;

            case "++":
                operation = Operation.Add;
                value     = 1;
                break;

            case "--":
                operation = Operation.Subtract;
                value     = 1;
                break;
            }

            if (operation == null)
            {
                Actions.AddRange(variable.SetVariable(value, varSetData.Target, index));
            }
            else
            {
                Actions.AddRange(variable.ModifyVariable((Operation)operation, value, varSetData.Target, index));
            }
        }
        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);
        }
Exemplo n.º 28
0
        override public Element New(CreateObjectNode node, ScopeGroup getter, ScopeGroup scope, TranslateRule context)
        {
            context.ParserData.SetupClasses();

            // Get the index to store the class.
            IndexedVar index        = IndexedVar.AssignInternalVarExt(context.VarCollection, scope, "New " + Name + " class index", context.IsGlobal); // Assigns the index variable.
            Element    takenIndexes = context.ParserData.ClassIndexes.GetVariable();

            // 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>(takenIndexes, new V_ArrayElement()),
                        // Filter
                        Element.Part <V_And>(
                            // If the previous index was not taken, use that index.
                            !(Element.Part <V_ArrayContains>(
                                  takenIndexes,
                                  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, just use the length of the class array subtracted by 1.
            firstFree = Element.TernaryConditional(
                new V_Compare(Element.Part <V_CountOf>(takenIndexes), Operators.NotEqual, new V_Number(0)),
                firstFree,
                Element.Part <V_CountOf>(context.ParserData.ClassArray.GetVariable()) - 1
                );

            context.Actions.AddRange(index.SetVariable(firstFree));

            context.Actions.AddRange(
                index.SetVariable(
                    Element.TernaryConditional(
                        // If the index equals -1, use the length of the class array instead.
                        new V_Compare(index.GetVariable(), Operators.Equal, new V_Number(-1)),
                        Element.Part <V_CountOf>(context.ParserData.ClassArray.GetVariable()),
                        index.GetVariable()
                        )
                    )
                );

            // Add the selected index to the taken indexes array.
            context.Actions.AddRange(
                context.ParserData.ClassIndexes.SetVariable(
                    Element.Part <V_Append>(
                        context.ParserData.ClassIndexes.GetVariable(),
                        index.GetVariable()
                        )
                    )
                );

            // The direct reference to the class variable.
            IndexedVar store = context.ParserData.ClassArray.CreateChild(scope, Name + " root", new Element[] { index.GetVariable() }, null);

            store.Index[0].SupportedType = store;
            store.Type = this;

            ScopeGroup typeScope = GetRootScope(index.GetVariable(), store, context.ParserData);

            SetupNew(getter, scope, store, typeScope, context, node);

            return(index.GetVariable());
        }
Exemplo n.º 29
0
 public void Free(IndexedVar var)
 {
     # pragma warning disable
     if (!REUSE_VARIABLES)
        void ParseStatement(ScopeGroup getter, ScopeGroup scope, Node statement, IndexedVar returnVar)
        {
            switch (statement)
            {
            // Method
            case MethodNode methodNode:
                Element method = ParseMethod(getter, scope, methodNode, false);
                return;

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

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

                ScopeGroup forGroup = scope.Child();

                Element array = ParseExpression(getter, scope, forEachNode.Array);

                IndexedVar index = IndexedVar.AssignInternalVarExt(VarCollection, scope, $"'{forEachNode.Variable.VariableName}' for index", IsGlobal);

                int offset = 0;

                Element getVariableReference()
                {
                    return(Element.Part <V_ValueInArray>(array, indexer()));
                }

                Element indexer()
                {
                    if (offset == 0)
                    {
                        return(index.GetVariable());
                    }
                    else
                    {
                        return(index.GetVariable() + getOffset());
                    }
                }

                V_Number getOffset()
                {
                    return(new V_Number(offset));
                }

                IndexedVar    arrayVar = null;
                ElementOrigin origin   = ElementOrigin.GetElementOrigin(array);
                if (origin == null && forEachNode.Variable.Type != null)
                {
                    throw new SyntaxErrorException("Could not get the type source.", forEachNode.Variable.Location);
                }
                if (origin != null)
                {
                    arrayVar = origin.OriginVar(VarCollection, null, null);
                }

                // Reset the counter.
                Actions.AddRange(index.SetVariable(0));

                // The action the for loop starts on.
                int forStartIndex = ContinueSkip.GetSkipCount();

                A_SkipIf skipCondition = new A_SkipIf()
                {
                    ParameterValues = new IWorkshopTree[2]
                };
                skipCondition.ParameterValues[0] =
                    !(index.GetVariable() < Element.Part <V_CountOf>(array)
                      );
                Actions.Add(skipCondition);

                List <A_SkipIf> rangeSkips = new List <A_SkipIf>();
                for (; offset < forEachNode.Repeaters; offset++)
                {
                    if (offset > 0)
                    {
                        //variable.Reference = getVariableReference();

                        A_SkipIf skipper = new A_SkipIf()
                        {
                            ParameterValues = new Element[2]
                        };
                        skipper.ParameterValues[0] = !(
                            index.GetVariable() + getOffset() < Element.Part <V_CountOf>(array)
                            );
                        rangeSkips.Add(skipper);
                        Actions.Add(skipper);
                    }

                    // Parse the for's block. Use a child to prevent conflicts with repeaters.
                    ScopeGroup tempChild = forGroup.Child();

                    Var variable;
                    if (arrayVar != null)
                    {
                        variable = arrayVar.CreateChild(tempChild, forEachNode.Variable.VariableName, new Element[] { indexer() }, forEachNode.Variable);
                        if (forEachNode.Variable.Type != null)
                        {
                            variable.Type = ParserData.GetDefinedType(forEachNode.Variable.Type, forEachNode.Variable.Location);
                        }
                    }
                    else
                    {
                        variable = new ElementReferenceVar(forEachNode.Variable.VariableName, tempChild, forEachNode, getVariableReference());
                    }

                    ParseBlock(tempChild, tempChild, forEachNode.Block, false, returnVar);
                    tempChild.Out(this);
                }
                // Take the foreach out of scope.
                forGroup.Out(this);

                // Increment the index
                Actions.AddRange(index.SetVariable(index.GetVariable() + forEachNode.Repeaters));

                // Add the for's finishing elements
                ContinueSkip.SetSkipCount(forStartIndex);
                Actions.Add(Element.Part <A_Loop>());

                rangeSkips.ForEach(var => var.ParameterValues[1] = new V_Number(GetSkipCount(var)));

                // Set the skip
                if (skipCondition != null)
                {
                    skipCondition.ParameterValues[1] = new V_Number(GetSkipCount(skipCondition));
                }

                ContinueSkip.ResetSkip();
                return;
            }

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

                ScopeGroup forContainer = scope.Child();

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

                ScopeGroup forGroup = forContainer.Child();

                // The action the for loop starts on.
                int forStartIndex = ContinueSkip.GetSkipCount();

                A_SkipIf skipCondition = null;
                // Skip if the condition is false.
                if (forNode.Expression != null)     // If it has an expression
                {
                    skipCondition = new A_SkipIf()
                    {
                        ParameterValues = new IWorkshopTree[2]
                    };
                    skipCondition.ParameterValues[0] = !(ParseExpression(forGroup, forGroup, forNode.Expression));
                    Actions.Add(skipCondition);
                }

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

                // Parse the statement
                if (forNode.Statement != null)
                {
                    ParseVarset(forGroup, forGroup, forNode.Statement);
                }

                // Take the for out of scope.
                forGroup.Out(this);

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

                // Set the skip
                if (skipCondition != null)
                {
                    skipCondition.ParameterValues[1] = new V_Number(GetSkipCount(skipCondition));
                }

                // Take the defined variable in the for out of scope
                forContainer.Out(this);

                ContinueSkip.ResetSkip();
                return;
            }

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

                // The action the while loop starts on.
                int whileStartIndex = ContinueSkip.GetSkipCount();

                A_SkipIf skipCondition = new A_SkipIf()
                {
                    ParameterValues = new IWorkshopTree[2]
                };
                skipCondition.ParameterValues[0] = !(ParseExpression(getter, scope, whileNode.Expression));
                Actions.Add(skipCondition);

                ScopeGroup whileGroup = scope.Child();

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

                // Take the while out of scope.
                whileGroup.Out(this);

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

                skipCondition.ParameterValues[1] = new V_Number(GetSkipCount(skipCondition));

                ContinueSkip.ResetSkip();
                return;
            }

            // If
            case IfNode ifNode:
            {
                A_SkipIf if_SkipIf = new A_SkipIf()
                {
                    ParameterValues = new IWorkshopTree[2]
                };
                if_SkipIf.ParameterValues[0] = !(ParseExpression(getter, scope, ifNode.IfData.Expression));

                Actions.Add(if_SkipIf);

                var ifScope = scope.Child();

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

                // Take the if out of scope.
                ifScope.Out(this);

                // 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;

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

                // Update the initial SkipIf's skip count now that we know the number of actions the if block has.
                if_SkipIf.ParameterValues[1] = new V_Number(GetSkipCount(if_SkipIf));

                // 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()
                    {
                        ParameterValues = new IWorkshopTree[2]
                    };
                    elseif_SkipIf.ParameterValues[0] = !(ParseExpression(getter, scope, ifNode.ElseIfData[i].Expression));

                    Actions.Add(elseif_SkipIf);

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

                    // Take the else-if out of scope.
                    elseifScope.Out(this);

                    // 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;

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

                    // Set the SkipIf's parameters.
                    elseif_SkipIf.ParameterValues[1] = new V_Number(GetSkipCount(elseif_SkipIf));
                }

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

                    // Take the else out of scope.
                    elseScope.Out(this);
                }

                // 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 (addIfSkip)
                {
                    if_Skip.ParameterValues = new IWorkshopTree[]
                    {
                        new V_Number(GetSkipCount(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(GetSkipCount(elseif_Skips[i]))
                        };
                    }
                }

                return;
            }

            // Return
            case ReturnNode returnNode:

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

                A_Skip returnSkip = new A_Skip();
                Actions.Add(returnSkip);
                Actions.Add(Element.Part <A_Skip>(new V_Number(-1)));
                ReturnSkips.Add(returnSkip);
                return;

            case DeleteNode deleteNode:
                DefinedClass.Delete(ParseExpression(getter, scope, deleteNode.Delete), this);
                return;

            // Define
            case DefineNode defineNode:
                ParseDefine(getter, scope, defineNode);
                return;

            case ExpressionTreeNode expressionTree:
                new ParseExpressionTree(this, getter, scope, expressionTree);
                return;

            default:
                throw new SyntaxErrorException("Expected statement.", statement.Location);
            }
        }