コード例 #1
0
ファイル: AST.cs プロジェクト: chenzuo/blue
    void FixCtors(
        ISemanticResolver s,
        ICLRtypeProvider provider
    )
    {
        // Add default ctor
        bool fFoundCtor = m_symbol.HasMethodHeader(Name);
            
        // Note that structs don't have a default ctor, but can have other ctors                        
        // But add a default ctor for classes if we don't have one.
        if (!fFoundCtor && IsClass)
        {                
            CtorChainStatement stmtChain = new CtorChainStatement();
            Modifiers mods = new Modifiers();
            mods.SetPublic();

            MethodDecl mdecl = new MethodDecl(
                new Identifier(Name, this.Location), 
                null, 
                null, 
                new BlockStatement(new LocalVarDecl[0], new Statement[] { stmtChain }), 
                //new AST.Modifiers(AST.Modifiers.EFlags.Public)
                mods
                );

            stmtChain.FinishInit(mdecl);
                
            mdecl.ResolveMember(m_symbol,s, null);
            mdecl.Symbol.SetInfo(provider);
                
            // Add to the end of the m_alMethods array so that we get codegen'ed!
            AddMethodToList(mdecl);
                
            Debug.Assert(m_symbol.HasMethodHeader(Name));
        }

        // @todo - perhaps we could just make the static initializer a static-ctor..
        // If we don't have a static ctor, but we do have static data, then add
        // a static ctor
        if (m_nodeStaticInit != null) 
        {
            bool fFoundStaticCtor = false;
            foreach(MethodDecl m in m_alMethods)
            {
                if (m.Mods.IsStatic && m.IsCtor)
                {
                    fFoundStaticCtor = true;
                    break;
                }
            }

            if (!fFoundStaticCtor)
            {
                Modifiers mods = new Modifiers();
                mods.SetStatic();
                mods.SetPublic();
                    
                MethodDecl mdecl2 = new MethodDecl(
                    new Identifier(Name, this.Location),
                    null,
                    null,
                    new BlockStatement(null, new Statement[]{}),
                    //new Modifiers(AST.Modifiers.EFlags.Static | Modifiers.EFlags.Public)
                    mods
                    );
                mdecl2.ResolveMember(m_symbol, s, null);
                mdecl2.Symbol.SetInfo(provider);
                AddMethodToList(mdecl2);
            }
        } // end check static ctor
    } // fix ctors
コード例 #2
0
ファイル: Parser.cs プロジェクト: chenzuo/blue
//-----------------------------------------------------------------------------
// Do a partial parse of the method decl (includes ctor), 
// Pass in the parameters that we've already parsed, which is everything 
// before the first '('. 
//
// ** Rules **
// methoddecl -> attrs type id '(' paramlist ')' '{' statementlist '}'
// methoddecl -> attrs type id '(' paramlist ')' ';'   // if abstract
//-----------------------------------------------------------------------------
    protected MethodDecl PartialParseMethodDecl(
        Modifiers mods, 
        TypeSig typeReturn,
        Identifier stMemberName,
        Genre genre // applies additional restrictions
    )
    {   
    // We should have already parsed the 'attrs type id'. So continue with param list
        
        ParamVarDecl [] arParams = ParseParamList();
        
        // Structs can't define a default ctor
        if ((genre == Genre.cStruct) && (typeReturn == null) && (arParams.Length == 0))
        {
            ThrowError(E_NoDefaultCtorForStructs(m_lexer.PeekNextToken().Location));
        }
        

        CtorChainStatement chain  = null;
    // If this is a constructor, then we can chain it
    // ctordecl -> mods type id '(' param_list ')' ':' (this|base) '(' param_list ')' '{' statementlist '}'
    // ctor can't be abstract / virtual. Can be static
        if (typeReturn == null)
        {   
            Token t = m_lexer.PeekNextToken();
            if (genre == Genre.cInterface)
            {
                ThrowError(E_NoCtorOnInterface(t.Location));
            }        
            
            if (t.TokenType == Token.Type.cColon)
            {                
                ConsumeNextToken();
                // Currently, 'base' & 'this' are just identifiers, not specific tokens
                Identifier id = this.ReadExpectedIdentifier();
                Exp [] arParams2 = ParseExpList();

                CtorChainStatement.ETarget eTarget = (CtorChainStatement.ETarget) (-1);
                
                if (id.Text == "this")
                    eTarget = CtorChainStatement.ETarget.cThis;
                else if (id.Text == "base")
                {
                    if (genre == Genre.cStruct)
                    {
                        ThrowError(E_NoBaseChainForStructs(id.Location));
                    }
                    eTarget = CtorChainStatement.ETarget.cBase;
                }
                else 
                {
                    ThrowError(E_BadCtorChain(id));
                }

                chain = new CtorChainStatement(eTarget, arParams2);
            } 
            else 
            {
                // If no explicit ctor chain, then we still have an implicit "base ()"
                // (except for static ctors, which can't be chained)
                if (!mods.IsStatic && (genre == Genre.cClass))                
                {                
                    chain = new CtorChainStatement();
                }
            }

            // Static ctors can't be chained
            if (chain != null)
            {
                if (mods.IsStatic)                
                {
                    ThrowError(E_NoChainForStaticCtor(stMemberName.Location));
                }
            }
        }


    // Parse body
        BlockStatement block = null;

        if (mods.IsAbstract)        
        {
        // For abstract methods, no body. Just end with a ';'
            ReadExpectedToken(Token.Type.cSemi);        
        } else 
        {        
        // Read method body. This will include the '{' ... '}'    
            block = ParseStatementBlock();
        }


        if (typeReturn == null)
        {
            if (mods.IsAbstract | mods.IsVirtual | (block == null))            
            {
                ThrowError(E_NoAbstractCtor(stMemberName));
            }
        }
        
        // Allocate the method decl
        MethodDecl nodeMethod = new MethodDecl(
            stMemberName, 
            typeReturn, 
            arParams, 
            block,
            mods);

        // If we have a chain, inject it into the statements
        if (chain != null)
        {
            nodeMethod.Body.InjectStatementAtHead(chain);
            chain.FinishInit(nodeMethod);
        }

        return nodeMethod;
    }