private Expression HandleIterateArray(IterateNode node) { var index = Expression.Variable(typeof(int)); var length = Expression.Variable(typeof(int)); var currentElement = Expression.Variable(node.ItemType, "current"); var exitLabel = Expression.Label(); PushScope(currentElement); var body = HandleNode(node.Body); PopScope(); var array = ParseExpression(node.Collection); var storedArray = Expression.Variable(array.Type); return(Expression.Block( new[] { length, storedArray }, Expression.Assign(storedArray, array), Expression.Assign(length, Expression.ArrayLength(storedArray)), Expression.IfThenElse(Expression.Equal(length, Expression.Constant(0)), HandleNode(node.EmptyBody), Expression.Block( new[] { index }, Expression.Assign(index, Expression.Constant(0)), Expression.Loop(Expression.Block( new[] { currentElement }, Expression.Assign(currentElement, Expression.ArrayIndex(storedArray, index)), body, Expression.Assign(index, Expression.Increment(index)), Expression.IfThen(Expression.Equal(index, length), Expression.Break(exitLabel)) ), exitLabel) ) ) )); }
public void Iterate <TNode, TKey>(TNode node, Action <TNode> action) where TNode : class, AvlNode_I <TNode, TKey> { if (node == null) { return; } var stack = new IterateNode <TNode>() { Node = node, }; while (stack != null) { TNode left; TNode right; if (stack.Status < 1 && (left = stack.Node.Left) != null) { stack.Status = 1; var newstack = new IterateNode <TNode>() { Node = left, Previous = stack, }; stack = newstack; continue; } if (stack.Status < 2) { action(stack.Node); stack.Status = 2; continue; } if (stack.Status < 3 && (right = stack.Node.Right) != null) { stack.Status = 3; var newstack = new IterateNode <TNode>() { Node = right, Previous = stack, }; stack = newstack; continue; } stack = stack.Previous; } }
public void Iterate(TNode node, Action <TNode> action) { if (IsNull(node)) { return; } var stack = new IterateNode <TNode>() { Node = node, }; while (stack != null) { TNode left; TNode right; if (stack.Status < 1 && (left = GetLeft(stack.Node)) != null) { stack.Status = 1; var newstack = new IterateNode <TNode>() { Node = left, Previous = stack, }; stack = newstack; continue; } if (stack.Status < 2) { action(stack.Node); stack.Status = 2; continue; } if (stack.Status < 3 && (right = GetRight(stack.Node)) != null) { stack.Status = 3; var newstack = new IterateNode <TNode>() { Node = right, Previous = stack, }; stack = newstack; continue; } stack = stack.Previous; } }
protected virtual TResult VisitIterateNode(IterateNode iterateNode) { var schema = this.VisitExpressionNode(iterateNode.Collection); this.VisitBlockNode(iterateNode.Body); this.VisitBlockNode(iterateNode.EmptyBody); return(schema); }
protected override IClientModel VisitIterateNode(IterateNode iterateNode) { var result = this.VisitExpressionNode(iterateNode.Collection); _modelStack.Push(_clientContext.BeginIterate(result)); this.Visit(iterateNode.Body); _modelStack.Pop(); _clientContext.EndIterate(); return(result); }
private Expression HandleIterate(IterateNode node) { if (node.Collection.ResultType.IsArray) { return(HandleIterateArray(node)); } var enumerableType = typeof(IEnumerable <>).MakeGenericType(node.ItemType); var getEnumeratorMethod = enumerableType.GetMethod("GetEnumerator"); var getCurrentMethod = getEnumeratorMethod.ReturnType.GetProperty("Current").GetGetMethod(); var currentElement = Expression.Variable(node.ItemType, "current"); var hasElements = Expression.Variable(typeof(bool), "hasElements"); var enumerator = Expression.Variable(getEnumeratorMethod.ReturnType, "enumerator"); var exitLabel = Expression.Label(); var collection = ParseExpression(node.Collection); if (collection.Type == typeof(object)) { collection = Expression.Convert(collection, enumerableType); } this.PushScope(currentElement); var loopBody = HandleNode(node.Body); this.PopScope(); return(Expression.Block( new[] { enumerator, hasElements }, Expression.Assign(hasElements, Expression.Constant(false)), Expression.Assign(enumerator, Expression.Call(collection, getEnumeratorMethod)), Expression.Loop(Expression.Block( Expression.IfThenElse(Expression.IsFalse(Expression.Call(enumerator, moveNextMethod)), Expression.Break(exitLabel), Expression.Block( new[] { currentElement }, Expression.Assign(currentElement, Expression.Property(enumerator, getCurrentMethod)), Expression.Assign(hasElements, Expression.Constant(true)), loopBody ) ) ), exitLabel), DisposeIfNeeded(enumerator), Expression.IfThen(Expression.IsFalse(hasElements), HandleNode(node.EmptyBody)) )); }
protected override JSchema VisitIterateNode(IterateNode iterateNode) { var schema = this.VisitExpressionNode(iterateNode.Collection); if (schema == null) { return(null); } var arrayItemSchema = new JSchema(); schema.Type = JSchemaType.Array; _schemas.Push(arrayItemSchema); this.VisitBlockNode(iterateNode.Body); this.VisitBlockNode(iterateNode.EmptyBody); arrayItemSchema = _schemas.Pop(); schema.Items.Add(arrayItemSchema); return(schema); }
private void EmitIterate(IterateNode node) { var allDone = emitter.DefineLabel(); var empty = emitter.DefineLabel(); if (node.Collection.ResultType.IsArray) { var done = emitter.DefineLabel(); var loop = emitter.DefineLabel(); using (var index = emitter.DeclareLocal(typeof(int))) using (var length = emitter.DeclareLocal(typeof(int))) using (var item = emitter.DeclareLocal(node.ItemType)) { EvaluateExpression(node.Collection); emitter.LoadLength(node.ItemType); emitter.StoreLocal(length); emitter.LoadLocal(length); emitter.BranchIfFalse(empty); emitter.LoadConstant(0); emitter.StoreLocal(index); emitter.MarkLabel(loop); emitter.LoadLocal(length); emitter.LoadLocal(index); emitter.CompareEqual(); emitter.BranchIfTrue(done); EvaluateExpression(node.Collection); emitter.LoadLocal(index); emitter.LoadElement(node.ItemType); emitter.StoreLocal(item); AddModelScope(e => e.LoadLocal(item)); EmitNode(node.Body); RemoveModelScope(); emitter.LoadLocal(index); emitter.LoadConstant(1); emitter.Add(); emitter.StoreLocal(index); emitter.Branch(loop); emitter.MarkLabel(done); emitter.Branch(allDone); } } else { var enumerable = typeof(IEnumerable <>).MakeGenericType(node.ItemType); var getEnumerator = enumerable.GetMethod("GetEnumerator"); var getCurrent = getEnumerator.ReturnType.GetProperty("Current").GetGetMethod(); var disposeEnumerator = typeof(IDisposable).IsAssignableFrom(getEnumerator.ReturnType); var loop = emitter.DefineLabel(); var done = emitter.DefineLabel(); EvaluateExpression(node.Collection); if (node.Collection.ResultType == typeof(object)) { emitter.CastClass(enumerable); } using (var item = emitter.DeclareLocal(node.ItemType)) using (var hasItems = emitter.DeclareLocal(typeof(bool))) using (var en = emitter.DeclareLocal(getEnumerator.ReturnType)) { emitter.CallMethod(getEnumerator); emitter.StoreLocal(en); emitter.MarkLabel(loop); emitter.LoadLocal(en); emitter.CallMethod(moveNextMethod); emitter.BranchIfFalse(done); emitter.LoadConstant(1); emitter.StoreLocal(hasItems); emitter.LoadLocal(en); emitter.CallMethod(getCurrent); emitter.StoreLocal(item); AddModelScope(e => e.LoadLocal(item)); EmitNode(node.Body); RemoveModelScope(); emitter.Branch(loop); emitter.MarkLabel(done); if (disposeEnumerator) { emitter.LoadLocal(en); emitter.CallMethod(disposeMethod); } emitter.LoadLocal(hasItems); emitter.BranchIfTrue(allDone); } } emitter.MarkLabel(empty); EmitNode(node.EmptyBody); emitter.MarkLabel(allDone); }