1 ///////////////////////////////////////////////////////////////////////////////
3 // This file implements the class definition mechanism of Prop.
5 ///////////////////////////////////////////////////////////////////////////////
8 #include <AD/strings/quark.h>
17 ///////////////////////////////////////////////////////////////////////////////
19 // Names of various class types
21 ///////////////////////////////////////////////////////////////////////////////
22 const char * ClassDefinition::class_type_name[ClassDefinition::LAST_CLASS] =
30 "attributegrammar class",
35 ///////////////////////////////////////////////////////////////////////////////
37 // Hashtable that contains all the classes indexed by name
39 ///////////////////////////////////////////////////////////////////////////////
40 HashTable ClassDefinition::defined_classes(string_hash, string_equal);
42 ClassDefinition * ClassDefinition::lookup_class(CLASS_TYPE ct, Id name)
43 { HashTable::Entry * e = defined_classes.lookup(name);
45 { error("%L%s %s has not been defined\n", class_type_name[ct], name);
48 { ClassDefinition * C = (ClassDefinition *)(e->v);
49 if (C->class_type != ct && ct != ANY_CLASS)
50 { error("%Lclass %s is not a %s\n"
51 "%!this is where %s %s was previously defined\n",
52 name, class_type_name[ct],
53 C->loc(), class_type_name[C->class_type], name);
60 void ClassDefinition::insert_class(ClassDefinition * C)
61 { HashTable::Entry * e = defined_classes.lookup(C->class_name);
63 { ClassDefinition * old_def = (ClassDefinition*)(e->v);
64 error("%Lredefinition of %s %s\n"
65 "%!this is where it was previously defined.\n",
66 class_type_name[C->class_type], C->class_name,
69 { defined_classes.insert(C->class_name,C);
73 ///////////////////////////////////////////////////////////////////////////////
75 // Constructor and destructors for datatype compiler
77 ///////////////////////////////////////////////////////////////////////////////
78 ClassDefinition::ClassDefinition
79 (CLASS_TYPE ct, Id id,
80 TyVars p, Inherits subclasses, TyQual qual, Decls body)
82 class_name(id), parameters(p), inherited_classes(subclasses),
83 qualifiers(qual), class_body(body)
84 { constructor_code = #[];
85 destructor_code = #[];
89 ClassDefinition::~ClassDefinition() {}
91 ///////////////////////////////////////////////////////////////////////////////
93 // Method to generate a class definition
95 ///////////////////////////////////////////////////////////////////////////////
96 void ClassDefinition::gen_class_definition(CodeGen& C)
97 { gen_class_predefinition(C);
98 C.pr ("%^%Hclass %s", parameters, class_name);
99 if (inherited_classes != #[]) C.pr (" : %I",inherited_classes);
101 gen_class_interface(C);
102 C.pr ("%&%-%^};\n", class_body);
103 gen_class_postdefinition(C);
106 ///////////////////////////////////////////////////////////////////////////////
108 // The default is to generate nothing for the following
110 ///////////////////////////////////////////////////////////////////////////////
111 void ClassDefinition::gen_class_predefinition(CodeGen& C) {}
112 void ClassDefinition::gen_class_interface(CodeGen& C) {}
113 void ClassDefinition::gen_class_postdefinition(CodeGen& C) {}
114 void ClassDefinition::gen_class_implementation(CodeGen& C, Tys, DefKind) {}
116 ///////////////////////////////////////////////////////////////////////////////
120 ///////////////////////////////////////////////////////////////////////////////
121 Id ClassDefinition::mangled_name() const { return mangle(class_name); }
122 Bool ClassDefinition::is_polymorphic() const { return parameters != #[]; }
123 Bool ClassDefinition::is_view() const { return qualifiers & QUALview; }
125 ///////////////////////////////////////////////////////////////////////////////
127 // Method to add a base class to the inheritance list
129 ///////////////////////////////////////////////////////////////////////////////
130 void ClassDefinition::add_base_class (Id name, Scope s, TyQual q)
132 inherited_classes = add_inherit(name,#[],inherited_classes,s,q);
135 void ClassDefinition::append_base_class (Id name, Scope s, TyQual q)
137 inherited_classes = append(inherited_classes,
138 add_inherit(name,#[],#[],s,q));
141 ///////////////////////////////////////////////////////////////////////////////
143 // Method to generate a constructor
145 ///////////////////////////////////////////////////////////////////////////////
146 void ClassDefinition::gen_class_constructor(CodeGen& C, Tys tys, DefKind k)
149 { case INTERFACE_DEFINITION:
150 C.pr("%^%s ", class_name); break;
151 case INLINE_IMPLEMENTATION:
152 C.pr("%^inline %s ", class_name); break;
153 case EXTERNAL_IMPLEMENTATION:
154 C.pr("%^%H %s%V::%s ",parameters, class_name, parameters, class_name);
156 case EXTERNAL_INSTANTIATION:
157 case EXTERNAL_DEFINITION:
158 C.pr("%^%s%P::%s ", class_name, tys, class_name);
162 gen_class_constructor_parameters(C, tys, k);
165 { case INLINE_IMPLEMENTATION:
166 case EXTERNAL_IMPLEMENTATION:
167 case EXTERNAL_INSTANTIATION:
168 gen_class_constructor_initializers(C, tys, k);
170 gen_class_constructor_body(C, tys, k);
171 if (constructor_code) C.pr("%^%&", constructor_code);
174 case INTERFACE_DEFINITION:
175 case EXTERNAL_DEFINITION:
180 ///////////////////////////////////////////////////////////////////////////////
182 // Method to generate a destructor
184 ///////////////////////////////////////////////////////////////////////////////
185 void ClassDefinition::gen_class_destructor(CodeGen& C, Tys tys, DefKind k)
187 Id v = (qualifiers & QUALvirtualdestr) ? "virtual " : "";
189 { case INTERFACE_DEFINITION:
190 C.pr("%^%s~%s()", v, class_name); break;
191 case INLINE_IMPLEMENTATION:
192 C.pr("%^inline %s~%s()", v, class_name); break;
193 case EXTERNAL_IMPLEMENTATION:
194 C.pr("%^%H %s%V::~%s()",
195 parameters, class_name, parameters, class_name);
197 case EXTERNAL_INSTANTIATION:
198 case EXTERNAL_DEFINITION:
199 C.pr("%^%s%P::~%s()", class_name, tys, class_name);
204 { case INLINE_IMPLEMENTATION:
205 case EXTERNAL_IMPLEMENTATION:
206 case EXTERNAL_INSTANTIATION:
208 gen_class_destructor_body(C,tys,k);
209 if (destructor_code) C.pr("%^%&", destructor_code);
212 case INTERFACE_DEFINITION:
213 case EXTERNAL_DEFINITION:
218 ///////////////////////////////////////////////////////////////////////////////
220 // Defaults method to generate various parts of the constructor and destructor
222 ///////////////////////////////////////////////////////////////////////////////
223 void ClassDefinition::gen_class_constructor_parameters(CodeGen& C,Tys,DefKind)
226 void ClassDefinition::gen_class_constructor_initializers(CodeGen&,Tys,DefKind)
229 void ClassDefinition::gen_class_constructor_body(CodeGen&,Tys,DefKind)
232 void ClassDefinition::gen_class_destructor_body(CodeGen&,Tys,DefKind)
236 ///////////////////////////////////////////////////////////////////////////////
238 // Method to add constructor code to a class
240 ///////////////////////////////////////////////////////////////////////////////
241 ClassDefinition * ClassDefinition::lookup_class_or_datatype
242 (Id class_name, Id constructor)
243 { match (lookup_ty(class_name))
244 { DATATYPEty ({ hierarchy ... }, _) | class_name == constructor:
245 { return hierarchy; }
247 { Cons cons = lookup_cons(constructor);
248 if (cons) return cons->class_def;
250 | _: { return lookup_class(ANY_CLASS,class_name); }
255 ///////////////////////////////////////////////////////////////////////////////
257 // Method to add constructor code to a class
259 ///////////////////////////////////////////////////////////////////////////////
260 void ClassDefinition::add_constructor_code
261 (Id class_name, Id constructor, Decls body)
262 { ClassDefinition * C = lookup_class_or_datatype(class_name,constructor);
263 if (C) C->constructor_code = append(C->constructor_code, body);
266 ///////////////////////////////////////////////////////////////////////////////
268 // Method to add destructor code to a class
270 ///////////////////////////////////////////////////////////////////////////////
271 void ClassDefinition::add_destructor_code
272 (Id class_name, Id destructor, Decls body)
273 { ClassDefinition * C = lookup_class_or_datatype(class_name,destructor);
274 if (C) C->destructor_code = append(C->destructor_code, body);