-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathhh_uses.c
100 lines (86 loc) · 2.72 KB
/
hh_uses.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* This file is part of Hedgehog LISP.
* Copyright (C) 2003, 2004 Oliotalo Ltd.
* See file LICENSE.LGPL for pertinent licensing conditions.
*
* Author: Kenneth Oksanen <cessu@iki.fi>
*/
/* This file implements uses analysis, i.e. it sets the `is_used'-flag
in all symbols reachable from the top-level program.
XXX Currently this does not pay attention to local variables that
in reality hide references to global functions. For example if any
reachable part of the code contains `(let ((hex ...)) ...)', then
the byte code of `hex' defined in `stdlib.lisp' will be included
even though in reality it won't be referred. */
#define HH_COMPILER 1
#include "hh_common.h"
#include "hh_ast.h"
static int has_changed;
static void hh_rec_uses(hh_ast_t *expr)
{
int i;
hh_ast_t *args;
int n_args;
if (expr == NULL)
return;
switch (expr->arity) {
case HH_AST_NIL:
case HH_AST_STRING:
case HH_AST_INTEGER:
case HH_AST_UNSIGNED_INTEGER:
return;
case HH_AST_SYMBOL:
if (expr->u.symbol->is_used == 0) {
expr->u.symbol->is_used = 1;
has_changed = 1;
}
return;
case 3:
if (expr->u.ast[0]->arity == HH_AST_SYMBOL
&& expr->u.ast[0]->u.symbol == hh_symbol_def) {
args = expr->u.ast[1];
/* Check the syntax of the argument list. */
args = expr->u.ast[1];
n_args = args->arity;
if (n_args == HH_AST_SYMBOL)
hh_fatal(args, "`def's of non-functions not yet implemented");
if (n_args == HH_AST_NIL
|| n_args > HH_AST_ATOMS_START
|| args->u.ast[0]->arity != HH_AST_SYMBOL)
hh_fatal(args, "Unrecognized form for `def'");
if (n_args > 127)
hh_fatal(args, "Too long argument list");
if (args->u.ast[0]->u.symbol->is_used == 1) {
/* The function is referred but it has not yet been traversed.
Traverse and mark traversed. */
hh_rec_uses(expr->u.ast[2]);
args->u.ast[0]->u.symbol->is_used = 2;
}
return;
}
default:
/* Apply `hh_rec_uses' recursively bottom-up. */
for (i = 1; i < expr->arity; i++)
hh_rec_uses(expr->u.ast[i]);
/* The head of the expression is treated a little smarter. If it
is any of the defined builtins, then *don't* traverse to the
symbol. */
if (expr->u.ast[0]->arity == HH_AST_SYMBOL) {
#define MODULE(name) /* Nothing. */
#define MODULE_END /* Nothing. */
#define BUILTIN(lisp_name, c_name, doc_string, args, code_gen) \
if (expr->u.ast[0]->u.symbol == hh_symbol_ ## c_name) \
return;
#include "hh_builtins.def"
}
/* The head is not any of the defined builtins, therefore traverse
it too. */
hh_rec_uses(expr->u.ast[0]);
}
}
void hh_uses(hh_ast_t *prog)
{
do {
has_changed = 0;
hh_rec_uses(prog);
} while (has_changed);
}