1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-20 18:18:51 +03:00
mal/awk/env.awk
2015-08-26 10:13:25 +09:00

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
}