/// <summary> /// Expands the foreach loop if it iterates over T[]. /// </summary> private NodeBase expandArray(Context ctx) { var arrayVar = ctx.Scope.DeclareImplicit(ctx, IterableExpression.Resolve(ctx), false); var idxVar = ctx.Scope.DeclareImplicit(ctx, typeof(int), false); var lenVar = ctx.Scope.DeclareImplicit(ctx, typeof(int), false); return(Expr.Block( Expr.Set(idxVar, Expr.Int(0)), Expr.Set(arrayVar, IterableExpression), Expr.Set(lenVar, Expr.GetMember(Expr.Get(arrayVar), "Length")), Expr.While( Expr.Less( Expr.Get(idxVar), Expr.Get(lenVar) ), Expr.Block( getIndexAssignment( Expr.GetIdx( Expr.Get(arrayVar), Expr.Get(idxVar) ) ), Expr.Set( idxVar, Expr.Add(Expr.Get(idxVar), Expr.Int(1)) ), Body ) ) )); }
protected override NodeBase expand(Context ctx, bool mustReturn) { if (IterableExpression != null) { var type = IterableExpression.Resolve(ctx); if (type.IsArray) { return(expandArray(ctx)); } return(expandEnumerable(ctx, mustReturn)); } return(expandRange(ctx)); }
/// <summary> /// Calculates the variable type and other required values for enumeration of an IEnumerable`1. /// </summary> private void detectEnumerableType(Context ctx) { var seqType = IterableExpression.Resolve(ctx); if (seqType.IsArray) { _VariableType = seqType.GetElementType(); return; } var ifaces = seqType.ResolveInterfaces(); if (seqType.IsInterface) { ifaces = ifaces.Union(new[] { seqType }).ToArray(); } var generic = ifaces.FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable <>)); if (generic != null) { _EnumeratorType = typeof(IEnumerator <>).MakeGenericType(generic.GetGenericArguments()[0]); } else if (ifaces.Contains(typeof(IEnumerable))) { _EnumeratorType = typeof(IEnumerator); } else { error(IterableExpression, CompilerMessages.TypeNotIterable, seqType); } _CurrentProperty = ctx.ResolveProperty(_EnumeratorType, "Current"); _VariableType = _CurrentProperty.PropertyType; }