/// <summary> /// Called when the item is an if 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(IfItem target) { if (target == null) throw new ArgumentNullException("target"); ILGenerator gen = compiler.CurrentGenerator; Label next = gen.DefineLabel(), end = gen.DefineLabel(); // if (!{Exp}.IsTrue) goto next; target.Exp.Accept(this); gen.Emit(OpCodes.Callvirt, typeof(ILuaValue).GetMethod("get_IsTrue")); gen.Emit(OpCodes.Brfalse, next); // {Block} target.Block.Accept(this); // goto end; gen.Emit(OpCodes.Br, end); // next: gen.MarkLabel(next); foreach (var item in target.Elses) { // if (!{item.Item1}.IsTrue) goto next; next = gen.DefineLabel(); item.Expression.Accept(this); gen.Emit(OpCodes.Callvirt, typeof(ILuaValue).GetMethod("get_IsTrue")); gen.Emit(OpCodes.Brfalse, next); // {item.Item2} item.Block.Accept(this); // goto end; gen.Emit(OpCodes.Br, end); // next: gen.MarkLabel(next); } if (target.ElseBlock != null) target.ElseBlock.Accept(this); // end: gen.MarkLabel(end); return target; }
/// <summary> /// Called when the item is an if 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(IfItem target) { if (target == null) throw new ArgumentNullException("target"); target.Exp.Accept(this); using (tree.Block(true)) target.Block.Accept(this); for (int i = 0; i < target.Elses.Count; i++) { using (tree.Block(true)) { target.Elses[i].Expression.Accept(this); target.Elses[i].Block.Accept(this); } } if (target.ElseBlock != null) { using (tree.Block(true)) target.ElseBlock.Accept(this); } return target; }
/// <summary> /// Reads an if statement from the input. /// </summary> /// <param name="input">Where to read input from.</param> /// <param name="prev">The token to append what is read into.</param> /// <returns>The object that was read.</returns> protected virtual IParseStatement ReadIf(ITokenizer input, ref Token prev) { var debug = input.Read(); // read 'if' IfItem i = new IfItem(); if (debug.Value != "if") throw new InvalidOperationException(string.Format(Resources.MustBeOn, "if", "ReadIf")); // read the initial expression i.Exp = ReadExp(input, ref debug); // read 'then' var name = Read(input, ref debug); if (name.Value != "then") throw new SyntaxException( string.Format(Resources.TokenInvalid, name.Value, "if"), input.Name, debug); // read the block var readBlock = ReadBlock(input, ref debug); i.Block = readBlock; // handle elseif(s) while ((name = input.Peek()).Value == "elseif") { Read(input, ref debug); // read 'elseif' // read the expression var readExp = ReadExp(input, ref debug); // read 'then' name = Read(input, ref debug); if (name.Value != "then") throw new SyntaxException( string.Format(Resources.TokenInvalid, name.Value, "elseif"), input.Name, debug); // read the block readBlock = ReadBlock(input, ref debug); i.AddElse(readExp, readBlock); } // handle else if (name.Value != "else" && name.Value != "end") throw new SyntaxException( string.Format(Resources.TokenInvalid, name.Value, "if"), input.Name, debug); if (name.Value == "else") { Read(input, ref debug); // read 'else' // read the block readBlock = ReadBlock(input, ref debug); i.ElseBlock = readBlock; } // read 'end' name = Read(input, ref debug); if (name.Value != "end") throw new SyntaxException( string.Format(Resources.TokenInvalid, name.Value, "if"), input.Name, debug); prev.Append(debug); i.Debug = debug; return i; }