1 ///////////////////////////////////////////////////////////////////////////////
3 // This file handles datatype instantiation processing.
5 ///////////////////////////////////////////////////////////////////////////////
12 #include <AD/strings/quark.h>
14 ///////////////////////////////////////////////////////////////////////////////
16 // Equality and hashing on cons/tys pairs
18 ///////////////////////////////////////////////////////////////////////////////
19 unsigned int id_tys_hash(HashTable::Key a)
20 { Pair<Id,Tys> key = (Pair<Id,Tys>)a;
21 return (unsigned int)key->fst + tys_hash(key->snd);
23 Bool id_tys_equal(HashTable::Key a, HashTable::Key b)
24 { Pair<Id,Tys> x = (Pair<Id,Tys>)a;
25 Pair<Id,Tys> y = (Pair<Id,Tys>)b;
26 return x->fst == y->fst && tys_equal(x->snd,y->snd);
29 unsigned int pid_hash(Pid pid)
31 { PERSISTid id: { return string_hash(id); }
32 | PERSISTnone: { return 1235; }
36 Bool pid_equal(Pid a, Pid b)
38 { PERSISTid a, PERSISTid b: { return string_equal(a,b); }
39 | _, _: { return false; }
43 ///////////////////////////////////////////////////////////////////////////////
45 // Global hashtables to store mapping from types to persistent Id's
48 ///////////////////////////////////////////////////////////////////////////////
49 HashTable type_pid_map(id_tys_hash, id_tys_equal);
50 HashTable pid_type_map(pid_hash, pid_equal);
52 ///////////////////////////////////////////////////////////////////////////////
54 // Enter a new persistent id entry
56 ///////////////////////////////////////////////////////////////////////////////
57 void update_persistent(Id id, Tys tys, Pid pid)
58 { Pair<Id,Tys> key = pair(id,tys);
59 HashTable::Entry * e1 = type_pid_map.lookup((HashTable::Key)key);
60 HashTable::Entry * e2 = pid_type_map.lookup((HashTable::Key)pid);
62 { error ("%Lpersistence redefined for type %s%P\n",id,tys);
65 { Pair<Id,Tys> previous = (Pair<Id,Tys>)(e2->v);
66 error ("%Lpersistence pid %Q already allocated for type %s%P\n",
67 pid, previous->fst, previous->snd);
69 if (e1 == 0 && e2 == 0)
70 { type_pid_map.insert(key,(HashTable::Value)pid);
71 pid_type_map.insert((HashTable::Key)pid,key);
74 // add persistent qualifier to the constructor's type
76 { DATATYPEty ({ qualifiers ... },_): { qualifiers |= QUALpersistent; }
77 | _: { error("%Ltype %s%P is not a datatype\n",id,tys); }
81 ///////////////////////////////////////////////////////////////////////////////
83 // Lookup a new persistent id entry
85 ///////////////////////////////////////////////////////////////////////////////
86 Pid lookup_persistent(Id id, Tys tys)
87 { Pair<Id,Tys> key = pair(id,tys);
88 HashTable::Entry * e1 = type_pid_map.lookup((HashTable::Key)key);
90 { return value_of(Pid, type_pid_map, e1); }
92 { error ("%Lpersist object id is undefined for %s%P\n",id,tys);
97 ///////////////////////////////////////////////////////////////////////////////
99 // Method to generate datatype instantiate code.
101 ///////////////////////////////////////////////////////////////////////////////
102 void DatatypeCompiler::instantiate_datatypes(Bool extern_def, Tys tys)
104 for_each(Ty, ty, tys)
106 { TYCONty (IDtycon id, args):
107 { match (lookup_ty(id))
108 { TYCONty(tycon as DATATYPEtycon
109 { id, tyvars, polyty, qualifiers, opt, unit, arg,
110 inherit, terms ... },_):
111 { if ((qualifiers & QUALview) == 0)
113 (extern_def, id, tyvars, args, unit, arg,
114 qualifiers, opt, polyty,inherit, terms);
116 | NOty: { error ("%Ltype %T is undefined\n", ty); }
117 | _: { error("%Ltype %T is not a datatype\n", ty); }
120 | _: { error ("%Ltype %T is undefined\n", ty); }
125 ///////////////////////////////////////////////////////////////////////////////
127 // Instantiate one datatype
129 ///////////////////////////////////////////////////////////////////////////////
130 void DatatypeCompiler::instantiate_datatype
131 (Bool extern_def, Id id, TyVars tyvars, Tys tys, int unit,
132 int arg, int qual, int opt, Ty polyty, Inherits inherits, Cons terms[])
133 { int arity = unit + arg;
135 // Generate inference interface.
136 if (qual & QUALprintable)
137 gen_pretty_printer(extern_def, deref_all(TYCONty(IDtycon(id),tys)), tys);
139 // Generate inference interface.
140 if ((qual & QUALrelation) && ! extern_def) {
141 pr ("%^%/%^// Relation class %s interface%^%/"
142 "%^Fact::RelTag a_%s::relation_tag = 0;"
143 "%^static InitialiseFact %s_dummy__(a_%s::relation_tag);"
144 "%^Fact::RelTag a_%s::get_tag() const { return a_%s::relation_tag; }\n\n",
145 id, id, id, id, id, id);
148 // Generate garbage collection tracing methods.
149 // Generate persistence read/write methods.
151 Bool has_persistence = false;
153 if (!(opt & OPTsubclassless) && arg > 0) {
154 if (qual & QUALcollectable)
155 { has_gc = gen_gc_trace(extern_def,
156 id, tyvars, tys, #[], NOty, polyty, opt, inherits, has_gc);
158 if (qual & QUALpersistent)
160 gen_persistence(extern_def, id, tyvars, tys, 0, NOty,
161 polyty, opt, inherits, has_persistence);
165 if (!extern_def && options.save_space
166 && ! (opt & OPTsubclassless) && tys == #[])
167 gen_class_destructor(id,#[],0,NOty,qual,opt,false);
169 for (int i = 0; i < arity; i++)
171 { ONEcons { name, cons_ty, ty = ty as ! NOty, opt = my_opt,
173 alg_ty = TYCONty(DATATYPEtycon { tyvars ... }, _) ... }:
174 { Ty arg_ty = apply_ty(cons_ty, tys);
175 if (qual & QUALcollectable)
176 gen_gc_trace(extern_def, id, tyvars, tys, name, arg_ty,
177 polyty, opt, inherits, has_gc);
178 if (qual & QUALpersistent)
179 gen_persistence(extern_def, id, tyvars, tys, name, arg_ty,
180 polyty, opt, inherits, has_persistence);
181 if (! extern_def && options.save_space && tyvars == #[]) {
182 Bool save = print_default_value;
183 print_default_value = false;
184 gen_class_constructor(id,#[],name,unit,arg,opt,arg_ty,false,cons_qual);
185 gen_datatype_constructor(id,#[],name,unit,arg,opt|my_opt,arg_ty,false,cons_qual);
186 gen_class_destructor(id,#[],name,ty,qual,opt|my_opt,false);
187 print_default_value = save;
195 ///////////////////////////////////////////////////////////////////////////////
197 // Method to generate the GC tracing method for one subclass
199 ///////////////////////////////////////////////////////////////////////////////
200 Bool DatatypeCompiler::gen_gc_trace
201 (Bool extern_def, Id id, TyVars tyvars, Tys tys, Id name,
202 Ty ty, Ty alg_ty, int opt, Inherits inherits, Bool has_gc)
204 if (extern_def && tys == #[]) return false;
206 Bool is_base = (name == 0) || (opt & OPTsubclassless);
208 pr ("%^%/%^// GC tracing method for base class of %s%P%^%/", id, tys);
210 pr ("%^%/%^// GC tracing method for %s%P::%S %T%^%/", id, tys, name, ty);
211 pr ("%^void %s_%S%P::trace(GC * _gc_)%s\n",
212 (is_base ? "a" : id), (is_base ? id : name), tys,(extern_def ? ";" : ""));
214 if (extern_def) return false;
217 // Generate code for to call trace methods of superclasses.
219 { for_each (Inherit, i, inherits)
221 { { super_class, qualifiers ... }:
222 { if ((qualifiers & QUALcollectable) || is_gc_ty(super_class))
223 { Ty super_ty = apply_ty(mkpolyty(super_class,tyvars), tys);
224 pr ("%^%t::trace(_gc_);", super_ty, "");
232 // Generate code for to invoke trace on each collectable component
234 { Bool is_array_con = is_array_constructor(name);
235 if (has_gc) pr("%^a_%s%P::trace(_gc_);",id,tys);
236 if (is_array_con) ty = TYCONty(ARRAYtycon(IDexp("len_")),#[ty]);
238 { TYCONty(TUPLEtycon, tys):
240 for_each(Ty, t, tys) { gen_trace(t, index_of(i)); i++; }
242 | TYCONty(RECORDtycon (labs,_), tys):
244 for(l = labs, t = tys; l; l = l->#2, t = t->#2)
245 gen_trace(t->#1,l->#1);
247 | ty: { gen_trace(ty,name); }
255 ///////////////////////////////////////////////////////////////////////////////
257 // Generate tracing code for one component.
259 ///////////////////////////////////////////////////////////////////////////////
260 void DatatypeCompiler::gen_trace (Ty ty, Id exp)
263 { ARRAYty(ty,bound) | bound != NOexp:
266 "%^for (_i_ = (%e) - 1; _i_ >= 0; --_i_)%+"
267 "%^%S[_i_] = (%t)_gc_->trace(%S[_i_]);"
269 bound, exp, ty, "", exp);
271 | ty: { if (is_gc_ty(ty))
272 { if (is_pointer_ty(ty))
273 pr("%S = (%t)_gc_->trace(%S); ", exp, ty, "", exp);
275 pr("%S.trace(_gc_); ", exp);
279 pr ("// %T\n", deref_all(ty));
282 ///////////////////////////////////////////////////////////////////////////////
284 // Method to generate the persistence read/write methods for one subclass
286 ///////////////////////////////////////////////////////////////////////////////
287 Bool DatatypeCompiler::gen_persistence
288 (Bool extern_def, Id id, TyVars tyvars, Tys tys, Id name,
289 Ty ty, Ty alg_ty, int opt, Inherits inherits, Bool has_persistence)
291 if (extern_def) return false;
293 Bool is_base = (name == 0) || (opt & OPTsubclassless);
295 pr ("%^%/%^// Persistence read/write methods for base class of %s%P%^%/",
298 pr ("%^%/%^// Persistence read/write methods for %s%P::%S %T%^%/",
301 Id prefix = is_base ? "a" : id;
302 Id suffix = is_base ? id : name;
304 Pid pid = lookup_persistent(id, tys);
305 Id object_type = temp_vars.new_label();
306 pr ("%^static PObjectType %s(%Q \"(%s%P::%s)\");"
307 "%^const PObjectType& %s_%S%P::persist_type_id() const { return %s; }",
308 object_type, pid, id, tys, (name ? name : "base_class"),
309 prefix, suffix, tys, object_type
312 // base class cannot have its own object factory
314 pr ("%^static PObjectFactory< %s_%S%P > %s(%s);\n",
315 prefix, suffix, tys, temp_vars.new_label(), object_type);
317 pr ("%^Pistream& %s_%S%P::persist_read (Pistream& _f_)\n",
318 prefix, suffix, tys, inherits);
320 gen_persist_IO_body(id,tyvars,tys,name,ty,">>",inherits,has_persistence);
321 pr ("%^Postream& %s_%S%P::persist_write (Postream& _f_) const\n",
322 prefix, suffix, tys, inherits);
324 gen_persist_IO_body(id,tyvars,tys,name,ty,"<<",inherits,has_persistence);
325 return has_persistence;
328 ///////////////////////////////////////////////////////////////////////////////
330 // Method to generate the persistence read/write method body.
332 ///////////////////////////////////////////////////////////////////////////////
333 Bool DatatypeCompiler::gen_persist_IO_body
334 (Id id, TyVars tyvars, Tys tys, Id name, Ty ty, Id io, Inherits inherits,
335 Bool has_persistence)
336 { Id read_or_write = io[0] == '>' ? "read" : "write";
339 { if (is_array_constructor(name))
340 ty = TYCONty(ARRAYtycon(IDexp("len_")),#[ty]);
342 pr ("%^a_%s%P::persist_%s(_f_);", id, tys, read_or_write);
344 { TYCONty(TUPLEtycon, tys):
346 for_each(Ty, t, tys) { gen_persist_IO(t, index_of(i), io); i++; }
348 | TYCONty(RECORDtycon (labs,_), tys):
350 for(l = labs, t = tys; l; l = l->#2, t = t->#2)
351 gen_persist_IO(t->#1,l->#1,io);
353 | ty: { gen_persist_IO(ty,name,io); }
356 // generate base class persistence calls.
357 for_each(Inherit, i, inherits)
359 { { super_class, qualifiers ... }:
360 { if ((qualifiers & QUALpersistent) ||
361 has_qual(QUALpersistent,super_class))
362 { Ty super_ty = apply_ty(mkpolyty(super_class,tyvars), tys);
363 pr ("%^%t::persist_%s(_f_);", super_ty, "", read_or_write);
364 has_persistence = true;
372 return has_persistence;
375 ///////////////////////////////////////////////////////////////////////////////
377 // Method to generate a persistence read/write call.
379 ///////////////////////////////////////////////////////////////////////////////
380 void DatatypeCompiler::gen_persist_IO(Ty ty, Id exp, Id io)
381 { Bool is_reading = io[0] == '>';
383 match (deref_all(ty))
384 { ARRAYty(ty,bound) | bound != NOexp:
385 { pr ("%^{ int _i_;%+"
386 "%^for (_i_ = (%e) - 1; _i_ >= 0; --_i_)%+",
389 if (is_reading && is_datatype(ty))
390 pr("%^%S[_i_] = (%t)read_object(_f_); ", exp, ty, "");
392 pr("%^_f_ %s %S[_i_]; ", io, exp);
395 | ty: { if (is_reading && is_datatype(ty))
396 pr("%^%S = (%t)read_object(_f_); ", exp, ty, "");
398 pr("%^_f_ %s %S; ", io, exp);
401 pr ("// %T\n", deref_all(ty));