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

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

Fix vertical spacing with new Ccheck revision.

  • Property mode set to 100644
File size: 56.9 KB
Line 
1/*
2 * Copyright (c) 2011 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/**
30 * @file Implements a walk on the program that computes and checks static
31 * types. 'Types' the program.
32 *
33 * If a type error is encountered, stype_note_error() is called to set
34 * the typing error flag.
35 */
36
37#include <stdio.h>
38#include <stdlib.h>
39#include <assert.h>
40#include "cspan.h"
41#include "debug.h"
42#include "intmap.h"
43#include "list.h"
44#include "mytypes.h"
45#include "run_texpr.h"
46#include "stree.h"
47#include "strtab.h"
48#include "stype_expr.h"
49#include "symbol.h"
50#include "tdata.h"
51
52#include "stype.h"
53
54static void stype_csi(stype_t *stype, stree_csi_t *csi);
55static void stype_ctor(stype_t *stype, stree_ctor_t *ctor);
56static void stype_ctor_body(stype_t *stype, stree_ctor_t *ctor);
57static void stype_fun(stype_t *stype, stree_fun_t *fun);
58static void stype_var(stype_t *stype, stree_var_t *var);
59static void stype_prop(stype_t *stype, stree_prop_t *prop);
60
61static void stype_fun_sig(stype_t *stype, stree_csi_t *outer_csi,
62 stree_fun_sig_t *sig, tdata_fun_sig_t **rtsig);
63static void stype_fun_body(stype_t *stype, stree_fun_t *fun);
64static void stype_block(stype_t *stype, stree_block_t *block);
65
66static void stype_class_impl_check(stype_t *stype, stree_csi_t *csi);
67static void stype_class_impl_check_if(stype_t *stype, stree_csi_t *csi,
68 tdata_item_t *iface_ti);
69static void stype_class_impl_check_mbr(stype_t *stype, stree_csi_t *csi,
70 tdata_tvv_t *if_tvv, stree_csimbr_t *ifmbr);
71static void stype_class_impl_check_fun(stype_t *stype,
72 stree_symbol_t *cfun_sym, tdata_tvv_t *if_tvv, stree_symbol_t *ifun_sym);
73static void stype_class_impl_check_prop(stype_t *stype,
74 stree_symbol_t *cprop_sym, tdata_tvv_t *if_tvv, stree_symbol_t *iprop_sym);
75
76static void stype_vdecl(stype_t *stype, stree_vdecl_t *vdecl_s);
77static void stype_if(stype_t *stype, stree_if_t *if_s);
78static void stype_switch(stype_t *stype, stree_switch_t *switch_s);
79static void stype_while(stype_t *stype, stree_while_t *while_s);
80static void stype_for(stype_t *stype, stree_for_t *for_s);
81static void stype_raise(stype_t *stype, stree_raise_t *raise_s);
82static void stype_break(stype_t *stype, stree_break_t *break_s);
83static void stype_return(stype_t *stype, stree_return_t *return_s);
84static void stype_exps(stype_t *stype, stree_exps_t *exp_s, bool_t want_value);
85static void stype_wef(stype_t *stype, stree_wef_t *wef_s);
86
87static stree_expr_t *stype_convert_tprimitive(stype_t *stype,
88 stree_expr_t *expr, tdata_item_t *dest);
89static stree_expr_t *stype_convert_tprim_tobj(stype_t *stype,
90 stree_expr_t *expr, tdata_item_t *dest);
91static stree_expr_t *stype_convert_tobject(stype_t *stype, stree_expr_t *expr,
92 tdata_item_t *dest);
93static stree_expr_t *stype_convert_tarray(stype_t *stype, stree_expr_t *expr,
94 tdata_item_t *dest);
95static stree_expr_t *stype_convert_tdeleg(stype_t *stype, stree_expr_t *expr,
96 tdata_item_t *dest);
97static stree_expr_t *stype_convert_tenum(stype_t *stype, stree_expr_t *expr,
98 tdata_item_t *dest);
99static stree_expr_t *stype_convert_tfun_tdeleg(stype_t *stype,
100 stree_expr_t *expr, tdata_item_t *dest);
101static stree_expr_t *stype_convert_tvref(stype_t *stype, stree_expr_t *expr,
102 tdata_item_t *dest);
103
104static bool_t stype_fun_sig_equal(stype_t *stype, tdata_fun_sig_t *asig,
105 tdata_fun_sig_t *sdig);
106
107/** Type module.
108 *
109 * If the module contains a type error, @a stype->error will be set
110 * when this function returns.
111 *
112 * @param stype Static typing object
113 * @param module Module to type
114 */
115void stype_module(stype_t *stype, stree_module_t *module)
116{
117 list_node_t *mbr_n;
118 stree_modm_t *mbr;
119
120#ifdef DEBUG_TYPE_TRACE
121 printf("Type module.\n");
122#endif
123 stype->current_csi = NULL;
124 stype->proc_vr = NULL;
125
126 mbr_n = list_first(&module->members);
127 while (mbr_n != NULL) {
128 mbr = list_node_data(mbr_n, stree_modm_t *);
129
130 switch (mbr->mc) {
131 case mc_csi:
132 stype_csi(stype, mbr->u.csi);
133 break;
134 case mc_enum:
135 stype_enum(stype, mbr->u.enum_d);
136 break;
137 }
138
139 mbr_n = list_next(&module->members, mbr_n);
140 }
141}
142
143/** Type CSI.
144 *
145 * @param stype Static typing object
146 * @param csi CSI to type
147 */
148static void stype_csi(stype_t *stype, stree_csi_t *csi)
149{
150 list_node_t *csimbr_n;
151 stree_csimbr_t *csimbr;
152 stree_csi_t *prev_ctx;
153
154#ifdef DEBUG_TYPE_TRACE
155 printf("Type CSI '");
156 symbol_print_fqn(csi_to_symbol(csi));
157 printf("'.\n");
158#endif
159 prev_ctx = stype->current_csi;
160 stype->current_csi = csi;
161
162 csimbr_n = list_first(&csi->members);
163 while (csimbr_n != NULL) {
164 csimbr = list_node_data(csimbr_n, stree_csimbr_t *);
165
166 switch (csimbr->cc) {
167 case csimbr_csi:
168 stype_csi(stype, csimbr->u.csi);
169 break;
170 case csimbr_ctor:
171 stype_ctor(stype, csimbr->u.ctor);
172 break;
173 case csimbr_deleg:
174 stype_deleg(stype, csimbr->u.deleg);
175 break;
176 case csimbr_enum:
177 stype_enum(stype, csimbr->u.enum_d);
178 break;
179 case csimbr_fun:
180 stype_fun(stype, csimbr->u.fun);
181 break;
182 case csimbr_var:
183 stype_var(stype, csimbr->u.var);
184 break;
185 case csimbr_prop:
186 stype_prop(stype, csimbr->u.prop);
187 break;
188 }
189
190 csimbr_n = list_next(&csi->members, csimbr_n);
191 }
192
193 if (csi->cc == csi_class)
194 stype_class_impl_check(stype, csi);
195
196 stype->current_csi = prev_ctx;
197}
198
199/** Type a constructor.
200 *
201 * @param stype Static typing object.
202 * @param ctor Constructor to type.
203 */
204static void stype_ctor(stype_t *stype, stree_ctor_t *ctor)
205{
206#ifdef DEBUG_TYPE_TRACE
207 printf("Type constructor '");
208 symbol_print_fqn(ctor_to_symbol(ctor));
209 printf("'.\n");
210#endif
211 if (ctor->titem == NULL)
212 stype_ctor_header(stype, ctor);
213
214 stype_ctor_body(stype, ctor);
215}
216
217/** Type constructor header.
218 *
219 * @param stype Static typing object.
220 * @param ctor Constructor to type.
221 */
222void stype_ctor_header(stype_t *stype, stree_ctor_t *ctor)
223{
224 stree_symbol_t *ctor_sym;
225 tdata_item_t *ctor_ti;
226 tdata_fun_t *tfun;
227 tdata_fun_sig_t *tsig;
228
229#ifdef DEBUG_TYPE_TRACE
230 printf("Type constructor '");
231 symbol_print_fqn(ctor_to_symbol(ctor));
232 printf("' header.\n");
233#endif
234 if (ctor->titem != NULL)
235 return; /* Constructor header has already been typed. */
236
237 ctor_sym = ctor_to_symbol(ctor);
238
239 /* Type function signature. */
240 stype_fun_sig(stype, ctor_sym->outer_csi, ctor->sig, &tsig);
241
242 ctor_ti = tdata_item_new(tic_tfun);
243 tfun = tdata_fun_new();
244 ctor_ti->u.tfun = tfun;
245 tfun->tsig = tsig;
246
247 ctor->titem = ctor_ti;
248}
249
250/** Type constructor body.
251 *
252 * @param stype Static typing object
253 * @param ctor Constructor
254 */
255static void stype_ctor_body(stype_t *stype, stree_ctor_t *ctor)
256{
257#ifdef DEBUG_TYPE_TRACE
258 printf("Type constructor '");
259 symbol_print_fqn(ctor_to_symbol(ctor));
260 printf("' body.\n");
261#endif
262 assert(stype->proc_vr == NULL);
263
264 stype->proc_vr = stype_proc_vr_new();
265 stype->proc_vr->proc = ctor->proc;
266 list_init(&stype->proc_vr->block_vr);
267
268 stype_block(stype, ctor->proc->body);
269
270 free(stype->proc_vr);
271 stype->proc_vr = NULL;
272}
273
274/** Type delegate.
275 *
276 * @param stype Static typing object.
277 * @param deleg Delegate to type.
278 */
279void stype_deleg(stype_t *stype, stree_deleg_t *deleg)
280{
281 stree_symbol_t *deleg_sym;
282 tdata_item_t *deleg_ti;
283 tdata_deleg_t *tdeleg;
284 tdata_fun_sig_t *tsig;
285
286#ifdef DEBUG_TYPE_TRACE
287 printf("Type delegate '");
288 symbol_print_fqn(deleg_to_symbol(deleg));
289 printf("'.\n");
290#endif
291 if (deleg->titem == NULL) {
292 deleg_ti = tdata_item_new(tic_tdeleg);
293 deleg->titem = deleg_ti;
294 tdeleg = tdata_deleg_new();
295 deleg_ti->u.tdeleg = tdeleg;
296 } else {
297 deleg_ti = deleg->titem;
298 assert(deleg_ti->u.tdeleg != NULL);
299 tdeleg = deleg_ti->u.tdeleg;
300 }
301
302 if (tdeleg->tsig != NULL)
303 return; /* Delegate has already been typed. */
304
305 deleg_sym = deleg_to_symbol(deleg);
306
307 /* Type function signature. Store result in deleg->titem. */
308 stype_fun_sig(stype, deleg_sym->outer_csi, deleg->sig, &tsig);
309
310 tdeleg->deleg = deleg;
311 tdeleg->tsig = tsig;
312}
313
314/** Type enum.
315 *
316 * @param stype Static typing object
317 * @param enum_d Enum to type
318 */
319void stype_enum(stype_t *stype, stree_enum_t *enum_d)
320{
321 tdata_item_t *titem;
322 tdata_enum_t *tenum;
323
324 (void) stype;
325
326#ifdef DEBUG_TYPE_TRACE
327 printf("Type enum '");
328 symbol_print_fqn(enum_to_symbol(enum_d));
329 printf("'.\n");
330#endif
331 if (enum_d->titem == NULL) {
332 titem = tdata_item_new(tic_tenum);
333 tenum = tdata_enum_new();
334 titem->u.tenum = tenum;
335 tenum->enum_d = enum_d;
336
337 enum_d->titem = titem;
338 }
339}
340
341/** Type function.
342 *
343 * We split typing of function header and body because at the point we
344 * are typing the body of some function we may encounter function calls.
345 * To type a function call we first need to type the header of the function
346 * being called.
347 *
348 * @param stype Static typing object.
349 * @param fun Function to type.
350 */
351static void stype_fun(stype_t *stype, stree_fun_t *fun)
352{
353#ifdef DEBUG_TYPE_TRACE
354 printf("Type function '");
355 symbol_print_fqn(fun_to_symbol(fun));
356 printf("'.\n");
357#endif
358 if (fun->titem == NULL)
359 stype_fun_header(stype, fun);
360
361 stype_fun_body(stype, fun);
362}
363
364/** Type function header.
365 *
366 * Types the header of @a fun (but not its body).
367 *
368 * @param stype Static typing object
369 * @param fun Funtction
370 */
371void stype_fun_header(stype_t *stype, stree_fun_t *fun)
372{
373 stree_symbol_t *fun_sym;
374 tdata_item_t *fun_ti;
375 tdata_fun_t *tfun;
376 tdata_fun_sig_t *tsig;
377
378#ifdef DEBUG_TYPE_TRACE
379 printf("Type function '");
380 symbol_print_fqn(fun_to_symbol(fun));
381 printf("' header.\n");
382#endif
383 if (fun->titem != NULL)
384 return; /* Function header has already been typed. */
385
386 fun_sym = fun_to_symbol(fun);
387
388 /* Type function signature. */
389 stype_fun_sig(stype, fun_sym->outer_csi, fun->sig, &tsig);
390
391 fun_ti = tdata_item_new(tic_tfun);
392 tfun = tdata_fun_new();
393 fun_ti->u.tfun = tfun;
394 tfun->tsig = tsig;
395
396 fun->titem = fun_ti;
397}
398
399/** Type function signature.
400 *
401 * Types the function signature @a sig.
402 *
403 * @param stype Static typing object
404 * @param outer_csi CSI within which the signature is defined.
405 * @param sig Function signature
406 */
407static void stype_fun_sig(stype_t *stype, stree_csi_t *outer_csi,
408 stree_fun_sig_t *sig, tdata_fun_sig_t **rtsig)
409{
410 list_node_t *arg_n;
411 stree_proc_arg_t *arg;
412 tdata_item_t *titem;
413 tdata_fun_sig_t *tsig;
414
415#ifdef DEBUG_TYPE_TRACE
416 printf("Type function signature.\n");
417#endif
418 tsig = tdata_fun_sig_new();
419
420 list_init(&tsig->arg_ti);
421
422 /*
423 * Type formal arguments.
424 */
425 arg_n = list_first(&sig->args);
426 while (arg_n != NULL) {
427 arg = list_node_data(arg_n, stree_proc_arg_t *);
428
429 /* XXX Because of overloaded builtin WriteLine. */
430 if (arg->type == NULL) {
431 list_append(&tsig->arg_ti, NULL);
432 arg_n = list_next(&sig->args, arg_n);
433 continue;
434 }
435
436 run_texpr(stype->program, outer_csi, arg->type, &titem);
437 list_append(&tsig->arg_ti, titem);
438
439 arg_n = list_next(&sig->args, arg_n);
440 }
441
442 /* Variadic argument */
443 if (sig->varg != NULL) {
444 /* Check type and verify it is an array. */
445 run_texpr(stype->program, outer_csi, sig->varg->type, &titem);
446 tsig->varg_ti = titem;
447
448 if (titem->tic != tic_tarray && titem->tic != tic_ignore) {
449 printf("Error: Packed argument is not an array.\n");
450 stype_note_error(stype);
451 }
452 }
453
454 /* Return type */
455 if (sig->rtype != NULL) {
456 run_texpr(stype->program, outer_csi, sig->rtype, &titem);
457 tsig->rtype = titem;
458 }
459
460 *rtsig = tsig;
461}
462
463/** Type function body.
464 *
465 * Types the body of function @a fun (if it has one).
466 *
467 * @param stype Static typing object
468 * @param fun Funtction
469 */
470static void stype_fun_body(stype_t *stype, stree_fun_t *fun)
471{
472#ifdef DEBUG_TYPE_TRACE
473 printf("Type function '");
474 symbol_print_fqn(fun_to_symbol(fun));
475 printf("' body.\n");
476#endif
477 assert(stype->proc_vr == NULL);
478
479 /* Declarations and builtin functions do not have a body. */
480 if (fun->proc->body == NULL)
481 return;
482
483 stype->proc_vr = stype_proc_vr_new();
484 stype->proc_vr->proc = fun->proc;
485 list_init(&stype->proc_vr->block_vr);
486
487 stype_block(stype, fun->proc->body);
488
489 free(stype->proc_vr);
490 stype->proc_vr = NULL;
491}
492
493/** Type member variable.
494 *
495 * @param stype Static typing object
496 * @param var Member variable
497 */
498static void stype_var(stype_t *stype, stree_var_t *var)
499{
500 tdata_item_t *titem;
501
502 run_texpr(stype->program, stype->current_csi, var->type,
503 &titem);
504 if (titem->tic == tic_ignore) {
505 /* An error occured. */
506 stype_note_error(stype);
507 }
508}
509
510/** Type property.
511 *
512 * @param stype Static typing object
513 * @param prop Property
514 */
515static void stype_prop(stype_t *stype, stree_prop_t *prop)
516{
517#ifdef DEBUG_TYPE_TRACE
518 printf("Type property '");
519 symbol_print_fqn(prop_to_symbol(prop));
520 printf("'.\n");
521#endif
522 if (prop->titem == NULL)
523 stype_prop_header(stype, prop);
524
525 stype->proc_vr = stype_proc_vr_new();
526 list_init(&stype->proc_vr->block_vr);
527
528 /* Property declarations do not have a getter body. */
529 if (prop->getter != NULL && prop->getter->body != NULL) {
530 stype->proc_vr->proc = prop->getter;
531 stype_block(stype, prop->getter->body);
532 }
533
534 /* Property declarations do not have a setter body. */
535 if (prop->setter != NULL && prop->setter->body != NULL) {
536 stype->proc_vr->proc = prop->setter;
537 stype_block(stype, prop->setter->body);
538 }
539
540 free(stype->proc_vr);
541 stype->proc_vr = NULL;
542}
543
544/** Type property header.
545 *
546 * @param stype Static typing object
547 * @param prop Property
548 */
549void stype_prop_header(stype_t *stype, stree_prop_t *prop)
550{
551 tdata_item_t *titem;
552
553#ifdef DEBUG_TYPE_TRACE
554 printf("Type property '");
555 symbol_print_fqn(prop_to_symbol(prop));
556 printf("' header.\n");
557#endif
558 run_texpr(stype->program, stype->current_csi, prop->type,
559 &titem);
560 if (titem->tic == tic_ignore) {
561 /* An error occured. */
562 stype_note_error(stype);
563 return;
564 }
565
566 prop->titem = titem;
567}
568
569/** Type statement block.
570 *
571 * @param stype Static typing object
572 * @param block Statement block
573 */
574static void stype_block(stype_t *stype, stree_block_t *block)
575{
576 stree_stat_t *stat;
577 list_node_t *stat_n;
578 stype_block_vr_t *block_vr;
579 list_node_t *bvr_n;
580
581#ifdef DEBUG_TYPE_TRACE
582 printf("Type block.\n");
583#endif
584
585 /* Create block visit record. */
586 block_vr = stype_block_vr_new();
587 intmap_init(&block_vr->vdecls);
588
589 /* Add block visit record to the stack. */
590 list_append(&stype->proc_vr->block_vr, block_vr);
591
592 stat_n = list_first(&block->stats);
593 while (stat_n != NULL) {
594 stat = list_node_data(stat_n, stree_stat_t *);
595 stype_stat(stype, stat, b_false);
596
597 stat_n = list_next(&block->stats, stat_n);
598 }
599
600 /* Remove block visit record from the stack, */
601 bvr_n = list_last(&stype->proc_vr->block_vr);
602 assert(list_node_data(bvr_n, stype_block_vr_t *) == block_vr);
603 list_remove(&stype->proc_vr->block_vr, bvr_n);
604}
605
606/** Verify that class fully implements all interfaces as it claims.
607 *
608 * @param stype Static typing object
609 * @param csi CSI to check
610 */
611static void stype_class_impl_check(stype_t *stype, stree_csi_t *csi)
612{
613 list_node_t *pred_n;
614 stree_texpr_t *pred_te;
615 tdata_item_t *pred_ti;
616
617#ifdef DEBUG_TYPE_TRACE
618 printf("Verify that class implements all interfaces.\n");
619#endif
620 assert(csi->cc == csi_class);
621
622 pred_n = list_first(&csi->inherit);
623 while (pred_n != NULL) {
624 pred_te = list_node_data(pred_n, stree_texpr_t *);
625 run_texpr(stype->program, csi, pred_te, &pred_ti);
626
627 assert(pred_ti->tic == tic_tobject);
628 switch (pred_ti->u.tobject->csi->cc) {
629 case csi_class:
630 break;
631 case csi_struct:
632 assert(b_false);
633 /* Fallthrough */
634 case csi_interface:
635 /* Store to impl_if_ti for later use. */
636 list_append(&csi->impl_if_ti, pred_ti);
637
638 /* Check implementation of this interface. */
639 stype_class_impl_check_if(stype, csi, pred_ti);
640 break;
641 }
642
643 pred_n = list_next(&csi->inherit, pred_n);
644 }
645}
646
647/** Verify that class fully implements an interface.
648 *
649 * @param stype Static typing object
650 * @param csi CSI to check
651 * @param iface Interface that must be fully implemented
652 */
653static void stype_class_impl_check_if(stype_t *stype, stree_csi_t *csi,
654 tdata_item_t *iface_ti)
655{
656 tdata_tvv_t *iface_tvv;
657 list_node_t *pred_n;
658 tdata_item_t *pred_ti;
659 tdata_item_t *pred_sti;
660
661 stree_csi_t *iface;
662 list_node_t *ifmbr_n;
663 stree_csimbr_t *ifmbr;
664
665 assert(csi->cc == csi_class);
666
667 assert(iface_ti->tic == tic_tobject);
668 iface = iface_ti->u.tobject->csi;
669 assert(iface->cc == csi_interface);
670
671#ifdef DEBUG_TYPE_TRACE
672 printf("Verify that class fully implements interface.\n");
673#endif
674 /* Compute TVV for this interface reference. */
675 stype_titem_to_tvv(stype, iface_ti, &iface_tvv);
676
677 /*
678 * Recurse to accumulated interfaces.
679 */
680 pred_n = list_first(&iface->impl_if_ti);
681 while (pred_n != NULL) {
682 pred_ti = list_node_data(pred_n, tdata_item_t *);
683 assert(pred_ti->tic == tic_tobject);
684 assert(pred_ti->u.tobject->csi->cc == csi_interface);
685
686 /* Substitute real type parameters to predecessor reference. */
687 tdata_item_subst(pred_ti, iface_tvv, &pred_sti);
688
689 /* Check accumulated interface. */
690 stype_class_impl_check_if(stype, csi, pred_sti);
691
692 pred_n = list_next(&iface->impl_if_ti, pred_n);
693 }
694
695 /*
696 * Check all interface members.
697 */
698 ifmbr_n = list_first(&iface->members);
699 while (ifmbr_n != NULL) {
700 ifmbr = list_node_data(ifmbr_n, stree_csimbr_t *);
701 stype_class_impl_check_mbr(stype, csi, iface_tvv, ifmbr);
702
703 ifmbr_n = list_next(&iface->members, ifmbr_n);
704 }
705}
706
707/** Verify that class fully implements an interface member.
708 *
709 * @param stype Static typing object
710 * @param csi CSI to check
711 * @param if_tvv TVV for @a ifmbr
712 * @param ifmbr Interface that must be fully implemented
713 */
714static void stype_class_impl_check_mbr(stype_t *stype, stree_csi_t *csi,
715 tdata_tvv_t *if_tvv, stree_csimbr_t *ifmbr)
716{
717 stree_symbol_t *cmbr_sym;
718 stree_symbol_t *ifmbr_sym;
719 stree_ident_t *ifmbr_name;
720
721 assert(csi->cc == csi_class);
722
723#ifdef DEBUG_TYPE_TRACE
724 printf("Verify that class implements interface member.\n");
725#endif
726 ifmbr_name = stree_csimbr_get_name(ifmbr);
727
728 cmbr_sym = symbol_search_csi(stype->program, csi, ifmbr_name);
729 if (cmbr_sym == NULL) {
730 printf("Error: CSI '");
731 symbol_print_fqn(csi_to_symbol(csi));
732 printf("' should implement '");
733 symbol_print_fqn(csimbr_to_symbol(ifmbr));
734 printf("' but it does not.\n");
735 stype_note_error(stype);
736 return;
737 }
738
739 ifmbr_sym = csimbr_to_symbol(ifmbr);
740 if (cmbr_sym->sc != ifmbr_sym->sc) {
741 printf("Error: CSI '");
742 symbol_print_fqn(csi_to_symbol(csi));
743 printf("' implements '");
744 symbol_print_fqn(csimbr_to_symbol(ifmbr));
745 printf("' as a different kind of symbol.\n");
746 stype_note_error(stype);
747 }
748
749 switch (cmbr_sym->sc) {
750 case sc_csi:
751 case sc_ctor:
752 case sc_deleg:
753 case sc_enum:
754 /*
755 * Checked at parse time. Interface should not have these
756 * member types.
757 */
758 assert(b_false);
759 /* Fallthrough */
760 case sc_fun:
761 stype_class_impl_check_fun(stype, cmbr_sym, if_tvv, ifmbr_sym);
762 break;
763 case sc_var:
764 /*
765 * Checked at parse time. Interface should not have these
766 * member types.
767 */
768 assert(b_false);
769 /* Fallthrough */
770 case sc_prop:
771 stype_class_impl_check_prop(stype, cmbr_sym, if_tvv, ifmbr_sym);
772 break;
773 }
774}
775
776/** Verify that class properly implements a function from an interface.
777 *
778 * @param stype Static typing object
779 * @param cfun_sym Function symbol in class
780 * @param if_tvv TVV for @a ifun_sym
781 * @param ifun_sym Function declaration symbol in interface
782 */
783static void stype_class_impl_check_fun(stype_t *stype,
784 stree_symbol_t *cfun_sym, tdata_tvv_t *if_tvv, stree_symbol_t *ifun_sym)
785{
786 stree_fun_t *cfun;
787 tdata_fun_t *tcfun;
788 stree_fun_t *ifun;
789 tdata_item_t *sifun_ti;
790 tdata_fun_t *tifun;
791
792#ifdef DEBUG_TYPE_TRACE
793 printf("Verify that class '");
794 symbol_print_fqn(csi_to_symbol(cfun_sym->outer_csi));
795 printf("' implements function '");
796 symbol_print_fqn(ifun_sym);
797 printf("' properly.\n");
798#endif
799 assert(cfun_sym->sc == sc_fun);
800 cfun = cfun_sym->u.fun;
801
802 assert(ifun_sym->sc == sc_fun);
803 ifun = ifun_sym->u.fun;
804
805 assert(cfun->titem->tic == tic_tfun);
806 tcfun = cfun->titem->u.tfun;
807
808 tdata_item_subst(ifun->titem, if_tvv, &sifun_ti);
809 assert(sifun_ti->tic == tic_tfun);
810 tifun = sifun_ti->u.tfun;
811
812 if (!stype_fun_sig_equal(stype, tcfun->tsig, tifun->tsig)) {
813 cspan_print(cfun->name->cspan);
814 printf(" Error: Type of function '");
815 symbol_print_fqn(cfun_sym);
816 printf("' (");
817 tdata_item_print(cfun->titem);
818 printf(") does not match type of '");
819 symbol_print_fqn(ifun_sym);
820 printf("' (");
821 tdata_item_print(sifun_ti);
822 printf(") which it should implement.\n");
823 stype_note_error(stype);
824 }
825}
826
827/** Verify that class properly implements a function from an interface.
828 *
829 * @param stype Static typing object
830 * @param cprop_sym Property symbol in class
831 * @param if_tvv TVV for @a ifun_sym
832 * @param iprop_sym Property declaration symbol in interface
833 */
834static void stype_class_impl_check_prop(stype_t *stype,
835 stree_symbol_t *cprop_sym, tdata_tvv_t *if_tvv, stree_symbol_t *iprop_sym)
836{
837 stree_prop_t *cprop;
838 stree_prop_t *iprop;
839 tdata_item_t *siprop_ti;
840
841#ifdef DEBUG_TYPE_TRACE
842 printf("Verify that class '");
843 symbol_print_fqn(csi_to_symbol(cprop_sym->outer_csi));
844 printf("' implements property '");
845 symbol_print_fqn(iprop_sym);
846 printf("' properly.\n");
847#endif
848 assert(cprop_sym->sc == sc_prop);
849 cprop = cprop_sym->u.prop;
850
851 assert(iprop_sym->sc == sc_prop);
852 iprop = iprop_sym->u.prop;
853
854 tdata_item_subst(iprop->titem, if_tvv, &siprop_ti);
855
856 if (!tdata_item_equal(cprop->titem, siprop_ti)) {
857 cspan_print(cprop->name->cspan);
858 printf(" Error: Type of property '");
859 symbol_print_fqn(cprop_sym);
860 printf("' (");
861 tdata_item_print(cprop->titem);
862 printf(") does not match type of '");
863 symbol_print_fqn(iprop_sym);
864 printf("' (");
865 tdata_item_print(siprop_ti);
866 printf(") which it should implement.\n");
867 stype_note_error(stype);
868 }
869
870 if (iprop->getter != NULL && cprop->getter == NULL) {
871 cspan_print(cprop->name->cspan);
872 printf(" Error: Property '");
873 symbol_print_fqn(cprop_sym);
874 printf("' is missing a getter, which is required by '");
875 symbol_print_fqn(iprop_sym);
876 printf("'.\n");
877 stype_note_error(stype);
878 }
879
880 if (iprop->setter != NULL && cprop->setter == NULL) {
881 cspan_print(cprop->name->cspan);
882 printf(" Error: Property '");
883 symbol_print_fqn(cprop_sym);
884 printf("' is missing a setter, which is required by '");
885 symbol_print_fqn(iprop_sym);
886 printf("'.\n");
887 stype_note_error(stype);
888 }
889}
890
891/** Type statement
892 *
893 * Types a statement. If @a want_value is @c b_true, then warning about
894 * ignored expression value will be supressed for this statement (but not
895 * for nested statemens). This is used in interactive mode.
896 *
897 * @param stype Static typing object
898 * @param stat Statement to type
899 * @param want_value @c b_true to allow ignoring expression value
900 */
901void stype_stat(stype_t *stype, stree_stat_t *stat, bool_t want_value)
902{
903#ifdef DEBUG_TYPE_TRACE
904 printf("Type statement.\n");
905#endif
906 switch (stat->sc) {
907 case st_vdecl:
908 stype_vdecl(stype, stat->u.vdecl_s);
909 break;
910 case st_if:
911 stype_if(stype, stat->u.if_s);
912 break;
913 case st_switch:
914 stype_switch(stype, stat->u.switch_s);
915 break;
916 case st_while:
917 stype_while(stype, stat->u.while_s);
918 break;
919 case st_for:
920 stype_for(stype, stat->u.for_s);
921 break;
922 case st_raise:
923 stype_raise(stype, stat->u.raise_s);
924 break;
925 case st_break:
926 stype_break(stype, stat->u.break_s);
927 break;
928 case st_return:
929 stype_return(stype, stat->u.return_s);
930 break;
931 case st_exps:
932 stype_exps(stype, stat->u.exp_s, want_value);
933 break;
934 case st_wef:
935 stype_wef(stype, stat->u.wef_s);
936 break;
937 }
938}
939
940/** Type local variable declaration statement.
941 *
942 * @param stype Static typing object
943 * @param vdecl_s Variable delcaration statement
944 */
945static void stype_vdecl(stype_t *stype, stree_vdecl_t *vdecl_s)
946{
947 stype_block_vr_t *block_vr;
948 stree_vdecl_t *old_vdecl;
949 tdata_item_t *titem;
950
951#ifdef DEBUG_TYPE_TRACE
952 printf("Type variable declaration statement.\n");
953#endif
954 block_vr = stype_get_current_block_vr(stype);
955 old_vdecl = (stree_vdecl_t *) intmap_get(&block_vr->vdecls,
956 vdecl_s->name->sid);
957
958 if (old_vdecl != NULL) {
959 printf("Error: Duplicate variable declaration '%s'.\n",
960 strtab_get_str(vdecl_s->name->sid));
961 stype_note_error(stype);
962 }
963
964 run_texpr(stype->program, stype->current_csi, vdecl_s->type,
965 &titem);
966 if (titem->tic == tic_ignore) {
967 /* An error occured. */
968 stype_note_error(stype);
969 return;
970 }
971
972 /* Annotate with variable type */
973 vdecl_s->titem = titem;
974
975 intmap_set(&block_vr->vdecls, vdecl_s->name->sid, vdecl_s);
976}
977
978/** Type @c if statement.
979 *
980 * @param stype Static typing object
981 * @param if_s @c if statement
982 */
983static void stype_if(stype_t *stype, stree_if_t *if_s)
984{
985 stree_expr_t *ccond;
986 list_node_t *ifc_node;
987 stree_if_clause_t *ifc;
988
989#ifdef DEBUG_TYPE_TRACE
990 printf("Type 'if' statement.\n");
991#endif
992 ifc_node = list_first(&if_s->if_clauses);
993
994 /* Walk through all if/elif clauses. */
995
996 while (ifc_node != NULL) {
997 /* Get if/elif clause */
998 ifc = list_node_data(ifc_node, stree_if_clause_t *);
999
1000 /* Convert condition to boolean type. */
1001 stype_expr(stype, ifc->cond);
1002 ccond = stype_convert(stype, ifc->cond,
1003 stype_boolean_titem(stype));
1004
1005 /* Patch code with augmented expression. */
1006 ifc->cond = ccond;
1007
1008 /* Type the @c if/elif block */
1009 stype_block(stype, ifc->block);
1010
1011 ifc_node = list_next(&if_s->if_clauses, ifc_node);
1012 }
1013
1014 /* Type the @c else block */
1015 if (if_s->else_block != NULL)
1016 stype_block(stype, if_s->else_block);
1017}
1018
1019/** Type @c switch statement.
1020 *
1021 * @param stype Static typing object
1022 * @param switch_s @c switch statement
1023 */
1024static void stype_switch(stype_t *stype, stree_switch_t *switch_s)
1025{
1026 stree_expr_t *expr, *cexpr;
1027 list_node_t *whenc_node;
1028 stree_when_t *whenc;
1029 list_node_t *expr_node;
1030 tdata_item_t *titem1, *titem2;
1031
1032#ifdef DEBUG_TYPE_TRACE
1033 printf("Type 'switch' statement.\n");
1034#endif
1035 stype_expr(stype, switch_s->expr);
1036
1037 titem1 = switch_s->expr->titem;
1038 if (titem1 == NULL) {
1039 cspan_print(switch_s->expr->cspan);
1040 printf(" Error: Switch expression has no value.\n");
1041 stype_note_error(stype);
1042 return;
1043 }
1044
1045 /* Walk through all when clauses. */
1046 whenc_node = list_first(&switch_s->when_clauses);
1047
1048 while (whenc_node != NULL) {
1049 /* Get when clause */
1050 whenc = list_node_data(whenc_node, stree_when_t *);
1051
1052 /* Walk through all expressions of the when clause */
1053 expr_node = list_first(&whenc->exprs);
1054 while (expr_node != NULL) {
1055 expr = list_node_data(expr_node, stree_expr_t *);
1056
1057 stype_expr(stype, expr);
1058 titem2 = expr->titem;
1059 if (titem2 == NULL) {
1060 cspan_print(expr->cspan);
1061 printf(" Error: When expression has no value.\n");
1062 stype_note_error(stype);
1063 return;
1064 }
1065
1066 /* Convert expression to same type as switch expr. */
1067 cexpr = stype_convert(stype, expr, titem1);
1068
1069 /* Patch code with augmented expression. */
1070 list_node_setdata(expr_node, cexpr);
1071
1072 expr_node = list_next(&whenc->exprs, expr_node);
1073 }
1074
1075 /* Type the @c when block */
1076 stype_block(stype, whenc->block);
1077
1078 whenc_node = list_next(&switch_s->when_clauses, whenc_node);
1079 }
1080
1081 /* Type the @c else block */
1082 if (switch_s->else_block != NULL)
1083 stype_block(stype, switch_s->else_block);
1084}
1085
1086/** Type @c while statement
1087 *
1088 * @param stype Static typing object
1089 * @param while_s @c while statement
1090 */
1091static void stype_while(stype_t *stype, stree_while_t *while_s)
1092{
1093 stree_expr_t *ccond;
1094
1095#ifdef DEBUG_TYPE_TRACE
1096 printf("Type 'while' statement.\n");
1097#endif
1098 /* Convert condition to boolean type. */
1099 stype_expr(stype, while_s->cond);
1100 ccond = stype_convert(stype, while_s->cond,
1101 stype_boolean_titem(stype));
1102
1103 /* Patch code with augmented expression. */
1104 while_s->cond = ccond;
1105
1106 /* While is a breakable statement. Increment counter. */
1107 stype->proc_vr->bstat_cnt += 1;
1108
1109 /* Type the body of the loop */
1110 stype_block(stype, while_s->body);
1111
1112 stype->proc_vr->bstat_cnt -= 1;
1113}
1114
1115/** Type @c for statement.
1116 *
1117 * @param stype Static typing object
1118 * @param for_s @c for statement
1119 */
1120static void stype_for(stype_t *stype, stree_for_t *for_s)
1121{
1122#ifdef DEBUG_TYPE_TRACE
1123 printf("Type 'for' statement.\n");
1124#endif
1125 /* For is a breakable statement. Increment counter. */
1126 stype->proc_vr->bstat_cnt += 1;
1127
1128 stype_block(stype, for_s->body);
1129
1130 stype->proc_vr->bstat_cnt -= 1;
1131}
1132
1133/** Type @c raise statement.
1134 *
1135 * @param stype Static typing object
1136 * @param raise_s @c raise statement
1137 */
1138static void stype_raise(stype_t *stype, stree_raise_t *raise_s)
1139{
1140#ifdef DEBUG_TYPE_TRACE
1141 printf("Type 'raise' statement.\n");
1142#endif
1143 stype_expr(stype, raise_s->expr);
1144}
1145
1146/** Type @c break statement */
1147static void stype_break(stype_t *stype, stree_break_t *break_s)
1148{
1149#ifdef DEBUG_TYPE_TRACE
1150 printf("Type 'break' statement.\n");
1151#endif
1152 (void) break_s;
1153
1154 /* Check whether there is an active statement to break from. */
1155 if (stype->proc_vr->bstat_cnt == 0) {
1156 printf("Error: Break statement outside of while or for.\n");
1157 stype_note_error(stype);
1158 }
1159}
1160
1161/** Type @c return statement */
1162static void stype_return(stype_t *stype, stree_return_t *return_s)
1163{
1164 stree_symbol_t *outer_sym;
1165 stree_fun_t *fun;
1166 stree_prop_t *prop;
1167
1168 stree_expr_t *cexpr;
1169 tdata_item_t *dtype;
1170
1171#ifdef DEBUG_TYPE_TRACE
1172 printf("Type 'return' statement.\n");
1173#endif
1174 if (return_s->expr != NULL)
1175 stype_expr(stype, return_s->expr);
1176
1177 /* Determine the type we need to return. */
1178
1179 outer_sym = stype->proc_vr->proc->outer_symbol;
1180 switch (outer_sym->sc) {
1181 case sc_fun:
1182 fun = symbol_to_fun(outer_sym);
1183 assert(fun != NULL);
1184
1185 /* XXX Memoize to avoid recomputing. */
1186 if (fun->sig->rtype != NULL) {
1187 run_texpr(stype->program, outer_sym->outer_csi,
1188 fun->sig->rtype, &dtype);
1189
1190 if (return_s->expr == NULL) {
1191 printf("Error: Return without a value in "
1192 "function returning value.\n");
1193 stype_note_error(stype);
1194 }
1195 } else {
1196 dtype = NULL;
1197
1198 if (return_s->expr != NULL) {
1199 printf("Error: Return with a value in "
1200 "value-less function.\n");
1201 stype_note_error(stype);
1202 }
1203 }
1204 break;
1205 case sc_prop:
1206 prop = symbol_to_prop(outer_sym);
1207 assert(prop != NULL);
1208
1209 if (stype->proc_vr->proc == prop->getter) {
1210 if (return_s->expr == NULL) {
1211 printf("Error: Return without a value in "
1212 "getter.\n");
1213 stype_note_error(stype);
1214 }
1215 } else {
1216 if (return_s->expr == NULL) {
1217 printf("Error: Return with a value in "
1218 "setter.\n");
1219 stype_note_error(stype);
1220 }
1221 }
1222
1223 /* XXX Memoize to avoid recomputing. */
1224 run_texpr(stype->program, outer_sym->outer_csi, prop->type,
1225 &dtype);
1226 break;
1227 default:
1228 assert(b_false);
1229 }
1230
1231 if (dtype != NULL && return_s->expr != NULL) {
1232 /* Convert to the return type. */
1233 cexpr = stype_convert(stype, return_s->expr, dtype);
1234
1235 /* Patch code with the augmented expression. */
1236 return_s->expr = cexpr;
1237 }
1238}
1239
1240/** Type expression statement.
1241 *
1242 * @param stype Static typing object
1243 * @param exp_s Expression statement
1244 */
1245static void stype_exps(stype_t *stype, stree_exps_t *exp_s, bool_t want_value)
1246{
1247#ifdef DEBUG_TYPE_TRACE
1248 printf("Type expression statement.\n");
1249#endif
1250 stype_expr(stype, exp_s->expr);
1251
1252 if (want_value == b_false && exp_s->expr->titem != NULL) {
1253 cspan_print(exp_s->expr->cspan);
1254 printf(" Warning: Expression value ignored.\n");
1255 }
1256}
1257
1258/** Type with-except-finally statement.
1259 *
1260 * @param stype Static typing object
1261 * @param wef_s With-except-finally statement
1262 */
1263static void stype_wef(stype_t *stype, stree_wef_t *wef_s)
1264{
1265 list_node_t *ec_n;
1266 stree_except_t *ec;
1267
1268#ifdef DEBUG_TYPE_TRACE
1269 printf("Type WEF statement.\n");
1270#endif
1271 /* Type the @c with block. */
1272 if (wef_s->with_block != NULL)
1273 stype_block(stype, wef_s->with_block);
1274
1275 /* Type the @c except clauses. */
1276 ec_n = list_first(&wef_s->except_clauses);
1277 while (ec_n != NULL) {
1278 ec = list_node_data(ec_n, stree_except_t *);
1279 run_texpr(stype->program, stype->current_csi, ec->etype,
1280 &ec->titem);
1281 stype_block(stype, ec->block);
1282
1283 ec_n = list_next(&wef_s->except_clauses, ec_n);
1284 }
1285
1286 /* Type the @c finally block. */
1287 if (wef_s->finally_block != NULL)
1288 stype_block(stype, wef_s->finally_block);
1289}
1290
1291/** Convert expression of one type to another type.
1292 *
1293 * If the type of expression @a expr is not compatible with @a dtype
1294 * (i.e. there does not exist an implicit conversion from @a expr->type to
1295 * @a dtype), this function will produce an error (Cannot convert A to B).
1296 *
1297 * Otherwise it will either return the expression unmodified (if there is
1298 * no action to take at run time) or it will return a new expression
1299 * while clobbering the old one. Typically this would just attach the
1300 * expression as a subtree of the conversion.
1301 *
1302 * Note: No conversion that would require modifying @a expr is implemented
1303 * yet.
1304 *
1305 * @param stype Static typing object
1306 * @param expr Expression
1307 * @param dest Destination type
1308 */
1309stree_expr_t *stype_convert(stype_t *stype, stree_expr_t *expr,
1310 tdata_item_t *dest)
1311{
1312 tdata_item_t *src;
1313
1314 src = expr->titem;
1315
1316#ifdef DEBUG_TYPE_TRACE
1317 printf("Convert '");
1318 tdata_item_print(src);
1319 printf("' to '");
1320 tdata_item_print(dest);
1321 printf("'.\n");
1322#endif
1323
1324 if (dest == NULL) {
1325 printf("Error: Conversion destination is not valid.\n");
1326 stype_note_error(stype);
1327 return expr;
1328 }
1329
1330 if (src == NULL) {
1331 cspan_print(expr->cspan);
1332 printf(" Error: Conversion source is not valid.\n");
1333 stype_note_error(stype);
1334 return expr;
1335 }
1336
1337 if (dest->tic == tic_ignore || src->tic == tic_ignore)
1338 return expr;
1339
1340 /*
1341 * Special case: Nil to object.
1342 */
1343 if (src->tic == tic_tprimitive && src->u.tprimitive->tpc == tpc_nil) {
1344 if (dest->tic == tic_tobject)
1345 return expr;
1346 }
1347
1348 if (src->tic == tic_tprimitive && dest->tic == tic_tobject) {
1349 return stype_convert_tprim_tobj(stype, expr, dest);
1350 }
1351
1352 if (src->tic == tic_tfun && dest->tic == tic_tdeleg) {
1353 return stype_convert_tfun_tdeleg(stype, expr, dest);
1354 }
1355
1356 if (src->tic == tic_tebase) {
1357 stype_convert_failure(stype, convc_implicit, expr, dest);
1358 printf("Invalid use of reference to enum type in "
1359 "expression.\n");
1360 return expr;
1361 }
1362
1363 if (src->tic != dest->tic) {
1364 stype_convert_failure(stype, convc_implicit, expr, dest);
1365 return expr;
1366 }
1367
1368 switch (src->tic) {
1369 case tic_tprimitive:
1370 expr = stype_convert_tprimitive(stype, expr, dest);
1371 break;
1372 case tic_tobject:
1373 expr = stype_convert_tobject(stype, expr, dest);
1374 break;
1375 case tic_tarray:
1376 expr = stype_convert_tarray(stype, expr, dest);
1377 break;
1378 case tic_tdeleg:
1379 expr = stype_convert_tdeleg(stype, expr, dest);
1380 break;
1381 case tic_tebase:
1382 /* Conversion destination should never be enum-base */
1383 assert(b_false);
1384 /* Fallthrough */
1385 case tic_tenum:
1386 expr = stype_convert_tenum(stype, expr, dest);
1387 break;
1388 case tic_tfun:
1389 assert(b_false);
1390 /* Fallthrough */
1391 case tic_tvref:
1392 expr = stype_convert_tvref(stype, expr, dest);
1393 break;
1394 case tic_ignore:
1395 assert(b_false);
1396 }
1397
1398 return expr;
1399}
1400
1401/** Convert expression of primitive type to primitive type.
1402 *
1403 * @param stype Static typing object
1404 * @param expr Expression
1405 * @param dest Destination type
1406 */
1407static stree_expr_t *stype_convert_tprimitive(stype_t *stype,
1408 stree_expr_t *expr, tdata_item_t *dest)
1409{
1410 tdata_item_t *src;
1411
1412#ifdef DEBUG_TYPE_TRACE
1413 printf("Convert primitive type.\n");
1414#endif
1415 src = expr->titem;
1416 assert(src->tic == tic_tprimitive);
1417 assert(dest->tic == tic_tprimitive);
1418
1419 /* Check if both have the same tprimitive class. */
1420 if (src->u.tprimitive->tpc != dest->u.tprimitive->tpc)
1421 stype_convert_failure(stype, convc_implicit, expr, dest);
1422
1423 return expr;
1424}
1425
1426/** Convert expression of primitive type to object type.
1427 *
1428 * This function implements autoboxing. It modifies the code by inserting
1429 * the boxing operation.
1430 *
1431 * @param stype Static typing object
1432 * @param expr Expression
1433 * @param dest Destination type
1434 */
1435static stree_expr_t *stype_convert_tprim_tobj(stype_t *stype,
1436 stree_expr_t *expr, tdata_item_t *dest)
1437{
1438 tdata_item_t *src;
1439 builtin_t *bi;
1440 stree_symbol_t *csi_sym;
1441 stree_symbol_t *bp_sym;
1442 stree_box_t *box;
1443 stree_expr_t *bexpr;
1444
1445#ifdef DEBUG_TYPE_TRACE
1446 printf("Convert primitive type to object.\n");
1447#endif
1448 src = expr->titem;
1449 assert(src->tic == tic_tprimitive);
1450 assert(dest->tic == tic_tobject);
1451
1452 bi = stype->program->builtin;
1453 csi_sym = csi_to_symbol(dest->u.tobject->csi);
1454
1455 /* Make compiler happy. */
1456 bp_sym = NULL;
1457
1458 switch (src->u.tprimitive->tpc) {
1459 case tpc_bool:
1460 bp_sym = bi->boxed_bool;
1461 break;
1462 case tpc_char:
1463 bp_sym = bi->boxed_char;
1464 break;
1465 case tpc_int:
1466 bp_sym = bi->boxed_int;
1467 break;
1468 case tpc_nil:
1469 assert(b_false);
1470 /* Fallthrough */
1471 case tpc_string:
1472 bp_sym = bi->boxed_string;
1473 break;
1474 case tpc_resource:
1475 stype_convert_failure(stype, convc_implicit, expr, dest);
1476 return expr;
1477 }
1478
1479 /* Target type must be boxed @a src or Object */
1480 if (csi_sym != bp_sym && csi_sym != bi->gf_class)
1481 stype_convert_failure(stype, convc_implicit, expr, dest);
1482
1483 /* Patch the code to box the primitive value */
1484 box = stree_box_new();
1485 box->arg = expr;
1486 bexpr = stree_expr_new(ec_box);
1487 bexpr->u.box = box;
1488 bexpr->titem = dest;
1489
1490 /* No action needed to optionally convert boxed type to Object */
1491
1492 return bexpr;
1493}
1494
1495/** Convert expression of object type to object type.
1496 *
1497 * @param stype Static typing object
1498 * @param expr Expression
1499 * @param dest Destination type
1500 */
1501static stree_expr_t *stype_convert_tobject(stype_t *stype, stree_expr_t *expr,
1502 tdata_item_t *dest)
1503{
1504 tdata_item_t *src;
1505 tdata_item_t *pred_ti;
1506
1507#ifdef DEBUG_TYPE_TRACE
1508 printf("Convert object type.\n");
1509#endif
1510 src = expr->titem;
1511 assert(src->tic == tic_tobject);
1512 assert(dest->tic == tic_tobject);
1513
1514 /*
1515 * Find predecessor of the right type. This determines the
1516 * type arguments that the destination type should have.
1517 */
1518 pred_ti = stype_tobject_find_pred(stype, src, dest);
1519 if (pred_ti == NULL) {
1520 stype_convert_failure(stype, convc_implicit, expr, dest);
1521 printf("Not a base class or implemented or accumulated "
1522 "interface.\n");
1523 return expr;
1524 }
1525
1526 /*
1527 * Verify that type arguments match with those specified for
1528 * conversion destination.
1529 */
1530 if (stype_targs_check_equal(stype, pred_ti, dest) != EOK) {
1531 stype_convert_failure(stype, convc_implicit, expr, dest);
1532 return expr;
1533 }
1534
1535 return expr;
1536}
1537
1538/** Convert expression of array type to array type.
1539 *
1540 * @param stype Static typing object
1541 * @param expr Expression
1542 * @param dest Destination type
1543 */
1544static stree_expr_t *stype_convert_tarray(stype_t *stype, stree_expr_t *expr,
1545 tdata_item_t *dest)
1546{
1547 tdata_item_t *src;
1548
1549#ifdef DEBUG_TYPE_TRACE
1550 printf("Convert array type.\n");
1551#endif
1552 src = expr->titem;
1553 assert(src->tic == tic_tarray);
1554 assert(dest->tic == tic_tarray);
1555
1556 /* Compare rank and base type. */
1557 if (src->u.tarray->rank != dest->u.tarray->rank) {
1558 stype_convert_failure(stype, convc_implicit, expr, dest);
1559 return expr;
1560 }
1561
1562 /* XXX Should we convert each element? */
1563 if (tdata_item_equal(src->u.tarray->base_ti,
1564 dest->u.tarray->base_ti) != b_true) {
1565 stype_convert_failure(stype, convc_implicit, expr, dest);
1566 }
1567
1568 return expr;
1569}
1570
1571/** Convert expression of delegate type to delegate type.
1572 *
1573 * @param stype Static typing object
1574 * @param expr Expression
1575 * @param dest Destination type
1576 */
1577static stree_expr_t *stype_convert_tdeleg(stype_t *stype, stree_expr_t *expr,
1578 tdata_item_t *dest)
1579{
1580 tdata_item_t *src;
1581 tdata_deleg_t *sdeleg, *ddeleg;
1582
1583#ifdef DEBUG_TYPE_TRACE
1584 printf("Convert delegate type.\n");
1585#endif
1586 src = expr->titem;
1587 assert(src->tic == tic_tdeleg);
1588 assert(dest->tic == tic_tdeleg);
1589
1590 sdeleg = src->u.tdeleg;
1591 ddeleg = dest->u.tdeleg;
1592
1593 /*
1594 * XXX We need to redesign handling of generic types to handle
1595 * delegates in generic CSIs properly.
1596 */
1597
1598 /* Destination should never be anonymous delegate. */
1599 assert(ddeleg->deleg != NULL);
1600
1601 /* Both must be the same delegate. */
1602 if (sdeleg->deleg != ddeleg->deleg) {
1603 stype_convert_failure(stype, convc_implicit, expr, dest);
1604 return expr;
1605 }
1606
1607 return expr;
1608}
1609
1610/** Convert expression of enum type to enum type.
1611 *
1612 * @param stype Static typing object
1613 * @param expr Expression
1614 * @param dest Destination type
1615 */
1616static stree_expr_t *stype_convert_tenum(stype_t *stype, stree_expr_t *expr,
1617 tdata_item_t *dest)
1618{
1619 tdata_item_t *src;
1620 tdata_enum_t *senum, *denum;
1621
1622#ifdef DEBUG_TYPE_TRACE
1623 printf("Convert enum type.\n");
1624#endif
1625 src = expr->titem;
1626 assert(src->tic == tic_tenum);
1627 assert(dest->tic == tic_tenum);
1628
1629 senum = src->u.tenum;
1630 denum = dest->u.tenum;
1631
1632 /*
1633 * XXX How should enum types interact with generics?
1634 */
1635
1636 /* Both must be of the same enum type (with the same declaration). */
1637 if (senum->enum_d != denum->enum_d) {
1638 stype_convert_failure(stype, convc_implicit, expr, dest);
1639 return expr;
1640 }
1641
1642 return expr;
1643}
1644
1645/** Convert expression of function type to delegate type.
1646 *
1647 * @param stype Static typing object
1648 * @param expr Expression
1649 * @param dest Destination type
1650 */
1651static stree_expr_t *stype_convert_tfun_tdeleg(stype_t *stype,
1652 stree_expr_t *expr, tdata_item_t *dest)
1653{
1654 tdata_item_t *src;
1655 tdata_fun_t *sfun;
1656 tdata_deleg_t *ddeleg;
1657 tdata_fun_sig_t *ssig, *dsig;
1658
1659#ifdef DEBUG_TYPE_TRACE
1660 printf("Convert delegate type.\n");
1661#endif
1662 src = expr->titem;
1663 assert(src->tic == tic_tfun);
1664 assert(dest->tic == tic_tdeleg);
1665
1666 sfun = src->u.tfun;
1667 ddeleg = dest->u.tdeleg;
1668
1669 ssig = sfun->tsig;
1670 assert(ssig != NULL);
1671 dsig = stype_deleg_get_sig(stype, ddeleg);
1672 assert(dsig != NULL);
1673
1674 /* Signature type must match. */
1675
1676 if (!stype_fun_sig_equal(stype, ssig, dsig)) {
1677 stype_convert_failure(stype, convc_implicit, expr, dest);
1678 return expr;
1679 }
1680
1681 /*
1682 * XXX We should also compare attributes. Either the
1683 * tdeleg should be extended or we should get them
1684 * from stree_deleg.
1685 */
1686
1687 return expr;
1688}
1689
1690/** Convert expression of variable type to variable type.
1691 *
1692 * @param stype Static typing object
1693 * @param expr Expression
1694 * @param dest Destination type
1695 */
1696static stree_expr_t *stype_convert_tvref(stype_t *stype, stree_expr_t *expr,
1697 tdata_item_t *dest)
1698{
1699 tdata_item_t *src;
1700
1701#ifdef DEBUG_TYPE_TRACE
1702 printf("Convert variable type.\n");
1703#endif
1704 src = expr->titem;
1705
1706 /* Currently only allow if both types are the same. */
1707 if (src->u.tvref->targ != dest->u.tvref->targ) {
1708 stype_convert_failure(stype, convc_implicit, expr, dest);
1709 return expr;
1710 }
1711
1712 return expr;
1713}
1714
1715/** Display conversion error message and note error.
1716 *
1717 * @param stype Static typing object
1718 * @param expr Original expression
1719 * @param dest Destination type
1720 */
1721void stype_convert_failure(stype_t *stype, stype_conv_class_t convc,
1722 stree_expr_t *expr, tdata_item_t *dest)
1723{
1724 cspan_print(expr->cspan);
1725 printf(" Error: ");
1726 switch (convc) {
1727 case convc_implicit:
1728 printf("Cannot implicitly convert '");
1729 break;
1730 case convc_as:
1731 printf("Cannot use 'as' to convert '");
1732 break;
1733 }
1734
1735 tdata_item_print(expr->titem);
1736 printf(" to ");
1737 tdata_item_print(dest);
1738 printf(".\n");
1739
1740 stype_note_error(stype);
1741}
1742
1743/** Box value.
1744 *
1745 * This function implements implicit boxing. It modifies the code by inserting
1746 * the boxing operation.
1747 *
1748 * @param stype Static typing object
1749 * @param expr Expression
1750 * @return Modified expression.
1751 */
1752stree_expr_t *stype_box_expr(stype_t *stype, stree_expr_t *expr)
1753{
1754 tdata_item_t *src;
1755 builtin_t *bi;
1756 stree_symbol_t *bp_sym;
1757 stree_box_t *box;
1758 stree_expr_t *bexpr;
1759 tdata_object_t *tobject;
1760
1761#ifdef DEBUG_TYPE_TRACE
1762 printf("Boxing.\n");
1763#endif
1764 src = expr->titem;
1765 assert(src->tic == tic_tprimitive);
1766
1767 bi = stype->program->builtin;
1768
1769 /* Make compiler happy. */
1770 bp_sym = NULL;
1771
1772 switch (src->u.tprimitive->tpc) {
1773 case tpc_bool:
1774 bp_sym = bi->boxed_bool;
1775 break;
1776 case tpc_char:
1777 bp_sym = bi->boxed_char;
1778 break;
1779 case tpc_int:
1780 bp_sym = bi->boxed_int;
1781 break;
1782 case tpc_nil:
1783 assert(b_false);
1784 /* Fallthrough */
1785 case tpc_string:
1786 bp_sym = bi->boxed_string;
1787 break;
1788 case tpc_resource:
1789 cspan_print(expr->cspan);
1790 printf(" Error: Cannot use ");
1791 tdata_item_print(expr->titem);
1792 printf(" as an object.\n");
1793
1794 stype_note_error(stype);
1795 return expr;
1796 }
1797
1798 /* Patch the code to box the primitive value */
1799 box = stree_box_new();
1800 box->arg = expr;
1801 bexpr = stree_expr_new(ec_box);
1802 bexpr->u.box = box;
1803 bexpr->titem = tdata_item_new(tic_tobject);
1804 tobject = tdata_object_new();
1805 bexpr->titem->u.tobject = tobject;
1806
1807 tobject->csi = symbol_to_csi(bp_sym);
1808 assert(tobject->csi != NULL);
1809
1810 return bexpr;
1811}
1812
1813/** Find predecessor CSI and return its type item.
1814 *
1815 * Looks for predecessor of CSI type @a src that matches @a dest.
1816 * The type maches if they use the same generic CSI definition, type
1817 * arguments are ignored. If found, returns the type arguments that
1818 * @a dest should have in order to be a true predecessor of @a src.
1819 *
1820 * @param stype Static typing object
1821 * @param src Source type
1822 * @param dest Destination type
1823 * @return Type matching @a dest with correct type arguments
1824 */
1825tdata_item_t *stype_tobject_find_pred(stype_t *stype, tdata_item_t *src,
1826 tdata_item_t *dest)
1827{
1828 stree_csi_t *src_csi;
1829 tdata_tvv_t *tvv;
1830 tdata_item_t *b_ti, *bs_ti;
1831
1832 list_node_t *pred_n;
1833 stree_texpr_t *pred_te;
1834
1835 tdata_item_t *res_ti;
1836
1837#ifdef DEBUG_TYPE_TRACE
1838 printf("Find CSI predecessor.\n");
1839#endif
1840 assert(src->tic == tic_tobject);
1841 assert(dest->tic == tic_tobject);
1842
1843 if (src->u.tobject->csi == dest->u.tobject->csi)
1844 return src;
1845
1846 src_csi = src->u.tobject->csi;
1847 stype_titem_to_tvv(stype, src, &tvv);
1848
1849 res_ti = NULL;
1850
1851 switch (dest->u.tobject->csi->cc) {
1852 case csi_class:
1853 /* Destination is a class. Look at base class. */
1854 pred_te = symbol_get_base_class_ref(stype->program,
1855 src_csi);
1856 if (pred_te != NULL) {
1857 run_texpr(stype->program, src_csi, pred_te,
1858 &b_ti);
1859 } else if (src_csi->base_csi != NULL &&
1860 src->u.tobject->csi->cc == csi_class) {
1861 /* No explicit reference. Use grandfather class. */
1862 b_ti = tdata_item_new(tic_tobject);
1863 b_ti->u.tobject = tdata_object_new();
1864 b_ti->u.tobject->csi = src_csi->base_csi;
1865 b_ti->u.tobject->static_ref = sn_nonstatic;
1866
1867 list_init(&b_ti->u.tobject->targs);
1868 } else {
1869 /* No match */
1870 return NULL;
1871 }
1872
1873 /* Substitute type variables to get predecessor type. */
1874 tdata_item_subst(b_ti, tvv, &bs_ti);
1875 assert(bs_ti->tic == tic_tobject);
1876
1877 /* Recurse to compute the rest of the path. */
1878 res_ti = stype_tobject_find_pred(stype, bs_ti, dest);
1879 if (b_ti->tic == tic_ignore) {
1880 /* An error occured. */
1881 return NULL;
1882 }
1883 break;
1884 case csi_struct:
1885 assert(b_false);
1886 /* Fallthrough */
1887 case csi_interface:
1888 /*
1889 * Destination is an interface. Look at implemented
1890 * or accumulated interfaces.
1891 */
1892 pred_n = list_first(&src_csi->inherit);
1893 while (pred_n != NULL) {
1894 pred_te = list_node_data(pred_n, stree_texpr_t *);
1895 run_texpr(stype->program, src_csi, pred_te,
1896 &b_ti);
1897
1898 /* Substitute type variables to get predecessor type. */
1899 tdata_item_subst(b_ti, tvv, &bs_ti);
1900 assert(bs_ti->tic == tic_tobject);
1901
1902 /* Recurse to compute the rest of the path. */
1903 res_ti = stype_tobject_find_pred(stype, bs_ti, dest);
1904 if (res_ti != NULL)
1905 break;
1906
1907 pred_n = list_next(&src_csi->inherit, pred_n);
1908 }
1909 break;
1910 }
1911
1912 return res_ti;
1913}
1914
1915/** Check whether type arguments of expression type and another type are equal.
1916 *
1917 * Compare type arguments of the type of @a expr and of type @a b_ti.
1918 * @a convc denotes the type of conversion for which we perform this check
1919 * (for sake of error reporting).
1920 *
1921 * If the type arguments are not equal a typing error and a conversion error
1922 * message is generated.
1923 *
1924 * @param stype Static typing object
1925 * @param expr Expression
1926 * @param b_ti b_tiination type
1927 * @return EOK if equal, EINVAL if not.
1928 */
1929errno_t stype_targs_check_equal(stype_t *stype, tdata_item_t *a_ti,
1930 tdata_item_t *b_ti)
1931{
1932 list_node_t *arg_a_n, *arg_b_n;
1933 tdata_item_t *arg_a, *arg_b;
1934
1935 (void) stype;
1936
1937#ifdef DEBUG_TYPE_TRACE
1938 printf("Check if type arguments match.\n");
1939#endif
1940 assert(a_ti->tic == tic_tobject);
1941 assert(b_ti->tic == tic_tobject);
1942
1943 /*
1944 * Verify that type arguments match with those specified for
1945 * conversion b_tiination.
1946 */
1947 arg_a_n = list_first(&a_ti->u.tobject->targs);
1948 arg_b_n = list_first(&b_ti->u.tobject->targs);
1949
1950 while (arg_a_n != NULL && arg_b_n != NULL) {
1951 arg_a = list_node_data(arg_a_n, tdata_item_t *);
1952 arg_b = list_node_data(arg_b_n, tdata_item_t *);
1953
1954 if (tdata_item_equal(arg_a, arg_b) != b_true) {
1955 /* Diferent argument type */
1956 printf("Different argument type '");
1957 tdata_item_print(arg_a);
1958 printf("' vs. '");
1959 tdata_item_print(arg_b);
1960 printf("'.\n");
1961 return EINVAL;
1962 }
1963
1964 arg_a_n = list_next(&a_ti->u.tobject->targs, arg_a_n);
1965 arg_b_n = list_next(&b_ti->u.tobject->targs, arg_b_n);
1966 }
1967
1968 if (arg_a_n != NULL || arg_b_n != NULL) {
1969 /* Diferent number of arguments */
1970 printf("Different number of arguments.\n");
1971 return EINVAL;
1972 }
1973
1974 return EOK;
1975}
1976
1977/** Determine if two type signatures are equal.
1978 *
1979 * XXX This does not compare the attributes, which are missing from
1980 * @c tdata_fun_sig_t.
1981 *
1982 * @param stype Static typing object
1983 * @param asig First function signature type
1984 * @param bsig Second function signature type
1985 */
1986static bool_t stype_fun_sig_equal(stype_t *stype, tdata_fun_sig_t *asig,
1987 tdata_fun_sig_t *bsig)
1988{
1989 list_node_t *aarg_n, *barg_n;
1990 tdata_item_t *aarg_ti, *barg_ti;
1991
1992 (void) stype;
1993
1994 /* Compare types of arguments */
1995 aarg_n = list_first(&asig->arg_ti);
1996 barg_n = list_first(&bsig->arg_ti);
1997
1998 while (aarg_n != NULL && barg_n != NULL) {
1999 aarg_ti = list_node_data(aarg_n, tdata_item_t *);
2000 barg_ti = list_node_data(barg_n, tdata_item_t *);
2001
2002 if (!tdata_item_equal(aarg_ti, barg_ti))
2003 return b_false;
2004
2005 aarg_n = list_next(&asig->arg_ti, aarg_n);
2006 barg_n = list_next(&bsig->arg_ti, barg_n);
2007 }
2008
2009 if (aarg_n != NULL || barg_n != NULL)
2010 return b_false;
2011
2012 /* Compare variadic argument */
2013
2014 if (asig->varg_ti != NULL || bsig->varg_ti != NULL) {
2015 if (asig->varg_ti == NULL ||
2016 bsig->varg_ti == NULL) {
2017 return b_false;
2018 }
2019
2020 if (!tdata_item_equal(asig->varg_ti, bsig->varg_ti)) {
2021 return b_false;
2022 }
2023 }
2024
2025 /* Compare return type */
2026
2027 if (asig->rtype != NULL || bsig->rtype != NULL) {
2028 if (asig->rtype == NULL ||
2029 bsig->rtype == NULL) {
2030 return b_false;
2031 }
2032
2033 if (!tdata_item_equal(asig->rtype, bsig->rtype)) {
2034 return b_false;
2035 }
2036 }
2037
2038 return b_true;
2039}
2040
2041/** Get function signature from delegate.
2042 *
2043 * Function signature can be missing if the delegate type is incomplete.
2044 * This is used to break circular dependency when typing delegates.
2045 * If this happens, we type the delegate, which gives us the signature.
2046 */
2047tdata_fun_sig_t *stype_deleg_get_sig(stype_t *stype, tdata_deleg_t *tdeleg)
2048{
2049 if (tdeleg->tsig == NULL)
2050 stype_deleg(stype, tdeleg->deleg);
2051
2052 /* Now we should have a signature. */
2053 assert(tdeleg->tsig != NULL);
2054 return tdeleg->tsig;
2055}
2056
2057/** Convert tic_tobject type item to TVV,
2058 *
2059 * We split generic type application into two steps. In the first step
2060 * we match argument names of @a ti->csi to argument values in @a ti
2061 * to produce a TVV (name to value map for type arguments). That is the
2062 * purpose of this function.
2063 *
2064 * In the second step we substitute variables in another type item
2065 * with their values using the TVV. This is performed by tdata_item_subst().
2066 *
2067 * @param stype Static typing object.
2068 * @param ti Type item of class tic_tobject.
2069 * @param rtvv Place to store pointer to new TVV.
2070 */
2071void stype_titem_to_tvv(stype_t *stype, tdata_item_t *ti, tdata_tvv_t **rtvv)
2072{
2073 tdata_tvv_t *tvv;
2074 stree_csi_t *csi;
2075
2076 list_node_t *formal_n;
2077 list_node_t *real_n;
2078
2079 stree_targ_t *formal_arg;
2080 tdata_item_t *real_arg;
2081
2082 assert(ti->tic == tic_tobject);
2083
2084 tvv = tdata_tvv_new();
2085 intmap_init(&tvv->tvv);
2086
2087 csi = ti->u.tobject->csi;
2088 formal_n = list_first(&csi->targ);
2089 real_n = list_first(&ti->u.tobject->targs);
2090
2091 while (formal_n != NULL && real_n != NULL) {
2092 formal_arg = list_node_data(formal_n, stree_targ_t *);
2093 real_arg = list_node_data(real_n, tdata_item_t *);
2094
2095 /* Store argument value into valuation. */
2096 tdata_tvv_set_val(tvv, formal_arg->name->sid, real_arg);
2097
2098 formal_n = list_next(&csi->targ, formal_n);
2099 real_n = list_next(&ti->u.tobject->targs, real_n);
2100 }
2101
2102 if (formal_n != NULL || real_n != NULL) {
2103 printf("Error: Incorrect number of type arguments.\n");
2104 stype_note_error(stype);
2105
2106 /* Fill missing arguments with recovery type items. */
2107 while (formal_n != NULL) {
2108 formal_arg = list_node_data(formal_n, stree_targ_t *);
2109 /* Store recovery value into valuation. */
2110 tdata_tvv_set_val(tvv, formal_arg->name->sid,
2111 stype_recovery_titem(stype));
2112
2113 formal_n = list_next(&csi->targ, formal_n);
2114 }
2115 }
2116
2117 *rtvv = tvv;
2118}
2119
2120/** Return a boolean type item.
2121 *
2122 * @param stype Static typing object
2123 * @return New boolean type item.
2124 */
2125tdata_item_t *stype_boolean_titem(stype_t *stype)
2126{
2127 tdata_item_t *titem;
2128 tdata_primitive_t *tprimitive;
2129
2130 (void) stype;
2131
2132 titem = tdata_item_new(tic_tprimitive);
2133 tprimitive = tdata_primitive_new(tpc_bool);
2134 titem->u.tprimitive = tprimitive;
2135
2136 return titem;
2137}
2138
2139/** Find a local variable in the current function.
2140 *
2141 * @param stype Static typing object
2142 * @param name Name of variable (SID).
2143 * @return Pointer to variable declaration or @c NULL if not
2144 * found.
2145 */
2146stree_vdecl_t *stype_local_vars_lookup(stype_t *stype, sid_t name)
2147{
2148 stype_proc_vr_t *proc_vr;
2149 stype_block_vr_t *block_vr;
2150 stree_vdecl_t *vdecl;
2151 list_node_t *node;
2152
2153 proc_vr = stype->proc_vr;
2154 node = list_last(&proc_vr->block_vr);
2155
2156 /* Walk through all block visit records. */
2157 while (node != NULL) {
2158 block_vr = list_node_data(node, stype_block_vr_t *);
2159 vdecl = intmap_get(&block_vr->vdecls, name);
2160 if (vdecl != NULL)
2161 return vdecl;
2162
2163 node = list_prev(&proc_vr->block_vr, node);
2164 }
2165
2166 /* No match */
2167 return NULL;
2168}
2169
2170/** Find argument of the current procedure.
2171 *
2172 * @param stype Static typing object
2173 * @param name Name of argument (SID).
2174 * @return Pointer to argument declaration or @c NULL if not
2175 * found.
2176 */
2177stree_proc_arg_t *stype_proc_args_lookup(stype_t *stype, sid_t name)
2178{
2179 stype_proc_vr_t *proc_vr;
2180
2181 stree_symbol_t *outer_sym;
2182 stree_ctor_t *ctor;
2183 stree_fun_t *fun;
2184 stree_prop_t *prop;
2185
2186 list_t *args;
2187 list_node_t *arg_node;
2188 stree_proc_arg_t *varg;
2189 stree_proc_arg_t *arg;
2190 stree_proc_arg_t *setter_arg;
2191
2192 proc_vr = stype->proc_vr;
2193 outer_sym = proc_vr->proc->outer_symbol;
2194
2195 setter_arg = NULL;
2196
2197#ifdef DEBUG_TYPE_TRACE
2198 printf("Look for argument named '%s'.\n", strtab_get_str(name));
2199#endif
2200
2201 /* Make compiler happy. */
2202 args = NULL;
2203 varg = NULL;
2204
2205 switch (outer_sym->sc) {
2206 case sc_ctor:
2207 ctor = symbol_to_ctor(outer_sym);
2208 assert(ctor != NULL);
2209 args = &ctor->sig->args;
2210 varg = ctor->sig->varg;
2211 break;
2212 case sc_fun:
2213 fun = symbol_to_fun(outer_sym);
2214 assert(fun != NULL);
2215 args = &fun->sig->args;
2216 varg = fun->sig->varg;
2217 break;
2218 case sc_prop:
2219 prop = symbol_to_prop(outer_sym);
2220 assert(prop != NULL);
2221 args = &prop->args;
2222 varg = prop->varg;
2223
2224 /* If we are in a setter, look also at setter argument. */
2225 if (prop->setter == proc_vr->proc)
2226 setter_arg = prop->setter_arg;
2227 break;
2228 case sc_csi:
2229 case sc_deleg:
2230 case sc_enum:
2231 case sc_var:
2232 assert(b_false);
2233 }
2234
2235 arg_node = list_first(args);
2236 while (arg_node != NULL) {
2237 arg = list_node_data(arg_node, stree_proc_arg_t *);
2238 if (arg->name->sid == name) {
2239 /* Match */
2240#ifdef DEBUG_TYPE_TRACE
2241 printf("Found argument.\n");
2242#endif
2243 return arg;
2244 }
2245
2246 arg_node = list_next(args, arg_node);
2247 }
2248
2249 /* Variadic argument */
2250 if (varg != NULL && varg->name->sid == name) {
2251#ifdef DEBUG_TYPE_TRACE
2252 printf("Found variadic argument.\n");
2253#endif
2254 return varg;
2255 }
2256
2257 /* Setter argument */
2258 if (setter_arg != NULL && setter_arg->name->sid == name) {
2259#ifdef DEBUG_TYPE_TRACE
2260 printf("Found setter argument.\n");
2261#endif
2262 return setter_arg;
2263
2264 }
2265
2266#ifdef DEBUG_TYPE_TRACE
2267 printf("Not found.\n");
2268#endif
2269 /* No match */
2270 return NULL;
2271}
2272
2273/** Note a static typing error that has been immediately recovered.
2274 *
2275 * @param stype Static typing object
2276 */
2277void stype_note_error(stype_t *stype)
2278{
2279 stype->error = b_true;
2280}
2281
2282/** Construct a special type item for recovery.
2283 *
2284 * The recovery item is propagated towards the expression root and causes
2285 * any further typing errors in the expression to be supressed.
2286 *
2287 * @param stype Static typing object
2288 */
2289tdata_item_t *stype_recovery_titem(stype_t *stype)
2290{
2291 tdata_item_t *titem;
2292
2293 (void) stype;
2294
2295 titem = tdata_item_new(tic_ignore);
2296 return titem;
2297}
2298
2299/** Get current block visit record.
2300 *
2301 * @param stype Static typing object
2302 */
2303stype_block_vr_t *stype_get_current_block_vr(stype_t *stype)
2304{
2305 list_node_t *node;
2306
2307 node = list_last(&stype->proc_vr->block_vr);
2308 return list_node_data(node, stype_block_vr_t *);
2309}
2310
2311/** Allocate new procedure visit record.
2312 *
2313 * @return New procedure VR
2314 */
2315stype_proc_vr_t *stype_proc_vr_new(void)
2316{
2317 stype_proc_vr_t *proc_vr;
2318
2319 proc_vr = calloc(1, sizeof(stype_proc_vr_t));
2320 if (proc_vr == NULL) {
2321 printf("Memory allocation failed.\n");
2322 exit(1);
2323 }
2324
2325 return proc_vr;
2326}
2327
2328/** Allocate new block visit record.
2329 *
2330 * @return New block VR
2331 */
2332stype_block_vr_t *stype_block_vr_new(void)
2333{
2334 stype_block_vr_t *block_vr;
2335
2336 block_vr = calloc(1, sizeof(stype_block_vr_t));
2337 if (block_vr == NULL) {
2338 printf("Memory allocation failed.\n");
2339 exit(1);
2340 }
2341
2342 return block_vr;
2343}
Note: See TracBrowser for help on using the repository browser.