-
Notifications
You must be signed in to change notification settings - Fork 0
/
escape.sml
88 lines (88 loc) · 3 KB
/
escape.sml
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
structure FindEscape:
sig
val findEscape: Absyn.exp -> unit
end =
struct
(* fun say s = TextIO.output (TextIO.stdOut, s ^"\n") *)
type depth = int
type escEnv = (depth * bool ref) Symbol.table
structure A = Absyn
structure S = Symbol
fun traverseVar(env, d, A.SimpleVar (name, _)) =
let
val (dec_depth, escape) = case S.look (env, name) of
SOME(e) => e
| NONE => (0, ref false)
in
if dec_depth <> d
then escape := true
else ()
end
| traverseVar (env, d, A.FieldVar (var, _, _)) = (traverseVar(env, d, var))
| traverseVar (env, d, A.SubscriptVar (var, _, _)) = (traverseVar(env, d, var))
and traverseExp (env, d) =
let
fun trexp (A.VarExp var) = traverseVar(env, d, var)
| trexp (A.CallExp {args, ...}) = ( map trexp args; () )
| trexp (A.OpExp {left, right, ...}) = (trexp left; trexp right)
| trexp (A.RecordExp {fields, ...}) =
( map (fn (_, exp, _) => trexp exp) fields; ())
| trexp (A.SeqExp exp_pos_list ) =
( map (fn (exp, _) => trexp exp) exp_pos_list; ())
| trexp (A.AssignExp {var, exp, ...}) = (traverseVar (env, d, var); trexp exp)
| trexp (A.IfExp {test, then', else', ...}) =
(
trexp test;
trexp then';
case else' of
SOME(exp) => trexp exp
| NONE => ()
)
| trexp (A.WhileExp {test, body, ...}) = (trexp test; trexp body)
| trexp (A.ForExp {var, escape, lo, hi, body, ...}) =
(
trexp lo;
trexp hi;
escape := false;
let
val env' = S.enter (env, var, (d, escape))
in
traverseExp (env', d) body
end
)
| trexp (A.LetExp {decs, body, ...}) =
let
fun acc_env (dec, env) = traverseDecs (env, d, dec)
val env' = foldl acc_env env decs
in
traverseExp (env', d) body
end
| trexp (A.ArrayExp {size, init, ...}) = (trexp size; trexp init)
| trexp (A.BreakExp _) = ()
| trexp (A.NilExp) = ()
| trexp (A.IntExp _) = ()
| trexp (A.StringExp _) = ()
in
trexp
end
and traverseDecs(env, d, A.FunctionDec({params, body, ...}::dec_tail)): escEnv =
let
fun addFunParam ({name, escape, typ, pos
}, env) =
( escape := false;
S.enter (env, name, (d+1, escape)))
val env' = foldl addFunParam env params
in
traverseExp (env', d+1) body;
traverseDecs(env, d, A.FunctionDec(dec_tail));
env
end
| traverseDecs (env, d, A.VarDec{name, escape, init, ...}) =
(
traverseExp (env, d) init;
escape := false;
S.enter (env, name, (d, escape))
)
| traverseDecs (env, d, _) = env
fun findEscape(prog) = traverseExp (S.empty, 0) prog
end