예제 #1
0
 public override Statement VisitForEach(ForEach forEach)
 {
     WriteStart("foreach (");
     this.VisitTypeReference(forEach.TargetVariableType);
     Write(" ");
     this.VisitExpression(forEach.TargetVariable);
     Write(" in ");
     this.VisitExpression(forEach.SourceEnumerable);
     Write(")");
     this.VisitBlock(forEach.Body);
     return forEach;
 }
예제 #2
0
    void AddWriteStream(TypeNode type, StatementList statements, TypeNode referringType, Expression src, Identifier writer) {
      // Generate the following code:
      // XxxxSerializer s = new XxxxSerializer();
      // foreach (Xxxx x in src) {
      //    s.Serialize(x,writer);
      // }
      // Where Xxxx is the element type for the given stream type.

      if (type.Template == SystemTypes.GenericNonEmptyIEnumerable) {
        type = Checker.GetIEnumerableTypeFromNonEmptyIEnumerableStruct(this.module, type);
      } else {
        statements = AddCheckForNull(statements, Duplicate(src, referringType), type);
      }
      TypeNode ceType = Checker.GetCollectionElementType(type);  
      //todo: should check that type has an IEnumerator.

      Identifier loopVariable = Identifier.For("e");
      loopVariable.Type = ceType;
      Block body = new Block();
      body.Statements = new StatementList();

      Expression name, ns;
      GetNameAndNamespace(ceType, out name, out ns);

      // call the Serialize method on it, passing the member we're serializing.  
      if (!AddWriteSimpleType(ceType, body.Statements, referringType, writer, loopVariable, name, ns)) {
        AddCallSerializer(ceType, body.Statements, loopVariable, writer, name, ns);
      }

      ForEach fe = new ForEach(ceType, loopVariable, src, body);      
      statements.Add(fe);
    }
예제 #3
0
        public override Statement VisitForEach(ForEach forEach)
        {
            Statement rVal = base.VisitForEach(forEach);
            //
            // Create a temporary variable to hold our enumerator position
            //
            forEach.ScopeForTemporaryVariables.Members.Add(
                new Field(forEach.ScopeForTemporaryVariables, null, FieldFlags.Public,
                    new Identifier("____" + forEach.UniqueKey.ToString(CultureInfo.InvariantCulture)),
                    SystemTypes.Int32, new Literal(0, SystemTypes.Int32)));

            // Add the local variables we've added here to the method's "locals" list.

            Class scope;
            for (scope = forEach.ScopeForTemporaryVariables; scope is BlockScope; scope = scope.BaseClass)
                ;

            MethodScope mScope = scope as MethodScope;
            Debug.Assert(mScope != null);

            for (int i = 0, n = forEach.ScopeForTemporaryVariables.Members.Count; i < n; i++)
            {
                Member m = forEach.ScopeForTemporaryVariables.Members[i];
                ZMethod zMethod = mScope.DeclaringMethod as ZMethod;
                Debug.Assert(zMethod != null);
                zMethod.LocalVars.Add((Field)m);
            }

            return rVal;
        }
예제 #4
0
 public override Statement VisitForEach(ForEach forEach)
 {
     if (forEach == null) return null;
     return base.VisitForEach((ForEach)forEach.Clone());
 }
예제 #5
0
 public virtual Statement VisitForEach(ForEach forEach)
 {
     if (forEach == null) return null;
     forEach.TargetVariableType = this.VisitTypeReference(forEach.TargetVariableType);
     forEach.TargetVariable = this.VisitTargetExpression(forEach.TargetVariable);
     forEach.SourceEnumerable = this.VisitExpression(forEach.SourceEnumerable);
     forEach.InductionVariable = this.VisitTargetExpression(forEach.InductionVariable);
     forEach.Invariants = this.VisitLoopInvariantList(forEach.Invariants);
     forEach.Body = this.VisitBlock(forEach.Body);
     return forEach;
 }
예제 #6
0
 private ForEach ParseForEach(TokenSet followers){
   ForEach forEach = new ForEach();
   forEach.StatementTerminatesNormallyIfEnumerableIsNull = false;
   forEach.StatementTerminatesNormallyIfEnumeratorIsNull = false;
   forEach.SourceContext = this.scanner.CurrentSourceContext;
   Debug.Assert(this.currentToken == Token.Foreach);
   this.GetNextToken();
   SourceContext sctx = this.scanner.CurrentSourceContext;
   this.Skip(Token.LeftParenthesis);
   forEach.TargetVariableType = forEach.TargetVariableTypeExpression =
     this.ParseTypeExpression(null, followers|Parser.IdentifierOrNonReservedKeyword|Token.In|Token.RightParenthesis);
   forEach.TargetVariable = this.scanner.GetIdentifier();
   if (this.currentToken == Token.In)
     this.HandleError(Error.BadForeachDecl);
   else
     this.SkipIdentifierOrNonReservedKeyword();
   this.Skip(Token.In);
   forEach.SourceEnumerable = this.ParseExpression(followers|Token.RightParenthesis);
   this.ParseBracket(sctx, Token.RightParenthesis, followers|Token.ElementsSeen|Token.Invariant|Parser.StatementStart, Error.ExpectedRightParenthesis);
   if (this.currentToken == Token.ElementsSeen){
     this.GetNextToken();
     forEach.InductionVariable = this.scanner.GetIdentifier();
     this.SkipIdentifierOrNonReservedKeyword();
     this.SkipSemiColon(followers);
   }
   forEach.Invariants = this.ParseLoopInvariants(followers);
   SourceContext savedCompoundStatementOpeningContext = this.compoundStatementOpeningContext;
   forEach.SourceContext.EndPos = this.scanner.endPos;
   this.compoundStatementOpeningContext = forEach.SourceContext;
   Block b = this.ParseStatementAsBlock(followers);
   forEach.Body = b;
   if (b != null)
     forEach.SourceContext.EndPos = b.SourceContext.EndPos;
   this.compoundStatementOpeningContext = savedCompoundStatementOpeningContext;
   return forEach;
 }
예제 #7
0
 /// <summary>
 /// To be C# compliant, we should not allow anything to be the source of a foreach loop (which includes
 /// comprehensions) unless it either has a GetEnumerator() method or if it is an array.
 /// (It used to be that we would happily use something that was already an Enumerator, but that leads
 /// to a problem: once the enumerator is exhausted, there is not necessarily a good, automatic, way to
 /// reset it. And there isn't necessarily a good way to clone it beforehand.)
 /// </summary>
 /// <param name="forEach">The AST that represents the foreach loop</param>
 /// <returns>Either whatever the base visitor returns or else null (if there is an error)</returns>
 public override Statement VisitForEach(ForEach forEach) {
   Statement s = base.VisitForEach(forEach);
   ForEach f = s as ForEach;
   if (f != null) {
     // don't allow a source enumerable that is just an enumerator
     CollectionEnumerator cEnumerator = f.SourceEnumerable as CollectionEnumerator;
     if (cEnumerator != null && cEnumerator.GetEnumerator == null) {
       // Then it is not a type that supports GetEnumerator(), but if it is an array, then we'll let it slide.
       TypeNode possiblyArrayType = this.typeSystem.GetUnderlyingType(cEnumerator.Collection.Type) as ArrayType;
       if (possiblyArrayType == null) {
         this.HandleError(forEach,
           Error.ForEachMissingMember,
           this.GetTypeName(cEnumerator.Collection.Type),
           this.GetTypeName(cEnumerator.Collection.Type),
           "GetEnumerator");
         return null;
       }
     }
   }
   return s;
 }
예제 #8
0
        public override Statement VisitForEach(ForEach forEach)
        {
            Normalizer normalizer = new Normalizer(false);
            Identifier incrVar = new Identifier("____" + forEach.UniqueKey.ToString(CultureInfo.InvariantCulture));

            Expression sourceEnumerable = normalizer.VisitExpression(forEach.SourceEnumerable);

            Statement incrStmt = Templates.GetStatementTemplate("foreachIncrementer");
            Replacer.Replace(incrStmt, "_iterator", incrVar);
            BasicBlock incrBlock = new BasicBlock(incrStmt);
            AddBlock(incrBlock);
            incrBlock.MiddleOfTransition = true;
            incrBlock.SkipNormalizer = true;
            incrBlock.SourceContext = forEach.SourceContext;

            PushContinuationStack(incrBlock);
            this.Visit(forEach.Body);
            BasicBlock bodyBlock = PopContinuationStack();

            Statement derefStmt = Templates.GetStatementTemplate("foreachDeref");
            Replacer.Replace(derefStmt, "_tmpVar",
                             normalizer.VisitExpression(forEach.TargetVariable));
            Replacer.Replace(derefStmt, "_collectionExpr", sourceEnumerable);
            Replacer.Replace(derefStmt, "_collectionType",
                             new Identifier(forEach.SourceEnumerable.Type.FullName));
            Replacer.Replace(derefStmt, "_iterator", incrVar);
            BasicBlock derefBlock = new BasicBlock(derefStmt, bodyBlock);
            AddBlock(derefBlock);
            derefBlock.MiddleOfTransition = true;
            derefBlock.SkipNormalizer = true;

            Expression testExpr = Templates.GetExpressionTemplate("foreachTest");
            Replacer.Replace(testExpr, "_iterator", incrVar);
            Replacer.Replace(testExpr, "_sourceEnumerable", sourceEnumerable);
            BasicBlock testBlock = new BasicBlock(null, testExpr, derefBlock, CurrentContinuation);
            AddBlock(testBlock);
            testBlock.SkipNormalizer = true;

            incrBlock.UnconditionalTarget = testBlock;

            Statement initStmt = Templates.GetStatementTemplate("foreachInit");
            Replacer.Replace(initStmt, "_iterator", incrVar);
            BasicBlock initBlock = new BasicBlock(initStmt, testBlock);
            AddBlock(initBlock);
            initBlock.MiddleOfTransition = true;
            initBlock.SkipNormalizer = true;
            initBlock.SourceContext = forEach.SourceContext;

            CurrentContinuation = initBlock;

            return forEach;
        }
예제 #9
0
        //
        // We support iteration over arrays and sets
        //
        public override Statement VisitForEach(ForEach forEach)
        {
            if (forEach == null) return null;
            forEach.TargetVariableType = this.VisitTypeReference(forEach.TargetVariableType);
            forEach.TargetVariable = this.VisitTargetExpression(forEach.TargetVariable);
            forEach.SourceEnumerable = this.VisitExpression(forEach.SourceEnumerable);
            if (forEach.TargetVariableType == null || forEach.TargetVariable == null || forEach.SourceEnumerable == null)
                return null;

            TypeNode collectionType = forEach.SourceEnumerable.Type;
            Set setCollection = collectionType as Set;
            ZArray arrayCollection = collectionType as ZArray;

            TypeNode memberType = null;
            if (setCollection != null)
                memberType = setCollection.SetType;
            if (arrayCollection != null)
                memberType = arrayCollection.ElementType;

            if (memberType == null)
            {
                this.HandleError(forEach.SourceEnumerable, Error.InvalidForeachSource);
                return null;
            }

            if (memberType != forEach.TargetVariableType)
            {
                this.HandleError(forEach.TargetVariable, Error.InvalidForeachTargetType);
                return null;
            }

            forEach.Body = this.VisitBlock(forEach.Body);
            return forEach;
        }
예제 #10
0
 public EventingVisitor(Action<ForEach> visitForEach) { VisitedForEach += visitForEach; } public event Action<ForEach> VisitedForEach; public override Statement VisitForEach(ForEach forEach) { if (VisitedForEach != null) VisitedForEach(forEach); return base.VisitForEach(forEach); }