public ClassData SetupClasses() { if (_classData == null) { _classData = new ClassData(VarCollection); InitialGlobal.ActionSet.AddAction(_classData.ClassIndexes.SetVariable(0, null, Constants.MAX_ARRAY_LENGTH)); } return(_classData); }
public IndexReference Create(ActionSet actionSet, ClassData classData) { // Classes are stored in the class array (`classData.ClassArray`), // this stores the index where the new class is created at. var classReference = actionSet.VarCollection.Assign("_new_" + Name + "_class_index", actionSet.IsGlobal, true); classData.GetClassIndex(Identifier, classReference, actionSet); // Get object variables. BaseSetup(actionSet, (Element)classReference.GetVariable()); return(classReference); }
public IWorkshopTree Parse(ActionSet actionSet, bool asElement = true) { ClassData classData = actionSet.Translate.DeltinScript.SetupClasses(); // Parse the expression. IWorkshopTree expressionResult = expression.Parse(actionSet); // Get the class identifier of the input expression. IWorkshopTree classIdentifier = Element.Part <V_ValueInArray>(classData.ClassIndexes.GetVariable(), expressionResult); // Check if the expression's class identifier and the type are equal. return(new V_Compare(classIdentifier, Operators.Equal, new V_Number(checkingIfType.Identifier))); }
public ClassData SetupClasses() { if (_classData == null) { _classData = new ClassData(VarCollection); InitialGlobal.ActionSet.AddAction(_classData.ClassArray.SetVariable(new V_EmptyArray())); if (DefinedType.CLASS_INDEX_WORKAROUND) { InitialGlobal.ActionSet.AddAction(_classData.ClassIndexes.SetVariable(new V_EmptyArray())); } } return(_classData); }
public override IWorkshopTree New(ActionSet actionSet, Constructor constructor, IWorkshopTree[] constructorValues, object[] additionalParameterData) { actionSet = actionSet.New(actionSet.IndexAssigner.CreateContained()); ClassData classData = actionSet.Translate.DeltinScript.GetComponent <ClassData>(); // Classes are stored in the class array (`classData.ClassArray`), // this stores the index where the new class is created at. var classReference = Create(actionSet, classData); New(actionSet, new NewClassInfo(classReference, constructor, constructorValues, additionalParameterData)); // Return the reference. return(classReference.GetVariable()); }
public override IWorkshopTree New(ActionSet actionSet, Constructor constructor, IWorkshopTree[] constructorValues, object[] additionalParameterData) { actionSet = actionSet.New(actionSet.IndexAssigner.CreateContained()); ClassData classData = actionSet.Translate.DeltinScript.GetComponent <ClassData>(); // Classes are stored in the class array (`classData.ClassArray`), // this stores the index where the new class is created at. var classReference = actionSet.VarCollection.Assign("_new_" + Name + "_class_index", actionSet.IsGlobal, true); classData.GetClassIndex(Identifier, classReference, actionSet); // Get object variables. BaseSetup(actionSet, (Element)classReference.GetVariable()); New(actionSet, new NewClassInfo(classReference, constructor, constructorValues, additionalParameterData)); // Return the reference. return(classReference.GetVariable()); }
public override void WorkshopInit(DeltinScript translateInfo) { if (workshopInitialized) { return; } workshopInitialized = true; ClassData classData = translateInfo.GetComponent <ClassData>(); Identifier = classData.AssignID(); int stackOffset = StackStart(false); Extends?.WorkshopInit(translateInfo); for (int i = 0; i < ObjectVariables.Count; i++) { ObjectVariables[i].SetArrayStore(classData.GetClassVariableStack(translateInfo.VarCollection, i + stackOffset)); } }
private IWorkshopTree ParseVirtual(ActionSet actionSet, MethodCall methodCall) { // Create the switch that chooses the overload. SwitchBuilder typeSwitch = new SwitchBuilder(actionSet); // Loop through all potential methods. IMethod[] options = Attributes.AllOverrideOptions(); // Get the call settings. MethodCall callSettings = new MethodCall(methodCall.ParameterValues, methodCall.AdditionalParameterData) { ResolveOverrides = false, ResolveReturnHandler = false, ReturnHandler = new ReturnHandler(actionSet, Name, true) }; // Parse the current overload. typeSwitch.NextCase(new V_Number(((ClassType)Attributes.ContainingType).Identifier)); Parse(actionSet, callSettings); foreach (IMethod option in options) { // The action set for the overload. ActionSet optionSet = actionSet.New(actionSet.IndexAssigner.CreateContained()); // Add the object variables of the selected method. option.Attributes.ContainingType.AddObjectVariablesToAssigner(optionSet.CurrentObject, optionSet.IndexAssigner); // Go to next case then parse the block. typeSwitch.NextCase(new V_Number(((ClassType)option.Attributes.ContainingType).Identifier)); option.Parse(optionSet, callSettings); } ClassData classData = actionSet.Translate.DeltinScript.SetupClasses(); // Finish the switch. typeSwitch.Finish(Element.Part <V_ValueInArray>(classData.ClassIndexes.GetVariable(), actionSet.CurrentObject)); callSettings.ReturnHandler.ApplyReturnSkips(); return(callSettings.ReturnHandler.GetReturnedValue()); }
private void ParseVirtual() { // Loop through all potential methods. DefinedMethod[] options = Array.ConvertAll(Method.Attributes.AllOverrideOptions(), iMethod => (DefinedMethod)iMethod); // Create the switch that chooses the overload. SwitchBuilder typeSwitch = new SwitchBuilder(BuilderSet); // Parse the current overload. if (Method.Attributes.Virtual) { typeSwitch.AddDefault(); } else { typeSwitch.NextCase(new V_Number(((ClassType)Method.Attributes.ContainingType).Identifier)); } TranslateSegment(BuilderSet, Method); foreach (DefinedMethod option in options) { // The action set for the overload. ActionSet optionSet = BuilderSet.New(BuilderSet.IndexAssigner.CreateContained()); // Add the object variables of the selected method. option.Attributes.ContainingType.AddObjectVariablesToAssigner(optionSet.CurrentObject, optionSet.IndexAssigner); // Go to next case then parse the block. typeSwitch.NextCase(new V_Number(((ClassType)option.Attributes.ContainingType).Identifier)); // Iterate through every type. foreach (CodeType type in BuilderSet.Translate.DeltinScript.Types.AllTypes) { // If 'type' does not equal the current virtual option's containing class... if (option.Attributes.ContainingType != type // ...and 'type' implements the containing class... && type.Implements(option.Attributes.ContainingType) // ...and 'type' does not have their own function implementation... && AutoImplemented(option.Attributes.ContainingType, options.Select(o => o.Attributes.ContainingType).ToArray(), type)) { // ...then add an additional case for 'type's class identifier. typeSwitch.NextCase(new V_Number(((ClassType)type).Identifier)); } } if (option.subroutineInfo == null) { TranslateSegment(optionSet, option); } else { option.SetupSubroutine(); BuilderSet.AddAction(Element.Part <A_StartRule>(option.subroutineInfo.Subroutine, EnumData.GetEnumValue(IfAlreadyExecuting.DoNothing))); if (Method.DoesReturnValue) { ReturnHandler.ReturnValue(option.subroutineInfo.ReturnHandler.GetReturnedValue()); } } if (Method.IsSubroutine) { option.virtualSubroutineAssigned = Method; } } ClassData classData = BuilderSet.Translate.DeltinScript.GetComponent <ClassData>(); // Finish the switch. typeSwitch.Finish(Element.Part <V_ValueInArray>(classData.ClassIndexes.GetVariable(), BuilderSet.CurrentObject)); }
public static void GetClassIndex(IndexReference classReference, ActionSet actionSet, ClassData classData) { // GetClassIndex() is less server load intensive than GetClassIndexWorkaround, // but due to a workshop bug with `Index Of Array Value`, the workaround may // need to be used instead. if (!CLASS_INDEX_WORKAROUND) { // Get the index of the first null value in the class array. actionSet.AddAction(classReference.SetVariable( Element.Part <V_IndexOfArrayValue>( classData.ClassArray.GetVariable(), new V_Null() ) )); // If the index equals -1, use the count of the class array instead. // TODO: Try setting the 1000th index of the class array to null instead. actionSet.AddAction(classReference.SetVariable( Element.TernaryConditional( new V_Compare(classReference.GetVariable(), Operators.Equal, new V_Number(-1)), Element.Part <V_CountOf>(classData.ClassArray.GetVariable()), classReference.GetVariable() ) )); } else { // 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>(classData.ClassIndexes.GetVariable(), new V_ArrayElement()), // Filter Element.Part <V_And>( // If the previous index was not taken, use that index. !Element.Part <V_ArrayContains>( classData.ClassIndexes.GetVariable(), 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, use the length of the class array subtracted by 1. firstFree = Element.TernaryConditional( new V_Compare(Element.Part <V_CountOf>(classData.ClassIndexes.GetVariable()), Operators.NotEqual, new V_Number(0)), firstFree, Element.Part <V_CountOf>(classData.ClassArray.GetVariable()) - 1 ); actionSet.AddAction(classReference.SetVariable(firstFree)); actionSet.AddAction(classReference.SetVariable( Element.TernaryConditional( // If the index equals -1, use the length of the class array instead. new V_Compare(classReference.GetVariable(), Operators.Equal, new V_Number(-1)), Element.Part <V_CountOf>(classData.ClassArray.GetVariable()), classReference.GetVariable() ) )); // Add the selected index to the taken indexes array. actionSet.AddAction( classData.ClassIndexes.SetVariable( Element.Part <V_Append>( classData.ClassIndexes.GetVariable(), classReference.GetVariable() ) ) ); } }
public IWorkshopTree ParseVirtual() { IMacroOption[] options = AllOptions(); //If there are no overrides, don't bother creating the lookup table if (options.Length == 1) { return(options[0].Parse(ActionSet)); } List <IWorkshopTree> expElements = new List <IWorkshopTree>(); List <int> resolves = new List <int>(); List <int> identifiers = new List <int>(); bool needsResolve = false; foreach (var option in options) { var optionSet = ActionSet.New(ActionSet.IndexAssigner.CreateContained()); option.Type().AddObjectVariablesToAssigner(optionSet.CurrentObject, optionSet.IndexAssigner); int currentIndex = expElements.Count; expElements.Add(option.Parse(optionSet)); resolves.Add(currentIndex); identifiers.Add(((ClassType)option.Type()).Identifier); // Iterate through every type. foreach (CodeType type in ActionSet.Translate.DeltinScript.Types.AllTypes) { // If 'type' does not equal the current virtual option's containing class... if (option.Type() != type // ...and 'type' implements the containing class... && type.Implements(option.Type()) // ...and 'type' does not have their own function implementation... && Deltin.Deltinteger.Parse.FunctionBuilder.VirtualLookupTable.AutoImplemented(option.Type(), options.Select(option => option.Type()).ToArray(), type)) // ...then add an additional case for 'type's class identifier. { needsResolve = true; resolves.Add(currentIndex); identifiers.Add(((ClassType)type).Identifier); } } } Element expArray = Element.CreateArray(expElements.ToArray()); Element resolveArray = Element.CreateArray(resolves.Select(i => new V_Number(i)).ToArray()); Element identArray = Element.CreateArray(identifiers.Select(i => new V_Number(i)).ToArray()); ClassData classData = ActionSet.Translate.DeltinScript.GetComponent <ClassData>(); Element classIdentifier = Element.Part <V_ValueInArray>(classData.ClassIndexes.GetVariable(), ActionSet.CurrentObject); /* * class A // Class identifier: 5 * { * virtual define Macro: 2; * } * class B : A // Class identifier: 6 * { * override define Macro: 3; * } * In this case, the macro can be resolved like so: * [2, 3][Index Of([5, 6], class id)] * This output will not work in this case: * class A // Class identifier: 5 * { * virtual define Macro: 2; * } * class B : A // Class identifier: 6 * { * override define Macro: 3; * } * class C : B // Class identifier: 7 * { * } * C does not implement 'Macro'. This will cause the output to be the same as above. * This is not correct. Since C implements B, it should return 3. Since Index Of returns -1, the macro will return 0 if 'new C().Macro' is called. * If this case happens, 'needsResolve' will be true. When it is true, do this instead: * [2, 3][0, 1, 1][IndexOf([5, 6, 7], class id)] * '[0, 1, 1]' will map the index to the correct macro value. */ if (needsResolve) { return(expArray[resolveArray[Element.Part <V_IndexOfArrayValue>(identArray, classIdentifier)]]); } else { return(expArray[Element.Part <V_IndexOfArrayValue>(identArray, classIdentifier)]); } }