source: mainline/uspace/app/sbi/src/run_texpr.c@ 36f0738

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 36f0738 was dc12262, checked in by Martin Decky <martin@…>, 8 years ago

add standardized case fallthrough comment annotations, add actual missing breaks

GCC 7.1's attribute((fallthrough)) would be more elegant, but unfortunatelly this annotation is incompatible with previous versions of GCC (it generates an empty declaration error)

  • Property mode set to 100644
File size: 12.5 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file Evaluate type expressions. */
30
31#include <assert.h>
32#include <stdlib.h>
33#include "cspan.h"
34#include "debug.h"
35#include "list.h"
36#include "mytypes.h"
37#include "stree.h"
38#include "strtab.h"
39#include "symbol.h"
40#include "tdata.h"
41
42#include "run_texpr.h"
43
44static void run_taccess(stree_program_t *prog, stree_csi_t *ctx,
45 stree_taccess_t *taccess, tdata_item_t **res);
46static void run_tindex(stree_program_t *prog, stree_csi_t *ctx,
47 stree_tindex_t *tindex, tdata_item_t **res);
48static void run_tliteral(stree_program_t *prog, stree_csi_t *ctx,
49 stree_tliteral_t *tliteral, tdata_item_t **res);
50static void run_tnameref(stree_program_t *prog, stree_csi_t *ctx,
51 stree_tnameref_t *tnameref, tdata_item_t **res);
52static void run_tapply(stree_program_t *prog, stree_csi_t *ctx,
53 stree_tapply_t *tapply, tdata_item_t **res);
54
55/** Evaluate type expression.
56 *
57 * Evaluate type expression (this produces a type item). If a type error
58 * occurs, the resulting type item is of class @c tic_ignore.
59 *
60 * @param prog Program
61 * @param ctx Current CSI (context)
62 * @param texpr Type expression to evaluate
63 * @param res Place to store type result
64 */
65void run_texpr(stree_program_t *prog, stree_csi_t *ctx, stree_texpr_t *texpr,
66 tdata_item_t **res)
67{
68 switch (texpr->tc) {
69 case tc_taccess:
70 run_taccess(prog, ctx, texpr->u.taccess, res);
71 break;
72 case tc_tindex:
73 run_tindex(prog, ctx, texpr->u.tindex, res);
74 break;
75 case tc_tliteral:
76 run_tliteral(prog, ctx, texpr->u.tliteral, res);
77 break;
78 case tc_tnameref:
79 run_tnameref(prog, ctx, texpr->u.tnameref, res);
80 break;
81 case tc_tapply:
82 run_tapply(prog, ctx, texpr->u.tapply, res);
83 break;
84 }
85}
86
87/** Evaluate type access expression.
88 *
89 * Evaluate operation per the type access ('.') operator.
90 *
91 * @param prog Program
92 * @param ctx Current CSI (context)
93 * @param taccess Type access expression to evaluate
94 * @param res Place to store type result
95 */
96static void run_taccess(stree_program_t *prog, stree_csi_t *ctx,
97 stree_taccess_t *taccess, tdata_item_t **res)
98{
99 stree_symbol_t *sym;
100 tdata_item_t *targ_i = NULL;
101 tdata_item_t *titem = NULL;;
102 tdata_object_t *tobject;
103 tdata_deleg_t *tdeleg;
104 stree_csi_t *base_csi;
105 stree_deleg_t *deleg;
106 stree_enum_t *enum_d;
107 tdata_enum_t *tenum;
108
109#ifdef DEBUG_RUN_TRACE
110 printf("Evaluating type access operation.\n");
111#endif
112 /* Evaluate base type. */
113 run_texpr(prog, ctx, taccess->arg, &targ_i);
114
115 if (targ_i->tic == tic_ignore) {
116 *res = tdata_item_new(tic_ignore);
117 return;
118 }
119
120 if (targ_i->tic != tic_tobject) {
121 cspan_print(taccess->texpr->cspan);
122 printf(" Error: Using '.' with type which is not an "
123 "object.\n");
124 *res = tdata_item_new(tic_ignore);
125 return;
126 }
127
128 /* Get base CSI. */
129 base_csi = targ_i->u.tobject->csi;
130
131 sym = symbol_lookup_in_csi(prog, base_csi, taccess->member_name);
132 if (sym == NULL) {
133 cspan_print(taccess->member_name->cspan);
134 printf(" Error: CSI '");
135 symbol_print_fqn(csi_to_symbol(base_csi));
136 printf("' has no member named '%s'.\n",
137 strtab_get_str(taccess->member_name->sid));
138 *res = tdata_item_new(tic_ignore);
139 return;
140 }
141
142 switch (sym->sc) {
143 case sc_csi:
144 /* Construct type item. */
145 titem = tdata_item_new(tic_tobject);
146 tobject = tdata_object_new();
147 titem->u.tobject = tobject;
148
149 tobject->static_ref = sn_nonstatic;
150 tobject->csi = sym->u.csi;
151 list_init(&tobject->targs);
152 break;
153 case sc_ctor:
154 /* It is not possible to reference a constructor explicitly. */
155 assert(b_false);
156 /* Fallthrough */
157 case sc_deleg:
158 /* Fetch stored delegate type. */
159 deleg = symbol_to_deleg(sym);
160 assert(deleg != NULL);
161 if (deleg->titem == NULL) {
162 /*
163 * Prepare a partial delegate which will be completed
164 * later.
165 */
166 titem = tdata_item_new(tic_tdeleg);
167 tdeleg = tdata_deleg_new();
168 titem->u.tdeleg = tdeleg;
169 tdeleg->deleg = deleg;
170 tdeleg->tsig = NULL;
171
172 deleg->titem = titem;
173 } else {
174 titem = deleg->titem;
175 }
176 break;
177 case sc_enum:
178 /* Fetch stored enum type. */
179 enum_d = symbol_to_enum(sym);
180 assert(enum_d != NULL);
181 if (enum_d->titem == NULL) {
182 /*
183 * Prepare a partial enum whic will be completed
184 * later.
185 */
186 titem = tdata_item_new(tic_tenum);
187 tenum = tdata_enum_new();
188 titem->u.tenum = tenum;
189 tenum->enum_d = enum_d;
190 } else {
191 titem = enum_d->titem;
192 }
193 break;
194 case sc_fun:
195 case sc_var:
196 case sc_prop:
197 cspan_print(taccess->member_name->cspan);
198 printf(" Error: Symbol '");
199 symbol_print_fqn(sym);
200 printf("' is not a type.\n");
201 titem = tdata_item_new(tic_ignore);
202 break;
203 }
204
205 *res = titem;
206}
207
208/** Evaluate type indexing expression.
209 *
210 * Evaluate operation per the type indexing ('[', ']') operator.
211 * A type indexing operation may have extents specified or only rank
212 * specified.
213 *
214 * @param prog Program
215 * @param ctx Current CSI (context)
216 * @param tindex Type indexing expression to evaluate
217 * @param res Place to store type result
218 */
219static void run_tindex(stree_program_t *prog, stree_csi_t *ctx,
220 stree_tindex_t *tindex, tdata_item_t **res)
221{
222 tdata_item_t *base_ti = NULL;
223 tdata_item_t *titem;
224 tdata_array_t *tarray;
225 stree_expr_t *arg_expr;
226 list_node_t *arg_node;
227
228#ifdef DEBUG_RUN_TRACE
229 printf("Evaluating type index operation.\n");
230#endif
231 /* Evaluate base type. */
232 run_texpr(prog, ctx, tindex->base_type, &base_ti);
233
234 if (base_ti->tic == tic_ignore) {
235 *res = tdata_item_new(tic_ignore);
236 return;
237 }
238
239 /* Construct type item. */
240 titem = tdata_item_new(tic_tarray);
241 tarray = tdata_array_new();
242 titem->u.tarray = tarray;
243
244 tarray->base_ti = base_ti;
245 tarray->rank = tindex->n_args;
246
247 /* Copy extents. */
248 list_init(&tarray->extents);
249 arg_node = list_first(&tindex->args);
250
251 while (arg_node != NULL) {
252 arg_expr = list_node_data(arg_node, stree_expr_t *);
253 list_append(&tarray->extents, arg_expr);
254 arg_node = list_next(&tindex->args, arg_node);
255 }
256
257 *res = titem;
258}
259
260/** Evaluate type literal expression.
261 *
262 * @param prog Program
263 * @param ctx Current CSI (context)
264 * @param tliteral Type literal
265 * @param res Place to store type result
266 */
267static void run_tliteral(stree_program_t *prog, stree_csi_t *ctx,
268 stree_tliteral_t *tliteral, tdata_item_t **res)
269{
270 tdata_item_t *titem;
271 tdata_primitive_t *tprimitive;
272 tprimitive_class_t tpc;
273
274#ifdef DEBUG_RUN_TRACE
275 printf("Evaluating type literal.\n");
276#endif
277 (void) prog;
278 (void) ctx;
279 (void) tliteral;
280
281 /* Make compiler happy. */
282 tpc = 0;
283
284 switch (tliteral->tlc) {
285 case tlc_bool: tpc = tpc_bool; break;
286 case tlc_char: tpc = tpc_char; break;
287 case tlc_int: tpc = tpc_int; break;
288 case tlc_string: tpc = tpc_string; break;
289 case tlc_resource: tpc = tpc_resource; break;
290 }
291
292 /* Construct type item. */
293 titem = tdata_item_new(tic_tprimitive);
294 tprimitive = tdata_primitive_new(tpc);
295 titem->u.tprimitive = tprimitive;
296
297 *res = titem;
298}
299
300static void run_tnameref(stree_program_t *prog, stree_csi_t *ctx,
301 stree_tnameref_t *tnameref, tdata_item_t **res)
302{
303 stree_symbol_t *sym;
304 tdata_item_t *titem;
305 tdata_object_t *tobject;
306 stree_targ_t *targ;
307 tdata_vref_t *tvref;
308 stree_deleg_t *deleg;
309 tdata_deleg_t *tdeleg;
310 stree_enum_t *enum_d;
311 tdata_enum_t *tenum;
312
313#ifdef DEBUG_RUN_TRACE
314 printf("Evaluating type name reference.\n");
315 printf("'%s'\n", strtab_get_str(tnameref->name->sid));
316#endif
317 /* In interactive mode we are not in a class */
318 if (ctx != NULL) {
319 /* Look for type argument */
320 targ = stree_csi_find_targ(ctx, tnameref->name);
321
322 if (targ != NULL) {
323 /* Found type argument */
324#ifdef DEBUG_RUN_TRACE
325 printf("Found type argument '%s'.\n",
326 strtab_get_str(tnameref->name->sid));
327#endif
328 titem = tdata_item_new(tic_tvref);
329 tvref = tdata_vref_new();
330 titem->u.tvref = tvref;
331 tvref->targ = targ;
332
333 *res = titem;
334 return;
335 }
336 }
337
338 /* Look for symbol */
339 sym = symbol_lookup_in_csi(prog, ctx, tnameref->name);
340 if (sym == NULL) {
341 cspan_print(tnameref->texpr->cspan);
342 printf(" Error: Symbol '%s' not found.\n",
343 strtab_get_str(tnameref->name->sid));
344 *res = tdata_item_new(tic_ignore);
345 return;
346 }
347
348 /* Make compiler happy. */
349 titem = NULL;
350
351 switch (sym->sc) {
352 case sc_csi:
353 /* Construct type item. */
354 titem = tdata_item_new(tic_tobject);
355 tobject = tdata_object_new();
356 titem->u.tobject = tobject;
357
358 tobject->static_ref = sn_nonstatic;
359 tobject->csi = sym->u.csi;
360 list_init(&tobject->targs);
361 break;
362 case sc_ctor:
363 /* It is not possible to reference a constructor explicitly. */
364 assert(b_false);
365 /* Fallthrough */
366 case sc_deleg:
367 /* Fetch stored delegate type. */
368 deleg = symbol_to_deleg(sym);
369 assert(deleg != NULL);
370 if (deleg->titem == NULL) {
371 /*
372 * Prepare a partial delegate which will be completed
373 * later.
374 */
375 titem = tdata_item_new(tic_tdeleg);
376 tdeleg = tdata_deleg_new();
377 titem->u.tdeleg = tdeleg;
378 tdeleg->deleg = deleg;
379 tdeleg->tsig = NULL;
380
381 deleg->titem = titem;
382 } else {
383 titem = deleg->titem;
384 }
385 break;
386 case sc_enum:
387 /* Fetch stored enum type. */
388 enum_d = symbol_to_enum(sym);
389 assert(enum_d != NULL);
390 if (enum_d->titem == NULL) {
391 /*
392 * Prepare a partial enum whic will be completed
393 * later.
394 */
395 titem = tdata_item_new(tic_tenum);
396 tenum = tdata_enum_new();
397 titem->u.tenum = tenum;
398 tenum->enum_d = enum_d;
399 } else {
400 titem = enum_d->titem;
401 }
402 break;
403 case sc_fun:
404 case sc_var:
405 case sc_prop:
406 cspan_print(tnameref->texpr->cspan);
407 printf(" Error: Symbol '");
408 symbol_print_fqn(sym);
409 printf("' is not a type.\n");
410 titem = tdata_item_new(tic_ignore);
411 break;
412 }
413
414 *res = titem;
415}
416
417/** Evaluate type application expression.
418 *
419 * In a type application expression type arguments are applied to a generic
420 * CSI.
421 *
422 * @param prog Program
423 * @param ctx Current CSI (context)
424 * @param tapply Type application expression
425 * @param res Place to store type result
426 */
427static void run_tapply(stree_program_t *prog, stree_csi_t *ctx,
428 stree_tapply_t *tapply, tdata_item_t **res)
429{
430 tdata_item_t *base_ti;
431 tdata_item_t *arg_ti;
432 tdata_item_t *titem;
433 tdata_object_t *tobject;
434
435 list_node_t *arg_n;
436 stree_texpr_t *arg;
437
438 list_node_t *farg_n;
439
440#ifdef DEBUG_RUN_TRACE
441 printf("Evaluating type apply operation.\n");
442#endif
443 /* Construct type item. */
444 titem = tdata_item_new(tic_tobject);
445 tobject = tdata_object_new();
446 titem->u.tobject = tobject;
447
448 /* Evaluate base (generic) type. */
449 run_texpr(prog, ctx, tapply->gtype, &base_ti);
450
451 if (base_ti->tic != tic_tobject) {
452 cspan_print(tapply->gtype->cspan);
453 printf(" Error: Base type of generic application is not "
454 "a CSI.\n");
455 *res = tdata_item_new(tic_ignore);
456 return;
457 }
458
459 tobject->static_ref = sn_nonstatic;
460 tobject->csi = base_ti->u.tobject->csi;
461 list_init(&tobject->targs);
462
463 /* Evaluate type arguments. */
464 farg_n = list_first(&tobject->csi->targ);
465 arg_n = list_first(&tapply->targs);
466 while (farg_n != NULL && arg_n != NULL) {
467 arg = list_node_data(arg_n, stree_texpr_t *);
468
469 run_texpr(prog, ctx, arg, &arg_ti);
470
471 if (arg_ti->tic == tic_ignore) {
472 *res = tdata_item_new(tic_ignore);
473 return;
474 }
475
476 list_append(&tobject->targs, arg_ti);
477
478 farg_n = list_next(&tobject->csi->targ, farg_n);
479 arg_n = list_next(&tapply->targs, arg_n);
480 }
481
482 if (farg_n != NULL || arg_n != NULL) {
483 cspan_print(tapply->texpr->cspan);
484 printf(" Error: Incorrect number of type arguments.\n");
485 *res = tdata_item_new(tic_ignore);
486 return;
487 }
488
489 *res = titem;
490}
Note: See TracBrowser for help on using the repository browser.