Add gensym and clean `or` macro to stepA of 19 implementations (part 3)
[jackhill/mal.git] / awk / env.awk
1 function env_new(outer, params, args, idx, len, i, j, lst, param)
2 {
3 if (params != "") {
4 params = substr(params, 2)
5 len = types_heap[params]["len"]
6 if (len >= 2 && types_heap[params][len - 2] == "'&") {
7 if (types_heap[args]["len"] < len - 1) {
8 return "!\"Invalid argument length for the function. Expects at least " (len - 2) " arguments, supplied " (types_heap[args]["len"] - 1) "."
9 }
10 } else {
11 if (types_heap[args]["len"] != len + 1) {
12 return "!\"Invalid argument length for the function. Expects exactly " len " arguments, supplied " (types_heap[args]["len"] - 1) "."
13 }
14 }
15 }
16 env_heap[env_heap_index]["ref"] = 1
17 env_heap[env_heap_index]["outer"] = outer
18 if (params != "") {
19 for (i = 0; i < len; ++i) {
20 param = types_heap[params][i]
21 if (param == "'&") {
22 idx = types_allocate()
23 env_set(env_heap_index, types_heap[params][++i], "(" idx)
24 len = types_heap[args]["len"]
25 for (j = 0; i < len; ++j) {
26 types_addref(types_heap[idx][j] = types_heap[args][i++])
27 }
28 types_heap[idx]["len"] = j
29 break
30 }
31 env_set(env_heap_index, param, types_heap[args][i + 1])
32 types_addref(types_heap[args][i + 1])
33 }
34 }
35 if (outer != "") {
36 env_addref(outer)
37 }
38 return env_heap_index++
39 }
40
41 function env_set(env, key, val)
42 {
43 if (key in env_heap[env]) {
44 types_release(env_heap[env][key])
45 }
46 if (val ~ /^\&/) {
47 env_builtinnames[substr(val, 2)] = substr(key, 2)
48 }
49 env_heap[env][key] = val
50 }
51
52 function env_find(env, key)
53 {
54 while (env != "") {
55 if (key in env_heap[env]) {
56 return env
57 }
58 env = env_heap[env]["outer"]
59 }
60 return env
61 }
62
63 function env_get(env, key)
64 {
65 env = env_find(env, key)
66 if (env != "") {
67 return env_heap[env][key]
68 }
69 return "!\"'" substr(key, 2) "' not found"
70 }
71
72 function env_addref(env)
73 {
74 env_heap[env]["ref"]++
75 }
76
77 function env_release(env, i, outer)
78 {
79 while (env != "" && --env_heap[env]["ref"] == 0) {
80 for (i in env_heap[env]) {
81 if (i ~ /^'/) {
82 types_release(env_heap[env][i])
83 }
84 }
85 outer = env_heap[env]["outer"]
86 delete env_heap[env]
87 env = outer
88 }
89 }
90
91 function env_dump(i, j)
92 {
93 for (i = 0; i < env_heap_index; i++) {
94 if (i in env_heap) {
95 if (isarray(env_heap[i])) {
96 if (!("checked" in env_heap[i]) || env_heap[i]["checked"] != env_heap[i]["ref"]) {
97 for (j in env_heap[i]) {
98 print " env_heap[" i "][" j "] = " env_heap[i][j]
99 }
100 }
101 } else {
102 print " env_heap[" i "] = " env_heap[i]
103 }
104 }
105 }
106 }
107
108 function env_check(env, i, outer)
109 {
110 if (env_heap[env]["checked"]++) {
111 return
112 }
113 for (i in env_heap[env]) {
114 if (i != "ref" && i != "outer") {
115 types_check(env_heap[env][i])
116 }
117 }
118 outer = env_heap[env]["outer"]
119 if (outer in env_heap) {
120 env_check(outer)
121 }
122 }
123
124 BEGIN {
125 env_heap_index = 0
126 }