Exemple #1
0
        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;
        }
Exemple #2
0
        public override AstNode Visit(LockStatement node)
        {
            // Create the block lexical scope.
            LexicalScope blockScope = CreateLexicalScope(node);
            node.SetScope(blockScope);

            // Push the scope.
            PushScope(blockScope);

            // Visit the mutex expression.
            Expression mutexExpr = node.GetMutexExpression();
            mutexExpr.Accept(this);

            // Make sure its a reference object
            IChelaType mutexType = mutexExpr.GetNodeType();
            if(!mutexType.IsReference())
                Error(mutexExpr, "expected an object expression.");
            mutexType = DeReferenceType(mutexType);

            // Remove the variable layer.
            if(mutexType.IsReference())
                mutexType = DeReferenceType(mutexType);

            // Must be a class or an interface.
            if(!mutexType.IsClass() && !mutexType.IsInterface())
                Error(mutexExpr, "expected a class/interface instance.");

            // Create the mutex local.
            TokenPosition position = node.GetPosition();
            string mutexName = GenSym();
            AstNode decl = new LocalVariablesDeclaration(new TypeNode(TypeKind.Object, position),
                    new VariableDeclaration(mutexName, node.GetMutexExpression(), position),
                        position);

            // Chela.Threading.Monitor variable.
            TypeNode monitor = new TypeNode(TypeKind.Other, position);
            Structure threadingMonitor = (Structure)currentModule.GetThreadingMember("Monitor", true);
            if(threadingMonitor == null)
                Error(node, "couldn't use lock when the runtime doesn't define Chela.Threading.Monitor" );
            monitor.SetOtherType(threadingMonitor);

            // Enter into the mutex.
            AstNode enterMutex = new CallExpression(new MemberAccess(monitor, "Enter", position),
                                    new VariableReference(mutexName, position), position);
            decl.SetNext(enterMutex);

            // Try finally
            AstNode exitMutex = new CallExpression(new MemberAccess(monitor, "Exit", position),
                                    new VariableReference(mutexName, position), position);
            FinallyStatement finallyStmnt = new FinallyStatement(exitMutex, position);

            // Try statement.
            TryStatement tryStmnt = new TryStatement(node.GetChildren(), null, finallyStmnt, position);
            enterMutex.SetNext(tryStmnt);

            // Replace my children.
            node.SetChildren(decl);

            // Visit the block children.
            VisitList(node.GetChildren());

            // Restore the scope.
            PopScope();

            return node;
        }