コード例 #1
0
        /// <summary>Adapts the var tag base for compiling.</summary>
        /// <param name="ccse">The compiled CSE.</param>
        /// <param name="tab">The TagArgumentBit.</param>
        /// <param name="i">The command index.</param>
        /// <param name="values">Related adaptation values.</param>
        public override TagReturnType Adapt(CompiledCommandStackEntry ccse, TagArgumentBit tab, int i, CILAdaptationValues values)
        {
            string       vn    = tab.Bits[0].Variable.ToString().ToLowerFast();
            CommandEntry entry = ccse.Entries[i];

            if (!entry.VarLookup.TryGetValue(vn, out SingleCILVariable locVar))
            {
                throw new ErrorInducedException("Var tag cannot compile: unknown variable name input '" + vn + "' (That variable name cannot be found. Have you declared it in this script section? Consider using the 'require' command.)");
            }
            tab.Start                 = tab.TagSystem.LVar;
            tab.Bits[0].Key           = "\0lvar";
            tab.Bits[0].Handler       = null;
            tab.Bits[0].OriginalInput = "[" + tab.Bits[0].Variable.ToString() + "]";
            tab.Bits[0].Variable      = new Argument()
            {
                WasQuoted = false, Bits = new ArgumentBit[] { new TextArgumentBit(locVar.Index, tab.Engine) }
            };
            return(locVar.Type);
        }
コード例 #2
0
 /// <summary>Adapts the template tab base for compiling.</summary>
 /// <param name="ccse">The compiled CSE.</param>
 /// <param name="tab">The TagArgumentBit.</param>
 /// <param name="i">The command index.</param>
 /// <param name="values">Related adaptation values.</param>
 public virtual TagReturnType Adapt(CompiledCommandStackEntry ccse, TagArgumentBit tab, int i, CILAdaptationValues values)
 {
     return(default);
コード例 #3
0
        /// <summary>Compiles a command script.</summary>
        /// <param name="script">The command script to compile.</param>
        /// <returns>The compiled result.</returns>
        public static CompiledCommandStackEntry Compile(CommandScript script)
        {
            string tname = "__script__" + IDINCR++ + "__" + NameTrimMatcher.TrimToMatches(script.Name);
            CompiledCommandStackEntry Created = new()
            {
                Entries      = script.CommandArray,
                Script       = script,
                AssemblyName = tname
            };
            AssemblyName              asmname  = new(tname) { Name = tname };
            AssemblyBuilder           asmbuild = AssemblyBuilder.DefineDynamicAssembly(asmname, AssemblyBuilderAccess.RunAndCollect);
            ModuleBuilder             modbuild = asmbuild.DefineDynamicModule(tname);
            CompiledCommandStackEntry ccse     = Created;

            ccse.AdaptedILPoints = new Label[ccse.Entries.Length + 1];
            TypeBuilder        typebuild_c   = modbuild.DefineType(tname + "__CENTRAL", TypeAttributes.Class | TypeAttributes.Public, typeof(CompiledCommandRunnable));
            MethodBuilder      methodbuild_c = typebuild_c.DefineMethod("Run", MethodAttributes.Public | MethodAttributes.Virtual, typeof(void), RUN_METHOD_PARAMETERS);
            ILGeneratorTracker ilgen         = new ILGeneratorTracker(methodbuild_c.GetILGenerator(), new Type[] { typebuild_c }.JoinWith(RUN_METHOD_PARAMETERS), $"Script_{tname}").ConfigureTracker(Created.System);

            ilgen.AddCode(OpCodes.Nop, tname, "--- SCRIPT ---");
            CILAdaptationValues values = new()
            {
                Entry          = ccse,
                Script         = script,
                ILGen          = ilgen,
                Method         = methodbuild_c,
                DBMode         = script.Debug,
                EntryFields    = new FieldInfo[ccse.Entries.Length],
                ArgumentFields = new FieldInfo[ccse.Entries.Length][],
                Type           = typebuild_c
            };

            for (int i = 0; i < ccse.Entries.Length; i++)
            {
                values.EntryFields[i] = typebuild_c.DefineField("_field_entry_" + i, typeof(CommandEntry), FieldAttributes.Public | FieldAttributes.InitOnly);
            }
            values.PushVarSet();
            for (int i = 0; i < ccse.AdaptedILPoints.Length; i++)
            {
                ccse.AdaptedILPoints[i] = ilgen.DefineLabel();
            }
            int tagID = 0;
            List <TagArgumentBit>     toClean = new();
            List <ILGeneratorTracker> ILGens
#if SAVE
                = new();
#else
                = null;
#endif
            values.Trackers = ILGens;
            List <KeyValuePair <FieldInfo, Object> > specialFieldValues = new();
            for (int i = 0; i < ccse.Entries.Length; i++)
            {
                CommandEntry curEnt = ccse.Entries[i];
                curEnt.CCSE      = ccse;
                curEnt.DBMode    = values.DBMode;
                curEnt.VarLookup = values.CreateVarLookup();
                for (int a = 0; a < curEnt.Arguments.Length; a++)
                {
                    Argument arg = curEnt.Arguments[a];
                    for (int b = 0; b < arg.Bits.Length; b++)
                    {
                        if (arg.Bits[b] is TagArgumentBit tab)
                        {
                            tagID++;
                            try
                            {
                                GenerateTagData(typebuild_c, ccse, tab, ref tagID, values, i, toClean, (a + 1).ToString(), curEnt, specialFieldValues, ILGens);
                            }
                            catch (TagErrorInducedException ex)
                            {
                                TagException(curEnt, "argument " + TextStyle.Separate + a + TextStyle.Base, tab, ex.SubTagIndex, ex);
                            }
                            catch (ErrorInducedException ex)
                            {
                                TagException(curEnt, "argument " + TextStyle.Separate + a + TextStyle.Base, tab, 0, ex);
                            }
                        }
                    }
                    ILGeneratorTracker compiled = ArgumentCompiler.Compile(arg, Created, values);
                    curEnt.Arguments[a] = arg.TrueForm;
                    ILGens?.Add(compiled);
                }
                foreach (KeyValuePair <string, Argument> argPair in curEnt.NamedArguments)
                {
                    for (int b = 0; b < argPair.Value.Bits.Length; b++)
                    {
                        if (argPair.Value.Bits[b] is TagArgumentBit tab)
                        {
                            tagID++;
                            try
                            {
                                GenerateTagData(typebuild_c, ccse, tab, ref tagID, values, i, toClean, "named " + argPair.Key, curEnt, specialFieldValues, ILGens);
                            }
                            catch (TagErrorInducedException ex)
                            {
                                TagException(curEnt, "named argument '" + TextStyle.Separate + argPair.Key + TextStyle.Base + "'", tab, ex.SubTagIndex, ex);
                            }
                            catch (ErrorInducedException ex)
                            {
                                TagException(curEnt, "named argument '" + TextStyle.Separate + argPair.Key + TextStyle.Base + "'", tab, 0, ex);
                            }
                        }
                    }
                    ILGeneratorTracker compiled = ArgumentCompiler.Compile(argPair.Value, Created, values);
                    ILGens?.Add(compiled);
                }
                if (!curEnt.IsCallback)
                {
                    try
                    {
                        curEnt.Command.PreAdaptToCIL(values, i);
                    }
                    catch (ErrorInducedException ex)
                    {
                        throw new ErrorInducedException("On script line " + curEnt.ScriptLine + " (" + curEnt.CommandLine + "), early compile (PreAdapt) error occured: " + ex.Message);
                    }
                    curEnt.VarLookup = values.CreateVarLookup();
                }
                if (curEnt.NamedArguments.TryGetValue(CommandEntry.SAVE_NAME_ARG_ID, out Argument avarname))
                {
                    if (!curEnt.VarLookup.ContainsKey(avarname.ToString()))
                    {
                        throw new ErrorInducedException("Error in command line " + curEnt.ScriptLine + ": (" + curEnt.CommandLine + "): Invalid variable save name: " + avarname.ToString());
                    }
                }
                if (curEnt.IsCallback)
                {
                    try
                    {
                        curEnt.Command.PreAdaptToCIL(values, i);
                    }
                    catch (ErrorInducedException ex)
                    {
                        throw new ErrorInducedException("On script line " + curEnt.ScriptLine + " (" + curEnt.CommandLine + "), early compile (PreAdapt) error occured: " + ex.Message);
                    }
                }
                curEnt.DBMode = values.DBMode;
            }
            values.LoadRunnable();
            ilgen.Emit(OpCodes.Ldfld, CompiledCommandRunnable.IndexField);
            ilgen.Emit(OpCodes.Switch, ccse.AdaptedILPoints);
            for (int i = 0; i < ccse.Entries.Length; i++)
            {
                ilgen.Comment($"Begin command code section {i}: {ccse.Entries[i].CommandLine}");
                ilgen.MarkLabel(ccse.AdaptedILPoints[i]);
                try
                {
                    ccse.Entries[i].Command.AdaptToCIL(values, i);
                }
                catch (ErrorInducedException ex)
                {
                    throw new ErrorInducedException("On script line " + ccse.Entries[i].ScriptLine + " (" + ccse.Entries[i].CommandLine + "), compile error (Adapt) occured: " + ex.Message);
                }
            }
            ilgen.MarkLabel(ccse.AdaptedILPoints[^ 1]);
            values.MarkCommand(ccse.Entries.Length);
            ilgen.Emit(OpCodes.Ret);
            typebuild_c.DefineMethodOverride(methodbuild_c, CompiledCommandRunnable.RunMethod);
            ConstructorBuilder ctor      = typebuild_c.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CONSTRUCTOR_PARAMS);
            ILGeneratorTracker ctorilgen = new ILGeneratorTracker(ctor.GetILGenerator(), new Type[] { typebuild_c }.JoinWith(CONSTRUCTOR_PARAMS), tname).ConfigureTracker(ccse.System);
            ILGens?.Add(ctorilgen);
            ctorilgen.Emit(OpCodes.Ldarg_0);                                   // Load 'this'
            ctorilgen.Emit(OpCodes.Ldarg_1);                                   // Load: CCSE
            ctorilgen.Emit(OpCodes.Stfld, CompiledCommandRunnable.EntryField); // Store it to the readonly field.
            for (int i = 0; i < values.EntryFields.Length; i++)
            {
                ctorilgen.Emit(OpCodes.Ldarg_0);                      // Load 'this'
                ctorilgen.Emit(OpCodes.Ldarg_2);                      // Load input array
                ctorilgen.Emit(OpCodes.Ldc_I4, i);                    // Load index in the array
                ctorilgen.Emit(OpCodes.Ldelem_Ref);                   // Load the value from the array
                ctorilgen.Emit(OpCodes.Stfld, values.EntryFields[i]); // Store it to the readonly field.
                FieldInfo[] argFields = values.ArgumentFields[i];
                if (argFields != null)
                {
                    for (int arg = 0; arg < argFields.Length; arg++)
                    {
                        if (argFields[arg] != null)
                        {
                            ctorilgen.Emit(OpCodes.Ldarg_0);                                         // Load 'this'
                            ctorilgen.Emit(OpCodes.Ldarg_0);                                         // Load 'this'
                            ctorilgen.Emit(OpCodes.Ldfld, values.EntryFields[i]);                    // Load the entry field
                            ctorilgen.Emit(OpCodes.Ldfld, CILAdaptationValues.Entry_ArgumentsField); // Load the arguments field
                            ctorilgen.Emit(OpCodes.Ldc_I4, arg);                                     // Load the argument index
                            ctorilgen.Emit(OpCodes.Ldelem_Ref);                                      // Load the argument value from the array
                            ctorilgen.Emit(OpCodes.Stfld, argFields[arg]);                           // Store it to the readonly field.
                        }
                    }
                }
            }
            for (int i = 0; i < specialFieldValues.Count; i++)
            {
                ctorilgen.Emit(OpCodes.Ldarg_0);                                        // Load 'this'
                ctorilgen.Emit(OpCodes.Ldarg_3);                                        // Load input array
                ctorilgen.Emit(OpCodes.Ldc_I4, i);                                      // Load index in the array
                ctorilgen.Emit(OpCodes.Ldelem_Ref);                                     // Load the value from the array
                ctorilgen.Emit(OpCodes.Castclass, specialFieldValues[i].Key.FieldType); // Guarantee the type.
                ctorilgen.Emit(OpCodes.Stfld, specialFieldValues[i].Key);               // Store it to the field.
            }
            ctorilgen.Emit(OpCodes.Ret);                                                // return
            Type     t_c         = typebuild_c.CreateType();
            object[] fieldValues = new object[specialFieldValues.Count];
            for (int i = 0; i < fieldValues.Length; i++)
            {
                fieldValues[i] = specialFieldValues[i].Value;
            }
            CompiledCommandRunnable runnable = Activator.CreateInstance(t_c, ccse, ccse.Entries, fieldValues) as CompiledCommandRunnable;
            ccse.ReferenceCompiledRunnable = runnable;
            ccse.Variables = values.Variables.ToArray();
            foreach (SingleCILVariable variable in ccse.Variables)
            {
                variable.Field = variable.Field.DeclaringType.GetField(variable.Field.Name); // Patch runtime field issues
            }
            ccse.VariableSetters = new Action <CompiledCommandRunnable, TemplateObject> [ccse.Variables.Length];
            runnable.EntryData   = new AbstractCommandEntryData[Created.Entries.Length];
            runnable.Debug       = script.Debug;
#if SAVE
            StringBuilder outp = new();
            for (int i = 0; i < ilgen.Codes.Count; i++)
            {
                outp.Append(ilgen.Codes[i].Key + ": " + ilgen.Codes[i].Value?.ToString()?.Replace("\n", "\\n")?.Replace("\r", "\\r") + "\n");
            }
            for (int n = 0; n < ILGens.Count; n++)
            {
                outp.Append("\n\n\n// -----\n\n\n");
                for (int i = 0; i < ILGens[n].Codes.Count; i++)
                {
                    outp.Append(ILGens[n].Codes[i].Key + ": " + ILGens[n].Codes[i].Value?.ToString()?.Replace("\n", "\\n")?.Replace("\r", "\\r") + "\n");
                }
            }
            System.IO.File.WriteAllText("script_" + tname + ".il", outp.ToString());
#endif
            return(Created);
        }
コード例 #4
0
        /// <summary>Adapts the var tag base for compiling.</summary>
        /// <param name="ccse">The compiled CSE.</param>
        /// <param name="tab">The TagArgumentBit.</param>
        /// <param name="i">The command index.</param>
        /// <param name="values">Related adaptation values.</param>
        public override TagReturnType Adapt(CompiledCommandStackEntry ccse, TagArgumentBit tab, int i, CILAdaptationValues values)
        {
            int index = (int)((tab.Bits[0].Variable.Bits[0] as TextArgumentBit).InputValue as IntegerTag).Internal;

            return(values.LocalVariableType(index));
        }