public void Out(TranslateRule context) { if (!IsInScope) { throw new Exception("ScopeGroup is already out of scope."); } IsInScope = false; foreach (IScopeable var in InScope) { if (var is IndexedVar) { ((IndexedVar)var).OutOfScope(context); VarCollection.Free((IndexedVar)var); } } for (int i = 0; i < Children.Count; i++) { if (Children[0].IsInScope) { throw new Exception(); } } }
public ClassData(VarCollection varCollection) { ClassArray = varCollection.Assign("_classArray", true, false); if (DefinedType.CLASS_INDEX_WORKAROUND) { ClassIndexes = varCollection.Assign("_classIndexes", true, false); } }
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 ActionSet(TranslateRule translate, DocRange genericErrorRange, List <IActionList> actions) { Translate = translate; IsGlobal = translate.IsGlobal; ActionList = translate.Actions; VarCollection = translate.DeltinScript.VarCollection; IndexAssigner = translate.DeltinScript.DefaultIndexAssigner; }
public TranslateRule(Rule rule, ScopeGroup root, ParsingData parserData) { VarCollection = parserData.VarCollection; ParserData = parserData; Rule = rule; IsGlobal = Rule.IsGlobal; ContinueSkip = new ContinueSkip(IsGlobal, Actions, VarCollection); }
public IndexReference GetClassVariableStack(VarCollection collection, int index) { if (index > VariableStacks.Count) { throw new Exception("Variable stack skipped"); } if (index == VariableStacks.Count) { VariableStacks.Add(collection.Assign("_objectVariable_" + index, true, false)); } return(VariableStacks[index]); }
private ActionSet(ActionSet other) { Translate = other.Translate; IsGlobal = other.IsGlobal; ActionList = other.ActionList; VarCollection = other.VarCollection; GenericErrorRange = other.GenericErrorRange; IndexAssigner = other.IndexAssigner; ReturnHandler = other.ReturnHandler; CurrentObject = other.CurrentObject; This = other.This; IndentCount = other.IndentCount; IsRecursive = other.IsRecursive; }
public IGettable Add(VarCollection varCollection, Var var, bool isGlobal, IWorkshopTree referenceValue, bool recursive = false) { if (varCollection == null) { throw new ArgumentNullException(nameof(varCollection)); } if (var == null) { throw new ArgumentNullException(nameof(var)); } if (references.ContainsKey(var)) { throw new Exception(var.Name + " was already added into the variable index assigner."); } IGettable assigned; // A gettable/settable variable if (var.Settable()) { assigned = varCollection.Assign(var, isGlobal); if (recursive) { assigned = new RecursiveIndexReference((IndexReference)assigned); } references.Add(var, assigned); } // Element reference else if (var.VariableType == VariableType.ElementReference) { if (referenceValue == null) { throw new ArgumentNullException(nameof(referenceValue)); } assigned = new WorkshopElementReference(referenceValue); references.Add(var, assigned); } else { throw new NotImplementedException(); } return(assigned); }
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); }
public IGettable Add(VarCollection varCollection, IIndexReferencer var, bool isGlobal, IWorkshopTree referenceValue, bool recursive = false) { if (varCollection == null) { throw new ArgumentNullException(nameof(varCollection)); } if (var == null) { throw new ArgumentNullException(nameof(var)); } CheckIfAdded(var); IGettable assigned; // A gettable/settable variable if (var.Settable()) { assigned = varCollection.Assign(var, isGlobal); if (recursive || var.Recursive) { assigned = new RecursiveIndexReference((IndexReference)assigned); } references.Add(var, assigned); } // Element reference else if (var.VariableType == VariableType.ElementReference) { if (referenceValue == null) { throw new ArgumentNullException(nameof(referenceValue)); } assigned = new WorkshopElementReference(referenceValue); references.Add(var, assigned); } else { throw new NotImplementedException(); } return(assigned); }
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); }
public IndexReference AddIndexReference(VarCollection varCollection, Var var, bool isGlobal, bool recursive = false) { if (varCollection == null) { throw new ArgumentNullException(nameof(varCollection)); } if (var == null) { throw new ArgumentNullException(nameof(var)); } CheckIfAdded(var); IndexReference assigned = varCollection.Assign(var, isGlobal); if (recursive) { assigned = new RecursiveIndexReference((IndexReference)assigned); } references.Add(var, assigned); return(assigned); }
private TranslateRule(RuleNode ruleNode, ScopeGroup root, ParsingData parserData) { VarCollection = parserData.VarCollection; ParserData = parserData; Rule = new Rule(ruleNode.Name, ruleNode.Event, ruleNode.Team, ruleNode.Player); Rule.Disabled = ruleNode.Disabled; IsGlobal = Rule.IsGlobal; ContinueSkip = new ContinueSkip(IsGlobal, Actions, VarCollection); ParseConditions(root, ruleNode.Conditions); // Parse the block of the rule. ScopeGroup ruleScope = root.Child(); ParseBlock(ruleScope, ruleScope, ruleNode.Block, false, null); // Fulfill remaining returns. FulfillReturns(0); Finish(); }
public void Add(VarCollection varCollection, Var var, bool isGlobal, IWorkshopTree referenceValue, bool recursive = false) { if (varCollection == null) { throw new ArgumentNullException(nameof(varCollection)); } if (var == null) { throw new ArgumentNullException(nameof(var)); } // A gettable/settable variable if (var.Settable()) { var assigned = varCollection.Assign(var, isGlobal); if (recursive) { assigned = new RecursiveIndexReference(assigned); } references.Add(var, assigned); } // Element reference else if (var.VariableType == VariableType.ElementReference) { if (referenceValue == null) { throw new ArgumentNullException(nameof(referenceValue)); } references.Add(var, new WorkshopElementReference(referenceValue)); } else { throw new NotImplementedException(); } }
void Translate() { // Get the reserved variables and IDs foreach (ScriptFile script in ScriptFiles) { if (script.Context.reserved_global()?.reserved_list() != null) { foreach (var name in script.Context.reserved_global().reserved_list().PART()) { VarCollection.Reserve(name.GetText(), true); } foreach (var id in script.Context.reserved_global().reserved_list().NUMBER()) { VarCollection.Reserve(int.Parse(id.GetText()), true, null, null); } } if (script.Context.reserved_player()?.reserved_list() != null) { foreach (var name in script.Context.reserved_player().reserved_list().PART()) { VarCollection.Reserve(name.GetText(), false); } foreach (var id in script.Context.reserved_player().reserved_list().NUMBER()) { VarCollection.Reserve(int.Parse(id.GetText()), false, null, null); } } } // Get the enums foreach (ScriptFile script in ScriptFiles) { foreach (var enumContext in script.Context.enum_define()) { var newEnum = new DefinedEnum(new ParseInfo(script, this), enumContext); types.Add(newEnum); definedTypes.Add(newEnum); } } // Get the types foreach (ScriptFile script in ScriptFiles) { foreach (var typeContext in script.Context.type_define()) { var newType = new DefinedType(new ParseInfo(script, this), GlobalScope, typeContext); types.Add(newType); definedTypes.Add(newType); } } // Get the methods and macros foreach (ScriptFile script in ScriptFiles) { // Get the methods. foreach (var methodContext in script.Context.define_method()) { var newMethod = new DefinedMethod(new ParseInfo(script, this), RulesetScope, RulesetScope, methodContext, null); } // Get the macros. foreach (var macroContext in script.Context.define_macro()) { GetMacro(new ParseInfo(script, this), RulesetScope, RulesetScope, macroContext); } } // Get the defined variables. foreach (ScriptFile script in ScriptFiles) { foreach (var varContext in script.Context.define()) { Var newVar = new RuleLevelVariable(RulesetScope, new DefineContextHandler(new ParseInfo(script, this), varContext)); rulesetVariables.Add(newVar); // Add the variable to the player variables scope if it is a player variable. if (newVar.VariableType == VariableType.Player) { PlayerVariableScope.CopyVariable(newVar); } } } foreach (var applyType in types) { if (applyType is ClassType classType) { classType.ResolveElements(); } } foreach (var apply in applyBlocks) { apply.SetupParameters(); } foreach (var apply in applyBlocks) { apply.SetupBlock(); } foreach (var apply in applyBlocks) { apply.CallInfo?.CheckRecursion(); } // Get the rules foreach (ScriptFile script in ScriptFiles) { foreach (var ruleContext in script.Context.ow_rule()) { rules.Add(new RuleAction(new ParseInfo(script, this), RulesetScope, ruleContext)); } } }
public ActionSet(bool isGlobal, VarCollection varCollection) { IsGlobal = isGlobal; VarCollection = varCollection; ActionList = new List <IActionList>(); }
public WorkshopArrayBuilder(VarCollection varCollection) => _varCollection = varCollection;
void ToWorkshop(Func <VarCollection, Rule[]> addRules) { VarCollection.Setup(); InitialGlobal = new TranslateRule(this, "Initial Global", RuleEvent.OngoingGlobal); InitialPlayer = new TranslateRule(this, "Initial Player", RuleEvent.OngoingPlayer); WorkshopRules = new List <Rule>(); foreach (var variable in rulesetVariables) { // Assign the variable an index. DefaultIndexAssigner.Add(VarCollection, variable, true, null); var assigner = DefaultIndexAssigner[variable] as IndexReference; if (assigner != null && variable.InitialValue != null) { var addToInitialRule = GetInitialRule(variable.VariableType == VariableType.Global); addToInitialRule.ActionSet.AddAction(assigner.SetVariable( (Element)variable.InitialValue.Parse(addToInitialRule.ActionSet) )); } } foreach (var rule in rules) { var translate = new TranslateRule(this, rule); WorkshopRules.Add(translate.GetRule()); } if (InitialPlayer.Actions.Count > 0) { WorkshopRules.Insert(0, InitialPlayer.GetRule()); } if (InitialGlobal.Actions.Count > 0) { WorkshopRules.Insert(0, InitialGlobal.GetRule()); } if (addRules != null) { WorkshopRules.AddRange(addRules.Invoke(VarCollection).Where(rule => rule != null)); } // Get the final workshop string. StringBuilder result = new StringBuilder(); I18n.I18n.I18nWarningMessage(result, I18n.I18n.CurrentLanguage); // Get the variables. VarCollection.ToWorkshop(result, I18n.I18n.CurrentLanguage); result.AppendLine(); // Get the rules. foreach (var rule in WorkshopRules) { result.AppendLine(rule.ToWorkshop(I18n.I18n.CurrentLanguage)); } WorkshopCode = result.ToString(); }
void Translate() { List <IApplyBlock> applyMethods = new List <IApplyBlock>(); // Get the reserved variables and IDs foreach (ScriptFile script in ScriptFiles) { if (script.Context.reserved_global()?.reserved_list() != null) { foreach (var name in script.Context.reserved_global().reserved_list().PART()) { VarCollection.Reserve(name.GetText(), true); } foreach (var id in script.Context.reserved_global().reserved_list().NUMBER()) { VarCollection.Reserve(int.Parse(id.GetText()), true, null, null); } } if (script.Context.reserved_player()?.reserved_list() != null) { foreach (var name in script.Context.reserved_player().reserved_list().PART()) { VarCollection.Reserve(name.GetText(), false); } foreach (var id in script.Context.reserved_player().reserved_list().NUMBER()) { VarCollection.Reserve(int.Parse(id.GetText()), false, null, null); } } } // Get the enums foreach (ScriptFile script in ScriptFiles) { foreach (var enumContext in script.Context.enum_define()) { var newEnum = new DefinedEnum(new ParseInfo(script, this), enumContext); types.Add(newEnum); definedTypes.Add(newEnum); } } // Get the types foreach (ScriptFile script in ScriptFiles) { foreach (var typeContext in script.Context.type_define()) { var newType = new DefinedType(new ParseInfo(script, this), GlobalScope, typeContext, applyMethods); types.Add(newType); definedTypes.Add(newType); } } // Get the methods and macros foreach (ScriptFile script in ScriptFiles) { // Get the methods. foreach (var methodContext in script.Context.define_method()) { var newMethod = new DefinedMethod(new ParseInfo(script, this), RulesetScope, methodContext); applyMethods.Add(newMethod); //RulesetScope.AddMethod(newMethod, script.Diagnostics, DocRange.GetRange(methodContext.name)); } // Get the macros. foreach (var macroContext in script.Context.define_macro()) { GetMacro(new ParseInfo(script, this), RulesetScope, macroContext, applyMethods); } } // Get the defined variables. foreach (ScriptFile script in ScriptFiles) { foreach (var varContext in script.Context.define()) { var newVar = Var.CreateVarFromContext(VariableDefineType.RuleLevel, new ParseInfo(script, this), varContext); newVar.Finalize(RulesetScope); rulesetVariables.Add(newVar); // Add the variable to the player variables scope if it is a player variable. if (newVar.VariableType == VariableType.Player) { PlayerVariableScope.AddVariable(newVar, null, null); } } } foreach (var apply in applyMethods) { apply.SetupBlock(); } foreach (var apply in applyMethods) { apply.CallInfo.CheckRecursion(); } // Get the rules foreach (ScriptFile script in ScriptFiles) { foreach (var ruleContext in script.Context.ow_rule()) { rules.Add(new RuleAction(new ParseInfo(script, this), RulesetScope, ruleContext)); } } }
public static ParserData GetParser(string document, Pos documentPos) { AntlrInputStream inputStream = new AntlrInputStream(document); // Lexer DeltinScriptLexer lexer = new DeltinScriptLexer(inputStream); CommonTokenStream commonTokenStream = new CommonTokenStream(lexer); // Parse DeltinScriptParser parser = new DeltinScriptParser(commonTokenStream); var errorListener = new ErrorListener(); parser.RemoveErrorListeners(); parser.AddErrorListener(errorListener); DeltinScriptParser.RulesetContext ruleSetContext = parser.ruleset(); List <Diagnostic> diagnostics = new List <Diagnostic>(); diagnostics.AddRange(errorListener.Errors); // Get the ruleset node. BuildAstVisitor bav = null; RulesetNode ruleSetNode = null; if (diagnostics.Count == 0) { bav = new BuildAstVisitor(documentPos, diagnostics); ruleSetNode = (RulesetNode)bav.Visit(ruleSetContext); } VarCollection varCollection = null; ScopeGroup root = null; List <UserMethod> userMethods = null; Rule[] rules = null; bool success = false; AdditionalErrorChecking aec = new AdditionalErrorChecking(parser, diagnostics); aec.Visit(ruleSetContext); bool parse = diagnostics.Count == 0; if (parse) { varCollection = new VarCollection(); root = new ScopeGroup(); userMethods = new List <UserMethod>(); foreach (var definedVar in ruleSetNode.DefinedVars) { varCollection.AssignDefinedVar(root, definedVar.IsGlobal, definedVar.VariableName, definedVar.Range); } // Get the user methods. for (int i = 0; i < ruleSetNode.UserMethods.Length; i++) { userMethods.Add(new UserMethod(ruleSetNode.UserMethods[i])); } // Parse the rules. rules = new Rule[ruleSetNode.Rules.Length]; for (int i = 0; i < rules.Length; i++) { try { var result = Translate.GetRule(ruleSetNode.Rules[i], root, varCollection, userMethods.ToArray()); rules[i] = result.Rule; diagnostics.AddRange(result.Diagnostics); } catch (SyntaxErrorException ex) { diagnostics.Add(new Diagnostic(ex.Message, ex.Range) { severity = Diagnostic.Error }); } } success = true; } return(new ParserData() { Parser = parser, RulesetContext = ruleSetContext, RuleSetNode = ruleSetNode, Bav = bav, Diagnostics = diagnostics, Rules = rules, UserMethods = userMethods?.ToArray(), Root = root, Success = success, VarCollection = varCollection }); }
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(); }
private ScopeGroup(VarCollection varCollection, ScopeGroup parent, bool recursive) : this(varCollection) { Parent = parent; Recursive = recursive; }
private ScopeGroup(VarCollection varCollection, ScopeGroup parent) : this(varCollection) { Parent = parent; Recursive = parent.Recursive; }
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); }
void ToWorkshop(Func <VarCollection, Rule[]> addRules) { // Set up the variable collection. VarCollection.Setup(); // Set up initial global and player rules. InitialGlobal = new TranslateRule(this, "Initial Global", RuleEvent.OngoingGlobal); InitialPlayer = new TranslateRule(this, "Initial Player", RuleEvent.OngoingPlayer); WorkshopRules = new List <Rule>(); // Assign static variables. foreach (var type in types) { type.WorkshopInit(this); } // Assign variables at the rule-set level. foreach (var variable in rulesetVariables) { // Assign the variable an index. DefaultIndexAssigner.Add(VarCollection, variable, true, null); var assigner = DefaultIndexAssigner[variable] as IndexReference; if (assigner != null && variable.InitialValue != null) { var addToInitialRule = GetInitialRule(variable.VariableType == VariableType.Global); addToInitialRule.ActionSet.AddAction(assigner.SetVariable( (Element)variable.InitialValue.Parse(addToInitialRule.ActionSet) )); } } // Setup single-instance methods. foreach (var method in subroutines) { method.SetupSubroutine(); } // Parse the rules. foreach (var rule in rules) { var translate = new TranslateRule(this, rule); WorkshopRules.Add(translate.GetRule()); } if (InitialPlayer.Actions.Count > 0) { WorkshopRules.Insert(0, InitialPlayer.GetRule()); } if (InitialGlobal.Actions.Count > 0) { WorkshopRules.Insert(0, InitialGlobal.GetRule()); } if (addRules != null) { WorkshopRules.AddRange(addRules.Invoke(VarCollection).Where(rule => rule != null)); } // Order the workshop rules by priority. WorkshopRules = WorkshopRules.OrderBy(wr => wr.Priority).ToList(); // Get the final workshop string. WorkshopBuilder result = new WorkshopBuilder(Language); LanguageInfo.I18nWarningMessage(result, Language); // Get the custom game settings. if (MergedLobbySettings != null) { Ruleset settings = Ruleset.Parse(MergedLobbySettings); settings.ToWorkshop(result); result.AppendLine(); } // Get the variables. VarCollection.ToWorkshop(result); result.AppendLine(); // Get the subroutines. SubroutineCollection.ToWorkshop(result); // Get the rules. foreach (var rule in WorkshopRules) { result.AppendLine(rule.ToWorkshop(Language, OptimizeOutput)); } WorkshopCode = result.ToString(); }
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); } } }
void ToWorkshop(Func <VarCollection, Rule[]> addRules) { // Set up the variable collection. VarCollection.Setup(); // Set up initial global and player rules. InitialGlobal = new TranslateRule(this, "Initial Global", RuleEvent.OngoingGlobal); InitialPlayer = new TranslateRule(this, "Initial Player", RuleEvent.OngoingPlayer); WorkshopRules = new List <Rule>(); // Init called types. foreach (var type in Types.CalledTypes.Distinct()) { type.WorkshopInit(this); } // Assign variables at the rule-set level. foreach (var variable in rulesetVariables) { // Assign the variable an index. var assigner = DefaultIndexAssigner.Add(VarCollection, variable, true, null) as IndexReference; // Assigner will be non-null if it is an IndexReference. if (assigner != null) { DebugVariables.Add(variable, assigner); // Initial value. if (variable.InitialValue != null) { var addToInitialRule = GetInitialRule(variable.VariableType == VariableType.Global); addToInitialRule.ActionSet.AddAction(assigner.SetVariable( (Element)variable.InitialValue.Parse(addToInitialRule.ActionSet) )); } } } // Setup single-instance methods. foreach (var method in subroutines) { method.SetupSubroutine(); } // Parse the rules. foreach (var rule in rules) { var translate = new TranslateRule(this, rule); Rule newRule = translate.GetRule(); WorkshopRules.Add(newRule); rule.ElementCountLens.RuleParsed(newRule); } // Add built-in rules. // Initial player if (InitialPlayer.Actions.Count > 0) { WorkshopRules.Insert(0, InitialPlayer.GetRule()); } // Initial global if (InitialGlobal.Actions.Count > 0) { WorkshopRules.Insert(0, InitialGlobal.GetRule()); } // Additional if (addRules != null) { WorkshopRules.AddRange(addRules.Invoke(VarCollection).Where(rule => rule != null)); } // Order the workshop rules by priority. WorkshopRules = WorkshopRules.OrderBy(wr => wr.Priority).ToList(); // Get the final workshop string. WorkshopBuilder result = new WorkshopBuilder(Language); LanguageInfo.I18nWarningMessage(result, Language); // Get the custom game settings. if (Importer.MergedLobbySettings != null) { Ruleset settings = Ruleset.Parse(Importer.MergedLobbySettings); settings.ToWorkshop(result); result.AppendLine(); } // Get the variables. VarCollection.ToWorkshop(result); result.AppendLine(); // Print class identifiers. Types.PrintClassIdentifiers(result); // Get the subroutines. SubroutineCollection.ToWorkshop(result); // Get the rules. for (int i = 0; i < WorkshopRules.Count; i++) { WorkshopRules[i].ToWorkshop(result, OptimizeOutput); ElementCount += WorkshopRules[i].ElementCount(OptimizeOutput); if (i != WorkshopRules.Count - 1) { result.AppendLine(); } } WorkshopCode = result.ToString(); }
public static TranslateResult GetRule(RuleNode ruleNode, ScopeGroup root, VarCollection varCollection, UserMethod[] userMethods) { var result = new Translate(ruleNode, root, varCollection, userMethods); return(new TranslateResult(result.Rule, result.Diagnostics.ToArray())); }
public ContinueSkip(bool isGlobal, List <Element> actions, VarCollection varCollection) { IsGlobal = isGlobal; Actions = actions; VarCollection = varCollection; }
public ScopeGroup(VarCollection varCollection) { VarCollection = varCollection; }