impls/bash: Minor changes to make it run under OSH
[jackhill/mal.git] / impls / bash / env.sh
1 #
2 # mal (Make a Lisp) environment definition
3 #
4
5 if [ -z "${__mal_env_included__}" ]; then
6 __mal_env_included=true
7
8 source $(dirname $0)/types.sh
9
10 # Any environment is a hash_map with an __outer__ key that refers to
11 # a parent environment (or nil)
12 ENV () {
13 r=
14 _hash_map
15 local env="${r}"
16 if [[ "${1}" ]]; then
17 outer="${1}"; shift
18 _assoc! "${env}" "__outer__" "${outer}"
19 else
20 _assoc! "${env}" "__outer__" "${__nil}"
21 fi
22 r="${env}"
23
24 if [[ "${1}" && "${@}" ]]; then
25 local binds=(${ANON["${1}"]}); shift
26 local idx=0
27 while [[ "${binds["${idx}"]}" ]]; do
28 local fp="${ANON["${binds["${idx}"]}"]}"
29 if [[ "${fp}" == "&" ]]; then
30 idx=$(( idx + 1 ))
31 fp="${ANON["${binds["${idx}"]}"]}"
32 _list "${@}"
33 _assoc! "${env}" "${fp}" "${r}"
34 break
35 else
36 _assoc! "${env}" "${fp}" "${1}"
37 shift
38 idx=$(( idx + 1 ))
39 fi
40 done
41 fi
42 r="${env}"
43 }
44
45 # Find the environment with the key set and return the environment
46 ENV_FIND () {
47 if _contains? "${1}" "${ANON["${2}"]}"; then
48 r="${1}"
49 else
50 local obj="${ANON["${1}"]}"
51 eval 'local outer=${'${obj}'["__outer__"]}'
52 if [[ "${outer}" && "${outer}" != "${__nil}" ]]; then
53 ENV_FIND "${outer}" "${2}"
54 else
55 r=
56 fi
57 fi
58 }
59
60 # Find the environment with the key set and return the value of the
61 # key in that environment. If no environment contains the key then
62 # return an error
63 ENV_GET () {
64 ENV_FIND "${1}" "${2}"
65 local env="${r}"
66 local key="${ANON["${2}"]}"
67 if [[ "${r}" ]]; then
68 local obj="${ANON["${env}"]}"
69 eval 'r=${'${obj}'["'${key}'"]}'
70 else
71 _error "'${key}' not found"
72 fi
73 }
74
75 ENV_SET () {
76 local key="${ANON["${2}"]}"
77 _assoc! "${1}" "${key}" "${3}"
78 }
79
80 fi