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); }
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; }
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)); }
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); }
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()); }
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; }
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 )); }
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; }
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()); }
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); }
// 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); }
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); }
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); } } }
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); }
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()); }
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); } }