예제 #1
0
        public override AstNode Visit(UsingObjectStatement node)
        {
            // Push the scope.
            PushScope(node.GetScope());

            // Visit the declarations.
            LocalVariablesDeclaration decls = node.GetLocals();
            decls.Accept(this);

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

            // Pop the scope.
            PopScope();

            return node;
        }
예제 #2
0
        public override AstNode Visit(UsingObjectStatement node)
        {
            // Create the using lexical scope.
            LexicalScope blockScope = CreateLexicalScope(node);
            node.SetScope(blockScope);

            // Push the scope.
            PushScope(blockScope);

            // Get the local declarations.
            LocalVariablesDeclaration decls = node.GetLocals();
            decls.Accept(this);

            // Check if disposing or deleting.
            IChelaType varType = decls.GetNodeType();
            bool pointer = varType.IsPointer();
            if(!pointer)
            {
                // Make sure it could implement IDisposable.
                varType = DeReferenceType(varType);
                if(!varType.IsStructure() && !varType.IsClass() && !varType.IsReference())
                    Error(node, "cannot dispose object that isn't a structure, class or interface.");

                // Make sure it does implement IDisposable.
                Structure building = (Structure) varType;
                Structure idisposable = currentModule.GetLangMember("IDisposable") as Interface;
                if(idisposable == null)
                    Error(node, "couldn't find IDisposable");
                if(building != idisposable && !building.Implements(idisposable))
                    Error(node, "object doesn't implement IDisposable.");
            }

            // Build the finally clause.
            TokenPosition position = node.GetPosition();
            AstNode finallyChildren = null;
            AstNode lastChild = null;
            AstNode decl = decls.GetDeclarations();
            while(decl != null)
            {
                AstNode disposeStmnt = null;
                if(pointer)
                {
                    // Delete the variable
                    Expression variable = new VariableReference(decl.GetName(), position);
                    disposeStmnt = new DeleteStatement(variable, position);
                }
                else
                {
                    // Call the variable dispose.
                    Expression functionExpr = new MemberAccess(new VariableReference(decl.GetName(), position), "Dispose", position);
                    Expression callExpr = new CallExpression(functionExpr, null, position);
                    disposeStmnt = new ExpressionStatement(callExpr, position);
                }

                // If not null.
                Expression notNull = new BinaryOperation(BinaryOperation.OpNEQ, new VariableReference(decl.GetName(), position), new NullConstant(position), position);
                IfStatement ifStmnt = new IfStatement(notNull, disposeStmnt, null, position);

                // Link the call.
                if(lastChild == null)
                {
                    finallyChildren = lastChild = ifStmnt;
                }
                else
                {
                    lastChild.SetNext(ifStmnt);
                    lastChild = ifStmnt;
                }

                // Dispose the next declaration.
                decl = decl.GetNext();
            }

            // Build the try-finally.
            FinallyStatement finallyClause = new FinallyStatement(finallyChildren, position);
            TryStatement tryStatement = new TryStatement(node.GetChildren(), null, finallyClause, position);

            // Substitute the children with the try.
            node.SetChildren(tryStatement);

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

            // Restore the scope.
            PopScope();

            return node;
        }