1 /** \file type.c
2 * split out of exppp.c 9/21/13
3 */
4
5 #include <stdlib.h>
6
7 #include <express/error.h>
8 #include <sc_memmgr.h>
9
10 #include "exppp.h"
11 #include "pp.h"
12 #include "pretty_where.h"
13 #include "pretty_expr.h"
14 #include "pretty_type.h"
15
16 /** print a type definition. I.e., a TYPE statement */
TYPE_out(Type t,int level)17 void TYPE_out( Type t, int level ) {
18 first_newline();
19 exppp_ref_info( &t->symbol );
20
21 raw( "%*sTYPE %s =", level, "", t->symbol.name );
22 if( TYPEget_head( t ) ) {
23 wrap( " %s", TYPEget_name( TYPEget_head( t ) ) );
24 } else {
25 TYPE_body_out( t, level + exppp_nesting_indent );
26 }
27
28 raw( ";\n" );
29
30 WHERE_out( t->where, level );
31
32 raw( "%*sEND_TYPE;", level, "" );
33 tail_comment( t->symbol.name );
34 }
35
36 /** prints type description (preceded by a space).
37 * I.e., the type of an attribute or other object
38 */
TYPE_head_out(Type t,int level)39 void TYPE_head_out( Type t, int level ) {
40 if( t->symbol.name ) {
41 int old_indent = indent2;
42 if( indent2 + ( int ) strlen( t->symbol.name ) > exppp_linelength ) {
43 indent2 = ( indent2 + level ) / 2;
44 }
45 wrap( " %s", t->symbol.name );
46 indent2 = old_indent;
47 } else {
48 TYPE_body_out( t, level );
49 }
50 }
51
TYPEunique_or_optional_out(TypeBody tb)52 void TYPEunique_or_optional_out( TypeBody tb ) {
53 if( tb->flags.unique ) {
54 wrap( " UNIQUE" );
55 }
56 if( tb->flags.optional ) {
57 wrap( " OPTIONAL" );
58 }
59 }
60
TYPE_body_out(Type t,int level)61 void TYPE_body_out( Type t, int level ) {
62 bool first_time = true;
63
64 Expression expr;
65 DictionaryEntry de;
66
67 TypeBody tb = TYPEget_body( t );
68
69 switch( tb->type ) {
70 case integer_:
71 wrap( " INTEGER" );
72 break;
73 case real_:
74 wrap( " REAL" );
75 break;
76 case string_:
77 wrap( " STRING" );
78 break;
79 case binary_:
80 wrap( " BINARY" );
81 break;
82 case boolean_:
83 wrap( " BOOLEAN" );
84 break;
85 case logical_:
86 wrap( " LOGICAL" );
87 break;
88 case number_:
89 wrap( " NUMBER" );
90 break;
91 case entity_:
92 wrap( " %s", tb->entity->symbol.name );
93 break;
94 case aggregate_:
95 case array_:
96 case bag_:
97 case set_:
98 case list_:
99 switch( tb->type ) {
100 /* ignore the aggregate bounds for now */
101 case aggregate_:
102 wrap( " AGGREGATE" );
103 if( tb->tag ) {
104 wrap( ":%s", tb->tag->symbol.name );
105 }
106 wrap( " OF" );
107 break;
108
109 case array_:
110 wrap( " ARRAY" );
111 EXPRbounds_out( tb );
112 wrap( " OF" );
113 TYPEunique_or_optional_out( tb );
114 break;
115
116 case bag_:
117 wrap( " BAG" );
118 EXPRbounds_out( tb );
119 wrap( " OF" );
120 break;
121
122 case set_:
123 wrap( " SET" );
124 EXPRbounds_out( tb );
125 wrap( " OF" );
126 break;
127
128 case list_:
129 wrap( " LIST" );
130 EXPRbounds_out( tb );
131 wrap( " OF" );
132 TYPEunique_or_optional_out( tb );
133 break;
134 default:
135 fprintf( stderr, "exppp: Reached default case, %s:%d", __FILE__, __LINE__ );
136 abort();
137 }
138
139 TYPE_head_out( tb->base, level );
140 break;
141 case enumeration_: {
142 int i, count = 0;
143 char ** names;
144
145 /*
146 * write names out in original order by first bucket sorting
147 * to a temporary array. This is trivial since all buckets
148 * will get filled with one and only one object.
149 */
150 DICTdo_type_init( t->symbol_table, &de, OBJ_EXPRESSION );
151 while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
152 count++;
153 }
154 names = ( char ** )sc_malloc( count * sizeof( char * ) );
155 DICTdo_type_init( t->symbol_table, &de, OBJ_EXPRESSION );
156 while( 0 != ( expr = ( Expression )DICTdo( &de ) ) ) {
157 names[expr->u.integer - 1] = expr->symbol.name;
158 }
159
160 wrap( " ENUMERATION OF\n" );
161
162 for( i = 0; i < count; i++ ) {
163 /* finish line from previous enum item */
164 if( !first_time ) {
165 raw( ",\n" );
166 }
167
168 /* start new enum item */
169 if( first_time ) {
170 raw( "%*s( ", level, "" );
171 first_time = false;
172 } else {
173 raw( "%*s ", level, "" );
174 }
175 raw( names[i] );
176 }
177 raw( " )" );
178 sc_free( ( char * )names );
179 }
180 break;
181 case select_:
182 wrap( " SELECT\n" );
183 LISTdo( tb->list, type, Type )
184 /* finish line from previous entity */
185 if( !first_time ) {
186 raw( ",\n" );
187 }
188
189 /* start new entity */
190 if( first_time ) {
191 raw( "%*s( ", level, "" );
192 first_time = false;
193 } else {
194 raw( "%*s ", level, "" );
195 }
196 raw( type->symbol.name );
197 LISTod
198
199 /* if empty, force a left paren */
200 if( first_time ) {
201 ERRORreport_with_symbol( ERROR_select_empty, &error_sym, t->symbol.name );
202 raw( "%*s( ", level, "" );
203 }
204 raw( " )" );
205 break;
206 case generic_:
207 wrap( " GENERIC" );
208 if( tb->tag ) {
209 wrap( ":%s", tb->tag->symbol.name );
210 }
211 break;
212 default:
213 wrap( " (* unknown type %d *)", tb->type );
214 }
215
216 if( tb->precision ) {
217 wrap( " ( " );
218 EXPR_out( tb->precision, 0 );
219 raw( " )" );
220 }
221 if( tb->flags.fixed ) {
222 wrap( " FIXED" );
223 }
224 }
225
TYPEto_string(Type t)226 char * TYPEto_string( Type t ) {
227 if( prep_string() ) {
228 return placeholder;
229 }
230 TYPE_out( t, 0 );
231 return ( finish_string() );
232 }
233
234 /** return length of buffer used */
TYPEto_buffer(Type t,char * buffer,int length)235 int TYPEto_buffer( Type t, char * buffer, int length ) {
236 if( prep_buffer( buffer, length ) ) {
237 return -1;
238 }
239 TYPE_out( t, 0 );
240 return( finish_buffer() );
241 }
242
TYPEout(Type t)243 void TYPEout( Type t ) {
244 prep_file();
245 TYPE_out( t, 0 );
246 finish_file();
247 }
248
TYPEhead_to_string(Type t)249 char * TYPEhead_to_string( Type t ) {
250 if( prep_string() ) {
251 return placeholder;
252 }
253 TYPE_head_out( t, 0 );
254 return ( finish_string() );
255 }
256
257 /** return length of buffer used */
TYPEhead_to_buffer(Type t,char * buffer,int length)258 int TYPEhead_to_buffer( Type t, char * buffer, int length ) {
259 if( prep_buffer( buffer, length ) ) {
260 return -1;
261 }
262 TYPE_out( t, 0 );
263 return( finish_buffer() );
264 }
265
TYPEhead_out(Type t)266 void TYPEhead_out( Type t ) {
267 prep_file();
268 TYPE_head_out( t, 0 );
269 finish_file();
270 }
271
TYPEbody_to_string(Type t)272 char * TYPEbody_to_string( Type t ) {
273 if( prep_string() ) {
274 return placeholder;
275 }
276 TYPE_body_out( t, 0 );
277 return ( finish_string() );
278 }
279
280 /** return length of buffer used */
TYPEbody_to_buffer(Type t,char * buffer,int length)281 int TYPEbody_to_buffer( Type t, char * buffer, int length ) {
282 if( prep_buffer( buffer, length ) ) {
283 return -1;
284 }
285 TYPE_body_out( t, 0 );
286 return( finish_buffer() );
287 }
288
TYPEbody_out(Type t)289 void TYPEbody_out( Type t ) {
290 prep_file();
291 TYPE_body_out( t, 0 );
292 finish_file();
293 }
294