/// <summary> /// Execute each expression. /// </summary> /// <returns></returns> public object VisitForEach(ForEachExpr expr) { expr.DoContinueRunning = true; expr.DoBreakLoop = false; expr.DoContinueLoop = false; // for(user in users) // Push scope for var name var source = this.Ctx.Memory.Get<object>(expr.SourceName) as LObject; IEnumerator enumerator = null; if (source.Type == LTypes.Array) enumerator = ((IList)source.GetValue()).GetEnumerator(); else if (source.Type == LTypes.Map) enumerator = ((IDictionary)source.GetValue()).GetEnumerator(); expr.DoContinueRunning = enumerator.MoveNext(); while (expr.DoContinueRunning) { // Set the next value of "x" in for(x in y). var current = enumerator.Current is LObject ? enumerator.Current : LangTypeHelper.ConvertToLangClass(enumerator.Current); this.Ctx.Memory.SetValue(expr.VarName, current); if (expr.Statements != null && expr.Statements.Count > 0) { foreach (var stmt in expr.Statements) { stmt.Evaluate(this); this.Ctx.Limits.CheckLoop(expr); // If Break statment executed. if (expr.DoBreakLoop) { expr.DoContinueRunning = false; break; } // Continue statement. else if (expr.DoContinueLoop) break; } } else break; // Break loop here. if (expr.DoContinueRunning == false) break; // Increment. expr.DoContinueRunning = enumerator.MoveNext(); } return LObjects.Null; }
/// <summary> /// Creates a unary expression with symbol scope, context, script refernce set. /// </summary> /// <param name="varname"></param> /// <param name="sourceName"></param> /// <returns></returns> public static Expr ForEach(string varname, string sourceName, TokenData token) { var exp = new ForEachExpr(); exp.VarName = varname; exp.SourceName = sourceName; SetupContext(exp, token); return exp; }