예제 #1
0
        /// <summary>Adapts a command entry to CIL.</summary>
        /// <param name="values">The adaptation-relevant values.</param>
        /// <param name="entry">The relevant entry ID.</param>
        public override void AdaptToCIL(CILAdaptationValues values, int entry)
        {
            CommandEntry cent  = values.CommandAt(entry);
            bool         debug = cent.DBMode.ShouldShow(DebugMode.FULL);

            values.MarkCommand(entry);
            TagReturnType     returnType = ArgumentCompiler.ReturnType(cent.Arguments[2], values);
            string            lvarname   = cent.Arguments[0].ToString().ToLowerFast();
            SingleCILVariable locVar     = cent.VarLookup[lvarname];

            // This method:
            // runnable.Var = TYPE.CREATE_FOR(tagdata, runnable.entry.arg2());
            // or:
            // runnable.Var = runnable.entry.arg2();
            values.LoadRunnable();
            values.LoadArgumentObject(entry, 2);
            if (cent.Arguments.Length > 4)
            {
                string        type_name           = cent.Arguments[4].ToString().ToLowerFast();
                TagType       specifiedType       = cent.System.TagSystem.Types.RegisteredTypes[type_name];
                TagReturnType specifiedReturnType = new(specifiedType, specifiedType.Meta.RawInternal);
                values.EnsureType(returnType, specifiedReturnType); // Ensure the correct object type.
                returnType = specifiedReturnType;
            }
            else
            {
                TagReturnType specifiedReturnType = new(returnType.Type, returnType.Type.Meta.RawInternal);
                values.EnsureType(returnType, specifiedReturnType); // Ensure the correct object type.
                returnType = specifiedReturnType;
            }
            values.ILGen.Emit(OpCodes.Stfld, locVar.Field); // Push the result into the local var
            if (debug)                                      // If in debug mode...
            {
                values.LoadLocalVariable(locVar.Index);     // Load variable.
                if (returnType.IsRaw)
                {
                    values.ILGen.Emit(OpCodes.Newobj, returnType.Type.RawInternalConstructor); // Handle raw translation if needed.
                }
                values.ILGen.Emit(OpCodes.Ldstr, lvarname);                                    // Load the variable name as a string.
                values.ILGen.Emit(OpCodes.Ldstr, returnType.Type.TypeName);                    // Load the variable type name as a string.
                values.LoadQueue();                                                            // Load the queue
                values.LoadEntry(entry);                                                       // Load the entry
                values.ILGen.Emit(OpCodes.Call, Method_DebugHelper);                           // Call the debug method
            }
        }
예제 #2
0
        /// <summary>Adapts a command entry to CIL.</summary>
        /// <param name="values">The adaptation-relevant values.</param>
        /// <param name="entry">The present entry ID.</param>
        public override void AdaptToCIL(CILAdaptationValues values, int entry)
        {
            CommandEntry cent = values.CommandAt(entry);
            bool         db   = cent.DBMode <= DebugMode.FULL;

            if (cent.IsCallback)
            {
                int lvar_ind_loc = GetSaveLoc(values, entry);
                values.LoadQueue();
                if (db)
                {
                    values.LoadEntry(entry);
                }
                else
                {
                    values.ILGen.Emit(OpCodes.Ldc_I4, cent.BlockStart - 1);
                }
                values.LoadLocalVariable(lvar_ind_loc);
                values.ILGen.Emit(OpCodes.Call, db ? TryForeachCILMethod : TryForeachCILMethodNoDebug);
                values.ILGen.Emit(OpCodes.Brtrue, values.Entry.AdaptedILPoints[cent.BlockStart]);
                return;
            }
            string arg = cent.Arguments[0].ToString();

            if (arg == "stop")
            {
                for (int i = entry - 1; i >= 0; i--)
                {
                    CommandEntry nextEntry = values.Entry.Entries[i];
                    if (nextEntry.Command is not ForeachCommand || nextEntry.IsCallback)
                    {
                        continue;
                    }
                    string a0 = nextEntry.Arguments[0].ToString();
                    if (a0 == "start" && nextEntry.InnerCommandBlock != null)
                    {
                        if (db)
                        {
                            values.LoadQueue();
                            values.LoadEntry(entry);
                            values.ILGen.Emit(OpCodes.Call, DebugStopMethod);
                        }
                        values.ILGen.Emit(OpCodes.Br, values.Entry.AdaptedILPoints[nextEntry.BlockEnd + 2]);
                        return;
                    }
                }
                throw new ErrorInducedException("Invalid 'foreach stop' command: not inside a foreach block!");
            }
            else if (arg == "next")
            {
                for (int i = entry - 1; i >= 0; i--)
                {
                    CommandEntry nextEntry = values.Entry.Entries[i];
                    if (nextEntry.Command is not ForeachCommand || nextEntry.IsCallback)
                    {
                        continue;
                    }
                    string a0 = nextEntry.Arguments[0].ToString();
                    if (a0 == "start" && nextEntry.InnerCommandBlock != null)
                    {
                        if (db)
                        {
                            values.LoadQueue();
                            values.LoadEntry(entry);
                            values.ILGen.Emit(OpCodes.Call, DebugNextMethod);
                        }
                        values.ILGen.Emit(OpCodes.Br, values.Entry.AdaptedILPoints[nextEntry.BlockEnd + 1]);
                        return;
                    }
                }
                throw new ErrorInducedException("Invalid 'foreach next' command: not inside a foreach block!");
            }
            else if (arg == "start")
            {
                SingleCILVariable locVar = cent.VarLookup[cent.GetSaveNameNoParse("foreach_value")];
                values.LoadQueue();
                values.LoadEntry(entry);
                values.LoadRunnable();
                values.ILGen.Emit(OpCodes.Call, CreateListItemMethod);
                values.ILGen.Emit(OpCodes.Stfld, locVar.Field);
                values.LoadLocalVariable(locVar.Index);
                values.ILGen.Emit(OpCodes.Call, db ? TryForeachNumberedCILMethod : TryForeachNumberedCIL_NoDebugMethod);
                values.ILGen.Emit(OpCodes.Brfalse, values.Entry.AdaptedILPoints[cent.BlockEnd + 2]);
            }
            else
            {
                throw new ErrorInducedException("Invalid 'foreach' command: unknown argument: " + arg);
            }
        }