source: mainline/uspace/app/sbi/src/symbol.c@ 88ab6e9

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 88ab6e9 was c5cb943d, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Update SBI to rev. 291.

  • Property mode set to 100644
File size: 15.5 KB
RevLine 
[09ababb7]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 Symbols. */
30
31#include <stdlib.h>
32#include <assert.h>
33#include "list.h"
34#include "mytypes.h"
35#include "strtab.h"
36#include "stree.h"
37
38#include "symbol.h"
39
40static stree_symbol_t *symbol_search_global(stree_program_t *prog,
41 stree_ident_t *name);
[fa36f29]42static stree_symbol_t *symbol_find_epoint_rec(stree_program_t *prog,
43 stree_ident_t *name, stree_csi_t *csi);
[09ababb7]44static stree_ident_t *symbol_get_ident(stree_symbol_t *symbol);
45
[38aaacc2]46/** Lookup symbol in CSI using a type expression.
47 *
48 * XXX This should be removed in favor of full type expression evaluation
49 * (run_texpr). This cannot work properly with generics.
50 *
51 * @param prog Program
52 * @param scope CSI used as base for relative references
53 * @param texpr Type expression
54 *
55 * @return Symbol referenced by type expression or @c NULL
56 * if not found
57 */
[09ababb7]58stree_symbol_t *symbol_xlookup_in_csi(stree_program_t *prog,
59 stree_csi_t *scope, stree_texpr_t *texpr)
60{
61 stree_symbol_t *a, *b;
62 stree_csi_t *a_csi;
63
64 switch (texpr->tc) {
65 case tc_tnameref:
66 return symbol_lookup_in_csi(prog, scope, texpr->u.tnameref->name);
67 case tc_taccess:
68 a = symbol_xlookup_in_csi(prog, scope, texpr->u.taccess->arg);
69 a_csi = symbol_to_csi(a);
70 if (a_csi == NULL) {
71 printf("Error: Symbol is not CSI.\n");
72 exit(1);
73 }
74 b = symbol_search_csi(prog, a_csi, texpr->u.taccess->member_name);
75 if (b == NULL) {
76 printf("Error: CSI '%s' not found\n", strtab_get_str(texpr->u.taccess->member_name->sid));
77 exit(1);
78 }
79 return b;
80 case tc_tapply:
[074444f]81 return symbol_xlookup_in_csi(prog, scope,
82 texpr->u.tapply->gtype);
[09ababb7]83 default:
84 assert(b_false);
85 }
86}
87
[1ebc1a62]88/** Lookup symbol reference in CSI.
[051bc69a]89 *
90 * XXX These functions should take just an sid, not a full identifier.
91 * Sometimes we search for a name which has no associated cspan.
[1ebc1a62]92 *
[38aaacc2]93 * @param prog Program to look in
94 * @param scope CSI in @a prog which is the base for references
95 * @param name Identifier of the symbol
[1ebc1a62]96 *
[38aaacc2]97 * @return Symbol or @c NULL if symbol not found
[1ebc1a62]98 */
[09ababb7]99stree_symbol_t *symbol_lookup_in_csi(stree_program_t *prog, stree_csi_t *scope,
100 stree_ident_t *name)
101{
102 stree_symbol_t *symbol;
103
104 /* This CSI node should have been processed. */
105 assert(scope == NULL || scope->ancr_state == ws_visited);
106
107 symbol = NULL;
108 while (scope != NULL && symbol == NULL) {
109 symbol = symbol_search_csi(prog, scope, name);
110 scope = csi_to_symbol(scope)->outer_csi;
111 }
112
113 if (symbol == NULL)
114 symbol = symbol_search_global(prog, name);
115
116 return symbol;
117}
118
119/** Look for symbol strictly in CSI.
120 *
121 * Look for symbol in definition of a CSI and its ancestors. (But not
122 * in lexically enclosing CSI.)
[38aaacc2]123 *
124 * @param prog Program to look in
125 * @param scope CSI in which to look
126 * @param name Identifier of the symbol
127 *
128 * @return Symbol or @c NULL if symbol not found.
[09ababb7]129 */
130stree_symbol_t *symbol_search_csi(stree_program_t *prog,
131 stree_csi_t *scope, stree_ident_t *name)
[051bc69a]132{
133 stree_csi_t *base_csi;
134 stree_symbol_t *symbol;
135
136 /* Look in new members in this class. */
137 symbol = symbol_search_csi_no_base(prog, scope, name);
138 if (symbol != NULL)
139 return symbol;
140
141 /* Try inherited members. */
[c5cb943d]142 base_csi = symbol_get_base_class(prog, scope);
143 if (base_csi != NULL)
[051bc69a]144 return symbol_search_csi(prog, base_csi, name);
145
146 /* No match */
147 return NULL;
148}
149
150/** Look for symbol strictly in CSI.
151 *
152 * Look for symbol in definition of a CSI and its ancestors. (But not
153 * in lexically enclosing CSI or in base CSI.)
154 *
155 * @param prog Program to look in
156 * @param scope CSI in which to look
157 * @param name Identifier of the symbol
158 *
159 * @return Symbol or @c NULL if symbol not found.
160 */
161stree_symbol_t *symbol_search_csi_no_base(stree_program_t *prog,
162 stree_csi_t *scope, stree_ident_t *name)
[09ababb7]163{
164 list_node_t *node;
165 stree_csimbr_t *csimbr;
166 stree_ident_t *mbr_name;
[fa36f29]167
168 (void) prog;
169
170 /* Look in new members in this class. */
[09ababb7]171
172 node = list_first(&scope->members);
173 while (node != NULL) {
174 csimbr = list_node_data(node, stree_csimbr_t *);
[051bc69a]175 mbr_name = stree_csimbr_get_name(csimbr);
[09ababb7]176
177 if (name->sid == mbr_name->sid) {
178 /* Match */
[051bc69a]179 return csimbr_to_symbol(csimbr);
[09ababb7]180 }
181
[051bc69a]182 node = list_next(&scope->members, node);
[fa36f29]183 }
184 /* No match */
[09ababb7]185 return NULL;
186}
187
[38aaacc2]188/** Look for symbol in global scope.
189 *
190 * @param prog Program to look in
191 * @param name Identifier of the symbol
192 *
193 * @return Symbol or @c NULL if symbol not found.
194 */
[09ababb7]195static stree_symbol_t *symbol_search_global(stree_program_t *prog,
196 stree_ident_t *name)
197{
198 list_node_t *node;
199 stree_modm_t *modm;
200 stree_symbol_t *symbol;
[051bc69a]201 stree_ident_t *mbr_name;
[09ababb7]202
203 node = list_first(&prog->module->members);
204 while (node != NULL) {
205 modm = list_node_data(node, stree_modm_t *);
[051bc69a]206
[c5cb943d]207 /* Make compiler happy. */
208 mbr_name = NULL;
209
[051bc69a]210 switch (modm->mc) {
211 case mc_csi: mbr_name = modm->u.csi->name; break;
212 case mc_enum: mbr_name = modm->u.enum_d->name; break;
213 }
214
[c5cb943d]215 /* The Clang static analyzer is just too picky. */
216 assert(mbr_name != NULL);
217
[051bc69a]218 if (name->sid == mbr_name->sid) {
[c5cb943d]219 /* Make compiler happy. */
220 symbol = NULL;
221
[09ababb7]222 /* Match */
223 switch (modm->mc) {
224 case mc_csi:
225 symbol = csi_to_symbol(modm->u.csi);
226 break;
[051bc69a]227 case mc_enum:
228 symbol = enum_to_symbol(modm->u.enum_d);
229 break;
[09ababb7]230 }
231 return symbol;
232 }
233 node = list_next(&prog->module->members, node);
234 }
235
236 return NULL;
237}
238
[c5cb943d]239/** Get explicit base class for a CSI.
240 *
241 * Note that if there is no explicit base class (class is derived implicitly
242 * from @c object, then @c NULL is returned.
243 *
244 * @param prog Program to look in
245 * @param csi CSI
246 *
247 * @return Base class (CSI) or @c NULL if no explicit base class.
248 */
249stree_csi_t *symbol_get_base_class(stree_program_t *prog, stree_csi_t *csi)
250{
251 list_node_t *pred_n;
252 stree_texpr_t *pred;
253 stree_symbol_t *pred_sym;
254 stree_csi_t *pred_csi;
255 stree_csi_t *outer_csi;
256
257 outer_csi = csi_to_symbol(csi)->outer_csi;
258
259 pred_n = list_first(&csi->inherit);
260 if (pred_n == NULL)
261 return NULL;
262
263 pred = list_node_data(pred_n, stree_texpr_t *);
264 pred_sym = symbol_xlookup_in_csi(prog, outer_csi, pred);
265 pred_csi = symbol_to_csi(pred_sym);
266 assert(pred_csi != NULL); /* XXX! */
267
268 if (pred_csi->cc == csi_class)
269 return pred_csi;
270
271 return NULL;
272}
273
274/** Get type expression referencing base class for a CSI.
275 *
276 * Note that if there is no explicit base class (class is derived implicitly
277 * from @c object, then @c NULL is returned.
278 *
279 * @param prog Program to look in
280 * @param csi CSI
281 *
282 * @return Type expression or @c NULL if no explicit base class.
283 */
284stree_texpr_t *symbol_get_base_class_ref(stree_program_t *prog,
285 stree_csi_t *csi)
286{
287 list_node_t *pred_n;
288 stree_texpr_t *pred;
289 stree_symbol_t *pred_sym;
290 stree_csi_t *pred_csi;
291 stree_csi_t *outer_csi;
292
293 outer_csi = csi_to_symbol(csi)->outer_csi;
294
295 pred_n = list_first(&csi->inherit);
296 if (pred_n == NULL)
297 return NULL;
298
299 pred = list_node_data(pred_n, stree_texpr_t *);
300 pred_sym = symbol_xlookup_in_csi(prog, outer_csi, pred);
301 pred_csi = symbol_to_csi(pred_sym);
302 assert(pred_csi != NULL); /* XXX! */
303
304 if (pred_csi->cc == csi_class)
305 return pred;
306
307 return NULL;
308}
309
[38aaacc2]310/** Find entry point.
311 *
312 * Perform a walk of all CSIs and look for a function with the name @a name.
313 *
314 * @param prog Program to look in
315 * @param name Name of entry point
316 *
317 * @return Symbol or @c NULL if symbol not found.
318 */
[fa36f29]319stree_symbol_t *symbol_find_epoint(stree_program_t *prog, stree_ident_t *name)
320{
321 list_node_t *node;
322 stree_modm_t *modm;
323 stree_symbol_t *entry, *etmp;
324
325 entry = NULL;
326
327 node = list_first(&prog->module->members);
328 while (node != NULL) {
329 modm = list_node_data(node, stree_modm_t *);
330 if (modm->mc == mc_csi) {
331 etmp = symbol_find_epoint_rec(prog, name, modm->u.csi);
332 if (etmp != NULL) {
333 if (entry != NULL) {
334 printf("Error: Duplicate entry point.\n");
335 exit(1);
336 }
337 entry = etmp;
338 }
339 }
340 node = list_next(&prog->module->members, node);
341 }
342
343 return entry;
344}
345
[38aaacc2]346/** Find entry point under CSI.
347 *
348 * Internal part of symbol_find_epoint() that recursively walks CSIs.
349 *
350 * @param prog Program to look in
351 * @param name Name of entry point
352 *
353 * @return Symbol or @c NULL if symbol not found.
354 */
[fa36f29]355static stree_symbol_t *symbol_find_epoint_rec(stree_program_t *prog,
356 stree_ident_t *name, stree_csi_t *csi)
357{
358 list_node_t *node;
359 stree_csimbr_t *csimbr;
360 stree_symbol_t *entry, *etmp;
[c5cb943d]361 stree_symbol_t *fun_sym;
[fa36f29]362
363 entry = NULL;
364
365 node = list_first(&csi->members);
366 while (node != NULL) {
367 csimbr = list_node_data(node, stree_csimbr_t *);
368
369 switch (csimbr->cc) {
370 case csimbr_csi:
371 etmp = symbol_find_epoint_rec(prog, name, csimbr->u.csi);
372 if (etmp != NULL) {
373 if (entry != NULL) {
374 printf("Error: Duplicate entry point.\n");
375 exit(1);
376 }
377 entry = etmp;
378 }
379 break;
380 case csimbr_fun:
[c5cb943d]381 fun_sym = fun_to_symbol(csimbr->u.fun);
382
383 if (csimbr->u.fun->name->sid == name->sid &&
384 stree_symbol_has_attr(fun_sym, sac_static)) {
[fa36f29]385 if (entry != NULL) {
386 printf("Error: Duplicate entry point.\n");
387 exit(1);
388 }
[c5cb943d]389 entry = fun_sym;
[fa36f29]390 }
391 default:
392 break;
393 }
394
395 node = list_next(&csi->members, node);
396 }
397
398 return entry;
399}
400
[38aaacc2]401/*
402 * The notion of symbol is designed as a common base class for several
403 * types of declarations with global and CSI scope. Here we simulate
404 * conversion from this base class (symbol) to derived classes (CSI,
405 * fun, ..) and vice versa.
406 */
407
408/** Convert symbol to delegate (base to derived).
409 *
410 * @param symbol Symbol
411 * @return Delegate or @c NULL if symbol is not a delegate
412 */
413stree_deleg_t *symbol_to_deleg(stree_symbol_t *symbol)
414{
415 if (symbol->sc != sc_deleg)
416 return NULL;
417
418 return symbol->u.deleg;
419}
420
421/** Convert delegate to symbol (derived to base).
422 *
423 * @param deleg Delegate
424 * @return Symbol
425 */
426stree_symbol_t *deleg_to_symbol(stree_deleg_t *deleg)
427{
428 assert(deleg->symbol);
429 return deleg->symbol;
430}
431
[051bc69a]432/** Convert symbol to enum (base to derived).
433 *
434 * @param symbol Symbol
435 * @return Enum or @c NULL if symbol is not a enum
436 */
437stree_enum_t *symbol_to_enum(stree_symbol_t *symbol)
438{
439 if (symbol->sc != sc_enum)
440 return NULL;
441
442 return symbol->u.enum_d;
443}
444
445/** Convert enum to symbol (derived to base).
446 *
447 * @param deleg Enum
448 * @return Symbol
449 */
450stree_symbol_t *enum_to_symbol(stree_enum_t *enum_d)
451{
452 assert(enum_d->symbol);
453 return enum_d->symbol;
454}
455
[38aaacc2]456/** Convert symbol to CSI (base to derived).
457 *
458 * @param symbol Symbol
459 * @return CSI or @c NULL if symbol is not a CSI
460 */
[09ababb7]461stree_csi_t *symbol_to_csi(stree_symbol_t *symbol)
462{
463 if (symbol->sc != sc_csi)
464 return NULL;
465
466 return symbol->u.csi;
467}
468
[38aaacc2]469/** Convert CSI to symbol (derived to base).
470 *
471 * @param csi CSI
472 * @return Symbol
473 */
[09ababb7]474stree_symbol_t *csi_to_symbol(stree_csi_t *csi)
475{
476 assert(csi->symbol);
477 return csi->symbol;
478}
479
[051bc69a]480/** Convert symbol to constructor (base to derived).
481 *
482 * @param symbol Symbol
483 * @return Constructor or @c NULL if symbol is not a constructor
484 */
485stree_ctor_t *symbol_to_ctor(stree_symbol_t *symbol)
486{
487 if (symbol->sc != sc_ctor)
488 return NULL;
489
490 return symbol->u.ctor;
491}
492
493/** Convert constructor to symbol (derived to base).
494 *
495 * @param ctor Constructor
496 * @return Symbol
497 */
498stree_symbol_t *ctor_to_symbol(stree_ctor_t *ctor)
499{
500 assert(ctor->symbol);
501 return ctor->symbol;
502}
503
504
[38aaacc2]505/** Convert symbol to function (base to derived).
506 *
507 * @param symbol Symbol
508 * @return Function or @c NULL if symbol is not a function
509 */
[09ababb7]510stree_fun_t *symbol_to_fun(stree_symbol_t *symbol)
511{
512 if (symbol->sc != sc_fun)
513 return NULL;
514
515 return symbol->u.fun;
516}
517
[38aaacc2]518/** Convert function to symbol (derived to base).
519 *
520 * @param fun Function
521 * @return Symbol
522 */
[09ababb7]523stree_symbol_t *fun_to_symbol(stree_fun_t *fun)
524{
525 assert(fun->symbol);
526 return fun->symbol;
527}
528
[38aaacc2]529/** Convert symbol to member variable (base to derived).
530 *
531 * @param symbol Symbol
532 * @return Variable or @c NULL if symbol is not a member variable
533 */
[09ababb7]534stree_var_t *symbol_to_var(stree_symbol_t *symbol)
535{
536 if (symbol->sc != sc_var)
537 return NULL;
538
539 return symbol->u.var;
540}
541
[38aaacc2]542/** Convert variable to symbol (derived to base).
543 *
544 * @param fun Variable
545 * @return Symbol
546 */
[09ababb7]547stree_symbol_t *var_to_symbol(stree_var_t *var)
548{
549 assert(var->symbol);
550 return var->symbol;
551}
552
[38aaacc2]553/** Convert symbol to property (base to derived).
554 *
555 * @param symbol Symbol
556 * @return Property or @c NULL if symbol is not a property
557 */
[09ababb7]558stree_prop_t *symbol_to_prop(stree_symbol_t *symbol)
559{
560 if (symbol->sc != sc_prop)
561 return NULL;
562
563 return symbol->u.prop;
564}
565
[051bc69a]566/** Get symbol from CSI member.
567 *
568 * A symbol corresponds to any CSI member. Return it.
569 *
570 * @param csimbr CSI member
571 * @return Symbol
572 */
[c5cb943d]573stree_symbol_t *csimbr_to_symbol(stree_csimbr_t *csimbr)
[051bc69a]574{
575 stree_symbol_t *symbol;
576
577 /* Keep compiler happy. */
578 symbol = NULL;
579
580 /* Match */
581 switch (csimbr->cc) {
582 case csimbr_csi:
583 symbol = csi_to_symbol(csimbr->u.csi);
584 break;
585 case csimbr_ctor:
586 symbol = ctor_to_symbol(csimbr->u.ctor);
587 break;
588 case csimbr_deleg:
589 symbol = deleg_to_symbol(csimbr->u.deleg);
590 break;
591 case csimbr_enum:
592 symbol = enum_to_symbol(csimbr->u.enum_d);
593 break;
594 case csimbr_fun:
595 symbol = fun_to_symbol(csimbr->u.fun);
596 break;
597 case csimbr_var:
598 symbol = var_to_symbol(csimbr->u.var);
599 break;
600 case csimbr_prop:
601 symbol = prop_to_symbol(csimbr->u.prop);
602 break;
603 }
604
605 return symbol;
606}
607
608
[38aaacc2]609/** Convert property to symbol (derived to base).
610 *
611 * @param fun Property
612 * @return Symbol
613 */
[09ababb7]614stree_symbol_t *prop_to_symbol(stree_prop_t *prop)
615{
616 assert(prop->symbol);
617 return prop->symbol;
618}
619
[38aaacc2]620/** Print fully qualified name of symbol.
621 *
622 * @param symbol Symbol
623 */
[39e8406]624void symbol_print_fqn(stree_symbol_t *symbol)
[09ababb7]625{
626 stree_ident_t *name;
627 stree_symbol_t *outer_sym;
628
629 if (symbol->outer_csi != NULL) {
630 outer_sym = csi_to_symbol(symbol->outer_csi);
[37f527b]631 symbol_print_fqn(outer_sym);
[09ababb7]632 printf(".");
633 }
634
635 name = symbol_get_ident(symbol);
636 printf("%s", strtab_get_str(name->sid));
637}
638
[38aaacc2]639/** Return symbol identifier.
640 *
641 * @param symbol Symbol
642 * @return Symbol identifier
643 */
[09ababb7]644static stree_ident_t *symbol_get_ident(stree_symbol_t *symbol)
645{
646 stree_ident_t *ident;
647
[c5cb943d]648 /* Make compiler happy. */
649 ident = NULL;
650
[09ababb7]651 switch (symbol->sc) {
652 case sc_csi: ident = symbol->u.csi->name; break;
[051bc69a]653 case sc_ctor: ident = symbol->u.ctor->name; break;
[38aaacc2]654 case sc_deleg: ident = symbol->u.deleg->name; break;
[051bc69a]655 case sc_enum: ident = symbol->u.enum_d->name; break;
[09ababb7]656 case sc_fun: ident = symbol->u.fun->name; break;
657 case sc_var: ident = symbol->u.var->name; break;
658 case sc_prop: ident = symbol->u.prop->name; break;
659 }
660
661 return ident;
662}
Note: See TracBrowser for help on using the repository browser.