/* scope.cc: Definitions for member functions that manage name binding */ #include #include "AST.h" #include "FieldDecl.h" #include "MethodDecl.h" #include "compiler.h" #include "decls.h" #include "errors.h" /* A default constructor for the class declared by ClassDeclNode CL, */ /* as it would be produced by the parser, had it been written */ /* explicitly: [public] polyshared Foo() { super(); } */ static TreeNode* defaultConstructor (TreeNode* cl) { unsigned flags = cl->flags() & Common::Public | Common::CompilerGenerated; if (!cl->decl()->asType()->isImmutable()) flags |= Common::PolysharedQ; return new ConstructorDeclNode ((Common::Modifiers) flags, NULL, new NameNode(TreeNode::omitted, cl->simpName()->ident(), NULL), NULL, new SuperConstructorCallNode(NULL, NULL, cl->position()), TreeNode::omitted, cl->position()); } /* Name resolution, pass 1: for ClassDeclNodes and */ /* InterfaceDeclNodes: modify *THIS to create Decls for all its */ /* members */ /* PACKAGE is the package environment containing all these nodes. */ void TreeNode::resolveClass(Decl *package, ClassDecl *cclass, Environ *fileEnv) { foriter (p, allChildren(), ChildIter) (*p)->resolveClass(package, cclass, fileEnv); } void CompileUnitNode::resolveClass(Decl *, ClassDecl *, Environ *) { types()->resolveClass(thePackage, NULL, environ()); } void TemplateDeclNode::resolveClass( Decl *, ClassDecl *, Environ * ) { } void ClassDeclNode::resolveClass(Decl *package, ClassDecl *, Environ *fileEnv) { ClassDecl &me = *decl(); me.visits = 1; assert(!(flags() & Interface)); if (flags() & Immutable) { if (!superClass()->absent()) error() << "immutable classes cannot extend classes" << endl; if (interfaces()->arity() > 0) error() << "immutable classes cannot implement interfaces" << endl; flags((Modifiers)(flags() | Final)); } else { ClassDecl *super = superClass()->absent() ? ObjectDecl : static_cast(superClass()->decl()); if (super->category() != Decl::Class) { error() << "class " << *simpName()->ident() << " cannot EXTEND interface " << *super->name() << endl; super = ObjectDecl; } superClass(super->asType()); me.superClass(super); me.interfaces(NULL); foriter (interface, interfaces()->allChildren(), ChildIter) { Decl *intf = (*interface)->decl(); if (intf->category() != Decl::Interface) error() << "class " << *simpName()->ident() << " cannot IMPLEMENT class " << *intf->name() << endl; else me.interfaces(cons(intf, me.interfaces())); } } members()->resolveClass(package, &me, fileEnv); if (me.environ()->lookupProper(me.name(), Decl::Constructor) == NULL) { members()->child(0, defaultConstructor(this)); members()->child(0)->resolveClass(package, &me, fileEnv); } } void FieldDeclNode::resolveClass(Decl *package, ClassDecl *cclass, Environ *fileEnv) { if (!cclass->superClass() && !(flags() & Static)) // immutable class flags((Common::Modifiers)(flags() | Final)); if ((flags() & Final) && (flags() & Volatile)) error() << "field " << *simpName()->ident() << " cannot be final and volatile" << endl; Decl* d; dtype()->resolveClass(package, cclass, fileEnv); d = cclass->environ()->lookupProper(simpName()->ident(), Decl::Field); if (d != NULL) { error() << "redeclaration of " << d->errorName() << endl; simpName()->decl(d); return; } d = new FieldDecl(simpName()->ident(), dtype(), cclass, flags(), this); cclass->environ()->add(d); simpName()->decl(d); } void MethodDeclNode::resolveClass(Decl *package, ClassDecl *cclass, Environ *fileEnv) { // methods in immutable classes and private methods are final if ((flags() & Private) || !cclass->superClass()) flags((Modifiers)(flags() | Final)); if (body()->absent()) { if (flags() & Abstract) { if (flags() & (Private | Static | Final | Synchronized | Native | Inline)) error() << "can't use private, static, final, synchronized, inline or native with abstract" << endl; } else if (!(flags() & Native)) error() << "abstract or native required on methods without a body" << endl; } else if (flags() & (Abstract | Native)) error() << "an abstract or native method cannot have a body" << endl; MethodNode::resolveClass(package, cclass, fileEnv); } void MethodNode::resolveClass(Decl *, ClassDecl *cclass, Environ *) { TypeNode *mType = typeFromMethodDeclNode(this); if (flags() & Static) { Modifiers forbidden = (Modifiers) (flags() & (Local | NonsharedQ | PolysharedQ)); if (forbidden) error() << "a static method cannot be " << stringifyModifiers( forbidden ) << endl; } // Check that this method is legal foriter (dd, cclass->environ()->lookupFirstProper(simpName()->ident(), Decl::Method), EnvironIter) if (mType->methodsConflict(dd->type())) error() << "illegal overloading of " << dd->errorName() << endl; Decl* d = new MethodDecl(simpName()->ident(), mType, Decl::Method, cclass, flags(), this); cclass->environ()->add(d); simpName()->decl(d); } void ConstructorDeclNode::resolveClass(Decl *, ClassDecl *cclass, Environ *) { flags( (Modifiers) (flags() | Local) ); TypeNode *mType = typeFromMethodDeclNode(this); // Check that this method is legal foriter (dd, cclass->environ()->lookupFirstProper(simpName()->ident(), Decl::Constructor), EnvironIter) if (mType->methodsConflict(dd->type())) error() << "illegal overloading of " << dd->errorName(); Decl* d = new MethodDecl(cclass->name(), mType, Decl::Constructor, cclass, flags(), this); cclass->environ()->add(d); simpName()->decl(d); } void StaticInitNode::resolveClass(Decl *, ClassDecl *, Environ *) { } void InterfaceDeclNode::resolveClass(Decl *package, ClassDecl *, Environ *fileEnv) { ClassDecl &me = *decl(); me.visits = 1; me.interfaces(NULL); foriter (interface, interfaces()->allChildren(), ChildIter) { Decl *intf = (*interface)->decl(); if (intf->category() != Decl::Interface) error() << "interface " << *simpName()->ident() << " cannot EXTEND class " << *intf->name() << endl; else me.interfaces(cons(intf, me.interfaces())); } members()->resolveClass(package, &me, fileEnv); foriter (decl, me.environ()->allProperDecls(), EnvironIter) { int modifiers = decl->modifiers(); switch (decl->category()) { case Decl::Method: modifiers |= Public | Abstract; break; case Decl::Field: modifiers |= Public | Final | Static; break; } decl->modifiers((Modifiers) modifiers); } }