/// <summary> /// Loads a LuaChunk from a pre-loaded string. /// </summary> /// <param name="chunk">The Lua script to load from.</param> /// <param name="name">The name to give the chunk.</param> /// <param name="override">True to load the file even if it is in the cache, otherwise false.</param> /// <param name="index">Stores the index of the loaded module.</param> /// <returns>The loaded chunk.</returns> /// <exception cref="System.ArgumentNullException">If chunk is null.</exception> /// <exception cref="ModMaker.Lua.Parser.SyntaxException">If there is /// syntax errors in the file.</exception> public ILuaValue LoadText(string chunk, string name, bool @override, out int index) { if (chunk == null) { throw new ArgumentNullException(nameof(chunk)); } lock (this) { var temp = Environment.Parser.UseCache; Environment.Parser.UseCache = !@override; var ret = Environment.CodeCompiler.Compile( Environment, PlainParser.Parse(Environment.Parser, chunk, name), name); Environment.Parser.UseCache = temp; if (!_chunks.Contains(ret)) { _chunks.Add(ret); } index = _chunks.IndexOf(ret); return(ret); } }
/// <summary> /// Gets a variables from a given Lua file using the given environment. /// </summary> /// <param name="env">The environment used to load the chunk.</param> /// <param name="path">The path to the Lua file.</param> /// <param name="names">The names of the variable to get.</param> /// <returns>The values of the variables or null if not found. The array is /// never null.</returns> /// <exception cref="System.ArgumentException">If path is not in the /// correct format -or- if names contains a null string.</exception> /// <exception cref="System.ArgumentNullException">If any arguments are null.</exception> /// <exception cref="System.IO.FileNotFoundException">If the given file /// could not be found.</exception> /// <exception cref="System.InvalidCastException">If one of the variables /// could not be converted to the given type.</exception> /// <exception cref="ModMaker.Lua.Parser.SyntaxException">If there are /// syntax errors in the file.</exception> public static T[] GetVariables <T>(ILuaEnvironment env, string path, params string[] names) { if (names == null) { throw new ArgumentNullException(nameof(names)); } if (path == null) { throw new ArgumentNullException(nameof(path)); } if (env == null) { throw new ArgumentNullException(nameof(env)); } if (names.Contains(null)) { throw new ArgumentException(string.Format(Resources.CannotContainNull, nameof(names))); } path = Path.GetFullPath(path); if (!File.Exists(path)) { throw new FileNotFoundException(); } var parsed = PlainParser.Parse( env.Parser, File.ReadAllText(path), Path.GetFileNameWithoutExtension(path)); var ret = env.CodeCompiler.Compile(env, parsed, Path.GetFileNameWithoutExtension(path)); ret.Invoke(LuaNil.Nil, false, -1, LuaMultiValue.Empty); return(names.Select(s => env[s].As <T>()).ToArray()); }
/// <summary> /// Loads a LuaChunk from a specified stream. /// </summary> /// <param name="stream">The stream to load the script from.</param> /// <param name="name">The name to give the chunk.</param> /// <param name="override">True to load the file even if it is in the /// cache, otherwise false.</param> /// <param name="index">Stores the index of the loaded module.</param> /// <returns>The loaded chunk.</returns> /// <exception cref="System.ArgumentNullException">If stream is null.</exception> /// <exception cref="ModMaker.Lua.Parser.SyntaxException">If there is /// syntax errors in the file.</exception> public ILuaValue Load(Stream stream, string name, bool @override, out int index) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } using (TextReader c = new StreamReader(stream)) { lock (this) { var temp = Environment.Parser.UseCache; Environment.Parser.UseCache = !@override; var ret = Environment.CodeCompiler.Compile( Environment, PlainParser.Parse(Environment.Parser, c.ReadToEnd(), name), name); Environment.Parser.UseCache = temp; if (!_chunks.Contains(ret)) { _chunks.Add(ret); } index = _chunks.IndexOf(ret); return(ret); } } }
protected override ILuaMultiValue _invokeInternal(ILuaMultiValue args) { if (args.Count < 1) { throw new ArgumentException("Expecting one argument to function 'dofile'."); } string file = args[0].GetValue() as string; if (string.IsNullOrEmpty(file)) { throw new ArgumentException("First argument to 'loadfile' must be a file path."); } if (!File.Exists(file)) { throw new FileNotFoundException("Unable to locate file at '" + file + "'."); } string chunk = File.ReadAllText(file); var parsed = PlainParser.Parse(_environment.Parser, chunk, Path.GetFileNameWithoutExtension(file)); var r = _environment.CodeCompiler.Compile(_environment, parsed, null); return(r.Invoke(LuaNil.Nil, false, -1, LuaMultiValue.Empty)); }
IParseItem _parseBlock(string input) { PlainParser target = new PlainParser(); var encoding = Encoding.UTF8; var stream = new MemoryStream(encoding.GetBytes(input)); return(target.Parse(stream, encoding, null)); }
protected override ILuaMultiValue _invokeInternal(ILuaMultiValue args) { if (args.Count < 1) { throw new ArgumentException("Expecting at least one argument to function 'load'."); } ILuaValue ld = args[0]; string chunk; if (ld.ValueType == LuaValueType.Function) { chunk = ""; while (true) { var ret = ld.Invoke(LuaNil.Nil, false, -1, _environment.Runtime.CreateMultiValue()); if (ret[0].ValueType == LuaValueType.String) { if (string.IsNullOrEmpty(ret[0].GetValue() as string)) { break; } else { chunk += ret[0].GetValue() as string; } } else { break; } } } else if (ld.ValueType == LuaValueType.String) { chunk = ld.GetValue() as string; } else { throw new ArgumentException("First argument to 'load' must be a string or a method."); } try { var parsed = PlainParser.Parse(_environment.Parser, chunk, null); return(_environment.Runtime.CreateMultiValue( _environment.CodeCompiler.Compile(_environment, parsed, null))); } catch (Exception e) { return(_environment.Runtime.CreateMultiValueFromObj(null, e.Message)); } }
protected override ILuaMultiValue _invokeInternal(ILuaMultiValue args) { if (args.Count < 1) { throw new ArgumentException("Expecting at least one argument to function 'loadfile'."); } string file = args[0].GetValue() as string; string mode = args[1].GetValue() as string; if (string.IsNullOrEmpty(file)) { throw new ArgumentException("First argument to 'loadfile' must be a file path."); } if (!File.Exists(file)) { throw new FileNotFoundException("Unable to locate file at '" + file + "'."); } if (string.IsNullOrEmpty(mode) && args.Count > 1) { throw new ArgumentException("Second argument to 'loadfile' must be a string mode."); } if (mode != "type") { throw new ArgumentException("The only mode supported by loadfile is 'type'."); } string chunk = File.ReadAllText(file); try { var parsed = PlainParser.Parse(_environment.Parser, chunk, Path.GetFileNameWithoutExtension(file)); return(_environment.Runtime.CreateMultiValue( _environment.CodeCompiler.Compile(_environment, parsed, null))); } catch (Exception e) { return(_environment.Runtime.CreateMultiValueFromObj(null, e.Message)); } }
ILuaValue _processFile(string path, string name, string partname, ILuaEnvironment env, List <Exception> exceptions) { if (path.EndsWith(".lua", StringComparison.OrdinalIgnoreCase)) { if (!this.AllowLua) { exceptions.Add(new InvalidOperationException( $"Cannot load file '{path}' because ModuleBinder.AllowLua is set to false.")); return(null); } var item = PlainParser.Parse( env.Parser, File.ReadAllText(path), System.IO.Path.GetFileNameWithoutExtension(path)); var chunk = env.CodeCompiler.Compile(env, item, null); return(chunk.Invoke(LuaNil.Nil, false, -1, LuaMultiValue.Empty).Single()); } else if (path.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) { var aname = AssemblyName.GetAssemblyName(path); if (WhitelistPublicKeys != null) { bool valid = false; foreach (var key in WhitelistPublicKeys) { if (key == null) { if (aname.GetPublicKey() == null) { valid = true; } } else { if (aname.GetPublicKey().ToStringBase16().ToLowerInvariant() == key.ToLowerInvariant()) { valid = true; } } } if (!valid) { exceptions.Add(new InvalidOperationException( "Cannot load file '" + path + "' because the assembly's public key is not in the white-list.")); return(null); } } // Process the assembly if (AllowAssemblies) { var a = Assembly.LoadFrom(path); var types = a.GetTypes(); if (types == null || types.Length == 0) { exceptions.Add(new InvalidOperationException( "Cannot load file '" + path + "' because it does not define any types.")); return(null); } else if (types.Length > 1) { HashSet <Type> validTypes = new HashSet <Type>(); bool matchesName(Type t) => t.Name == name || t.Name == partname || t.FullName == name || t.FullName == partname; foreach (var item in types.Where(t => matchesName(t) && _validType(t))) { validTypes.Add(item); } if (validTypes.Count > 1) { exceptions.Add(new InvalidOperationException( $"Cannot load file '{path}' because more than one type matches the given name.")); return(null); } else if (validTypes.Count == 0) { exceptions.Add(new InvalidOperationException( $"Cannot load file '{path}' because no types match the given name.")); return(null); } else { return(_processType(validTypes.First(), env)); } } else { return(_processType(types[0], env)); } } } return(null); }
public void GenralParse() { PlainParser target = new PlainParser(); TextElementEnumerator input1 = StringInfo.GetTextElementEnumerator( @"local a = 12 t = { [34]= function() print(i) end } function Some(a, ...) a, b, c = ... for i= 12, 23 do print(i) end end" ); IParseItem actual; actual = target.Parse(new Tokenizer(input1, null), null, null); // check the main block BlockItem block = actual as BlockItem; Assert.IsInstanceOf <BlockItem>(actual); Assert.IsNotNull(block.Children); Assert.AreEqual(3, block.Children.Count, "Block.Children.Count"); ValidateDebug(block.Debug, "Block", "local a = 12 t = { [ 34 ] = function ( ) print ( i ) end } function Some ( a , ... ) a , b , c = ... for i = 12 , 23 do print ( i ) end end", 1, 1, 8, 4); // check the return statement of the main block { ReturnItem ret = block.Return; Assert.IsInstanceOf <ReturnItem>(block.Return); ValidateDebug(ret.Debug, "Block.Return", null, 0, 0, 0, 0); Assert.IsNotNull(ret.Expressions); Assert.AreEqual(0, ret.Expressions.Count); } // local a = 12 { AssignmentItem init = block.Children[0] as AssignmentItem; Assert.IsNotNull(init, "Block.Children[0]"); Assert.AreEqual(true, init.Local); ValidateDebug(init.Debug, "Block.Children[0]", "local a = 12", 1, 1, 1, 13); // check the names { Assert.IsNotNull(init.Names, "Block.Children[0].Names"); Assert.AreEqual(1, init.Names.Count, "Block.Children[0].Names.Count"); NameItem name = init.Names[0] as NameItem; Assert.IsNotNull(name, "Block.Children[0].Names[0]"); Assert.AreEqual("a", name.Name, "Block.Children[0].Names[0].Name"); ValidateDebug(name.Debug, "Block.Children[0].Names[0]", "a", 1, 7, 1, 8); } // check the expressions { Assert.IsNotNull(init.Expressions, "Block.Children[0].Expressions"); Assert.AreEqual(1, init.Expressions.Count, "Block.Children[0].Expressions.Count"); LiteralItem literal = init.Expressions[0] as LiteralItem; Assert.IsNotNull(literal, "Block.Children[0].Expressions[0]"); Assert.AreEqual(12.0, literal.Value, "Block.Children[0].Expressions[0].Value"); ValidateDebug(literal.Debug, "Block.Children[0].Expressions[0]", "12", 1, 11, 1, 13); } } // t = { [34]= function() print(i) end } { AssignmentItem init = block.Children[1] as AssignmentItem; Assert.IsNotNull(init, "Block.Children[1]"); Assert.AreEqual(false, init.Local); ValidateDebug(init.Debug, "Block.Children[1]", "t = { [ 34 ] = function ( ) print ( i ) end }", 2, 1, 2, 38); // check the names { Assert.IsNotNull(init.Names, "Block.Children[1].Names"); Assert.AreEqual(1, init.Names.Count, "Block.Children[1].Names.Count"); NameItem name = init.Names[0] as NameItem; Assert.IsNotNull(name, "Block.Children[1].Names[0]"); Assert.AreEqual("t", name.Name, "Block.Children[1].Names[0].Name"); ValidateDebug(name.Debug, "Block.Children[1].Names[0]", "t", 2, 1, 2, 2); } // check the expressions { Assert.IsNotNull(init.Expressions, "Block.Children[1].Expressions"); Assert.AreEqual(1, init.Expressions.Count, "Block.Children[1].Expressions.Count"); TableItem table = init.Expressions[0] as TableItem; Assert.IsNotNull(table, "Block.Children[1].Expressions[0]"); ValidateDebug(table.Debug, "Block.Children[1].Expressions[0]", "{ [ 34 ] = function ( ) print ( i ) end }", 2, 5, 2, 38); Assert.IsNotNull(table.Fields, "Block.Children[1].Expressions[0].Fields"); Assert.AreEqual(1, table.Fields.Count, "Block.Children[1].Expressions[0].Fields.Count"); var field = table.Fields[0]; { LiteralItem literal = field.Key as LiteralItem; Assert.IsNotNull(literal, "Block.Children[1].Expressions[0].Fields[0].Item1"); Assert.AreEqual(34.0, literal.Value, "Block.Children[1].Expressions[0].Fields[0].Item1.Value"); ValidateDebug(literal.Debug, "Block.Children[1].Expressions[0].Fields[0].Item1", "34", 2, 8, 2, 10); } { FuncDefItem func = field.Value as FuncDefItem; Assert.IsNotNull(func, "Block.Children[1].Expressions[0].Fields[0].Item2"); Assert.IsNull(func.InstanceName, "Block.Children[1].Expressions[0].Fields[0].Item2.InstanceName"); Assert.IsNull(func.Prefix, "Block.Children[1].Expressions[0].Fields[0].Item2.Prefix"); Assert.AreEqual(false, func.Local, "Block.Children[1].Expressions[0].Fields[0].Item2.Local"); Assert.IsNull(func.FunctionInformation, "Block.Children[1].Expressions[0].Fields[0].Item2.FunctionInformation"); ValidateDebug(func.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2", "function ( ) print ( i ) end", 2, 13, 2, 36); // validate the block { BlockItem funcBlock = func.Block; Assert.IsNotNull(funcBlock, "Block.Children[1].Expressions[0].Fields[0].Item2.Block"); ValidateDebug(funcBlock.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2.Block", "print ( i )", 2, 24, 2, 32); // validate the return { ReturnItem ret = funcBlock.Return; Assert.IsNotNull(ret, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Return"); ValidateDebug(ret.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Return", null, 0, 0, 0, 0); Assert.IsNotNull(ret.Expressions, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Return.Expressions"); Assert.AreEqual(0, ret.Expressions.Count, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Return.Expressions.Count"); } // validate the statement { Assert.IsNotNull(funcBlock.Children, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children"); Assert.AreEqual(1, funcBlock.Children.Count, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children.Count"); // print ( i ) { FuncCallItem call = funcBlock.Children[0] as FuncCallItem; Assert.IsNotNull(call, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0]"); Assert.AreEqual(true, call.Statement, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Statement"); Assert.IsNull(call.InstanceName, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].InstanceName"); ValidateDebug(call.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0]", "print ( i )", 2, 24, 2, 32); // validate the prefix { NameItem name = call.Prefix as NameItem; Assert.IsNotNull(call.Prefix, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Prefix"); Assert.AreEqual("print", name.Name, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Prefix.Name"); ValidateDebug(name.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Prefix.Name", "print", 2, 24, 2, 29); } // validate the arguments { Assert.IsNotNull(call.Arguments, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Arguments"); Assert.AreEqual(1, call.Arguments.Count, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Arguments.Count"); NameItem name = call.Arguments[0].Expression as NameItem; Assert.IsNotNull(name, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Arguments[0]"); Assert.AreEqual("i", name.Name, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Arguments[0].Name"); ValidateDebug(name.Debug, "Block.Children[1].Expressions[0].Fields[0].Item2.Block.Children[0].Arguments[0]", "i", 2, 30, 2, 31); } } } } } } } // function Some(a, ...) { FuncDefItem func = block.Children[2] as FuncDefItem; Assert.IsNotNull(func, "Block.Children[2]"); Assert.AreEqual(false, func.Local, "Block.Children[2].Local"); Assert.IsNull(func.InstanceName, "Block.Children[2].InstanceName"); ValidateDebug(func.Debug, "Block.Children[2]", "function Some ( a , ... ) a , b , c = ... for i = 12 , 23 do print ( i ) end end", 3, 1, 8, 4); // validate the block { BlockItem someBlock = func.Block; ValidateDebug(someBlock.Debug, "Block.Children[2].Block", "a , b , c = ... for i = 12 , 23 do print ( i ) end", 4, 5, 7, 8); // validate the return { ReturnItem ret = someBlock.Return; Assert.IsNotNull(ret, "Block.Children[2].Block.Return"); ValidateDebug(ret.Debug, "Block.Children[2].Block.Return", null, 0, 0, 0, 0); Assert.IsNotNull(ret.Expressions, "Block.Children[2].Block.Return.Expressions"); Assert.AreEqual(0, ret.Expressions.Count, "Block.Children[2].Block.Return.Expressions.Count"); } // check the children { Assert.IsNotNull(someBlock.Children, "Block.Children[2].Block.Children"); Assert.AreEqual(2, someBlock.Children.Count, "Block.Children[2].Block.Children.Count"); // a , b , c = ... { AssignmentItem varInit = someBlock.Children[0] as AssignmentItem; Assert.IsNotNull(varInit, "Block.Children[2].Block.Children[0]"); Assert.AreEqual(false, varInit.Local, "Block.Children[2].Block.Children[0].Local"); ValidateDebug(varInit.Debug, "Block.Children[2].Block.Children[0]", "a , b , c = ...", 4, 5, 4, 18); // validate the names { Assert.IsNotNull(varInit.Names, "Block.Children[2].Block.Children[0].Names"); Assert.AreEqual(3, varInit.Names.Count, "Block.Children[2].Block.Children[0].Names.Count"); NameItem name = varInit.Names[0] as NameItem; Assert.IsNotNull(name, "Block.Children[2].Block.Children[0].Names[0]"); Assert.AreEqual(name.Name, "a", "Block.Children[2].Block.Children[0].Names[0].Name"); ValidateDebug(name.Debug, "Block.Children[2].Block.Children[0].Names[0]", "a", 4, 5, 4, 6); name = varInit.Names[1] as NameItem; Assert.IsNotNull(name, "Block.Children[2].Block.Children[0].Names[1]"); Assert.AreEqual(name.Name, "b", "Block.Children[2].Block.Children[0].Names[1].Name"); ValidateDebug(name.Debug, "Block.Children[2].Block.Children[0].Names[1]", "b", 4, 8, 4, 9); name = varInit.Names[2] as NameItem; Assert.IsNotNull(name, "Block.Children[2].Block.Children[0].Names[2]"); Assert.AreEqual(name.Name, "c", "Block.Children[2].Block.Children[0].Names[2].Name"); ValidateDebug(name.Debug, "Block.Children[2].Block.Children[0].Names[2]", "c", 4, 11, 4, 12); } // validate the expressions { Assert.IsNotNull(varInit.Expressions, "Block.Children[2].Block.Children[0].Expressions"); Assert.AreEqual(1, varInit.Expressions.Count, "Block.Children[2].Block.Children[0].Expressions.Count"); NameItem name = varInit.Expressions[0] as NameItem; Assert.IsNotNull(name, "Block.Children[2].Block.Children[0].Expressions[0]"); Assert.AreEqual(name.Name, "...", "Block.Children[2].Block.Children[0].Expressions[0].Name"); ValidateDebug(name.Debug, "Block.Children[2].Block.Children[0].Expressions[0]", "...", 4, 15, 4, 18); } } // for i= 12, 23 do print ( i ) end { ForNumItem forLoop = someBlock.Children[1] as ForNumItem; Assert.IsNotNull(forLoop, "Block.Children[2].Block.Children[1]"); ValidateDebug(forLoop.Debug, "Block.Children[2].Block.Children[1]", "for i = 12 , 23 do print ( i ) end", 5, 5, 7, 8); // validate the name { NameItem name = forLoop.Name; Assert.IsNotNull(name, "Block.Children[2].Block.Children[1].Name"); ValidateDebug(name.Debug, "Block.Children[2].Block.Children[1].Name", "i", 5, 9, 5, 10); Assert.AreEqual(name.Name, "i", "Block.Children[2].Block.Children[1].Name.Name"); } // validate the start { LiteralItem lit = forLoop.Start as LiteralItem; Assert.IsNotNull(lit, "Block.Children[2].Block.Children[1].Start"); Assert.AreEqual(12.0, lit.Value, "Block.Children[2].Block.Children[1].Start.Value"); ValidateDebug(lit.Debug, "Block.Children[2].Block.Children[1].Start", "12", 5, 12, 5, 14); } // validate the limit { LiteralItem lit = forLoop.Limit as LiteralItem; Assert.IsNotNull(lit, "Block.Children[2].Block.Children[1].Limit"); Assert.AreEqual(23.0, lit.Value, "Block.Children[2].Block.Children[1].Limit.Value"); ValidateDebug(lit.Debug, "Block.Children[2].Block.Children[1].Limit", "23", 5, 16, 5, 18); } // validate the step { Assert.IsNull(forLoop.Step, "Block.Children[2].Block.Children[1].Step"); } // validate the block { BlockItem forBlock = forLoop.Block; ValidateDebug(forBlock.Debug, "Block.Children[2].Block.Children[1].Block", "print ( i )", 6, 9, 6, 17); Assert.IsNull(forBlock.Return, "Block.Children[2].Block.Children[1].Block.Return"); // validate the statement { Assert.IsNotNull(forBlock.Children, "Block.Children[2].Block.Children[1].Block.Children"); Assert.AreEqual(1, forBlock.Children.Count, "Block.Children[2].Block.Children[1].Block.Children.Count"); // print ( i ) { FuncCallItem call = forBlock.Children[0] as FuncCallItem; Assert.IsNotNull(call, "Block.Children[2].Block.Children[1].Block.Children[0]"); Assert.AreEqual(true, call.Statement, "Block.Children[2].Block.Children[1].Block.Children[0].Statement"); Assert.IsNull(call.InstanceName, "Block.Children[2].Block.Children[1].Block.Children[0].InstanceName"); ValidateDebug(call.Debug, "Block.Children[2].Block.Children[1].Block.Children[0]", "print ( i )", 6, 9, 6, 17); // validate the prefix { NameItem name = call.Prefix as NameItem; Assert.IsNotNull(call.Prefix, "Block.Children[2].Block.Children[1].Block.Children[0].Prefix"); Assert.AreEqual("print", name.Name, "Block.Children[2].Block.Children[1].Block.Children[0].Prefix.Name"); ValidateDebug(name.Debug, "Block.Children[2].Block.Children[1].Block.Children[0].Prefix.Name", "print", 6, 9, 6, 14); } // validate the arguments { Assert.IsNotNull(call.Arguments, "Block.Children[2].Block.Children[1].Block.Children[0].Arguments"); Assert.AreEqual(1, call.Arguments.Count, "Block.Children[2].Block.Children[1].Block.Children[0].Arguments.Count"); NameItem name = call.Arguments[0].Expression as NameItem; Assert.IsNotNull(name, "Block.Children[2].Block.Children[1].Block.Children[0].Arguments[0]"); Assert.AreEqual("i", name.Name, "Block.Children[2].Block.Children[1].Block.Children[0].Arguments[0].Name"); ValidateDebug(name.Debug, "Block.Children[2].Block.Children[1].Block.Children[0].Arguments[0]", "i", 6, 15, 6, 16); } } } } } } } } }