Esempio n. 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="tag"></param>
        /// <returns></returns>
        internal static Type GuessIfType(this CompileContext ctx, ElseifTag tag)
        {
            var types   = new List <Type>();
            var hasVoid = false;

            for (var i = 0; i < tag.Children.Count; i++)
            {
                var type = ctx.GuessType(tag.Children[i]);
                if (type.FullName == "System.Void")
                {
                    hasVoid = true;
                }
                else
                {
                    types.Add(type);
                }
            }
            if (types.Count == 1)
            {
                return(types[0]);
            }
            if (types.Count == 0 && hasVoid)
            {
                return(typeof(void));
            }
            return(typeof(string));
        }
        /// <summary>
        /// calling the tag.
        /// </summary>
        /// <param name="il">The <see cref="ILGenerator"/></param>
        /// <param name="ctx">The <see cref="CompileContext"/></param>
        /// <param name="tag">The <see cref="ITag"/></param>
        /// <param name="before">The action.</param>
        /// <param name="completed">The action of the completed.</param>
        public static void CallTag(this ILGenerator il,
                                   CompileContext ctx,
                                   ITag tag,
                                   Action <ILGenerator, bool, bool> before,//hasReturn,call
                                   Action <ILGenerator, Type> completed)
        {
            if (tag is EndTag _ ||
                tag is CommentTag _)
            {
                return;
            }
            if (tag is TextTag textTag)
            {
                if (string.IsNullOrEmpty(textTag.Text))
                {
                    return;
                }
                before?.Invoke(il, true, false);
                var text = textTag.ToString(ctx.OutMode);
                il.Emit(OpCodes.Ldstr, text);
                completed?.Invoke(il, typeof(string));
                return;
            }
            if (tag is ITypeTag typeTag)
            {
                if (typeTag.Value == null)
                {
                    return;
                }
                before?.Invoke(il, true, false);
                Type returnType = il.CallTypeTag(typeTag);
                completed?.Invoke(il, returnType);
                return;
            }
            if (tag is SetTag setTag)
            {
                ctx.Set(setTag.Name, ctx.GuessType(setTag.Value));
            }
            var m = ctx.CompileTag(tag);

            if (m.ReturnType.FullName != "System.Void")
            {
                before?.Invoke(il, true, true);
                il.Emit(OpCodes.Call, m);
                completed?.Invoke(il, m.ReturnType);
            }
            else
            {
                before?.Invoke(il, false, true);
                il.Emit(OpCodes.Call, m);
                completed?.Invoke(il, null);
            }
        }
Esempio n. 3
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tag"></param>
        /// <param name="ctx"></param>
        /// <returns></returns>
        internal static MethodInfo IfCompile <T>(this CompileContext ctx, T tag) where T : ElseifTag
        {
            var stringBuilderType = typeof(StringBuilder);
            var t        = tag;
            var type     = ctx.GuessType(t);
            var mb       = ctx.CreateReutrnMethod <T>(type);
            var il       = mb.GetILGenerator();
            var labelEnd = il.DefineLabel();

            il.DeclareLocal(type);
            il.DeclareLocal(stringBuilderType);
            il.Emit(OpCodes.Newobj, stringBuilderType.GetConstructor(Type.EmptyTypes));
            il.Emit(OpCodes.Stloc_1);
            for (var i = 0; i < t.Children.Count; i++)
            {
                il.CallTag(ctx, t.Children[i], (nil, hasReturn, needCall) =>
                {
                    if (hasReturn)
                    {
                        nil.Emit(OpCodes.Ldloc_1);
                    }
                    if (needCall)
                    {
                        nil.Emit(OpCodes.Ldarg_0);
                        nil.Emit(OpCodes.Ldarg_1);
                    }
                }, (nil, returnType) =>
                {
                    if (returnType == null)
                    {
                        return;
                    }
                    nil.StringAppend(ctx, returnType);
                    nil.Emit(OpCodes.Pop);
                });
            }
            il.Emit(OpCodes.Ldloc_1);
            il.Call(stringBuilderType, stringBuilderType.GetMethodInfo("ToString", Type.EmptyTypes));
            il.Emit(OpCodes.Stloc_0);

            il.MarkLabel(labelEnd);
            il.Emit(OpCodes.Ldloc_0);
            il.Emit(OpCodes.Ret);
            return(mb.GetBaseDefinition());
        }