public override AstNode Visit(ForEachStatement node) { // Begin the node. builder.BeginNode(node); // Push the scope. PushScope(node.GetScope()); // Visit the children. VisitList(node.GetChildren()); // Pop the scope. PopScope(); return builder.EndNode(); }
public override AstNode Visit(ForEachStatement node) { // Push the scope. PushScope(node.GetScope()); // Visit the children. VisitList(node.GetChildren()); // Pop the scope. PopScope(); return node; }
public override AstNode Visit(ForEachStatement node) { // Create the foreach lexical scope. LexicalScope scope = CreateLexicalScope(node); node.SetScope(scope); // Push the lexical scope. PushScope(scope); // Get the element type expression. Expression typeExpr = node.GetTypeExpression(); // Visit the container expression. Expression containerExpr = node.GetContainerExpression(); containerExpr.Accept(this); // Get the container expression type. IChelaType containerType = containerExpr.GetNodeType(); if(!containerType.IsReference()) Error(containerExpr, "expected an object reference."); // Remove type references. containerType = DeReferenceType(containerType); if(containerType.IsReference()) containerType = DeReferenceType(containerType); // Use primitives associated types. if(!containerType.IsStructure() && !containerType.IsClass() && !containerType.IsInterface()) { IChelaType assoc = currentModule.GetAssociatedClass(containerType); if(assoc == null) Error(containerExpr, "cannot iterate a container of type {0}", assoc.GetFullName()); containerType = assoc; } // Get the GetEnumerator method group. Structure building = (Structure)containerType; FunctionGroup getEnumeratorGroup = building.FindMemberRecursive("GetEnumerator") as FunctionGroup; if(getEnumeratorGroup == null) Error(containerExpr, "cannot find GetEnumerator method in {0}", containerType.GetName()); // Use the first no static member. Function getEnumeratorFunction = null; foreach(FunctionGroupName gname in getEnumeratorGroup.GetFunctions()) { // Ignore static functions. if(gname.IsStatic()) continue; // Only one argument is supported. if(gname.GetFunctionType().GetArgumentCount() == 1) { getEnumeratorFunction = gname.GetFunction(); break; } } // Make sure the function was found. if(getEnumeratorFunction == null) Error(containerExpr, "{0} doesn't have a no static GetEnumerator() method.", containerType.GetName()); // Get the enumerator type. TokenPosition position = node.GetPosition(); TypeNode enumeratorTypeNode = new TypeNode(TypeKind.Other, position); enumeratorTypeNode.SetOtherType(getEnumeratorFunction.GetFunctionType().GetReturnType()); // Get the numerator. Expression enumeratorExpr = new CallExpression( new MemberAccess(node.GetContainerExpression(), "GetEnumerator", position), null, position); // Create a variable for the enumerator. string enumeratorName = GenSym(); LocalVariablesDeclaration declEnum = new LocalVariablesDeclaration(enumeratorTypeNode, new VariableDeclaration(enumeratorName, enumeratorExpr, position), position); // Create a variable for the current object. LocalVariablesDeclaration currentDecl = new LocalVariablesDeclaration(node.GetTypeExpression(), new VariableDeclaration(node.GetName(), null, position), position); declEnum.SetNext(currentDecl); // Get the current member. Expression currentProp = new MemberAccess(new VariableReference(enumeratorName, position), "Current", position); // Create the while job. AstNode whileJob = new ExpressionStatement( new AssignmentExpression(new VariableReference(node.GetName(), position), new CastOperation(typeExpr, currentProp, position), position), position); whileJob.SetNext(node.GetChildren()); // Create the loop with MoveNext condition. Expression moveNext = new CallExpression( new MemberAccess(new VariableReference(enumeratorName, position), "MoveNext", position), null, position); WhileStatement whileStmnt = new WhileStatement(moveNext, whileJob, position); currentDecl.SetNext(whileStmnt); // Change my children. node.SetChildren(declEnum); // Visit my children. VisitList(node.GetChildren()); // Restore the scope. PopScope(); return node; }