/// <summary>
        /// Called when the item is an assignment item.
        /// </summary>
        /// <param name="target">The object that was passed to IParseItem.Visit.</param>
        /// <returns>The passed target or a modification of it.</returns>
        /// <exception cref="System.ArgumentNullException">If target is null.</exception>
        public IParseItem Visit(AssignmentItem target)
        {
            if (target == null)
                throw new ArgumentNullException("target");

            ILGenerator gen = compiler.CurrentGenerator;

            // ILuaValue[] loc = new ILuaValue[{target.Expressions.Count}];
            LocalBuilder loc = compiler.CreateArray(typeof(ILuaValue), target.Expressions.Count);
            // ILuaValue[] names = new ILuaValue[{target.Names.Count}];
            LocalBuilder names = compiler.CreateArray(typeof(ILuaValue), target.Names.Count);

            // have to evaluate the name indexer expressions before
            //   setting the values otherwise the following will fail:
            // i, t[i] = i+1, 20
            for (int i = 0; i < target.Names.Count; i++)
            {
                if (target.Names[i] is IndexerItem)
                {
                    IndexerItem item = (IndexerItem)target.Names[i];
                    gen.Emit(OpCodes.Ldloc, names);
                    gen.Emit(OpCodes.Ldc_I4, i);
                    item.Expression.Accept(this);
                    gen.Emit(OpCodes.Stelem, typeof(ILuaValue));
                }
            }

            for (int i = 0; i < target.Expressions.Count; i++)
            {
                // loc[{i}] = {exps[i]};
                gen.Emit(OpCodes.Ldloc, loc);
                gen.Emit(OpCodes.Ldc_I4, i);
                target.Expressions[i].Accept(this);
                gen.Emit(OpCodes.Stelem, typeof(ILuaValue));
            }

            // ILuaMultiValue exp = E.Runtime.CreateMultiValue(loc);
            LocalBuilder exp = compiler.CreateTemporary(typeof(ILuaMultiValue));
            gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(OpCodes.Callvirt, typeof(ILuaEnvironment).GetMethod("get_Runtime"));
            gen.Emit(OpCodes.Ldloc, loc);
            gen.Emit(OpCodes.Callvirt, typeof(ILuaRuntime).GetMethod("CreateMultiValue"));
            gen.Emit(OpCodes.Stloc, exp);
            compiler.RemoveTemporary(loc);

            for (int i = 0; i < target.Names.Count; i++)
            {
                AssignValue(target.Names[i], target.Local,
                    !(target.Names[i] is IndexerItem) ? (Action)null : () =>
                    {
                        // only called if the target object is an indexer item.

                        // $index = names[{i}];
                        gen.Emit(OpCodes.Ldloc, names);
                        gen.Emit(OpCodes.Ldc_I4, i);
                        gen.Emit(OpCodes.Ldelem, typeof(ILuaValue));
                    },
                    () =>
                    {
                        // $value = exp[{i}];
                        gen.Emit(OpCodes.Ldloc, exp);
                        gen.Emit(OpCodes.Ldc_I4, i);
                        gen.Emit(OpCodes.Callvirt, typeof(ILuaMultiValue).GetMethod("get_Item"));
                    });
            }
            compiler.RemoveTemporary(exp);
            compiler.RemoveTemporary(names);

            return target;
        }
        /// <summary>
        /// Called when the item is an assignment item.
        /// </summary>
        /// <param name="target">The object that was passed to IParseItem.Visit.</param>
        /// <returns>The passed target or a modification of it.</returns>
        /// <exception cref="System.ArgumentNullException">If target is null.</exception>
        public IParseItem Visit(AssignmentItem target)
        {
            if (target == null)
                throw new ArgumentNullException("target");

            if (target.Local)
            {
                tree.DefineLocal(target.Names.Select(i => i as NameItem));
            }
            else
            {
                foreach (var item in target.Names)
                    item.Accept(this);
            }

            foreach (var item in target.Expressions)
                item.Accept(this);

            return target;
        }
Example #3
0
        /// <summary>
        /// Reads an assignment statement from the input.  The input is currently
        /// after the first name, on the comma or equal sign.  The debug token
        /// contains the name and should contain the entire statement.
        /// </summary>
        /// <param name="input">Where to read input from.</param>
        /// <param name="debug">Currently contains the first name, and after
        /// should contain the entire statement.</param>
        /// <param name="local">True if this is a local definition, otherwise false.</param>
        /// <param name="variable">The first variable that was read.</param>
        /// <returns>The statement that was read.</returns>
        protected virtual AssignmentItem ReadAssignment(ITokenizer input, ref Token debug, bool local, IParseVariable variable)
        {
            // read each of the variable names
            AssignmentItem assign = new AssignmentItem(local);
            assign.AddName(variable);
            while (input.Peek().Value == ",")
            {
                Read(input, ref debug); // read ','

                // read the left-hand-expression
                var exp = ReadExp(input, ref debug);
                if ((local && !(exp is NameItem)) || (!local && !(exp is IParseVariable)))
                    throw new SyntaxException(Resources.NameOrExpForVar, input.Name, debug);
                assign.AddName((IParseVariable)exp);
            }

            // read the initial values
            if (input.Peek().Value == "=")
            {
                Read(input, ref debug); // read '='
                assign.AddItem(ReadExp(input, ref debug));

                while (input.Peek().Value == ",")
                {
                    Read(input, ref debug); // read ','
                    assign.AddItem(ReadExp(input, ref debug));
                }
            }
            else if (!local)
                throw new SyntaxException(
                    string.Format(Resources.InvalidDefinition, "assignment"),
                    input.Name, debug);

            assign.Debug = debug;
            return assign;
        }