/// <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; }
/// <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; }