1 ///////////////////////////////////////////////////////////////////////////////
3 // This file implements the selection/projection code generation.
5 ///////////////////////////////////////////////////////////////////////////////
10 #include <AD/strings/quark.h>
13 #include "matchcom.ph"
17 ///////////////////////////////////////////////////////////////////////////////
19 // Method to compute the proper selector into a component argument
22 ///////////////////////////////////////////////////////////////////////////////
23 Exp select(Exp e, Cons c, Ty t) { return SELECTORexp(e,c,t); }
25 ///////////////////////////////////////////////////////////////////////////////
27 // Method to compute the proper selector into a component argument
30 ///////////////////////////////////////////////////////////////////////////////
31 Exp MatchCompiler::make_select
32 ( Exp e, // the expression
33 Cons c, // constructor
34 Ty expected_ty, // expected type (if applicable)
35 Id component // component to extract
38 Bool use_projection = component != 0;
41 alg_ty = DATATYPEty({ qualifiers ... },_),
43 } | qualifiers & QUALview: // A view
47 { TUPLEty _: { use_projection = false;
48 comp_ty = component_ty(ty,atol(component+1)); }
50 { use_projection = false;
51 comp_ty = component_ty(ty,component); }
52 | ty: { comp_ty = ty; }
55 Exp selector_exp = default_val(comp_ty);
56 if (selector_exp == NOexp)
57 { error ("%Lview accessor is undefined for constructor %s\n", name);
60 result = subst(selector_exp,&e);
63 alg_ty = DATATYPEty({ opt, id, tyvars ... },_),
71 { TYCONty(TUPLEtycon || RECORDtycon _,_): { simple = false; }
72 | _: { simple = true; }
74 if (is_array_constructor(name)) simple = false;
78 if (this_opt & OPTunboxed) {
79 result = APPexp(IDexp(#"deref_" + name), e);
81 if ((opt & OPTtaggedpointer) && tag != 0)
82 e = APPexp(IDexp(#"derefp"), e);
83 if (opt & OPTsubclassless) { // No subclass hierarchy
84 if (simple) result = ARROWexp(e,nm);
85 else result = DEREFexp(e);
86 } else { // with subclass hierachy
87 // Dereference the pointer if the pointer needs to be stripped
89 Exp downcast_exp = NOexp;
90 if (options.inline_casts && tyvars == #[]) {
92 CASTexp(mkptrty(mkidty(id + #"_" + nm,#[])),e);
93 } else if (options.inline_casts && expected_ty != NOty) {
94 match (deref_all(expected_ty))
97 CASTexp(mkptrty(mkidty(id + #"_" + nm,tys)),e);
99 | _: { bug("%Lmake_select"); }
102 downcast_exp = APPexp(IDexp(#"_" + nm),e);
104 if (simple) result = ARROWexp(downcast_exp,nm);
105 else result = DEREFexp(downcast_exp);
111 return use_projection ? DOTexp(result,component) : result;
114 ///////////////////////////////////////////////////////////////////////////////
116 // Method to compute the tag name of a constructor
118 ///////////////////////////////////////////////////////////////////////////////
119 Exp MatchCompiler::tag_name_of(Cons cons, Bool normalized)
123 alg_ty = DATATYPEty({ qualifiers ... },_),
125 | qualifiers & QUALview:
126 { if (view_predicate == NOexp)
127 { error("%Lview case for constructor %s is undefined\n",name);
130 return view_predicate;
132 | ONEcons { name, ty = NOty, alg_ty = DATATYPEty({ arg ... },_) ... }
134 { return IDexp(mangle(name)); }
135 | ONEcons { name, ty = NOty, alg_ty = DATATYPEty({ arg ... },_) ... }:
136 { return CASTexp(integer_ty,IDexp(mangle(name))); }
137 | ONEcons { name, alg_ty = DATATYPEty({ id, arg, unit, tyvars ... },_)
139 | ! normalized && tyvars == #[] && arg > 1:
140 { return IDexp(Quark("a_",id,"::tag_",mangle(name)));
142 | ONEcons { alg_ty = DATATYPEty({ arg, unit ... },_) ... }:
143 { int this_tag = tag_of(cons) + (normalized ? unit : 0);
144 return LITERALexp(INTlit(this_tag)); }
145 | _: { return NOexp; }
149 ///////////////////////////////////////////////////////////////////////////////
151 // Method to extract the tag from a term
153 ///////////////////////////////////////////////////////////////////////////////
154 Exp MatchCompiler::untag(Exp e, Ty ty)
156 { DATATYPEty ({ view_match, qualifiers ... }, _)
157 | qualifiers & QUALview: // a view
158 { if (view_match == NOexp)
159 { error("%Lview test for datatype %T is undefined\n", ty);
162 return subst(view_match,&e);
164 | DATATYPEty ({ arg ... },_) | arg > 0:
165 { return APPexp(IDexp(#"untag"),e); }
170 ///////////////////////////////////////////////////////////////////////////////
172 // Method to extract the tag from a term (optimized for arg/unit constructors)
174 ///////////////////////////////////////////////////////////////////////////////
175 Exp MatchCompiler::untag_one (Exp e, Cons c)
178 alg_ty = DATATYPEty ({ view_match, qualifiers ... }, _) ... }
179 | qualifiers & QUALview: // a view
180 { if (view_match == NOexp)
181 { error("%Lview test for constructor %s is undefined\n",name);
184 return subst(view_match,&e);
186 | ONEcons { ty = NOty, alg_ty = DATATYPEty ({ arg ... },_) ... }
189 | ONEcons { ty = NOty ... }:
190 { return CASTexp(integer_ty,e); }
191 | ONEcons { alg_ty = DATATYPEty({ qualifiers, opt ... }, _) ... }:
192 { if (opt & OPTtaggedpointer) e = APPexp(IDexp(#"untagp"),e);
193 else if (opt & OPTtagless) e = LITERALexp(INTlit(0));
194 else e = ARROWexp(e,#"tag__");
197 | _: { return NOexp; }