source: mainline/uspace/app/sbi/src/run_texpr.c

Last change on this file was 1433ecda, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix cstyle: make ccheck-fix and commit only files where all the changes are good.

  • Property mode set to 100644
File size: 12.6 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:
286 tpc = tpc_bool;
287 break;
288 case tlc_char:
289 tpc = tpc_char;
290 break;
291 case tlc_int:
292 tpc = tpc_int;
293 break;
294 case tlc_string:
295 tpc = tpc_string;
296 break;
297 case tlc_resource:
298 tpc = tpc_resource;
299 break;
300 }
301
302 /* Construct type item. */
303 titem = tdata_item_new(tic_tprimitive);
304 tprimitive = tdata_primitive_new(tpc);
305 titem->u.tprimitive = tprimitive;
306
307 *res = titem;
308}
309
310static void run_tnameref(stree_program_t *prog, stree_csi_t *ctx,
311 stree_tnameref_t *tnameref, tdata_item_t **res)
312{
313 stree_symbol_t *sym;
314 tdata_item_t *titem;
315 tdata_object_t *tobject;
316 stree_targ_t *targ;
317 tdata_vref_t *tvref;
318 stree_deleg_t *deleg;
319 tdata_deleg_t *tdeleg;
320 stree_enum_t *enum_d;
321 tdata_enum_t *tenum;
322
323#ifdef DEBUG_RUN_TRACE
324 printf("Evaluating type name reference.\n");
325 printf("'%s'\n", strtab_get_str(tnameref->name->sid));
326#endif
327 /* In interactive mode we are not in a class */
328 if (ctx != NULL) {
329 /* Look for type argument */
330 targ = stree_csi_find_targ(ctx, tnameref->name);
331
332 if (targ != NULL) {
333 /* Found type argument */
334#ifdef DEBUG_RUN_TRACE
335 printf("Found type argument '%s'.\n",
336 strtab_get_str(tnameref->name->sid));
337#endif
338 titem = tdata_item_new(tic_tvref);
339 tvref = tdata_vref_new();
340 titem->u.tvref = tvref;
341 tvref->targ = targ;
342
343 *res = titem;
344 return;
345 }
346 }
347
348 /* Look for symbol */
349 sym = symbol_lookup_in_csi(prog, ctx, tnameref->name);
350 if (sym == NULL) {
351 cspan_print(tnameref->texpr->cspan);
352 printf(" Error: Symbol '%s' not found.\n",
353 strtab_get_str(tnameref->name->sid));
354 *res = tdata_item_new(tic_ignore);
355 return;
356 }
357
358 /* Make compiler happy. */
359 titem = NULL;
360
361 switch (sym->sc) {
362 case sc_csi:
363 /* Construct type item. */
364 titem = tdata_item_new(tic_tobject);
365 tobject = tdata_object_new();
366 titem->u.tobject = tobject;
367
368 tobject->static_ref = sn_nonstatic;
369 tobject->csi = sym->u.csi;
370 list_init(&tobject->targs);
371 break;
372 case sc_ctor:
373 /* It is not possible to reference a constructor explicitly. */
374 assert(b_false);
375 /* Fallthrough */
376 case sc_deleg:
377 /* Fetch stored delegate type. */
378 deleg = symbol_to_deleg(sym);
379 assert(deleg != NULL);
380 if (deleg->titem == NULL) {
381 /*
382 * Prepare a partial delegate which will be completed
383 * later.
384 */
385 titem = tdata_item_new(tic_tdeleg);
386 tdeleg = tdata_deleg_new();
387 titem->u.tdeleg = tdeleg;
388 tdeleg->deleg = deleg;
389 tdeleg->tsig = NULL;
390
391 deleg->titem = titem;
392 } else {
393 titem = deleg->titem;
394 }
395 break;
396 case sc_enum:
397 /* Fetch stored enum type. */
398 enum_d = symbol_to_enum(sym);
399 assert(enum_d != NULL);
400 if (enum_d->titem == NULL) {
401 /*
402 * Prepare a partial enum whic will be completed
403 * later.
404 */
405 titem = tdata_item_new(tic_tenum);
406 tenum = tdata_enum_new();
407 titem->u.tenum = tenum;
408 tenum->enum_d = enum_d;
409 } else {
410 titem = enum_d->titem;
411 }
412 break;
413 case sc_fun:
414 case sc_var:
415 case sc_prop:
416 cspan_print(tnameref->texpr->cspan);
417 printf(" Error: Symbol '");
418 symbol_print_fqn(sym);
419 printf("' is not a type.\n");
420 titem = tdata_item_new(tic_ignore);
421 break;
422 }
423
424 *res = titem;
425}
426
427/** Evaluate type application expression.
428 *
429 * In a type application expression type arguments are applied to a generic
430 * CSI.
431 *
432 * @param prog Program
433 * @param ctx Current CSI (context)
434 * @param tapply Type application expression
435 * @param res Place to store type result
436 */
437static void run_tapply(stree_program_t *prog, stree_csi_t *ctx,
438 stree_tapply_t *tapply, tdata_item_t **res)
439{
440 tdata_item_t *base_ti;
441 tdata_item_t *arg_ti;
442 tdata_item_t *titem;
443 tdata_object_t *tobject;
444
445 list_node_t *arg_n;
446 stree_texpr_t *arg;
447
448 list_node_t *farg_n;
449
450#ifdef DEBUG_RUN_TRACE
451 printf("Evaluating type apply operation.\n");
452#endif
453 /* Construct type item. */
454 titem = tdata_item_new(tic_tobject);
455 tobject = tdata_object_new();
456 titem->u.tobject = tobject;
457
458 /* Evaluate base (generic) type. */
459 run_texpr(prog, ctx, tapply->gtype, &base_ti);
460
461 if (base_ti->tic != tic_tobject) {
462 cspan_print(tapply->gtype->cspan);
463 printf(" Error: Base type of generic application is not "
464 "a CSI.\n");
465 *res = tdata_item_new(tic_ignore);
466 return;
467 }
468
469 tobject->static_ref = sn_nonstatic;
470 tobject->csi = base_ti->u.tobject->csi;
471 list_init(&tobject->targs);
472
473 /* Evaluate type arguments. */
474 farg_n = list_first(&tobject->csi->targ);
475 arg_n = list_first(&tapply->targs);
476 while (farg_n != NULL && arg_n != NULL) {
477 arg = list_node_data(arg_n, stree_texpr_t *);
478
479 run_texpr(prog, ctx, arg, &arg_ti);
480
481 if (arg_ti->tic == tic_ignore) {
482 *res = tdata_item_new(tic_ignore);
483 return;
484 }
485
486 list_append(&tobject->targs, arg_ti);
487
488 farg_n = list_next(&tobject->csi->targ, farg_n);
489 arg_n = list_next(&tapply->targs, arg_n);
490 }
491
492 if (farg_n != NULL || arg_n != NULL) {
493 cspan_print(tapply->texpr->cspan);
494 printf(" Error: Incorrect number of type arguments.\n");
495 *res = tdata_item_new(tic_ignore);
496 return;
497 }
498
499 *res = titem;
500}
Note: See TracBrowser for help on using the repository browser.