1 ///////////////////////////////////////////////////////////////////////////////
3 // This file implements the low level routine for generating C++ output->
5 ///////////////////////////////////////////////////////////////////////////////
8 #include <AD/strings/charesc.h>
16 ///////////////////////////////////////////////////////////////////////////////
18 // Code generator constructor and destructor
20 ///////////////////////////////////////////////////////////////////////////////
22 : output(&cerr), anchored(true), tabbing(0), tab_unit(3) {}
23 CodeGen::~CodeGen() {}
24 void CodeGen::set_stream(ostream& s) { output = &s; }
26 ///////////////////////////////////////////////////////////////////////////////
28 // Convert literals to a type string.
30 ///////////////////////////////////////////////////////////////////////////////
31 fun literal_type_of INTlit _: Id: { return "integer"; }
32 | literal_type_of REALlit _: { return "real"; }
33 | literal_type_of CHARlit _: { return "character"; }
34 | literal_type_of BOOLlit _: { return "boolean"; }
35 | literal_type_of STRINGlit _ || REGEXPlit _: { return "string"; }
36 | literal_type_of QUARKlit _: { return "Quark"; }
37 | literal_type_of BIGINTlit _: { return "BigInt"; }
40 ///////////////////////////////////////////////////////////////////////////////
42 // Emit a string with indenting.
44 ///////////////////////////////////////////////////////////////////////////////
45 void CodeGen::gen_code(const char * code)
46 { const char * p, * q;
49 for (p = code; *p; ) {
53 if (tabbing == 0) my_tab = 0;
54 else for (my_tab = 0, q = p; *q == ' '; q++) my_tab++;
57 for (t = my_tab; *p == ' ' && t > 0; p++) t--;
58 for (t = tabbing; t > 0; t--) output->put(' ');
60 for (t = tabbing; *p == ' ' && t > 0; p++) t--;
61 for ( ; t > 0; t--) output->put(' ');
64 for ( ; *p == ' '; p++); output->put(' ');
68 if (*p == '\0') break;
70 if (*p == '\n') { line_no++; anchored = true; p++; break; }
76 ///////////////////////////////////////////////////////////////////////////////
78 // Decode a format string and dispatch to various printing routines.
80 ///////////////////////////////////////////////////////////////////////////////
81 ostream& CodeGen::outv(const char * fmt, va_list arg)
83 while ((c = *fmt++) != 0)
86 case 'i': (*output)<< va_arg(arg,int); anchored = false; break;
87 case 'c': c = (unsigned char)va_arg(arg,int);
88 output->put(c); anchored = (c == '\n'); break;
89 case 'C': gen_code(va_arg(arg,const char *)); break;
90 case 's': { const char * s = va_arg(arg,const char *);
93 anchored = (s[len-1] == '\n');
95 case 'S': (*output)<< mangle(va_arg(arg,const char *));
98 case 'q': (*output)<< va_arg(arg,QualId); anchored = false; break;
99 case 'e': (*output)<< va_arg(arg,Exp); anchored = false; break;
100 case 'f': { Bool save = pretty_print_exp;
101 pretty_print_exp = true;
102 (*output)<< va_arg(arg,Exp); anchored = false;
103 pretty_print_exp = save;
105 case 'E': { Exp e = va_arg(arg,Exp);
108 { pr ("%D", MARKEDdecl(loc, EXPdecl(e))); }
109 | _: {(*output)<< e; }
113 case 'l': (*output)<< va_arg(arg,Literal); anchored = false; break;
114 case 'p': (*output)<< va_arg(arg,Pat); anchored = false; break;
115 case 'r': (*output)<< va_arg(arg,MatchRule); anchored = false; break;
116 case 'b': { Ty ty = va_arg (arg,Ty);
117 Id name = va_arg (arg,Id);
118 Id id = mangle(name);
119 Parameter p = va_arg (arg,Parameter);
120 Bool is_array = is_array_constructor(name);
124 { pr ("%^const int len_;%^");
125 body_ty = mkarrayty(ty,LITERALexp(INTlit(0)));
130 #[integer_ty, mkptrty(QUALty(QUALconst,ty))],
133 print_parameter(*output, body_ty, id, p);
136 "%^inline int len() const { return len_; }"
137 "%^inline %t const& at(int i) const { return %S[i]; }"
138 "%^inline %t& at(int i) { return %S[i]; }"
139 "%^inline %t const * array() const { return %S; }"
140 "%^inline %t * array() { return %S; }",
141 ty, "", name, ty, "", name,
142 ty, "", name, ty, "", name);
145 print_parameter(*output, ty, id, p);
149 case 'T': (*output)<< va_arg(arg,Ty); anchored = false; break;
150 case 't': { Bool save = pretty_print_ty;
151 pretty_print_ty = false;
152 Ty ty = va_arg(arg,Ty);
153 ty_id = va_arg(arg,Id);
156 pretty_print_ty = save;
158 case 'V': print_tyvars(*output,va_arg(arg,TyVars), '<', '>', false);
159 anchored = false; break;
160 case 'P': { Tys tys = va_arg(arg,Tys);
161 Bool save = pretty_print_ty;
162 pretty_print_ty = false;
163 if (tys)(*output)<< '<' << tys << '>';
164 pretty_print_ty = save;
167 case 'Q': (*output)<< va_arg(arg,Pid); anchored = false; break;
168 case 'H': print_tyvars(*output,va_arg(arg,TyVars), '<', '>', true);
169 anchored = false; break;
170 case 'v': print_tyvars(*output,va_arg(arg,TyVars), '(', ')', false);
171 anchored = false; break;
172 case '#': { int l = va_arg(arg,int);
173 const char * f = va_arg(arg,const char *);
174 if (options.line_directives)
175 { if (! anchored)(*output)<< '\n';
176 (*output)<< "#line " << l << " \"" << f << "\"\n";
180 case '!': { const Loc * l = va_arg(arg, const Loc *);
181 if (! anchored)(*output)<< '\n';
182 if (options.GNU_style_message)
183 (*output)<< l->file_name << ':'
184 << l->begin_line << ": ";
186 (*output)<< '"' << l->file_name << "\", line "
187 << l->begin_line << ": ";
190 case 'L': if (options.GNU_style_message)
191 (*output)<< file << ':' << line << ": ";
193 (*output)<< '"' << file << "\", line " << line << ": ";
196 case 'w': if (options.strict_checking) errors++;
197 else(*output)<< "warning: ";
200 case 'M': (*output)<< va_arg(arg,Match); anchored = false; break;
201 case 'n': if (! anchored)(*output)<< '\n'; anchored = true; break;
202 case 'I': { Inherits i = va_arg(arg,Inherits);
206 case 'U': { Exp exp = va_arg(arg,Exp);
207 Ty ty = va_arg(arg,Ty);
208 (*output) << MatchCompiler::untag(exp,ty);
210 case '*': { Cons cons = va_arg(arg,Cons);
211 Bool normalized = va_arg(arg,Bool);
212 (*output) << MatchCompiler::tag_name_of(cons,
215 case '%': (*output)<< '%'; anchored = false; break;
216 case '?': if (! anchored) break;
217 case '^': { if (! anchored)(*output)<< '\n';
218 if (tabbing < 0) error ("Tab = %i\n", tabbing);
219 for (int i = tabbing; i > 0; i--)(*output)<< ' ';
220 anchored = (tabbing == 0);
222 case '+': tabbing += tab_unit; break;
223 case '-': tabbing -= tab_unit; break;
224 case '/': { for (int i = 79 - tabbing; i > 0; i--)(*output)<< '/';
225 (*output)<< '\n'; anchored = true;
227 case '=': (*output)<< "_equal_" << literal_type_of(va_arg(arg,Literal)); break;
228 case '<': (*output)<< "_less_" << literal_type_of(va_arg(arg,Literal)); break;
229 default: arg = printer(fmt[-1],arg); break;
232 else { output->put(c); anchored = (c == '\n'); }
237 ///////////////////////////////////////////////////////////////////////////////
241 ///////////////////////////////////////////////////////////////////////////////
242 ostream& CodeGen::pr(const char * fmt, ...)