initial
[prop.git] / prop-src / classdef.pcc
blobe16c77477643fa59c581bc9feda04a0e494150ca
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 //  This file implements the class definition mechanism of Prop.
4 //
5 ///////////////////////////////////////////////////////////////////////////////
7 #include <iostream.h>
8 #include <AD/strings/quark.h>
9 #include "ir.ph"
10 #include "ast.ph"
11 #include "classdef.h"
12 #include "type.h"
13 #include "list.h"
14 #include "hashtab.h"
15 #include "datatype.h"
17 ///////////////////////////////////////////////////////////////////////////////
19 //  Names of various class types
21 ///////////////////////////////////////////////////////////////////////////////
22 const char * ClassDefinition::class_type_name[ClassDefinition::LAST_CLASS] =
23 {  "datatype",
24    "rewrite class",
25    "syntax class",
26    "inference class",
27    "graphtype",
28    "dataflow class",
29    "datatype subclass",
30    "attributegrammar class",
31    "constraint class",
32    "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);
44    if (e == 0)
45    {  error("%L%s %s has not been defined\n", class_type_name[ct], name);
46       return 0;
47    } else
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);
54          return 0;
55       }
56       return C;
57    }
60 void ClassDefinition::insert_class(ClassDefinition * C)
61 {  HashTable::Entry * e = defined_classes.lookup(C->class_name);
62    if (e)
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,
67             old_def->loc());
68    } else
69    {  defined_classes.insert(C->class_name,C);
70    }
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) 
81    : class_type(ct), 
82      class_name(id), parameters(p), inherited_classes(subclasses),
83      qualifiers(qual), class_body(body)
84 {  constructor_code = #[];
85    destructor_code  = #[];
86    insert_class(this);
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);
100    C.pr (" {%+\n");
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 ///////////////////////////////////////////////////////////////////////////////
118 //  Useful methods
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)
131 {  
132    inherited_classes = add_inherit(name,#[],inherited_classes,s,q);
135 void ClassDefinition::append_base_class (Id name, Scope s, TyQual q)
136 {  
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)
148    switch (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); 
155          break;
156       case EXTERNAL_INSTANTIATION:
157       case EXTERNAL_DEFINITION:
158          C.pr("%^%s%P::%s ", class_name, tys, class_name); 
159          break;
160    }
162    gen_class_constructor_parameters(C, tys, k);
164    switch (k)
165    {  case INLINE_IMPLEMENTATION:
166       case EXTERNAL_IMPLEMENTATION:
167       case EXTERNAL_INSTANTIATION:
168          gen_class_constructor_initializers(C, tys, k);
169          C.pr("%^{%+");
170          gen_class_constructor_body(C, tys, k);
171          if (constructor_code) C.pr("%^%&", constructor_code);
172          C.pr("%-%^}");
173          break;
174       case INTERFACE_DEFINITION:
175       case EXTERNAL_DEFINITION:
176          C.pr(";"); break;
177    }
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 " : "";
188    switch (k)
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);
196          break;
197       case EXTERNAL_INSTANTIATION:
198       case EXTERNAL_DEFINITION:
199          C.pr("%^%s%P::~%s()", class_name, tys, class_name);
200          break;
201    }
203    switch (k)
204    {  case INLINE_IMPLEMENTATION:
205       case EXTERNAL_IMPLEMENTATION:
206       case EXTERNAL_INSTANTIATION:
207          C.pr("%^{%+");
208          gen_class_destructor_body(C,tys,k);
209          if (destructor_code) C.pr("%^%&", destructor_code);
210          C.pr("%-%^}");
211          break;
212       case INTERFACE_DEFINITION:
213       case EXTERNAL_DEFINITION:
214          C.pr(";"); break;
215    }
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) 
224 {  C.pr("()");
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; }
246    |  DATATYPEty (_,_):
247       {  Cons cons = lookup_cons(constructor);
248          if (cons) return cons->class_def;
249       }
250    |  _: { return lookup_class(ANY_CLASS,class_name); }
251    }
252    return 0;
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);