1 ///////////////////////////////////////////////////////////////////////////////
3 // This file implements the FunctorMap data structure
5 ///////////////////////////////////////////////////////////////////////////////
8 #include <AD/automata/treegram.ph>
9 #include <AD/automata/treegen.h>
10 #include <AD/rewrite/burs_gen.h>
11 #include <AD/strings/quark.h>
15 #include "matchcom.ph"
24 ///////////////////////////////////////////////////////////////////////////////
26 // Import some type definitions from the tree grammar and hash table
29 ///////////////////////////////////////////////////////////////////////////////
30 typedef TreeGrammar::TreeProduction TreeProduction;
31 typedef TreeGrammar::Cost TreeCost;
32 typedef HashTable::Key Key;
33 typedef HashTable::Value Value;
35 ///////////////////////////////////////////////////////////////////////////////
37 // Instantiate the vector id type
39 ///////////////////////////////////////////////////////////////////////////////
40 instantiate datatype VectorId;
42 ///////////////////////////////////////////////////////////////////////////////
44 // Hashing and equality on vector id's
46 ///////////////////////////////////////////////////////////////////////////////
47 unsigned int vector_id_hash(HashTable::Key k)
48 { VectorId id = (VectorId)k;
49 return (unsigned int)id->cons + ty_hash(id->ty) + id->arity;
51 Bool vector_id_equal(HashTable::Key a, HashTable::Key b)
52 { VectorId x = (VectorId)a;
53 VectorId y = (VectorId)b;
54 return x->cons == y->cons && x->arity == y->arity && ty_equal(x->ty,y->ty);
57 ///////////////////////////////////////////////////////////////////////////////
59 // Method to decorate cost expression and attribute bindings for
62 ///////////////////////////////////////////////////////////////////////////////
63 int decor_rewrite (Pat pat, int rule, int kid, PatternVarEnv& E)
65 { NOpat || LITERALpat _ || CONSpat _: { return kid; }
66 | MARKEDpat(_,p): { pat = p; }
67 | TYPEDpat(p,_): { pat = p; }
68 | GUARDpat(p,_): { pat = p; }
69 | APPpat (_,p): { pat = p; }
70 | CONTEXTpat(_,p): { pat = p; }
72 { return decor_rewrite(ps, rule, kid, E); }
73 | LISTpat{nil,cons,head=ps,tail=rest}:
74 { kid = decor_rewrite(ps, rule, kid, E); pat = rest; }
75 | VECTORpat { len, array, elements, head_flex, tail_flex ... }:
76 { kid = decor_rewrite(elements, rule,
77 decor_rewrite(array, rule, kid, E), E);
78 if (head_flex || tail_flex)
79 error("%Lflexible vector pattern currently not supported in rewriting: %p\n", pat);
83 { Id attrib_name = #"#" + id;
84 Id cost_name = #"$" + id;
86 E.add (attrib_name, SYNexp(kid, rule, mkvar(),true), ty, ISpositive);
87 E.add (cost_name, COSTexp(kid), ty, ISpositive);
95 ///////////////////////////////////////////////////////////////////////////////
97 // Decorate a pattern list.
99 ///////////////////////////////////////////////////////////////////////////////
100 int decor_rewrite (Pats pats, int rule, int kid, PatternVarEnv& E)
101 { for_each (Pat, p, pats) kid = decor_rewrite(p, rule, kid, E);
105 ///////////////////////////////////////////////////////////////////////////////
107 // Decorate rewriting patterns.
109 ///////////////////////////////////////////////////////////////////////////////
110 int decor_rewrite (Pat pat, int rule, PatternVarEnv& E)
112 E.add (#"##", THISSYNexp(rule,mkvar(),true), ty, ISpositive);
113 E.add (#"$$", THISCOSTexp(), ty, ISpositive);
114 return decor_rewrite (pat, rule, 0, E);
117 ///////////////////////////////////////////////////////////////////////////////
119 // Constructor of the functor mapping table.
121 ///////////////////////////////////////////////////////////////////////////////
122 FunctorMap::FunctorMap(Id name, MatchRules rules)
123 : literal_map(literal_hash,literal_equal,129),
124 var_map (string_hash,string_equal),
125 type_map (ty_hash,ty_equal),
126 vector_map (vector_id_hash,vector_id_equal),
127 rule_map (ty_hash,ty_equal),
128 topdown_rule_map (ty_hash,ty_equal),
129 before_rule_map (ty_hash,ty_equal),
130 preorder_rule_map (ty_hash,ty_equal),
131 postorder_rule_map (ty_hash,ty_equal),
132 protocols (ty_hash,ty_equal),
133 nonterm_map(string_hash,string_equal),
134 nonterm_rules(string_hash,string_equal),
135 nonterm_rules_bits(string_hash,string_equal),
136 chain_rules(string_hash,string_equal),
139 ///////////////////////////////////////////////////////////////////////////
141 // Initialize the internals.
143 ///////////////////////////////////////////////////////////////////////////
150 use_compression = true;
152 has_replacement = false;
154 has_cost_exp = false;
155 has_syn_attrib = false;
156 is_applicative = false;
157 gen_reducers = false;
158 dynamic_search = false;
164 rule_maps[MatchRuleInfo::BOTTOMUP] = &rule_map;
165 rule_maps[MatchRuleInfo::TOPDOWN] = &topdown_rule_map;
166 rule_maps[MatchRuleInfo::BEFORE] = &before_rule_map;
167 rule_maps[MatchRuleInfo::PREORDER] = &preorder_rule_map;
168 rule_maps[MatchRuleInfo::POSTORDER] = &postorder_rule_map;
170 TyQual qual = RewritingCompiler::lookup_qual(class_name);
171 if (qual & QUALtreeparser) gen_reducers = true;
172 if (qual & QUALapplicative) is_applicative = true;
174 int last_errors = errors;
175 enter_protocols(); // enter the protocols
176 // partition rule by type
177 bottomup_rules = partition_rules(rules);
178 check_for_missing_protocols();
179 if (errors != last_errors) { is_ok = false; return; }
180 build_tree_grammar(bottomup_rules);
182 // BUG fix, always use dynamic search algorithm when treeparser
183 // mode is on, since the class interface has to match.
184 //dynamic_search = gen_reducers && (has_cost || has_cost_exp);
185 dynamic_search = gen_reducers;
188 ///////////////////////////////////////////////////////////////////////////////
190 // Method to enter the protocols into the protocol map
192 ///////////////////////////////////////////////////////////////////////////////
193 void FunctorMap::enter_protocols ()
194 { Protocols Ps = RewritingCompiler::lookup_protocols(class_name);
195 { for_each (Protocol, p, Ps)
197 { PROTOCOL { ty, syn ... }:
198 { encode(ty); protocols.insert(ty,p);
199 if (syn != NOty) has_syn_attrib = true;
207 ///////////////////////////////////////////////////////////////////////////////
209 // Checks for missing protocol
211 ///////////////////////////////////////////////////////////////////////////////
212 void FunctorMap::check_for_missing_protocols()
213 { foreach_entry (e, type_map)
214 { Ty ty = Ty(type_map.key(e));
215 if (! protocols.contains(ty))
216 { error("%Lmissing type %T in the traversal list of rewrite class %s\n",
222 ///////////////////////////////////////////////////////////////////////////////
224 // Otherwise, build the tree grammar and the functor/variable name maps.
226 ///////////////////////////////////////////////////////////////////////////////
227 void FunctorMap::build_tree_grammar (MatchRules rules)
230 TreeProduction * Ps =
231 (TreeProduction *)mem_pool.c_alloc(sizeof(TreeProduction) * N);
233 ////////////////////////////////////////////////////////////////////////////
235 // Translate patterns into terms
237 ////////////////////////////////////////////////////////////////////////////
239 for_each (MatchRule, r, rules)
241 { MATCHrule(lhs,pat,guard,cost,_):
242 { int rule_no = lhs ? var_map[lhs] : 0;
245 { NOcost: { cst = 0; }
246 | INTcost c: { cst = c; has_cost = true; }
247 | EXPcost _: { cst = 0; has_cost_exp = true; }
249 Ps[i] = TreeProduction(rule_no,trans(pat),cst);
250 if (guard != NOexp || (r->option & MatchRuleInfo::FAILREWRITE))
252 if (r->option & MatchRuleInfo::REPLACEMENT)
253 has_replacement = true;
260 ////////////////////////////////////////////////////////////////////////////
262 // Compute the functor/variable names
264 ////////////////////////////////////////////////////////////////////////////
267 ////////////////////////////////////////////////////////////////////////////
269 // Compile the tree grammar
271 ////////////////////////////////////////////////////////////////////////////
272 G.compile (N, Ps, functor_names, variable_names, 0, functors - 1, 0);
275 ///////////////////////////////////////////////////////////////////////////////
277 // Method to convert literal patterns inside a set of matching rules
280 ///////////////////////////////////////////////////////////////////////////////
281 void FunctorMap::make_guard (MatchRules rules)
282 { match while (rules)
283 { #[MATCHrule(_,pat,guard,_,_) ... rest]:
284 { pat = make_guard(pat, guard);
290 ///////////////////////////////////////////////////////////////////////////////
292 // Method to convert literal patterns into guards.
294 ///////////////////////////////////////////////////////////////////////////////
295 Pat FunctorMap::make_guard (Pat pat, Exp& e)
297 // return pat; // BUG fix
299 { ASpat(a,p,b,c): { new_pat = ASpat(a,make_guard(p,e),b,c); }
300 | TYPEDpat(p,ty): { new_pat = TYPEDpat(make_guard(p,e),ty); }
301 | MARKEDpat(loc,p): { new_pat = MARKEDpat(loc,make_guard(p,e)); }
302 | TUPLEpat ps: { new_pat = TUPLEpat(make_guard(ps,e)); }
303 | RECORDpat(lab_pats,f): { new_pat = RECORDpat(make_guard(lab_pats,e),f); }
304 | APPpat(a,b): { new_pat = APPpat(make_guard(a,e),make_guard(b,e)); }
305 | LITERALpat (l as (INTlit _ || REALlit _ || CHARlit _ || BOOLlit _)):
306 { Exp guard_exp = BINOPexp("==",pat->selector,LITERALexp(l));
307 e = e == NOexp ? guard_exp : BINOPexp("&&",e,guard_exp);
310 | LISTpat{cons,nil,head=ps,tail=p}:
311 { new_pat = LISTpat'{cons = cons, nil = nil,
312 head = make_guard(ps,e), tail = make_guard(p,e)};
314 | VECTORpat { cons, elements, array, len, head_flex, tail_flex }:
315 { new_pat = VECTORpat'{ cons = cons,
316 elements = make_guard(elements,e),
317 array = make_guard(array,e),
318 len = make_guard(len,e),
319 head_flex = head_flex,
320 tail_flex = tail_flex
323 | _: { new_pat = pat; }
325 if (new_pat != pat && boxed(new_pat))
326 { new_pat->ty = pat->ty;
327 new_pat->selector = pat->selector;
332 ///////////////////////////////////////////////////////////////////////////////
334 // Unguard a pattern list
336 ///////////////////////////////////////////////////////////////////////////////
337 Pats FunctorMap::make_guard (Pats ps, Exp& e)
339 { #[]: { return #[]; }
340 | #[h ... t]: { return #[make_guard(h,e) ... make_guard(t,e)]; }
344 ///////////////////////////////////////////////////////////////////////////////
346 // Unguard a labeled pattern list
348 ///////////////////////////////////////////////////////////////////////////////
349 LabPats FunctorMap::make_guard (LabPats ps, Exp& e)
351 { #[]: { return #[]; }
352 | #[h ... t]: { LabPat lab_pat;
353 lab_pat.label = h.label;
354 lab_pat.pat = make_guard(h.pat,e);
355 return #[lab_pat ... make_guard(t,e)];
360 ///////////////////////////////////////////////////////////////////////////////
362 // Check whether we know of the type
364 ///////////////////////////////////////////////////////////////////////////////
365 Bool FunctorMap::is_known_type(Ty ty)
366 { return type_map.contains(ty) ||
367 ty_equal(ty, string_ty) ||
368 ty_equal(ty, quark_ty)
369 // ty_equal(ty, integer_ty) ||
370 // ty_equal(ty, bool_ty) ||
371 // ty_equal(ty, real_ty) ||
372 // ty_equal(ty, character_ty)
376 ///////////////////////////////////////////////////////////////////////////////
378 // Check whether we the type is rewritable.
380 ///////////////////////////////////////////////////////////////////////////////
381 Bool FunctorMap::is_rewritable_type(Ty ty) { return type_map.contains(ty); }
383 ///////////////////////////////////////////////////////////////////////////////
385 // Method to assign variable encoding to a non-terminal
387 ///////////////////////////////////////////////////////////////////////////////
388 void FunctorMap::encode (Id id)
389 { if (! var_map.contains(id))
390 { ++variables; var_map.insert(id,variables);
394 ///////////////////////////////////////////////////////////////////////////////
396 // Method to assign functor encoding to a type
398 ///////////////////////////////////////////////////////////////////////////////
399 void FunctorMap::encode (Ty ty)
400 { match (deref_all(ty))
401 { ty as TYCONty(DATATYPEtycon { unit, arg ... }, _):
402 { if (! type_map.contains(ty))
403 { type_map.insert(ty, functors);
404 functors += unit + arg;
407 | TYCONty(_,tys): { for_each(Ty, ty, tys) encode(ty); }
412 ///////////////////////////////////////////////////////////////////////////////
414 // Method to assign functor encoding to a pattern.
415 // Assign a functor value to each distinct literal and pattern constructor.
417 ///////////////////////////////////////////////////////////////////////////////
418 void FunctorMap::encode(Pat pat)
420 { NOpat || WILDpat _ || IDpat _: { return; }
421 | ASpat(_,p,_,_): { pat = p; }
422 | TYPEDpat(p,_): { pat = p; }
423 | MARKEDpat(_,p): { pat = p; }
426 for_each (Pat, p, ps) { i++; encode(p); }
427 if (max_arity < i) max_arity = i;
430 | RECORDpat(lab_pats,_):
431 { for_each (LabPat, p, lab_pats) { encode(p.pat); }
432 int arity = arity_of(pat->ty);
433 if (max_arity < arity) max_arity = arity;
436 | LITERALpat (l as (QUARKlit _ || STRINGlit _ || REGEXPlit _)):
437 { if (! literal_map.contains(l))
438 { literal_map.insert(l,functors);
443 | LITERALpat (INTlit _ || REALlit _ || CHARlit _ || BOOLlit _):
444 { bug ("%Luntransformed literal pattern %p found in rewriting\n",pat); }
447 TYCONty(DATATYPEtycon { unit, arg, terms ... },_)
449 { if (pat->ty != NOty && ! type_map.contains(pat->ty))
450 { type_map.insert(pat->ty, functors);
451 functors += unit + arg;
455 | APPpat(a,b): { encode(pat->ty); pat = b; }
456 | LISTpat{cons,nil,head=ps,tail=p}:
457 { Pat new_pat = CONSpat(nil);
458 new_pat->ty = pat->ty;
460 for_each (Pat, i, ps) encode(i);
461 if (max_arity < 2) max_arity = 2;
464 | VECTORpat { cons, elements ... }:
465 { Pat new_pat = CONSpat(cons);
466 new_pat->ty = pat->ty;
468 for_each (Pat, p, elements) encode(p);
469 int l = length(elements);
470 if (max_arity < l) max_arity = l;
472 { VectorId vec_id = vector_id(cons,pat->ty,l);
473 if ( ! vector_map.contains(vec_id))
474 { vector_map.insert(vec_id, functors);
480 | _: { error ("%LSorry: pattern not supported in rewriting: %p\n", pat); return; }
484 ///////////////////////////////////////////////////////////////////////////////
486 // Method to translate a pattern into a term.
488 ///////////////////////////////////////////////////////////////////////////////
489 TreeTerm FunctorMap::trans(Pat pat)
491 { NOpat || WILDpat _: { return wild_term; }
492 | ASpat(_,p,_,_): { pat = p; }
493 | TYPEDpat(p,_): { pat = p; }
494 | MARKEDpat(_,p): { pat = p; }
495 | LITERALpat (l as (QUARKlit _ || STRINGlit _ || REGEXPlit _)):
496 { return new_term(mem_pool,literal_map[l]); }
498 { return wild_term; }
500 { return var_map.contains(id) ? var_term(var_map[id]) : wild_term;
503 { int arity = length (pats);
504 TreeTerm * subterms =
505 (TreeTerm *)mem_pool.c_alloc(sizeof(TreeTerm) * arity);
507 for_each (Pat, p, pats)
508 { subterms[i++] = trans(p); }
509 return new_term(mem_pool,0,arity,subterms);
511 | RECORDpat (lab_pats,_):
512 { match (deref(pat->ty))
513 { RECORDty (labels,_,tys):
514 { Bool relevant[256]; int i; int arity;
517 { if (relevant[i++] = is_known_type(t)) arity++; }
518 TreeTerm * subterms =
519 (TreeTerm *)mem_pool.c_alloc(sizeof(TreeTerm) * arity);
520 for (i = 0; i < arity; i++)
521 subterms[i] = wild_term;
522 for_each (LabPat, p, lab_pats)
524 for (i = 0, labs = labels, ts = tys;
525 labs && ts; labs = labs->#2, ts = ts->#2)
526 { if (p.label == labs->#1)
527 { subterms[i] = trans(p.pat); break; }
528 if (is_known_type(ts->#1)) i++;
531 return new_term(mem_pool,0,arity,subterms);
533 | _: { bug("%Lillegal record pattern %p\n", pat); }
536 | APPpat(CONSpat(ONEcons
538 alg_ty = TYCONty(DATATYPEtycon { unit ... },_) ...
540 { TreeTerm a = trans(p);
541 match (arity_of(arg_ty)) and (a)
543 { return new_term(mem_pool,type_map[pat->ty]+unit+tag,1,&a);
545 | _, tree_term(f,_,_):
546 { f = type_map[pat->ty]+unit+tag; return a; }
548 { return new_term(mem_pool, type_map[pat->ty]+unit+tag, n);
552 | CONSpat(ONEcons { tag ... }):
553 { return new_term(mem_pool, type_map[pat->ty]+tag); }
554 | LISTpat{ nil, head = #[], tail = NOpat ... }:
555 { Pat p = CONSpat(nil); p->ty = pat->ty; pat = p; }
556 | LISTpat{ head = #[], tail ... }: { pat = tail; }
557 | LISTpat{ cons, nil, head = #[h ... t], tail }:
558 { Pat new_tail = LISTpat'{cons=cons,nil=nil,head=t,tail=tail};
559 Pat new_p = APPpat(CONSpat(cons),TUPLEpat(#[h, new_tail]));
560 new_p->ty = new_tail->ty = pat->ty;
563 | VECTORpat { cons, elements ... }:
564 { TreeTerm a = trans(TUPLEpat(elements));
565 int arity = length(elements);
568 { f = vector_map[vector_id(cons,pat->ty,arity)];
572 { bug ("%Lillegal pattern: %p\n", pat); return wild_term; }
575 | _: { error ("%LSorry: pattern not supported: %p\n", pat); return wild_term; }
579 ///////////////////////////////////////////////////////////////////////////////
581 // Compute ceil(ln(2))
583 ///////////////////////////////////////////////////////////////////////////////
586 while (n > 0) { n >>= 1; bits++; }
590 ///////////////////////////////////////////////////////////////////////////////
592 // Method to compute the rhs non-terminal (if it is a chain rule)
593 // Otherwise, returns NIL.
595 ///////////////////////////////////////////////////////////////////////////////
596 Id FunctorMap::chain_rule_rhs (Pat pat)
598 { IDpat (id,_,_): { return var_map.contains(id) ? id : 0; }
599 | ASpat(_,p,_,_): { return chain_rule_rhs(p); }
600 | MARKEDpat(_,p): { return chain_rule_rhs(p); }
601 | TYPEDpat(p,_): { return chain_rule_rhs(p); }
606 ///////////////////////////////////////////////////////////////////////////////
608 // Method to partition the set of rules according to the types of the
609 // patterns. Also encode the patterns in the process.
611 ///////////////////////////////////////////////////////////////////////////////
612 MatchRules FunctorMap::partition_rules (MatchRules rules)
613 { bottomup_rules = #[];
614 // First, we assign a new type variable for each lhs non-terminal.
615 { for_each (MatchRule, r, rules)
617 { MATCHrule(lhs,_,_,_,_):
618 { if (r->mode == MatchRuleInfo::BOTTOMUP)
619 { bottomup_rules = #[ r ... bottomup_rules ];
621 { HashTable::Entry * lhs_entry = nonterm_map.lookup(lhs);
622 if (! lhs_entry) nonterm_map.insert(lhs,mkvar());
623 encode(lhs); // compute encoding for the variable
624 HashTable::Entry * e = nonterm_rules.lookup(lhs);
625 if (! e) nonterm_rules.insert(lhs,#[r]);
626 else { e->v = #[ r ... MatchRules(e->v)]; }
627 } else if (dynamic_search)
628 error("%!missing non-terminal in tree grammar rule: %r\n",
631 { error("%!illegal non-terminal in non bottom-up rule: %r\n",
639 bottomup_rules = rev(bottomup_rules);
641 // Compute the size needed to encode each non-terminal
642 { foreach_entry (e, nonterm_rules)
643 { int bits = ln2(length(MatchRules(e->v))+1);
644 nonterm_rules_bits.insert(e->k,HashTable::Value(bits));
648 // Type check all the rules next.
649 // We have to also compute the type map for each lhs non-terminal.
650 // Of course, a non-terminal but have only one single type.
651 // This is done by unifying all occurances of a non-terminal.
653 patvar_typemap = &nonterm_map; // set the pattern variable type map
655 for_each (MatchRule, r, bottomup_rules)
657 { MATCHrule(lhs,pat,_,_,_):
659 Ty ty = r->ty = type_of(pat);
661 // Check the type of the non-terminal (if any).
663 { Ty lhs_ty = Ty(nonterm_map.lookup(lhs)->v);
664 if (! unify(lhs_ty, ty))
665 { error("%!type mismatch between nonterminal %s(type %T) and rule %r(type %T)\n",
666 r->loc(),lhs,lhs_ty,r,ty);
670 if (! is_datatype(ty))
671 error ("%!rule %r is of a non datatype: %T\n",r->loc(),r,ty);
673 // Collect chain rules.
675 { Id rhs = chain_rule_rhs(pat);
677 { HashTable::Entry * cr = chain_rules.lookup(rhs);
678 if (! cr) chain_rules.insert(rhs, #[r]);
679 else { cr->v = #[ r ... MatchRules(cr->v)]; }
680 r->is_chain_rule = true;
687 patvar_typemap = 0; // reset the pattern variable type map
689 // Now partition rules by type and assign functor encoding.
690 // Since we have also typed the rules, this is quite simple: just
691 // another pass. We have to make sure that after the type inference
692 // we don't have any more polymorphic types inside the patterns.
694 for_each (MatchRule, R, rules)
696 { MATCHrule(_,pat,guard,_,_) | R->mode != MatchRuleInfo::BOTTOMUP:
698 R->ty = type_of(pat);
699 HashTable::Entry * e = rule_maps[R->mode]->lookup(R->ty);
700 if (e) e->v = #[ R ... (MatchRules)e->v ];
701 else rule_maps[R->mode]->insert(R->ty,#[ R ]);
703 | MATCHrule(_,pat,guard,_,_):
704 { if (! is_ground(R->ty))
705 error ("%!rule %r has incomplete type %T\n",R->loc(),R,R->ty);
707 HashTable::Entry * e = rule_map.lookup(R->ty);
708 if (e) e->v = #[ R ... (MatchRules)e->v ];
709 else rule_map.insert(R->ty,#[ R ]);
711 // convert literals into guards
712 // BUG: 2-6-97 This doesn't work right since
713 // the guard testing is not prioritized properly !!!
714 pat = make_guard (pat, guard);
716 // assign functor encoding
719 R->rule_number = rule_num++;
724 return bottomup_rules;
727 ///////////////////////////////////////////////////////////////////////////////
729 // Method to compute the functor and variable table.
731 ///////////////////////////////////////////////////////////////////////////////
732 void FunctorMap::compute_names ()
734 functor_names = (Id *)mem_pool.c_alloc(sizeof(Id) * functors);
735 variable_names = (Id *)mem_pool.c_alloc(sizeof(Id) * (variables + N + 4));
737 { for (int i = N + variables - 1; i >= 0; i--) variable_names[i] = 0; }
738 { for (int i = functors - 1; i >= 0; i--) functor_names[i] = "???"; }
739 variable_names[0] = "_";
741 // Compute variable names
742 { foreach_entry (i,var_map)
743 variable_names[var_map.value(i)] = (Id)var_map.key(i);
746 // Compute literal names
747 { foreach_entry (i,literal_map)
748 { Literal l = (Literal)literal_map.key(i);
749 Functor f = literal_map.value(i);
751 ostrstream b(buf,sizeof(buf));
754 functor_names[f] = Quark(buf);
758 // Compute constructor names
759 { foreach_entry (i,type_map)
760 { Ty t = (Ty)type_map.key(i);
761 Functor f = type_map.value(i);
763 { TYCONty(DATATYPEtycon { unit, arg, terms ... },_):
764 { int arity = unit + arg;
765 for (int j = 0; j < arity; j++)
767 { ONEcons { name, ty, tag ... }:
768 { functor_names[f + (ty == NOty ? tag : tag + unit)] =
775 | _: { bug ("compute_names()"); }
780 // Compute vector constructor names
781 { foreach_entry (i, vector_map)
782 { VectorId id = (VectorId)vector_map.key(i);
783 Functor f = vector_map.value(i);
784 if (id->cons) functor_names[f] = id->cons->name;
789 ///////////////////////////////////////////////////////////////////////////////
791 // Method to print a report detailing the functor/variable encoding,
792 // the tree grammar and the generated table size.
794 ///////////////////////////////////////////////////////////////////////////////
795 void FunctorMap::print_report (ostream& log)
797 if (var_map.size() > 0)
798 { log << "Variable encoding:\n";
799 foreach_entry (e, var_map)
800 { log << "\tnon-terminal \"" << (Id)var_map.key(e) << "\"\t=\t"
801 << var_map.value(e) << '\n';
805 if (literal_map.size() > 0)
806 { log << "\nFunctor encoding for literals:\n";
807 foreach_entry (e, literal_map)
808 { log << "literal " << (Literal)literal_map.key(e) << "\t=\t"
809 << literal_map.value(e) << '\n';
813 log << "\nFunctor encoding for constructors:\n";
815 { foreach_entry (e, type_map)
816 { Ty t = (Ty)type_map.key(e);
817 Functor f = type_map.value(e);
818 log << "datatype " << t << ":\n";
820 { TYCONty(DATATYPEtycon { unit, arg, terms ... },_):
821 { int arity = unit + arg;
822 for (int i = 0; i < arity; i++)
824 { ONEcons { name, ty, tag ... }:
825 { log << '\t' << name << "\t=\t"
826 << f + (ty == NOty ? tag : tag + unit) << '\n';
839 log << "\nIndex compression is "
840 << (use_compression ? "enabled" : "disabled")
841 << "\nAlgorithm is " << tree_gen->algorithm();
842 tree_gen->print_report(log);
846 ///////////////////////////////////////////////////////////////////////////////
848 // Method to return the cost expression for a pattern.
850 ///////////////////////////////////////////////////////////////////////////////
851 Exp FunctorMap::cost_expr (Id lhs, Pat pat)
853 { NOexp: { return LITERALexp(INTlit(0)); }
854 | _: { return cost_expr(lhs,pat,LITERALexp(INTlit(1))); }
858 ///////////////////////////////////////////////////////////////////////////////
860 // Method to compute the cost expression for a pattern
862 ///////////////////////////////////////////////////////////////////////////////
863 Exp FunctorMap::cost_expr (Id lhs, Pat pat, Exp exp)
865 { NOpat || LITERALpat _ || CONSpat _: { return exp; }
866 | ASpat (_,p,_,_): { return cost_expr(lhs,p,exp); }
867 | MARKEDpat(_,p): { return cost_expr(lhs,p,exp); }
868 | TYPEDpat(p,_): { return cost_expr(lhs,p,exp); }
869 | GUARDpat(p,_): { return cost_expr(lhs,p,exp); }
870 | APPpat (_,p): { return cost_expr(lhs,p,exp); }
871 | CONTEXTpat(_,p): { return cost_expr(lhs,p,exp); }
872 | TUPLEpat ps: { return cost_expr(lhs,ps,exp); }
873 | EXTUPLEpat ps: { return cost_expr(lhs,ps,exp); }
874 | ARRAYpat (ps,_): { return cost_expr(lhs,ps,exp); }
875 | RECORDpat(lab_pats,_): { return cost_expr(lhs,lab_pats,exp); }
876 | LISTpat{head,tail ...}:
877 { return cost_expr(lhs,head,cost_expr(lhs,tail,exp)); }
878 | VECTORpat { len, array, elements ... }:
879 { return cost_expr(lhs,len,cost_expr(lhs,array,
880 cost_expr(lhs,elements,exp))); }
881 | IDpat (id,_,_): // skip
886 // BUG fix: if the argument type is not a datatype or
887 // not rewritable, then there is no cost to consider.
888 if (! is_datatype(pat->ty) || ! is_rewritable_type(pat->ty))
891 Ty state_rec_ty = mkptrty(mkidty(Quark(class_name,"_StateRec"),#[]));
895 CASTexp(state_rec_ty,
896 APPexp(ARROWexp(pat->selector,"get_state_rec"), TUPLEexp(#[]))),
897 "cost"), LITERALexp(INTlit(int(var_map[lhs]))));
898 return exp == NOexp ? cost_e : BINOPexp("+",cost_e,exp);
901 ///////////////////////////////////////////////////////////////////////////////
903 // Method to compute the cost expression for a pattern list
905 ///////////////////////////////////////////////////////////////////////////////
906 Exp FunctorMap::cost_expr (Id lhs, Pats pats, Exp exp)
908 { #[]: { return exp; }
909 | #[h ... t]: { return cost_expr(lhs,h,cost_expr(lhs,t,exp)); }
913 ///////////////////////////////////////////////////////////////////////////////
915 // Method to compute the cost expression for a labeled pattern list
917 ///////////////////////////////////////////////////////////////////////////////
918 Exp FunctorMap::cost_expr (Id lhs, LabPats pats, Exp exp)
920 { #[]: { return exp; }
921 | #[h ... t]: { return cost_expr(lhs,h.pat,cost_expr(lhs,t,exp)); }