public ClassData SetupClasses()
 {
     if (_classData == null)
     {
         _classData = new ClassData(VarCollection);
         InitialGlobal.ActionSet.AddAction(_classData.ClassIndexes.SetVariable(0, null, Constants.MAX_ARRAY_LENGTH));
     }
     return(_classData);
 }
Esempio n. 2
0
        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);
        }
Esempio n. 5
0
        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));
        }
Esempio n. 10
0
        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)]);
            }
        }