source: mainline/uspace/app/sbi/src/tdata.c@ 883fedc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 883fedc was 38aaacc2, checked in by Jiri Svoboda <jiri@…>, 16 years ago

Update SBI to rev. 207.

  • Property mode set to 100644
File size: 17.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 Run-time data representation. */
30
31#include <stdlib.h>
32#include <assert.h>
33#include "intmap.h"
34#include "list.h"
35#include "mytypes.h"
36#include "stree.h"
37#include "strtab.h"
38#include "symbol.h"
39
40#include "tdata.h"
41
42static void tdata_item_subst_tprimitive(tdata_primitive_t *torig,
43 tdata_tvv_t *tvv, tdata_item_t **res);
44static void tdata_item_subst_tobject(tdata_object_t *torig, tdata_tvv_t *tvv,
45 tdata_item_t **res);
46static void tdata_item_subst_tarray(tdata_array_t *torig, tdata_tvv_t *tvv,
47 tdata_item_t **res);
48static void tdata_item_subst_tdeleg(tdata_deleg_t *torig,
49 tdata_tvv_t *tvv, tdata_item_t **res);
50static void tdata_item_subst_tfun(tdata_fun_t *torig,
51 tdata_tvv_t *tvv, tdata_item_t **res);
52static void tdata_item_subst_tvref(tdata_vref_t *tvref, tdata_tvv_t *tvv,
53 tdata_item_t **res);
54
55static void tdata_item_subst_fun_sig(tdata_fun_sig_t *torig, tdata_tvv_t *tvv,
56 tdata_fun_sig_t **res);
57
58static void tdata_tprimitive_print(tdata_primitive_t *tprimitive);
59static void tdata_tobject_print(tdata_object_t *tobject);
60static void tdata_tarray_print(tdata_array_t *tarray);
61static void tdata_tdeleg_print(tdata_deleg_t *tdeleg);
62static void tdata_tfun_print(tdata_fun_t *tfun);
63static void tdata_tvref_print(tdata_vref_t *tvref);
64
65/** Determine if CSI @a a is derived from CSI described by type item @a tb.
66 *
67 * XXX This won't work with generics.
68 *
69 * @param a Potential derived CSI.
70 * @param tb Type of potentail base CSI.
71 */
72bool_t tdata_is_csi_derived_from_ti(stree_csi_t *a, tdata_item_t *tb)
73{
74 bool_t res;
75
76 switch (tb->tic) {
77 case tic_tobject:
78 res = stree_is_csi_derived_from_csi(a, tb->u.tobject->csi);
79 break;
80 default:
81 printf("Error: Base type is not a CSI.\n");
82 exit(1);
83 }
84
85 return res;
86}
87
88/**
89 * Determine if CSI described by type item @a a is derived from CSI described
90 * by type item @a tb.
91 *
92 * XXX This is somewhat complementary to stype_convert(). It is used for
93 * the explicit @c as conversion. It should only work for objects and only
94 * allow conversion from base to derived types. We might want to scrap this
95 * for a version specific to @c as. The current code does not work with
96 * generics.
97 *
98 * @param a Potential derived CSI.
99 * @param tb Type of potentail base CSI.
100 */
101bool_t tdata_is_ti_derived_from_ti(tdata_item_t *ta, tdata_item_t *tb)
102{
103 bool_t res;
104
105 switch (ta->tic) {
106 case tic_tobject:
107 res = tdata_is_csi_derived_from_ti(ta->u.tobject->csi, tb);
108 break;
109 default:
110 printf("Error: Derived type is not a CSI.\n");
111 exit(1);
112 }
113
114 return res;
115}
116
117/** Determine if two type items are equal (i.e. describe the same type).
118 *
119 * Needed to check compatibility of type arguments in which a parametrized
120 * type is not monotonous.
121 *
122 * @param a Type item
123 * @param b Type item
124 * @return @c b_true if equal, @c b_false if not.
125 */
126bool_t tdata_item_equal(tdata_item_t *a, tdata_item_t *b)
127{
128 /*
129 * Special case: Nil vs. object
130 *
131 * XXX Type of @c Nil should probably be @c object to avoid this
132 * madness.
133 */
134 if (a->tic == tic_tprimitive && a->u.tprimitive->tpc == tpc_nil) {
135 if (b->tic == tic_tobject)
136 return b_true;
137 } else if (b->tic == tic_tprimitive && b->u.tprimitive->tpc == tpc_nil) {
138 if (a->tic == tic_tobject)
139 return b_true;
140 }
141
142 if (a->tic != b->tic)
143 return b_false;
144
145 switch (a->tic) {
146 case tic_tprimitive:
147 /* Check if both have the same tprimitive class. */
148 return (a->u.tprimitive->tpc == b->u.tprimitive->tpc);
149 case tic_tobject:
150 /* Check if both use the same CSI definition. */
151 return (a->u.tobject->csi == b->u.tobject->csi);
152 case tic_tarray:
153 /* Compare rank and base type. */
154 if (a->u.tarray->rank != b->u.tarray->rank)
155 return b_false;
156
157 return tdata_item_equal(a->u.tarray->base_ti,
158 b->u.tarray->base_ti);
159 case tic_tvref:
160 /* Check if both refer to the same type argument. */
161 return (a->u.tvref->targ == b->u.tvref->targ);
162 default:
163 printf("Warning: Unimplemented: Compare types '");
164 tdata_item_print(a);
165 printf("' and '");
166 tdata_item_print(b);
167 printf("'.\n");
168 return b_true;
169 }
170}
171
172/** Substitute type variables in a type item.
173 *
174 * This is the second part of generic type application. In the first part
175 * obtained a TVV using stype_titem_to_tvv() and in this second part we
176 * actually substitute type variables in a type item for their values.
177 * @a tvv must contain all variables referenced in @a ti.
178 *
179 * @param ti Type item to substitute into.
180 * @param tvv Type variable valuation (values of type variables).
181 * @param res Place to store pointer to new type item.
182 */
183void tdata_item_subst(tdata_item_t *ti, tdata_tvv_t *tvv, tdata_item_t **res)
184{
185 switch (ti->tic) {
186 case tic_tprimitive:
187 tdata_item_subst_tprimitive(ti->u.tprimitive, tvv, res);
188 break;
189 case tic_tobject:
190 tdata_item_subst_tobject(ti->u.tobject, tvv, res);
191 break;
192 case tic_tarray:
193 tdata_item_subst_tarray(ti->u.tarray, tvv, res);
194 break;
195 case tic_tdeleg:
196 tdata_item_subst_tdeleg(ti->u.tdeleg, tvv, res);
197 break;
198 case tic_tfun:
199 tdata_item_subst_tfun(ti->u.tfun, tvv, res);
200 break;
201 case tic_tvref:
202 tdata_item_subst_tvref(ti->u.tvref, tvv, res);
203 break;
204 case tic_ignore:
205 *res = tdata_item_new(tic_ignore);
206 }
207}
208
209/** Substitute type variables in a primitive type item.
210 *
211 * @param torig Type item to substitute into.
212 * @param tvv Type variable valuation (values of type variables).
213 * @param res Place to store pointer to new type item.
214 */
215static void tdata_item_subst_tprimitive(tdata_primitive_t *torig,
216 tdata_tvv_t *tvv, tdata_item_t **res)
217{
218 tdata_primitive_t *tnew;
219
220 (void) tvv;
221
222 /* Plain copy */
223 tnew = tdata_primitive_new(torig->tpc);
224 *res = tdata_item_new(tic_tprimitive);
225 (*res)->u.tprimitive = tnew;
226}
227
228/** Substitute type variables in an object type item.
229 *
230 * @param torig Type item to substitute into.
231 * @param tvv Type variable valuation (values of type variables).
232 * @param res Place to store pointer to new type item.
233 */
234static void tdata_item_subst_tobject(tdata_object_t *torig, tdata_tvv_t *tvv,
235 tdata_item_t **res)
236{
237 tdata_object_t *tnew;
238 list_node_t *targ_n;
239 tdata_item_t *targ;
240 tdata_item_t *new_targ;
241
242 /* Copy static ref flag and base CSI. */
243 tnew = tdata_object_new();
244 tnew->static_ref = torig->static_ref;
245 tnew->csi = torig->csi;
246 list_init(&tnew->targs);
247
248 /* Substitute arguments */
249 targ_n = list_first(&torig->targs);
250 while (targ_n != NULL) {
251 targ = list_node_data(targ_n, tdata_item_t *);
252 tdata_item_subst(targ, tvv, &new_targ);
253 list_append(&tnew->targs, new_targ);
254
255 targ_n = list_next(&torig->targs, targ_n);
256 }
257
258 *res = tdata_item_new(tic_tobject);
259 (*res)->u.tobject = tnew;
260}
261
262/** Substitute type variables in an array type item.
263 *
264 * @param torig Type item to substitute into.
265 * @param tvv Type variable valuation (values of type variables).
266 * @param res Place to store pointer to new type item.
267 */
268static void tdata_item_subst_tarray(tdata_array_t *torig, tdata_tvv_t *tvv,
269 tdata_item_t **res)
270{
271 tdata_array_t *tnew;
272 list_node_t *ext_n;
273 stree_expr_t *extent;
274
275 tnew = tdata_array_new();
276
277 /* Substitute base type */
278 tdata_item_subst(torig->base_ti, tvv, &tnew->base_ti);
279
280 /* Copy rank and extents */
281 tnew->rank = torig->rank;
282 list_init(&tnew->extents);
283
284 ext_n = list_first(&torig->extents);
285 while (ext_n != NULL) {
286 extent = list_node_data(ext_n, stree_expr_t *);
287 list_append(&tnew->extents, extent);
288
289 ext_n = list_next(&tnew->extents, ext_n);
290 }
291
292 *res = tdata_item_new(tic_tarray);
293 (*res)->u.tarray = tnew;
294}
295
296/** Substitute type variables in a delegate type item.
297 *
298 * @param torig Type item to substitute into.
299 * @param tvv Type variable valuation (values of type variables).
300 * @param res Place to store pointer to new type item.
301 */
302static void tdata_item_subst_tdeleg(tdata_deleg_t *torig, tdata_tvv_t *tvv,
303 tdata_item_t **res)
304{
305 tdata_deleg_t *tnew;
306
307 tnew = tdata_deleg_new();
308 tnew->deleg = torig->deleg;
309 tdata_item_subst_fun_sig(torig->tsig, tvv, &tnew->tsig);
310
311 *res = tdata_item_new(tic_tdeleg);
312 (*res)->u.tdeleg = tnew;
313}
314
315/** Substitute type variables in a functional type item.
316 *
317 * @param torig Type item to substitute into.
318 * @param tvv Type variable valuation (values of type variables).
319 * @param res Place to store pointer to new type item.
320 */
321static void tdata_item_subst_tfun(tdata_fun_t *torig, tdata_tvv_t *tvv,
322 tdata_item_t **res)
323{
324 tdata_fun_t *tnew;
325
326 tnew = tdata_fun_new();
327 tdata_item_subst_fun_sig(torig->tsig, tvv, &tnew->tsig);
328
329 *res = tdata_item_new(tic_tfun);
330 (*res)->u.tfun = tnew;
331}
332
333/** Substitute type variables in a type-variable reference item.
334 *
335 * @param torig Type item to substitute into.
336 * @param tvv Type variable valuation (values of type variables).
337 * @param res Place to store pointer to new type item.
338 */
339static void tdata_item_subst_tvref(tdata_vref_t *tvref, tdata_tvv_t *tvv,
340 tdata_item_t **res)
341{
342 tdata_item_t *ti_new;
343
344 ti_new = tdata_tvv_get_val(tvv, tvref->targ->name->sid);
345 assert(ti_new != NULL);
346
347 /* XXX Might be better to clone here. */
348 *res = ti_new;
349}
350
351/** Substitute type variables in a function signature type fragment.
352 *
353 * @param torig Type item to substitute into.
354 * @param tvv Type variable valuation (values of type variables).
355 * @param res Place to store pointer to new type item.
356 */
357static void tdata_item_subst_fun_sig(tdata_fun_sig_t *torig, tdata_tvv_t *tvv,
358 tdata_fun_sig_t **res)
359{
360 tdata_fun_sig_t *tnew;
361 list_node_t *arg_n;
362 tdata_item_t *arg_ti;
363 tdata_item_t *narg_ti;
364
365 tnew = tdata_fun_sig_new();
366
367 /* Substitute type of each argument */
368 list_init(&tnew->arg_ti);
369 arg_n = list_first(&torig->arg_ti);
370 while (arg_n != NULL) {
371 arg_ti = list_node_data(arg_n, tdata_item_t *);
372
373 /* XXX Because of overloaded Builtin.WriteLine */
374 if (arg_ti == NULL)
375 narg_ti = NULL;
376 else
377 tdata_item_subst(arg_ti, tvv, &narg_ti);
378
379 list_append(&tnew->arg_ti, narg_ti);
380
381 arg_n = list_next(&torig->arg_ti, arg_n);
382 }
383
384 /* Substitute type of variadic argument */
385 if (torig->varg_ti != NULL)
386 tdata_item_subst(torig->varg_ti, tvv, &tnew->varg_ti);
387
388 /* Substitute return type */
389 if (torig->rtype != NULL)
390 tdata_item_subst(torig->rtype, tvv, &tnew->rtype);
391
392 *res = tnew;
393}
394
395
396/** Print type item.
397 *
398 * @param titem Type item
399 */
400void tdata_item_print(tdata_item_t *titem)
401{
402 if (titem == NULL) {
403 printf("none");
404 return;
405 }
406
407 switch (titem->tic) {
408 case tic_tprimitive:
409 tdata_tprimitive_print(titem->u.tprimitive);
410 break;
411 case tic_tobject:
412 tdata_tobject_print(titem->u.tobject);
413 break;
414 case tic_tarray:
415 tdata_tarray_print(titem->u.tarray);
416 break;
417 case tic_tdeleg:
418 tdata_tdeleg_print(titem->u.tdeleg);
419 break;
420 case tic_tfun:
421 tdata_tfun_print(titem->u.tfun);
422 break;
423 case tic_tvref:
424 tdata_tvref_print(titem->u.tvref);
425 break;
426 case tic_ignore:
427 printf("ignore");
428 break;
429 }
430}
431
432/** Print primitive type item.
433 *
434 * @param tprimitive Primitive type item
435 */
436static void tdata_tprimitive_print(tdata_primitive_t *tprimitive)
437{
438 switch (tprimitive->tpc) {
439 case tpc_bool: printf("bool"); break;
440 case tpc_char: printf("char"); break;
441 case tpc_int: printf("int"); break;
442 case tpc_nil: printf("nil"); break;
443 case tpc_string: printf("string"); break;
444 case tpc_resource: printf("resource"); break;
445 }
446}
447
448/** Print object type item.
449 *
450 * @param tobject Object type item
451 */
452static void tdata_tobject_print(tdata_object_t *tobject)
453{
454 stree_symbol_t *csi_sym;
455 list_node_t *arg_n;
456 tdata_item_t *arg;
457
458 csi_sym = csi_to_symbol(tobject->csi);
459 assert(csi_sym != NULL);
460 symbol_print_fqn(csi_sym);
461
462 arg_n = list_first(&tobject->targs);
463 while (arg_n != NULL) {
464 arg = list_node_data(arg_n, tdata_item_t *);
465 putchar('/');
466 tdata_item_print(arg);
467 arg_n = list_next(&tobject->targs, arg_n);
468 }
469}
470
471/** Print array type item.
472 *
473 * @param tarray Array type item
474 */
475static void tdata_tarray_print(tdata_array_t *tarray)
476{
477 int i;
478
479 tdata_item_print(tarray->base_ti);
480
481 printf("[");
482 for (i = 0; i < tarray->rank - 1; ++i)
483 printf(",");
484 printf("]");
485}
486
487/** Print delegate type item.
488 *
489 * @param tdeleg Delegate type item
490 */
491static void tdata_tdeleg_print(tdata_deleg_t *tdeleg)
492{
493 stree_symbol_t *deleg_sym;
494
495 deleg_sym = deleg_to_symbol(tdeleg->deleg);
496 symbol_print_fqn(deleg_sym);
497}
498
499/** Print function type item.
500 *
501 * @param tfun Function type item
502 */
503static void tdata_tfun_print(tdata_fun_t *tfun)
504{
505 list_node_t *arg_n;
506 tdata_item_t *arg_ti;
507 bool_t first;
508
509 printf("fun(");
510
511 arg_n = list_first(&tfun->tsig->arg_ti);
512 first = b_true;
513 while (arg_n != NULL) {
514 if (first == b_false)
515 printf("; ");
516 else
517 first = b_false;
518
519 arg_ti = list_node_data(arg_n, tdata_item_t *);
520 tdata_item_print(arg_ti);
521
522 arg_n = list_next(&tfun->tsig->arg_ti, arg_n);
523 }
524
525 printf(") : ");
526 tdata_item_print(tfun->tsig->rtype);
527}
528
529/** Print type variable reference type item.
530 *
531 * @param tvref Type variable reference type item
532 */
533static void tdata_tvref_print(tdata_vref_t *tvref)
534{
535 printf("%s", strtab_get_str(tvref->targ->name->sid));
536}
537
538/** Allocate new type item.
539 *
540 * @param tic Type item class
541 * @return New type item
542 */
543tdata_item_t *tdata_item_new(titem_class_t tic)
544{
545 tdata_item_t *titem;
546
547 titem = calloc(1, sizeof(tdata_item_t));
548 if (titem == NULL) {
549 printf("Memory allocation failed.\n");
550 exit(1);
551 }
552
553 titem->tic = tic;
554 return titem;
555}
556
557/** Allocate new array type item.
558 *
559 * @return New array type item
560 */
561tdata_array_t *tdata_array_new(void)
562{
563 tdata_array_t *tarray;
564
565 tarray = calloc(1, sizeof(tdata_array_t));
566 if (tarray == NULL) {
567 printf("Memory allocation failed.\n");
568 exit(1);
569 }
570
571 return tarray;
572}
573
574/** Allocate new object type item.
575 *
576 * @return New object type item
577 */
578tdata_object_t *tdata_object_new(void)
579{
580 tdata_object_t *tobject;
581
582 tobject = calloc(1, sizeof(tdata_object_t));
583 if (tobject == NULL) {
584 printf("Memory allocation failed.\n");
585 exit(1);
586 }
587
588 return tobject;
589}
590
591/** Allocate new primitive type item.
592 *
593 * @return New primitive type item
594 */
595tdata_primitive_t *tdata_primitive_new(tprimitive_class_t tpc)
596{
597 tdata_primitive_t *tprimitive;
598
599 tprimitive = calloc(1, sizeof(tdata_primitive_t));
600 if (tprimitive == NULL) {
601 printf("Memory allocation failed.\n");
602 exit(1);
603 }
604
605 tprimitive->tpc = tpc;
606 return tprimitive;
607}
608
609/** Allocate new delegate type item.
610 *
611 * @return New function type item
612 */
613tdata_deleg_t *tdata_deleg_new(void)
614{
615 tdata_deleg_t *tdeleg;
616
617 tdeleg = calloc(1, sizeof(tdata_deleg_t));
618 if (tdeleg == NULL) {
619 printf("Memory allocation failed.\n");
620 exit(1);
621 }
622
623 return tdeleg;
624}
625
626/** Allocate new functional type item.
627 *
628 * @return New function type item
629 */
630tdata_fun_t *tdata_fun_new(void)
631{
632 tdata_fun_t *tfun;
633
634 tfun = calloc(1, sizeof(tdata_fun_t));
635 if (tfun == NULL) {
636 printf("Memory allocation failed.\n");
637 exit(1);
638 }
639
640 return tfun;
641}
642
643/** Allocate new type variable reference type item.
644 *
645 * @return New type variable reference type item
646 */
647tdata_vref_t *tdata_vref_new(void)
648{
649 tdata_vref_t *tvref;
650
651 tvref = calloc(1, sizeof(tdata_vref_t));
652 if (tvref == NULL) {
653 printf("Memory allocation failed.\n");
654 exit(1);
655 }
656
657 return tvref;
658}
659
660/** Allocate new function signature type fragment.
661 *
662 * @return New function signature type fragment
663 */
664tdata_fun_sig_t *tdata_fun_sig_new(void)
665{
666 tdata_fun_sig_t *tfun_sig;
667
668 tfun_sig = calloc(1, sizeof(tdata_fun_sig_t));
669 if (tfun_sig == NULL) {
670 printf("Memory allocation failed.\n");
671 exit(1);
672 }
673
674 return tfun_sig;
675}
676
677/** Create a new type variable valuation.
678 *
679 * @retrun New type variable valuation
680 */
681tdata_tvv_t *tdata_tvv_new(void)
682{
683 tdata_tvv_t *tvv;
684
685 tvv = calloc(1, sizeof(tdata_tvv_t));
686 if (tvv == NULL) {
687 printf("Memory allocation failed.\n");
688 exit(1);
689 }
690
691 return tvv;
692}
693
694/** Get type variable value.
695 *
696 * Looks up value of the variable with name SID @a name in type
697 * variable valuation @a tvv.
698 *
699 * @param tvv Type variable valuation
700 * @param name Name of the variable (SID)
701 * @return Value of the type variable (type item) or @c NULL
702 * if not defined in @a tvv
703 */
704tdata_item_t *tdata_tvv_get_val(tdata_tvv_t *tvv, sid_t name)
705{
706 return (tdata_item_t *)intmap_get(&tvv->tvv, name);
707}
708
709/** Set tyoe variable value.
710 *
711 * Sets the value of variable with name SID @a name in type variable
712 * valuation @a tvv to the value @a tvalue.
713 *
714 * @param tvv Type variable valuation
715 * @param name Name of the variable (SID)
716 * @param tvalue Value to set (type item) or @c NULL to unset
717 */
718void tdata_tvv_set_val(tdata_tvv_t *tvv, sid_t name, tdata_item_t *tvalue)
719{
720 intmap_set(&tvv->tvv, name, tvalue);
721}
Note: See TracBrowser for help on using the repository browser.