private static IWorkshopTree CallSubroutine(DefinedMethod method, MethodCall call, ActionSet callerSet) { method.SetupSubroutine(); for (int i = 0; i < method.subroutineInfo.ParameterStores.Length; i++) { // Normal parameter push. if (!method.Attributes.Recursive) { callerSet.AddAction(method.subroutineInfo.ParameterStores[i].SetVariable((Element)call.ParameterValues[i])); } // Recursive parameter push. else { callerSet.AddAction(((RecursiveIndexReference)method.subroutineInfo.ParameterStores[i]).Push((Element)call.ParameterValues[i])); } } // Store the object the subroutine is executing with. if (method.subroutineInfo.ObjectStore != null) { // Normal if (!method.Attributes.Recursive) { callerSet.AddAction(method.subroutineInfo.ObjectStore.SetVariable((Element)callerSet.CurrentObject)); } // Recursive: Stack else { callerSet.AddAction(method.subroutineInfo.ObjectStore.ModifyVariable(Operation.AppendToArray, (Element)callerSet.CurrentObject)); } } switch (call.CallParallel) { // No parallel, call subroutine normally. case CallParallel.NoParallel: callerSet.AddAction(Element.Part <A_CallSubroutine>(method.subroutineInfo.Subroutine)); return(method.subroutineInfo.ReturnHandler.GetReturnedValue()); // Restart the subroutine if it is already running. case CallParallel.AlreadyRunning_RestartRule: callerSet.AddAction(Element.Part <A_StartRule>(method.subroutineInfo.Subroutine, EnumData.GetEnumValue(IfAlreadyExecuting.RestartRule))); return(null); // Do nothing if the subroutine is already running. case CallParallel.AlreadyRunning_DoNothing: callerSet.AddAction(Element.Part <A_StartRule>(method.subroutineInfo.Subroutine, EnumData.GetEnumValue(IfAlreadyExecuting.DoNothing))); return(null); default: throw new NotImplementedException(); } }
/// <summary>Determines if the specified type does not have their own implementation for the specified virtual function.</summary> /// <param name="virtualFunction">The virtual function to check overrides of.</param> /// <param name="options">All potential virtual functions.</param> /// <param name="type">The type to check.</param> private bool AutoImplemented(DefinedMethod virtualFunction, DefinedMethod[] options, CodeType type) { // Go through each class in the inheritance tree and check if it implements the function. CodeType current = type; while (current != null && current != virtualFunction.Attributes.ContainingType) { // If it does, return false. if (options.Any(option => option.Attributes.ContainingType == current)) { return(false); } current = current.Extends; } return(true); }
public static IWorkshopTree Call(DefinedMethod method, MethodCall call, ActionSet actionSet) { RecursiveStack lastCall = actionSet.Translate.MethodStack.FirstOrDefault(ms => ms.Function == method) as RecursiveStack; if (lastCall == null) { RecursiveStack parser = new RecursiveStack(method); actionSet.Translate.MethodStack.Add(parser); var result = parser.ParseCall(actionSet, call); actionSet.Translate.MethodStack.Remove(parser); return(result); } else { return(lastCall.RecursiveCall(actionSet, call)); } }
private static IWorkshopTree CallInlineRecursive(MethodBuilder builder, DefinedMethod method, MethodCall call, ActionSet callerSet) { RecursiveStack lastCall = RecursiveStack.GetRecursiveCall(callerSet.Translate.MethodStack, method); if (lastCall == null) { RecursiveStack parser = new RecursiveStack(builder); callerSet.Translate.MethodStack.Add(parser); parser.ParseCall(call); callerSet.Translate.MethodStack.Remove(parser); return(builder.ReturnHandler.GetReturnedValue()); } else { lastCall.RecursiveCall(call, callerSet); return(lastCall.Builder.ReturnHandler.GetReturnedValue()); } }
/// <summary>Calls the method.</summary> private IWorkshopTree ParseCall(ActionSet actionSet, MethodCall methodCall) { // Create the array used for continuing after a recursive call. continueArray = actionSet.VarCollection.Assign("_" + method.Name + "_recursiveContinue", actionSet.IsGlobal, false); nextContinue = actionSet.VarCollection.Assign("_" + method.Name + "_nextContinue", actionSet.IsGlobal, true); actionSet.InitialSet().AddAction(continueArray.SetVariable(new V_EmptyArray())); ReturnHandler returnHandler = methodCall.ReturnHandler ?? new ReturnHandler(actionSet, method.Name, method.multiplePaths); this.returnHandler = returnHandler; DefinedMethod.AssignParameters(actionSet, method.ParameterVars, methodCall.ParameterValues, true); actionSet.AddAction(Element.Part <A_While>(new V_True())); continueAt = new SkipStartMarker(actionSet); continueAt.SetSkipCount((Element)nextContinue.GetVariable()); actionSet.AddAction(continueAt); method.block.Translate(actionSet); PopParameterStacks(actionSet); // Pop the continueArray. actionSet.AddAction(Element.Part <A_SkipIf>(new V_Compare( Element.Part <V_CountOf>(continueArray.GetVariable()), Operators.Equal, new V_Number(0) ), new V_Number(3))); actionSet.AddAction(nextContinue.SetVariable(Element.Part <V_LastOf>(continueArray.GetVariable()))); actionSet.AddAction(continueArray.ModifyVariable(Operation.RemoveFromArrayByIndex, Element.Part <V_CountOf>(continueArray.GetVariable()) - 1)); actionSet.AddAction(endOfMethod); actionSet.AddAction(new A_End()); actionSet.AddAction(nextContinue.SetVariable(0)); return(returnHandler.GetReturnedValue()); }
public static IWorkshopTree Call(DefinedMethod method, MethodCall call, ActionSet callerSet) { // Subroutine call. if (method.IsSubroutine) { return(CallSubroutine(method, call, callerSet)); } // Inline else { MethodBuilder builder = new MethodBuilder(method, callerSet); // Inline-recursive method call. if (method.Attributes.Recursive) { return(CallInlineRecursive(builder, method, call, callerSet)); } else { if (method.virtualSubroutineAssigned != null) { // TODO: Maybe remove this? // Virtual in another subroutine return(Call(method.virtualSubroutineAssigned, call, callerSet)); } else { // Normal builder.BuilderSet = builder.BuilderSet.PackThis(); builder.AssignParameters(call); builder.SetupReturnHandler(); builder.ParseInner(); builder.ReturnHandler.ApplyReturnSkips(); return(builder.ReturnHandler.GetReturnedValue()); } } } }
public override void ResolveElements() { if (elementsResolved) { return; } // Get the type being extended. if (typeContext.TERNARY_ELSE() != null) { // If there is no type name, error. if (typeContext.extends == null) { parseInfo.Script.Diagnostics.Error("Expected type name.", DocRange.GetRange(typeContext.TERNARY_ELSE())); } else { // Get the type being inherited. CodeType inheriting = parseInfo.TranslateInfo.Types.GetCodeType(typeContext.extends.Text, parseInfo.Script.Diagnostics, DocRange.GetRange(typeContext.extends)); // GetCodeType will return null if the type is not found. if (inheriting != null) { inheriting.Call(parseInfo, DocRange.GetRange(typeContext.extends)); Inherit(inheriting, parseInfo.Script.Diagnostics, DocRange.GetRange(typeContext.extends)); (Extends as ClassType)?.ResolveElements(); } } } base.ResolveElements(); // Give DefinedMethod and GetMacro a scope to use in case of the static attribute. foreach (var definedMethod in typeContext.define_method()) { var newMethod = new DefinedMethod(parseInfo, operationalScope, staticScope, definedMethod, this); // Copy to serving scopes. if (newMethod.Static) { operationalScope.CopyMethod(newMethod); } else { serveObjectScope.CopyMethod(newMethod); } } // Get the macros. foreach (var macroContext in typeContext.define_macro()) { var newMacro = parseInfo.GetMacro(operationalScope, staticScope, macroContext); // Copy to serving scopes. if (newMacro is IMethod asMethod) { if (newMacro.Static) { operationalScope.CopyMethod(asMethod); } else { serveObjectScope.CopyMethod(asMethod); } } else { if (newMacro.Static) { operationalScope.CopyVariable((IVariable)newMacro); } else { serveObjectScope.CopyVariable((IVariable)newMacro); } } } // Get the variables defined in the type. foreach (var definedVariable in typeContext.define()) { Var newVar = new ClassVariable(operationalScope, staticScope, new DefineContextHandler(parseInfo, definedVariable)); // Copy to serving scopes. if (!newVar.Static) { ObjectVariables.Add(new ObjectVariable(newVar)); serveObjectScope.CopyVariable(newVar); } // Add to static scope. else { staticVariables.Add(newVar); staticScope.CopyVariable(newVar); operationalScope.CopyVariable(newVar); } } // Get the constructors. if (typeContext.constructor().Length > 0) { Constructors = new Constructor[typeContext.constructor().Length]; for (int i = 0; i < Constructors.Length; i++) { Constructors[i] = new DefinedConstructor(parseInfo, operationalScope, this, typeContext.constructor(i)); } } else { // If there are no constructors, create a default constructor. Constructors = new Constructor[] { new Constructor(this, new Location(parseInfo.Script.Uri, DocRange.GetRange(typeContext.name)), AccessLevel.Public) }; } // If the extend token exists, add completion that only contains all extendable classes. if (typeContext.TERNARY_ELSE() != null) { parseInfo.Script.AddCompletionRange(new CompletionRange( // Get the completion items of all types. parseInfo.TranslateInfo.Types.AllTypes .Where(t => t is ClassType ct && ct.CanBeExtended) .Select(t => t.GetCompletion()) .ToArray(), // Get the completion range. DocRange.GetRange(typeContext.TERNARY_ELSE(), parseInfo.Script.NextToken(typeContext.TERNARY_ELSE())), // This completion takes priority. CompletionRangeKind.ClearRest )); } parseInfo.Script.AddCodeLensRange(new ReferenceCodeLensRange(this, parseInfo, CodeLensSourceType.Type, DefinedAt.range)); }
public BlockTreeScan(bool doesReturnValue, ParseInfo parseInfo, DefinedMethod method) : this(parseInfo, method.Block, method.Name, method.Context.Identifier.Range) { ReturnsValue = doesReturnValue; }
public override void Parse(ActionSet actionSet, IWorkshopTree[] parameterValues, object[] additionalParameterData) { actionSet = actionSet.New(actionSet.IndexAssigner.CreateContained()).PackThis(); DefinedMethod.AssignParameters(actionSet, ParameterVars, parameterValues); Block.Translate(actionSet); }
public MethodBuilder(DefinedMethod method, ActionSet builderSet, ReturnHandler returnHandler = null) { Method = method; this.BuilderSet = builderSet; ReturnHandler = returnHandler; }
private static void TranslateSegment(ActionSet actionSet, DefinedMethod method) { method.Block.Translate(actionSet); }
public override void Parse(ActionSet actionSet, IWorkshopTree[] parameterValues) { actionSet = actionSet.New(actionSet.IndexAssigner.CreateContained()); DefinedMethod.AssignParameters(actionSet, ParameterVars, parameterValues); Block.Translate(actionSet); }
public BlockTreeScan(bool doesReturnValue, ParseInfo parseInfo, DefinedMethod method) : this(parseInfo, method.Block, method.Name, DocRange.GetRange(method.Context.name)) { ReturnsValue = doesReturnValue; }
public RecursiveMethodStack(DefinedMethod method, ReturnHandler returnHandler, IndexReference continueSkipArray, SkipEndMarker methodStart) : base(method) { ReturnHandler = returnHandler; ContinueSkipArray = continueSkipArray; MethodStart = methodStart; }
public DefinedType(ParseInfo parseInfo, Scope scope, DeltinScriptParser.Type_defineContext typeContext, List <IApplyBlock> applyMethods) : base(typeContext.name.Text) { this.translateInfo = parseInfo.TranslateInfo; if (translateInfo.IsCodeType(Name)) { parseInfo.Script.Diagnostics.Error($"A type with the name '{Name}' already exists.", DocRange.GetRange(typeContext.name)); } DefinedAt = new LanguageServer.Location(parseInfo.Script.Uri, DocRange.GetRange(typeContext.name)); translateInfo.AddSymbolLink(this, DefinedAt); if (typeContext.CLASS() != null) { TypeKind = TypeKind.Class; TypeKindString = "class"; } else if (typeContext.STRUCT() != null) { TypeKind = TypeKind.Struct; TypeKindString = "struct"; } else { throw new NotImplementedException(); } staticScope = translateInfo.GlobalScope.Child(TypeKindString + " " + Name); objectScope = staticScope.Child(TypeKindString + " " + Name); // Get the variables defined in the type. foreach (var definedVariable in typeContext.define()) { Var newVar = Var.CreateVarFromContext(VariableDefineType.InClass, parseInfo, definedVariable); newVar.Finalize(UseScope(newVar.Static)); if (!newVar.Static) { objectVariables.Add(newVar); } } // Todo: Static methods/macros. foreach (var definedMethod in typeContext.define_method()) { var newMethod = new DefinedMethod(parseInfo, UseScope(false), definedMethod); applyMethods.Add(newMethod); } foreach (var macroContext in typeContext.define_macro()) { DeltinScript.GetMacro(parseInfo, UseScope(false), macroContext, applyMethods); } // Get the constructors. if (typeContext.constructor().Length > 0) { Constructors = new Constructor[typeContext.constructor().Length]; for (int i = 0; i < Constructors.Length; i++) { Constructors[i] = new DefinedConstructor(parseInfo, this, typeContext.constructor(i)); applyMethods.Add((DefinedConstructor)Constructors[i]); } } else { // If there are no constructors, create a default constructor. Constructors = new Constructor[] { new Constructor(this, new Location(parseInfo.Script.Uri, DocRange.GetRange(typeContext.name)), AccessLevel.Public) }; } }
public override void ResolveElements() { if (elementsResolved) { return; } // Get the type being extended. // This is an array for future interface support. if (_typeContext.Inheriting.Count > 0 && _typeContext.Inheriting[0]) { var inheritToken = _typeContext.Inheriting[0]; // Get the type being inherited. CodeType inheriting = _parseInfo.TranslateInfo.Types.GetCodeType(inheritToken.Text, _parseInfo.Script.Diagnostics, inheritToken.Range); // GetCodeType will return null if the type is not found. if (inheriting != null) { inheriting.Call(_parseInfo, inheritToken.Range); Inherit(inheriting, _parseInfo.Script.Diagnostics, inheritToken.Range); (Extends as ClassType)?.ResolveElements(); } } base.ResolveElements(); // Get the declarations. foreach (var declaration in _typeContext.Declarations) { IScopeable scopeable; // Function if (declaration is FunctionContext function) { scopeable = new DefinedMethod(_parseInfo, operationalScope, staticScope, function, this); } // Macro function else if (declaration is MacroFunctionContext macroFunction) { scopeable = _parseInfo.GetMacro(operationalScope, staticScope, macroFunction); } // Variable else if (declaration is VariableDeclaration variable) { scopeable = new ClassVariable(operationalScope, staticScope, new DefineContextHandler(_parseInfo, variable)).GetVar(); } // Macro variable else if (declaration is MacroVarDeclaration macroVar) { scopeable = _parseInfo.GetMacro(operationalScope, staticScope, macroVar); } // Unknown else { throw new NotImplementedException(declaration.GetType().ToString()); } // Add the object variable if it is an IIndexReferencer. if (scopeable is IIndexReferencer referencer) { AddObjectVariable(referencer); } // Copy to scopes. // Method copy if (scopeable is IMethod method) { if (method.Static) { operationalScope.CopyMethod(method); } else { serveObjectScope.CopyMethod(method); } } // Variable copy else if (scopeable is IVariable variable) { if (scopeable.Static) { operationalScope.CopyVariable(variable); } else { serveObjectScope.CopyVariable(variable); } } else { throw new NotImplementedException(); } } // Get the constructors. if (_typeContext.Constructors.Count > 0) { Constructors = new Constructor[_typeContext.Constructors.Count]; for (int i = 0; i < Constructors.Length; i++) { Constructors[i] = new DefinedConstructor(_parseInfo, operationalScope, this, _typeContext.Constructors[i]); } } else { // If there are no constructors, create a default constructor. Constructors = new Constructor[] { new Constructor(this, new Location(_parseInfo.Script.Uri, DefinedAt.range), AccessLevel.Public) }; } // If the extend token exists, add completion that only contains all extendable classes. if (_typeContext.InheritToken != null && !_parseInfo.Script.IsTokenLast(_typeContext.InheritToken)) { _parseInfo.Script.AddCompletionRange(new CompletionRange( // Get the completion items of all types. _parseInfo.TranslateInfo.Types.AllTypes .Where(t => t is ClassType ct && ct.CanBeExtended) .Select(t => t.GetCompletion()) .ToArray(), // Get the completion range. _typeContext.InheritToken.Range.End + _parseInfo.Script.NextToken(_typeContext.InheritToken).Range.Start, // This completion takes priority. CompletionRangeKind.ClearRest )); } _parseInfo.Script.AddCodeLensRange(new ReferenceCodeLensRange(this, _parseInfo, CodeLensSourceType.Type, DefinedAt.range)); }
public RecursiveStack(DefinedMethod method) : base((IApplyBlock)method) { this.method = method; }
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)); } } }
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 void AddSubroutine(DefinedMethod method) { subroutines.Add(method); }