mirror of
https://github.com/kanaka/mal.git
synced 2024-11-13 01:43:50 +03:00
127 lines
2.7 KiB
Awk
127 lines
2.7 KiB
Awk
function env_new(outer, params, args, idx, len, i, j, lst, param)
|
|
{
|
|
if (params != "") {
|
|
params = substr(params, 2)
|
|
len = types_heap[params]["len"]
|
|
if (len >= 2 && types_heap[params][len - 2] == "'&") {
|
|
if (types_heap[args]["len"] < len - 1) {
|
|
return "!\"Invalid argument length for the function. Expects at least " (len - 2) " arguments, supplied " (types_heap[args]["len"] - 1) "."
|
|
}
|
|
} else {
|
|
if (types_heap[args]["len"] != len + 1) {
|
|
return "!\"Invalid argument length for the function. Expects exactly " len " arguments, supplied " (types_heap[args]["len"] - 1) "."
|
|
}
|
|
}
|
|
}
|
|
env_heap[env_heap_index]["ref"] = 1
|
|
env_heap[env_heap_index]["outer"] = outer
|
|
if (params != "") {
|
|
for (i = 0; i < len; ++i) {
|
|
param = types_heap[params][i]
|
|
if (param == "'&") {
|
|
idx = types_allocate()
|
|
env_set(env_heap_index, types_heap[params][++i], "(" idx)
|
|
len = types_heap[args]["len"]
|
|
for (j = 0; i < len; ++j) {
|
|
types_addref(types_heap[idx][j] = types_heap[args][i++])
|
|
}
|
|
types_heap[idx]["len"] = j
|
|
break
|
|
}
|
|
env_set(env_heap_index, param, types_heap[args][i + 1])
|
|
types_addref(types_heap[args][i + 1])
|
|
}
|
|
}
|
|
if (outer != "") {
|
|
env_addref(outer)
|
|
}
|
|
return env_heap_index++
|
|
}
|
|
|
|
function env_set(env, key, val)
|
|
{
|
|
if (key in env_heap[env]) {
|
|
types_release(env_heap[env][key])
|
|
}
|
|
if (val ~ /^\&/) {
|
|
env_builtinnames[substr(val, 2)] = substr(key, 2)
|
|
}
|
|
env_heap[env][key] = val
|
|
}
|
|
|
|
function env_find(env, key)
|
|
{
|
|
while (env != "") {
|
|
if (key in env_heap[env]) {
|
|
return env
|
|
}
|
|
env = env_heap[env]["outer"]
|
|
}
|
|
return env
|
|
}
|
|
|
|
function env_get(env, key)
|
|
{
|
|
env = env_find(env, key)
|
|
if (env != "") {
|
|
return env_heap[env][key]
|
|
}
|
|
return "!\"'" substr(key, 2) "' not found"
|
|
}
|
|
|
|
function env_addref(env)
|
|
{
|
|
env_heap[env]["ref"]++
|
|
}
|
|
|
|
function env_release(env, i, outer)
|
|
{
|
|
while (env != "" && --env_heap[env]["ref"] == 0) {
|
|
for (i in env_heap[env]) {
|
|
if (i ~ /^'/) {
|
|
types_release(env_heap[env][i])
|
|
}
|
|
}
|
|
outer = env_heap[env]["outer"]
|
|
delete env_heap[env]
|
|
env = outer
|
|
}
|
|
}
|
|
|
|
function env_dump(i, j)
|
|
{
|
|
for (i = 0; i < env_heap_index; i++) {
|
|
if (i in env_heap) {
|
|
if (isarray(env_heap[i])) {
|
|
if (!("checked" in env_heap[i]) || env_heap[i]["checked"] != env_heap[i]["ref"]) {
|
|
for (j in env_heap[i]) {
|
|
print " env_heap[" i "][" j "] = " env_heap[i][j]
|
|
}
|
|
}
|
|
} else {
|
|
print " env_heap[" i "] = " env_heap[i]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function env_check(env, i, outer)
|
|
{
|
|
if (env_heap[env]["checked"]++) {
|
|
return
|
|
}
|
|
for (i in env_heap[env]) {
|
|
if (i != "ref" && i != "outer") {
|
|
types_check(env_heap[env][i])
|
|
}
|
|
}
|
|
outer = env_heap[env]["outer"]
|
|
if (outer in env_heap) {
|
|
env_check(outer)
|
|
}
|
|
}
|
|
|
|
BEGIN {
|
|
env_heap_index = 0
|
|
}
|