1 /////////////////////////////////////////////////////////////////////////////
3 // This file implements the DatatypeClass
5 //////////////////////////////////////////////////////////////////////////////
6 #include <AD/strings/quark.h>
15 //////////////////////////////////////////////////////////////////////////////
17 // Constructor for DatatypeClass
19 //////////////////////////////////////////////////////////////////////////////
20 DatatypeClass::DatatypeClass
21 (CLASS_TYPE my_class_type,
22 Id cid, Id id, TyVars p, Inherits i, TyQual q, Decls d, Cons c,
23 DatatypeHierarchy * r)
24 : ClassDefinition(my_class_type,id,p,i,q,d),
25 constructor_name(cid), cons(c), root(r),
26 generating_list_special_forms(false),
27 cons_arg_ty(NOty), has_destructor(false)
29 is_const = (qualifiers & QUALconst) ? "const " : "";
30 is_list = is_list_constructor(constructor_name);
31 is_array = is_array_constructor(constructor_name);
34 DatatypeClass::~DatatypeClass() {}
36 //////////////////////////////////////////////////////////////////////////////
38 // Method to update the qualifiers and other
40 //////////////////////////////////////////////////////////////////////////////
41 void DatatypeHierarchy::get_info()
48 match (lookup_ty(datatype_name))
49 { DATATYPEty({ qualifiers = q, body = b, unit, arg, terms ... },_):
52 for (int i = 0; i < number_of_subclasses; i++)
53 { match (subclasses[i]->cons)
54 { ONEcons { inherit, qual, body ... }:
55 { // subclasses[i]->inherited_classes = inherit;
56 subclasses[i]->qualifiers |= qual;
57 subclasses[i]->class_body = body;
69 // Construct the inheritance list and fix it up if necessary
71 build_inheritance_list();
74 // Use inline methods if we are not in space saving mode
75 // or if the user specificately specified the inline qualifier
77 Bool must_inline = (qualifiers & QUALinline);
78 Bool must_not_inline = (qualifiers & QUALextern);
79 if (must_inline && must_not_inline)
80 { error("%Ldatatype %s%V cannot be inline and external at the same time",
81 datatype_name, parameters
84 if (must_inline) inline_methods = true;
85 else if (must_not_inline) inline_methods = false;
86 else inline_methods = (! options.save_space);
89 // Use a variant tag if we have subclasses in our hierarchy
90 // and if the tag is not embedded into the pointer representation
92 has_variant_tag = ((optimizations & OPTtagless) == 0);
94 has_destructor = (qualifiers & QUALvirtualdestr) || (cons && is_array);
97 //////////////////////////////////////////////////////////////////////////////
99 // Constructor for DatatypeHierarchy
101 //////////////////////////////////////////////////////////////////////////////
102 DatatypeHierarchy::DatatypeHierarchy
103 (Id id, TyVars p, Inherits i, TyQual q, TermDefs t, Decls d)
104 : DatatypeClass(DATATYPE_CLASS,id,#"a_" + id,p,i,q,d,NOcons,this),
105 datatype_name(id), term_defs(t), subclasses(0),
106 number_of_subclasses(0), datatype_ty(NOty)
108 unit_constructors = 0;
109 arg_constructors = 0;
110 constructor_terms = 0;
111 use_persist_base = false;
116 // Build the class hierarchy
118 build_class_hierarchy();
122 DatatypeHierarchy::~DatatypeHierarchy()
124 delete [] subclasses;
127 //////////////////////////////////////////////////////////////////////////////
129 // Method to build the class hierarchy given a datatype.
130 // We'll create a DatatypeClass object for each subclass.
132 //////////////////////////////////////////////////////////////////////////////
133 void DatatypeHierarchy::build_class_hierarchy()
135 // don't bother building the class hierarchy for views
136 if (is_view()) return;
138 // construct class hierarchy
139 match (lookup_ty(datatype_name))
140 { mytype as DATATYPEty({ unit, arg, opt, terms, hierarchy ... }, _):
141 { arity = unit + arg;
142 unit_constructors = unit;
143 arg_constructors = arg;
144 constructor_terms = terms;
146 datatype_ty = mytype;
148 if (arg > 0) // build class hierarchy only if we have more than
150 { if (opt & OPTsubclassless) // no subclass
151 { number_of_subclasses = 0;
152 for (int i = 0; i < arity; i++)
153 { if (terms[i]->ty != NOty)
155 constructor_name = cons->name;
156 is_list = is_list_constructor(constructor_name);
157 is_array = is_array_constructor(constructor_name);
158 class_body = append(class_body, terms[i]->body);
163 { number_of_subclasses = arg;
164 subclasses = new DatatypeClass * [number_of_subclasses];
165 for (int i = 0, j = 0; i < arity; i++)
166 { if (terms[i]->ty != NOty)
167 { subclasses[j++] = build_one_subclass(terms[i]);
177 //////////////////////////////////////////////////////////////////////////////
179 // Method to build one subclass in the hierarchy.
181 //////////////////////////////////////////////////////////////////////////////
182 DatatypeClass * DatatypeHierarchy::build_one_subclass(Cons cons)
184 { ONEcons { name, ty, location, inherit, body, qual, class_def ... }:
185 { return class_def = new DatatypeClass(
188 Quark(mangle(datatype_name),"_",mangle(name)),
190 add_inherit(class_name,parameters,inherit),
200 //////////////////////////////////////////////////////////////////////////////
202 // Method to build the inheritance list of the class hierachy.
204 //////////////////////////////////////////////////////////////////////////////
205 void DatatypeHierarchy::build_inheritance_list()
207 if (qualifiers & QUALrelation) append_base_class("Fact");
208 if (qualifiers & QUALrewritable) append_base_class("TermObj");
209 if (qualifiers & QUALpersistent) append_base_class("PObject");
211 if (qualifiers & QUALcollectable)
212 { // Make sure we are only inheriting from one collectable object
213 // Make sure virtual inheritance is not used.
214 // Make sure that the collectable object is the first base class.
218 for_each (Inherit, inh, inherited_classes)
219 { if((inh->qualifiers & QUALcollectable) || is_gc_ty(inh->super_class))
222 { msg("%!%wcollectable object %T must be first base class\n",
223 inh->loc(), inh->super_class);
226 if (inh->qualifiers & QUALvirtual)
227 { msg("%!%wvirtual inheritance of %T may fail"
228 " with garbage collection\n",
229 inh->loc(), inh->super_class);
234 { error("%Linheritance of multiple collectable object will fail\n");
237 { add_base_class("GCObject");
242 //////////////////////////////////////////////////////////////////////////////
244 // Method to generate a class constructor
246 //////////////////////////////////////////////////////////////////////////////
247 void DatatypeClass::gen_class_constructor(CodeGen& C, Tys tys, DefKind k)
249 ClassDefinition::gen_class_constructor(C,tys,k);
252 { generating_list_special_forms = true;
253 ClassDefinition::gen_class_constructor(C,tys,k);
254 generating_list_special_forms = false;
258 //////////////////////////////////////////////////////////////////////////////
260 // Method to generate the constructor parameters.
262 //////////////////////////////////////////////////////////////////////////////
263 void DatatypeClass::gen_class_constructor_parameters
264 (CodeGen& C, Tys tys, DefKind k)
266 Ty arg_ty = cons_arg_ty;
267 match (deref(arg_ty))
268 { TUPLEty #[a,b] | generating_list_special_forms:
269 { arg_ty = mktuplety(#[a]); }
274 { case EXTERNAL_IMPLEMENTATION:
275 case EXTERNAL_INSTANTIATION:
276 param = TYsimpleformal; break;
278 param = TYformal; break;
280 C.pr("%b", arg_ty, cons->name, param);
283 //////////////////////////////////////////////////////////////////////////////
285 // Method to generate the constructor initializers.
287 //////////////////////////////////////////////////////////////////////////////
288 void DatatypeClass::gen_class_constructor_initializers
289 (CodeGen& C, Tys tys, DefKind k)
292 { ONEcons { ty, cons_ty, name ... }:
297 // First generate the tag initializer
298 if (root->has_variant_tag)
299 { if (k == EXTERNAL_INSTANTIATION)
300 C.pr(" : %s%P(tag_%S)",
301 root->class_name, tys, constructor_name);
303 C.pr(" : %s%V(tag_%S)",
304 root->class_name, parameters, constructor_name);
305 colon = ""; comma = ", ";
308 // Now generate the initializers for the arguments
309 gen_constructor_initializers(C,tys,k,cons_arg_ty,colon,comma);
315 //////////////////////////////////////////////////////////////////////////////
317 // Method to generate the constructor initializers.
319 //////////////////////////////////////////////////////////////////////////////
320 void DatatypeClass::gen_constructor_initializers
321 (CodeGen& C, Tys tys, DefKind k, Ty ty, Id colon, Id comma)
324 { C.pr("%s%slen_(x__len_)", colon, comma);
325 colon = ""; comma = ", ";
326 ty = mkarrayty(ty,IDexp("len_"));
330 { TUPLEty #[]: // skip
331 | TUPLEty ts: // tuple arguments
334 { if (generating_list_special_forms && i == 2)
335 { if (k == EXTERNAL_INSTANTIATION)
336 C.pr("%s%s_%i((%s%P *)0)", colon, comma,
337 i, root->class_name, tys, i);
339 C.pr("%s%s_%i((%s%V *)0)", colon, comma,
340 i, root->class_name, parameters, i);
341 colon = ""; comma = ", ";
344 { if (! is_array_ty(t))
345 { C.pr("%s%s_%i(x_%i)", colon, comma, i, i);
346 colon = ""; comma = ", ";
352 | RECORDty (labels,_,tys): // record arguments
354 for (l = labels, t = tys; l && t; l = l->#2, t = t->#2) {
355 if (! is_array_ty(t->#1))
356 { C.pr("%s%s%s(x_%s)", colon, comma, l->#1, l->#1);
357 colon = ""; comma = ", ";
361 | ty: // single argument
362 { if (! is_array_ty(ty))
363 { C.pr("%s%s%S(x_%S)",
364 colon, comma, constructor_name, constructor_name);
365 colon = ""; comma = ", ";
371 //////////////////////////////////////////////////////////////////////////////
373 // Methods to generate body of a constructor
375 //////////////////////////////////////////////////////////////////////////////
376 void DatatypeClass::gen_class_constructor_body(CodeGen& C, Tys tys, DefKind k)
378 if (cons == NOcons) return;
382 { ty = mkarrayty(ty,IDexp("len_"));
385 // Now generate the initializers for array arguments
387 { TUPLEty #[]: // skip
388 | TUPLEty ts: // tuple arguments
391 { gen_array_initializer(C,tys,k,index_of(i),t,"x");
395 | RECORDty (labels,_,tys):
397 for(ls = labels, ts = tys; ls && ts; ls = ls->#2, ts = ts->#2)
398 { gen_array_initializer(C,tys,k,ls->#1,ts->#1,"x_");
401 | t: { gen_array_initializer(C,tys,k,mangle(cons->name),t,"x_"); }
405 //////////////////////////////////////////////////////////////////////////////
407 // Methods to generate body of a constructor
409 //////////////////////////////////////////////////////////////////////////////
410 void DatatypeClass::gen_array_initializer
411 (CodeGen& C, Tys tys, DefKind k, Id exp, Ty ty, Id prefix)
413 { ARRAYty(elem_ty,bound):
415 "%^for (int i__ = 0; i__ < (%e); i__++)"
419 { C.pr("%^typedef %t ELEMENT_TYPE__;"
420 "%^new (%S + i__) ELEMENT_TYPE__ (%s%S[i__]);",
421 elem_ty, "", exp, prefix, exp);
423 { C.pr("%^%S[i__] = %s%S[i__];", exp, prefix, exp);
432 //////////////////////////////////////////////////////////////////////////////
434 // Methods to generate array initialization code.
436 //////////////////////////////////////////////////////////////////////////////
438 //////////////////////////////////////////////////////////////////////////////
440 // Methods to generate destructor code.
442 //////////////////////////////////////////////////////////////////////////////
443 void DatatypeClass::gen_class_destructor_body(CodeGen& C, Tys tys, DefKind)
445 if (is_array && cons)
447 "%^for (int i__; i__ < len_; i__++)"
449 "%^typedef %t ELEMENT_TYPE;"
450 "%^(%S+i__)->~ELEMENT_TYPE();"
453 cons_arg_ty, "", constructor_name
458 //////////////////////////////////////////////////////////////////////////////
460 // Methods to generate the forward declarations for a datatype.
461 // These include unit constructors for the class.
463 //////////////////////////////////////////////////////////////////////////////
464 void DatatypeHierarchy::generate_forward_declarations(CodeGen& C)
466 // don't generate code for views
467 if (is_view()) return;
470 generate_forward_class_declarations(C);
471 generate_forward_constructor_declarations(C);
473 // don't generate code for forward definitions
474 if (term_defs == #[]) return;
476 generate_unit_constructors(C);
479 //////////////////////////////////////////////////////////////////////////////
481 // Method to generate forward class declarations.
482 // If the datatype is monomorphic, generate a typedef.
483 // Otherwise, generate a forward template declaration
486 //////////////////////////////////////////////////////////////////////////////
487 void DatatypeHierarchy::generate_forward_class_declarations(CodeGen& C)
488 { // Generate forward declarations only if we have at least one variant
489 if (arg_constructors == 0 && term_defs != #[]) return;
493 "%^// Forward class definition for %s%V"
496 "%n#ifndef datatype_%S_defined"
497 "%n#define datatype_%S_defined",
498 datatype_name, parameters, datatype_name, datatype_name
501 if (is_polymorphic())
502 { // Polymorphic datatypes
503 C.pr("%^%Hclass %s;", parameters, class_name);
504 C.pr("%n#define %s%v %s%s%V *\n",
505 datatype_name, parameters, is_const, class_name, parameters);
507 { // Monomorphic datatypes
508 C.pr("%^ class %s;", class_name);
509 C.pr("%^ typedef %s%s * %s;", is_const, class_name, datatype_name);
512 C.pr("%n#endif\n\n");
515 //////////////////////////////////////////////////////////////////////////////
517 // Method to generate forward declarations for datatype constructors.
519 //////////////////////////////////////////////////////////////////////////////
520 void DatatypeHierarchy::generate_forward_constructor_declarations(CodeGen& C)
525 //////////////////////////////////////////////////////////////////////////////
527 // Method to generate code for the definition of a datatype
529 //////////////////////////////////////////////////////////////////////////////
530 void DatatypeHierarchy::generate_datatype_definitions(CodeGen& C)
532 // don't generate code for views
533 if (is_view()) return;
535 // don't generate code for forward definitions
536 if (term_defs == #[]) return;
538 // If there are no argument constructors, don't generate code
541 if (arg_constructors == 0)
543 gen_class_postdefinition(C);
547 // Otherwise generate code for all the classes.
548 gen_class_definition(C);
549 for (int i = 0; i < number_of_subclasses; i++)
550 subclasses[i]->gen_class_definition(C);
552 // Generate datatype constructors
553 DefKind kind = inline_methods
554 ? INLINE_IMPLEMENTATION : INTERFACE_DEFINITION;
556 generate_datatype_constructors(C,#[],kind);
558 if (options.inline_casts == false || parameters != #[])
559 generate_downcasting_functions(C);
564 //////////////////////////////////////////////////////////////////////////////
566 // Method to generate the unit constructor names.
567 // If there are no argument constructors, represent the constructors as
568 // enum's. Otherwise, represent them as #define constants.
570 //////////////////////////////////////////////////////////////////////////////
571 void DatatypeHierarchy::generate_unit_constructors(CodeGen& C)
572 { if (unit_constructors == 0) return;
573 if (arg_constructors == 0)
574 generate_constructor_tags(C,"","", unit_constructors, constructor_terms);
576 generate_define_tags(C,unit_constructors,constructor_terms);
580 //////////////////////////////////////////////////////////////////////////////
582 // Method to generate the constructor tags as enum's.
583 // Constructor tags are used to represent unit constructors
586 //////////////////////////////////////////////////////////////////////////////
587 void DatatypeHierarchy::generate_constructor_tags
588 (CodeGen& C, Id enum_prefix, Id tag_prefix, int n, Cons terms[])
589 { C.pr("%^enum %s%s {%+", enum_prefix, datatype_name);
591 for (int i = 0; i < n; i++)
592 { if (comma) C.pr (", ");
593 if (i % 3 == 0) C.pr("%^");
594 C.pr("%s%S = %i", tag_prefix, terms[i]->name, tag_of(terms[i]));
600 //////////////////////////////////////////////////////////////////////////////
602 // Method to generate the unit constructor tags as #define constants.
603 // This is necessary if we have both unit and argument constructors
604 // for a type. If polymorphic types are used, the #define constants
605 // are not given a type.
607 //////////////////////////////////////////////////////////////////////////////
608 void DatatypeHierarchy::generate_define_tags(CodeGen& C, int n, Cons terms[])
609 { for (int i = 0; i < n; i++)
610 { if (is_polymorphic())
611 C.pr("%n# define %S %i", terms[i]->name, tag_of(terms[i]));
613 C.pr("%n# define %S (%s)%i",
614 terms[i]->name, datatype_name, tag_of(terms[i]));
618 //////////////////////////////////////////////////////////////////////////////
620 // Method to generate datatype constructor functions for a datatype.
621 // Datatype constructor functions are just external functions.
623 //////////////////////////////////////////////////////////////////////////////
624 void DatatypeHierarchy::generate_datatype_constructors
625 (CodeGen& C, Tys tys, DefKind kind)
629 "%^// Datatype constructor functions for %s%V"
632 datatype_name, parameters);
633 generate_datatype_constructor(C,tys,kind);
634 for (int i = 0; i < number_of_subclasses; i++)
635 { subclasses[i]->generate_datatype_constructor(C,tys,kind);
639 //////////////////////////////////////////////////////////////////////////////
641 // Method to generate a datatype constructor function.
643 //////////////////////////////////////////////////////////////////////////////
644 void DatatypeClass::generate_datatype_constructor
645 (CodeGen& C, Tys tys, DefKind kind)
647 // No datatype descriptor, then no datatype constructor function
648 if (cons == NOcons) return;
653 { case INLINE_IMPLEMENTATION: prefix = "inline "; break;
654 case INTERFACE_DEFINITION:
655 case EXTERNAL_DEFINITION: prefix = "extern "; break;
656 case EXTERNAL_IMPLEMENTATION:
657 case EXTERNAL_INSTANTIATION: prefix = ""; break;
660 // Generate special form constructors for lists and vectors
661 int special_forms = 1;
662 if (is_list) special_forms = 2;
663 else if (is_array) special_forms = options.max_vector_len + 2;
667 for (int form = 1; form <= special_forms; form++)
669 Ty formals_ty = cons_arg_ty;
670 Ty actuals_ty = cons_arg_ty;
671 Id formals_name = constructor_name;
673 // If it is a list special form, fake the second argument
674 if (is_list && form == 2)
675 { match (deref(formals_ty))
677 { formals_ty = actuals_ty = mktuplety(#[a]); }
678 | t: { bug("%LDatatypeClass::generate_datatype_constructor: %T\n",
683 // If it is an array special form, fake the parameter arguments
684 if (is_array && form >= 2)
686 { params = #[ cons_arg_ty ... params ];
687 labels = append(labels,#[index_of(form-2)]);
689 formals_ty = mkrecordty(labels,params,false);
690 formals_name = mangle(constructor_name);
694 { case EXTERNAL_INSTANTIATION:
695 case EXTERNAL_DEFINITION:
696 C.pr("%^%s%s%P * %S %b",
697 prefix, root->class_name, tys, constructor_name,
698 formals_ty, formals_name, TYsimpleformal);
701 C.pr("%^%H%s%s%V * %S %b",
703 prefix, root->class_name, parameters, constructor_name,
704 formals_ty, formals_name, TYformal);
708 // Don't generate code for interface definitions
709 if (kind == INTERFACE_DEFINITION ||
710 kind == EXTERNAL_DEFINITION) { C.pr(";"); continue; }
715 // Generate a temporary array
717 if (is_array && form >= 2)
718 { C.pr("%^const int x__len_ = %i;", form - 2);
719 C.pr("%^%t x_%S[%i];", cons_arg_ty, "", constructor_name, form - 2);
720 for (int i = 0; i < form - 2; i++)
721 C.pr("%^x_%S[%i] = x__%i;", constructor_name,i,i+1);
727 // In the tagged pointer representation, the variant tag is embedded
728 // within the data address.
730 if (root->optimizations & OPTtaggedpointer)
732 { case EXTERNAL_INSTANTIATION:
733 C.pr ("(%s%P*)((unsigned long)(", root->class_name, tys);
736 C.pr ("(%s%V*)((unsigned long)(", root->class_name, parameters);
742 // In the unboxed representation, the argument is embedded within
745 if (root->optimizations & OPTunboxed)
747 int tag_bits = DatatypeCompiler::max_embedded_bits;
748 for (int i = root->unit_constructors;
749 i >= DatatypeCompiler::max_embedded_tags; i >>= 1) tag_bits++;
750 C.pr ("(%s *)(((unsigned long)%b<<(%i+1))|%i)",
751 root->class_name, actuals_ty, constructor_name, TYactual,
752 tag_bits, (1 << tag_bits));
756 // The usual boxed implementation
762 { case EXTERNAL_INSTANTIATION:
764 C.pr ("(sizeof(%s%P)+sizeof(%t)*x__len_) ",
765 class_name, tys, cons_arg_ty, "");
766 C.pr ("%s%P %b", class_name, tys, actuals_ty,
767 constructor_name, TYactual);
771 C.pr ("(sizeof(%s%V)+sizeof(%t)*x__len_) ",
772 class_name, parameters, cons_arg_ty, "");
773 C.pr ("%s%V %b", class_name, parameters, actuals_ty,
774 constructor_name, TYactual);
779 if (root->optimizations & OPTtaggedpointer)
781 { case EXTERNAL_INSTANTIATION:
782 C.pr (")|%s%P::tag_%S)",
783 root->class_name, tys, constructor_name); break;
785 C.pr (")|%s%V::tag_%S)",
786 root->class_name, parameters, constructor_name); break;
795 //////////////////////////////////////////////////////////////////////////////
797 // Method to generate code before the interface
799 //////////////////////////////////////////////////////////////////////////////
800 void DatatypeClass::gen_class_predefinition(CodeGen& C)
803 { ONEcons { ty, name ... }:
807 "%^// Class for datatype constructor %s%V::%s"
810 root->datatype_name, parameters, name);
813 { cons_arg_ty = NOty;
816 "%^// Base class for datatype %s%V"
819 root->datatype_name, parameters);
824 //////////////////////////////////////////////////////////////////////////////
826 // Method to generate the interface of a class
828 //////////////////////////////////////////////////////////////////////////////
829 void DatatypeClass::gen_class_interface(CodeGen& C)
831 // Generate the internal representation
832 // if there is a constructor descripter and the
833 // argument is not represented in unboxed form.
834 C.pr("%-%^public:%+");
836 { ONEcons { name, opt, ty, location ... }:
837 { if ((opt & OPTunboxed) == 0)
838 { C.pr ("%#%^%b\n", location->begin_line, location->file_name,
845 DefKind kind = root->inline_methods
846 ? INLINE_IMPLEMENTATION : INTERFACE_DEFINITION;
848 // Generate the constructor of the class
850 { gen_class_constructor(C, #[], kind);
853 // Generate the destructor of the class
854 if ((root->qualifiers & QUALvirtualdestr) ||
855 (qualifiers & QUALvirtualdestr) ||
857 gen_class_destructor(C, #[], kind);
859 // Generate the method declarations for all different types
860 // of extra functionality
861 if (root->qualifiers & QUALpersistent) generate_persistence_interface(C);
862 //if (root->qualifiers & QUALvariable) generate_logic_interface(C);
863 if (root->qualifiers & QUALcollectable) generate_gc_interface(C);
864 if (root->qualifiers & QUALrelation) generate_inference_interface(C);
867 //////////////////////////////////////////////////////////////////////////////
869 // Method to generate the interface of a base class
871 //////////////////////////////////////////////////////////////////////////////
872 void DatatypeHierarchy::gen_class_interface(CodeGen& C)
874 // Generate tags for arg constructors
875 if (arg_constructors > 1)
876 { C.pr("%-%^public:%+");
877 generate_constructor_tags(C,"Tag_","tag_",
878 arg_constructors, constructor_terms + unit_constructors);
881 // Generate a variant tag and a base class constructor for it
882 // only if we have a variant_tag representation.
884 { C.pr("%-%^public:%+"
885 "%^const Tag_%s tag__; // variant tag"
887 "%^inline %s(Tag_%s t__) : tag__(t__) {%&}",
888 datatype_name, class_name, datatype_name, constructor_code
892 // Generate the untagging functions
893 generate_untagging_member_functions(C);
895 DatatypeClass::gen_class_interface(C);
898 //////////////////////////////////////////////////////////////////////////////
900 // Method to generate untagging functions for a datatype class.
901 // Three untagging functions are generated:
902 // int untag() const --- returns the variant tag of the class
903 // friend int untag(type * x) -- return a tag for the object x
904 // so that each variant (boxed or unboxed)
905 // gets a unique tag.
906 // friend int boxed(type * x) -- returns true if object is boxed.
908 //////////////////////////////////////////////////////////////////////////////
909 void DatatypeHierarchy::generate_untagging_member_functions(CodeGen& C)
911 ///////////////////////////////////////////////////////////////////////////
913 ///////////////////////////////////////////////////////////////////////////
914 // if (has_variant_tag)
915 // C.pr("%^inline int untag() const { return tag__; }");
918 void DatatypeHierarchy::generate_untagging_functions(CodeGen& C)
921 if (arg_constructors == 0) return;
923 ///////////////////////////////////////////////////////////////////////////
924 // Generate boxed() predicate
925 ///////////////////////////////////////////////////////////////////////////
926 if (unit_constructors == 0)
927 C.pr("%^%Hinline int boxed(const %s%V *) { return 1; }",
928 parameters, class_name, parameters);
929 else if (unit_constructors == 1)
930 C.pr("%^%Hinline int boxed(const %s%V * x) { return x != 0; }",
931 parameters, class_name, parameters);
933 C.pr("%^%Hinline int boxed(const %s%V * x)"
934 " { return (unsigned long)x >= %i; }",
935 parameters, class_name, parameters, unit_constructors);
937 ///////////////////////////////////////////////////////////////////////////
938 // Generate function that untags the pointer if
939 // the tags are embedded into a pointer.
940 ///////////////////////////////////////////////////////////////////////////
941 if (optimizations & OPTtaggedpointer)
944 "%^// Embbeded tag extraction functions"
947 "%^%Hinline int untagp(const %s%V * x)"
948 "%^ { return (unsigned long)x & %i; }"
949 "%^%Hinline %s%s%V * derefp(const %s%V * x)"
950 "%^ { return (%s%s%V*)((unsigned long)x & ~%i); }",
951 parameters, class_name, parameters,
952 DatatypeCompiler::max_embedded_tags - 1,
953 parameters,is_const,class_name, parameters, class_name, parameters,
954 is_const, class_name, parameters,
955 DatatypeCompiler::max_embedded_tags - 1);
958 ///////////////////////////////////////////////////////////////////////////
959 // Generate a generic untag function that works on all boxed
960 // and unboxed variants.
961 ///////////////////////////////////////////////////////////////////////////
962 if (unit_constructors == 0) {
963 // No unboxed variants.
964 if (optimizations & OPTtaggedpointer)
965 C.pr("%^%Hinline int untag(const %s%V * x) { return untagp(x); }",
966 parameters, class_name, parameters);
967 else if (arg_constructors == 1)
968 C.pr("%^%Hinline int untag(const %s%V *) { return 0; }",
969 parameters, class_name, parameters);
971 C.pr("%^%Hinline int untag(const %s%V * x) { return x->tag__; }",
972 parameters, class_name, parameters);
973 } else if (unit_constructors == 1) {
974 // Only one unboxed variants.
975 if (optimizations & OPTtaggedpointer)
976 C.pr("%^%Hinline int untag(const %s%V * x) "
977 "{ return x ? untagp(x)+1 : 0; }",
978 parameters, class_name, parameters);
979 else if (arg_constructors == 1)
980 C.pr("%^%Hinline int untag(const %s%V * x) { return x ? 1 : 0; }",
981 parameters, class_name, parameters);
983 C.pr("%^%Hinline int untag(const %s%V * x)"
984 " { return x ? (x->tag__+1) : 0; }",
985 parameters, class_name, parameters);
987 // More than one unboxed variants.
988 if (optimizations & OPTtaggedpointer)
989 C.pr("%^%Hinline int untag(const %s%V * x)"
990 " { return boxed(x) ? untagp(x) + %i : (int)x; }",
991 parameters, class_name, parameters, unit_constructors);
992 else if (arg_constructors == 1)
993 C.pr("%^%Hinline int untag(const %s%V * x)"
994 " { return boxed(x) ? %i : (int)x; }",
995 parameters, class_name, parameters, 1 + unit_constructors);
997 C.pr("%^%Hinline int untag(const %s%V * x)"
998 " { return boxed(x) ? x->tag__ + %i : (int)x; }",
999 parameters, class_name, parameters, unit_constructors);
1003 //////////////////////////////////////////////////////////////////////////////
1005 // Method to generate downcasting functions
1007 //////////////////////////////////////////////////////////////////////////////
1008 void DatatypeHierarchy::generate_downcasting_functions(CodeGen& C)
1012 "%^// Downcasting functions for %s%V"
1015 datatype_name, parameters);
1016 for (int i = 0; i < number_of_subclasses; i++)
1017 { DatatypeClass * D = subclasses[i];
1018 C.pr("%^%Hinline %s%V * _%S(const %s%V * _x_) { return (%s%V *)_x_; }",
1019 parameters, D->class_name, parameters, D->constructor_name,
1020 class_name, parameters, D->class_name, parameters);
1024 //////////////////////////////////////////////////////////////////////////////
1026 // Method to generate code right after the main class definition.
1028 //////////////////////////////////////////////////////////////////////////////
1029 void DatatypeClass::gen_class_postdefinition(CodeGen& C)
1033 // Interfaces for extra features
1034 if (root->qualifiers & QUALprintable) generate_print_interface(C);
1037 //////////////////////////////////////////////////////////////////////////////
1039 // Method to generate code right after the main class definition.
1041 //////////////////////////////////////////////////////////////////////////////
1042 void DatatypeHierarchy::gen_class_postdefinition(CodeGen& C)
1044 generate_untagging_functions(C);
1045 DatatypeClass::gen_class_postdefinition(C);