Exemplo n.º 1
0
 /// <summary>
 /// Implements a function definition based on a given function definition.
 /// </summary>
 /// <param name="funcName">The simple name of the function, can be null.</param>
 /// <param name="visitor">The current visitor object.</param>
 /// <param name="function">The function to generate for.</param>
 public void ImplementFunction(IParseItemVisitor visitor, FuncDefItem function, string funcName)
 {
     NameItem[] args = function.Arguments.ToArray();
     if (function.InstanceName != null)
     {
         args = new[] { new NameItem("self") }
     }
Exemplo n.º 2
0
        /// <summary>
        /// Dispatches to the specific visit method for this item type.
        /// </summary>
        /// <param name="visitor">The visitor object.</param>
        /// <returns>The object returned from the specific IParseItemVisitor method.</returns>
        /// <exception cref="System.ArgumentNullException">If visitor is null.</exception>
        public IParseItem Accept(IParseItemVisitor visitor)
        {
            if (visitor == null)
                throw new ArgumentNullException("visitor");

            return visitor.Visit(this);
        }
Exemplo n.º 3
0
        public IParseItem Accept(IParseItemVisitor visitor)
        {
            if (visitor == null)
            {
                throw new ArgumentNullException(nameof(visitor));
            }

            return(visitor.Visit(this));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Implements a function definition based on a given function definition.
        /// </summary>
        /// <param name="funcName">The simple name of the function, can be null.</param>
        /// <param name="visitor">The current visitor object.</param>
        /// <param name="function">The function to generate for.</param>
        public void ImplementFunction(IParseItemVisitor visitor, FuncDefItem function, string funcName)
        {
            NameItem[] args = function.Arguments.ToArray();
            if (function.InstanceName != null)
                args = new[] { new NameItem("self") }.Union(args).ToArray();

            // ILuaMultiValue function(ILuaEnvironment E, ILuaMultiValue args, ILuaValue target, bool memberCall);
            funcName = funcName ?? "<>__" + (_mid++);
            string name = curNest.members.Contains(funcName) ? funcName + "_" + (_mid++) : funcName;
            MethodBuilder mb = curNest.TypeDef.DefineMethod(name, MethodAttributes.Public,
                typeof(ILuaMultiValue),
                new Type[] { typeof(ILuaEnvironment), typeof(ILuaMultiValue), typeof(ILuaValue), typeof(bool) });
            var gen = mb.GetILGenerator();
            curNest = new NestInfo(curNest, gen, function.FunctionInformation.CapturedLocals,
                function.FunctionInformation.HasNested, function.FunctionInformation.CapturesParrent);

            // if this is an instance method, create a BaseAccessor object to help types.
            if (function.InstanceName != null)
            {
                // TODO: Add base accessor back.
                //var field = curNest.DefineLocal(new NameItem("base"));
            }

            // If this was an instance call, the first Lua argument is the 'target';
            // otherwise the it is the zero'th index in args.
            // int c = 0;
            var c = gen.DeclareLocal(typeof(int));
            if (args.Length > 0)
            {
                var field = curNest.DefineLocal(args[0]);
                var end = gen.DefineLabel();
                var else_ = gen.DefineLabel();

                // if (!memberCall) c = 1;
                // {field_0} = (memberCall ? target : args[0]);
                field.StartSet();
                  gen.Emit(OpCodes.Ldarg, 4);
                  gen.Emit(OpCodes.Brfalse, else_);
                    gen.Emit(OpCodes.Ldarg_3);
                    gen.Emit(OpCodes.Br, end);
                  gen.MarkLabel(else_);
                    gen.Emit(OpCodes.Ldc_I4_1);
                    gen.Emit(OpCodes.Stloc, c);
                    gen.Emit(OpCodes.Ldarg_2);
                    if (args[0].Name != "...")
                    {
                        gen.Emit(OpCodes.Ldc_I4_0);
                        gen.Emit(OpCodes.Callvirt, typeof(ILuaMultiValue).GetMethod("get_Item"));
                    }
                    else
                    {
                        if (args.Length != 1)
                            throw new InvalidOperationException("Variable arguments (...) only valid at end of argument list.");
                    }
                  gen.MarkLabel(end);
                field.EndSet();
            }

            for (int i = 1; i < args.Length; i++)
            {
                var field = curNest.DefineLocal(args[i]);

                if (args[i].Name == "...")
                {
                    if (i != args.Length - 1)
                        throw new InvalidOperationException("Variable arguments (...) only valid at end of argument list.");

                    // {field} = E.Runtime.CreateMultiValue(args.Skip({args.Length - 1});
                    field.StartSet();
                    gen.Emit(OpCodes.Ldarg_1);
                    gen.Emit(OpCodes.Callvirt, typeof(ILuaEnvironment).GetMethod("get_Runtime"));
                    gen.Emit(OpCodes.Ldarg_2);
                    gen.Emit(OpCodes.Ldc_I4, args.Length - 1);
                    gen.Emit(OpCodes.Call, typeof(Enumerable).GetMethod("Skip").MakeGenericMethod(typeof(object)));
                    gen.Emit(OpCodes.Callvirt, typeof(ILuaRuntime).GetMethod("CreateMultiValue"));
                    field.EndSet();
                }
                else
                {
                    // {field} = args[{i - 1} + c];
                    field.StartSet();
                    gen.Emit(OpCodes.Ldarg_2);
                    gen.Emit(OpCodes.Ldc_I4, i-1);
                    gen.Emit(OpCodes.Ldloc, c);
                    gen.Emit(OpCodes.Add);
                    gen.Emit(OpCodes.Callvirt, typeof(ILuaMultiValue).GetMethod("get_Item"));
                    field.EndSet();
                }
            }

            function.Block.Accept(visitor);

            if (curNest.TypeDef != null)
                curNest.TypeDef.CreateType();

            curNest = curNest.Parrent;
            // push a pointer to the new method onto the stack of the previous nest method
            //   the above line restores the nest to the previous state and this code will
            //   push the new method.
            //! push E.Runtime.CreateFunctionValue({name}, {nest.TypeDef}.GetMethod({name}), {nest.ThisInst != null ? nest.NestInst : this} );
            curNest.Generator.Emit(OpCodes.Ldarg_1);
            curNest.Generator.Emit(OpCodes.Callvirt, typeof(ILuaEnvironment).GetMethod("get_Runtime"));
            curNest.Generator.Emit(OpCodes.Ldstr, name);
            curNest.Generator.Emit(OpCodes.Ldtoken, curNest.TypeDef);
            curNest.Generator.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) }));
            curNest.Generator.Emit(OpCodes.Ldstr, name);
            curNest.Generator.Emit(OpCodes.Callvirt, typeof(Type).GetMethod("GetMethod", new[] { typeof(string) }));
            if (curNest.ThisInst != null)
                curNest.Generator.Emit(OpCodes.Ldloc, curNest.ThisInst);
            else
                curNest.Generator.Emit(OpCodes.Ldarg_0);
            curNest.Generator.Emit(OpCodes.Callvirt, typeof(ILuaRuntime).GetMethod("CreateImplementationFunction"));
        }
Exemplo n.º 5
0
 public IParseItem Accept(IParseItemVisitor visitor)
 {
     gen.Emit(OpCodes.Ldloc, prefix);
     return(this);
 }
Exemplo n.º 6
0
        /// <summary>
        /// Implements a function definition based on a given function definition.
        /// </summary>
        /// <param name="funcName">The simple name of the function, can be null.</param>
        /// <param name="visitor">The current visitor object.</param>
        /// <param name="function">The function to generate for.</param>
        public void ImplementFunction(IParseItemVisitor visitor, FuncDefItem function,
                                      string funcName)
        {
            NameItem[] args = function.Arguments.ToArray();
            if (function.InstanceName != null)
            {
                args = new[] { new NameItem("self") }.Concat(args).ToArray();
            }

            // ILuaMultiValue function(ILuaEnvironment E, ILuaMultiValue args, ILuaValue target,
            //                         bool memberCall);
            funcName ??= "<>__" + (_mid++);
            string        name = _curNest.Members.Contains(funcName) ? funcName + "_" + (_mid++) : funcName;
            MethodBuilder mb   = _curNest.TypeDef.DefineMethod(
                name, MethodAttributes.Public, typeof(ILuaMultiValue),
                new Type[] {
                typeof(ILuaEnvironment), typeof(ILuaMultiValue), typeof(ILuaValue), typeof(bool)
            });
            var gen = mb.GetILGenerator();

            _curNest = new NestInfo(
                _curNest, gen, function.FunctionInformation.CapturedLocals,
                function.FunctionInformation.HasNested, function.FunctionInformation.CapturesParent);

            // if this is an instance method, create a BaseAccessor object to help types.
            if (function.InstanceName != null)
            {
                // TODO: Add base accessor back.
                //var field = curNest.DefineLocal(new NameItem("base"));
            }

            // If this was an instance call, the first Lua argument is the 'target';
            // otherwise the it is the zero'th index in args.
            // int c = 0;
            var c = gen.DeclareLocal(typeof(int));

            if (args.Length > 0)
            {
                var field = _curNest.DefineLocal(args[0]);
                var end   = gen.DefineLabel();
                var else_ = gen.DefineLabel();

                // if (!memberCall) c = 1;
                // {field_0} = (memberCall ? target : args[0]);
                field.StartSet();
                gen.Emit(OpCodes.Ldarg, 4);
                gen.Emit(OpCodes.Brfalse, else_);
                gen.Emit(OpCodes.Ldarg_3);
                gen.Emit(OpCodes.Br, end);
                gen.MarkLabel(else_);
                gen.Emit(OpCodes.Ldc_I4_1);
                gen.Emit(OpCodes.Stloc, c);
                gen.Emit(OpCodes.Ldarg_2);
                if (args[0].Name != "...")
                {
                    gen.Emit(OpCodes.Ldc_I4_0);
                    gen.Emit(OpCodes.Callvirt, typeof(ILuaMultiValue).GetMethod("get_Item"));
                }
                else
                {
                    if (args.Length != 1)
                    {
                        throw new InvalidOperationException(
                                  "Variable arguments (...) only valid at end of argument list.");
                    }
                }
                gen.MarkLabel(end);
                field.EndSet();
            }

            for (int i = 1; i < args.Length; i++)
            {
                var field = _curNest.DefineLocal(args[i]);

                if (args[i].Name == "...")
                {
                    if (i != args.Length - 1)
                    {
                        throw new InvalidOperationException(
                                  "Variable arguments (...) only valid at end of argument list.");
                    }

                    // {field} = E.Runtime.CreateMultiValue(args.Skip({args.Length - 1});
                    field.StartSet();
                    gen.Emit(OpCodes.Ldarg_1);
                    gen.Emit(
                        OpCodes.Callvirt,
                        typeof(ILuaEnvironment).GetProperty(nameof(ILuaEnvironment.Runtime)).GetGetMethod());
                    gen.Emit(OpCodes.Ldarg_2);
                    gen.Emit(OpCodes.Ldc_I4, args.Length - 1);
                    gen.Emit(OpCodes.Call,
                             typeof(Enumerable).GetMethod(nameof(Enumerable.Skip))
                             .MakeGenericMethod(typeof(object)));
                    gen.Emit(OpCodes.Callvirt,
                             typeof(ILuaRuntime).GetMethod(nameof(ILuaRuntime.CreateMultiValue)));
                    field.EndSet();
                }
                else
                {
                    // {field} = args[{i - 1} + c];
                    field.StartSet();
                    gen.Emit(OpCodes.Ldarg_2);
                    gen.Emit(OpCodes.Ldc_I4, i - 1);
                    gen.Emit(OpCodes.Ldloc, c);
                    gen.Emit(OpCodes.Add);
                    gen.Emit(OpCodes.Callvirt, typeof(ILuaMultiValue).GetMethod("get_Item"));
                    field.EndSet();
                }
            }

            function.Block.Accept(visitor);

            if (_curNest.TypeDef != null)
            {
                _curNest.TypeDef.CreateType();
            }

            _curNest = _curNest.Parent;
            // push a pointer to the new method onto the stack of the previous nest method
            //   the above line restores the nest to the previous state and this code will
            //   push the new method.
            //! push E.Runtime.CreateFunctionValue({name}, {nest.TypeDef}.GetMethod({name}),
            //                                     {nest.ThisInst != null ? nest.NestInst : this} );
            _curNest.Generator.Emit(OpCodes.Ldarg_1);
            _curNest.Generator.Emit(
                OpCodes.Callvirt,
                typeof(ILuaEnvironment).GetProperty(nameof(ILuaEnvironment.Runtime)).GetGetMethod());
            _curNest.Generator.Emit(OpCodes.Ldstr, name);
            _curNest.Generator.Emit(OpCodes.Ldtoken, _curNest.TypeDef);
            _curNest.Generator.Emit(
                OpCodes.Call,
                typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle),
                                       new Type[] { typeof(RuntimeTypeHandle) }));
            _curNest.Generator.Emit(OpCodes.Ldstr, name);
            _curNest.Generator.Emit(
                OpCodes.Callvirt,
                typeof(Type).GetMethod(nameof(Type.GetMethod), new[] { typeof(string) }));
            if (_curNest.ThisInst != null)
            {
                _curNest.Generator.Emit(OpCodes.Ldloc, _curNest.ThisInst);
            }
            else
            {
                _curNest.Generator.Emit(OpCodes.Ldarg_0);
            }

            _curNest.Generator.Emit(
                OpCodes.Callvirt,
                typeof(ILuaRuntime).GetMethod(nameof(ILuaRuntime.CreateImplementationFunction)));
        }
Exemplo n.º 7
0
 public IParseItem Accept(IParseItemVisitor visitor)
 {
     gen.Emit(OpCodes.Ldloc, prefix);
     return this;
 }