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
//----------------------------------------------------------------------------- // Parse enum declaration // --> 'enum' id:name '{' enum_decl_list '}' //----------------------------------------------------------------------------- protected EnumDecl ParseEnum(Modifiers modsEnums) { ReadExpectedToken(Token.Type.cEnum); Identifier idName = ReadExpectedIdentifier(); FileRange f2 = this.BeginRange(); ReadExpectedToken(Token.Type.cLCurly); ArrayList a = new ArrayList(); // All enum fields are Static, Public, Literal // and have fieldtype set to type of the enum //Modifiers mods = new Modifiers(Modifiers.EFlags.Public | Modifiers.EFlags.Static); Modifiers mods = new Modifiers(); mods.SetPublic(); mods.SetStatic(); TypeSig tSig = new SimpleTypeSig(new SimpleObjExp(idName)); Identifier idPrev = null; Token t = m_lexer.PeekNextToken(); while(t.TokenType != Token.Type.cRCurly) { // Parse fields Identifier id = ReadExpectedIdentifier(); Exp expInit = null; t = m_lexer.PeekNextToken(); if (t.TokenType == Token.Type.cAssign) { ConsumeNextToken(); expInit = ParseExp(); } else { #if false // If no explicit assignment, then we must create one // first field -> '=0' if (idPrev == null) { expInit = new IntExp(0, id.Location); } // all other fields -> '= <prevfield> + '1' ' else { expInit = new BinaryExp( new SimpleObjExp(idPrev), new IntExp(1, id.Location), BinaryExp.BinaryOp.cAdd); } #endif } //EnumField e = new EnumField(id); FieldDecl e = new FieldDecl(id, tSig, mods, expInit); a.Add(e); // If no comma, then this had better be our last one t = m_lexer.PeekNextToken(); if (t.TokenType != Token.Type.cComma) { break; } ReadExpectedToken(Token.Type.cComma); idPrev = id; t = m_lexer.PeekNextToken(); } // while parsing fields ReadExpectedToken(Token.Type.cRCurly); // Convert array list to EnumField[] FieldDecl [] f = new FieldDecl[a.Count]; for(int i = 0; i < f.Length; i++) f[i] = (FieldDecl) a[i]; EnumDecl node = new EnumDecl(idName, f, modsEnums); node.SetLocation(this.EndRange(f2)); return node; }
// Resolve all the fields in this type. Only class/struct should call // this. void FixFields(ISemanticResolver s, ICLRtypeProvider provider) { Debug.Assert(!IsInterface); int cInstance = 0; int cStatic = 0; foreach(FieldDecl f in m_alFields) { f.ResolveMember(m_symbol, s, provider); //f.Symbol.SetInfo(provider); if (f.InitialExp != null) if (f.Mods.IsStatic) cStatic++; else cInstance++; } Statement [] stmtStatic = new Statement[cStatic]; Statement [] stmtInstance = new Statement[cInstance]; cStatic = 0; cInstance = 0; // Fields can have assignments. Make 2 helper functions to do // assignment for static & instance fields foreach(FieldDecl f in m_alFields) { if (f.InitialExp != null) { Statement stmt = new ExpStatement(new AssignStmtExp( new SimpleObjExp(new Identifier(f.Name, f.Location)), f.InitialExp)); if (f.Mods.IsStatic) { stmtStatic[cStatic] = stmt; cStatic++; } else { if (IsStruct) { //ThrowError_NoFieldInitForStructs(s, f); ThrowError(SymbolError.NoFieldInitForStructs(f)); } stmtInstance[cInstance] = stmt; cInstance ++; } } // end has initializer expression } Debug.Assert(cStatic == stmtStatic.Length); Debug.Assert(cInstance == stmtInstance.Length); // Create methods to initialize the static & instance fields. // Then the ctors can call these methods if (cStatic != 0) { Modifiers mods = new Modifiers(); mods.SetStatic(); mods.SetPrivate(); m_nodeStaticInit = new MethodDecl( new Identifier(".StaticInit", this.Location), new ResolvedTypeSig(typeof(void), s), new ParamVarDecl[0], new BlockStatement(null, stmtStatic), mods ); //AddMethodToList(m_nodeStaticInit); } if (cInstance != 0) { Modifiers mods = new Modifiers(); mods.SetPrivate(); m_nodeInstanceInit = new MethodDecl( new Identifier(".InstanceInit", this.Location), new ResolvedTypeSig(typeof(void), s), new ParamVarDecl[0], new BlockStatement(null, stmtInstance), mods ); AddMethodToList(m_nodeInstanceInit); } } // end fields
//----------------------------------------------------------------------------- // Parse Member attributes and return the bit flag // // ** rules ** // MemberAttr -> <any subset of {public, static, etc } > //----------------------------------------------------------------------------- protected Modifiers ParseModifiers() { AST.Modifiers mods = new Modifiers(); while(true) { Token t = m_lexer.PeekNextToken(); switch(t.TokenType) { case Token.Type.cAttrPublic: mods.SetPublic(); break; case Token.Type.cAttrProtected: mods.SetProtected(); break; case Token.Type.cAttrPrivate: mods.SetPrivate(); break; case Token.Type.cAttrStatic: mods.SetStatic(); break; case Token.Type.cAttrAbstract: mods.SetAbstract(); break; case Token.Type.cAttrVirtual: mods.SetVirtual(); break; case Token.Type.cAttrOverride: mods.SetOverride(); break; case Token.Type.cAttrInternal: mods.SetInternal(); break; case Token.Type.cAttrReadOnly: mods.SetReadOnly(); break; case Token.Type.cNew: mods.SetNew(); break; case Token.Type.cAttrSealed: mods.SetSealed(); break; // Return once we encounter something that's not a modifier default: { return mods; } } ConsumeNextToken(); } // We exit once we find a token that's not a modifier (or we find a duplicate modifier) }