1
1
mirror of https://github.com/kanaka/mal.git synced 2024-10-26 22:28:26 +03:00
mal/impls/make/env.mk
Joel Martin 8a19f60386 Move implementations into impls/ dir
- Reorder README to have implementation list after "learning tool"
  bullet.

- This also moves tests/ and libs/ into impls. It would be preferrable
  to have these directories at the top level.  However, this causes
  difficulties with the wasm implementations which need pre-open
  directories and have trouble with paths starting with "../../". So
  in lieu of that, symlink those directories to the top-level.

- Move the run_argv_test.sh script into the tests directory for
  general hygiene.
2020-02-10 23:50:16 -06:00

51 lines
1.8 KiB
Makefile

#
# mal (Make Lisp) Object Types and Functions
#
ifndef __mal_env_included
__mal_env_included := true
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(_TOP_DIR)types.mk
#
# ENV
#
# An ENV environment is a hash-map with an __outer__ reference to an
# outer environment
define BIND_ARGS
$(strip \
$(word 1,$(1) \
$(foreach fparam,$(call _nth,$(2),0),\
$(if $(call _EQ,&,$($(fparam)_value)),
$(call ENV_SET,$(1),$($(call _nth,$(2),1)_value),$(strip \
$(foreach new_list,$(call _list),
$(word 1,$(new_list) \
$(foreach val,$(3),$(call _conj!,$(new_list),$(val))))))),\
$(foreach val,$(word 1,$(3)),\
$(call ENV_SET,$(1),$($(fparam)_value),$(val))\
$(foreach left,$(call srest,$(2)),\
$(if $(call _EQ,0,$(call _count,$(left))),\
,\
$(call BIND_ARGS,$(1),$(left),$(wordlist 2,$(words $(3)),$(3))))))))))
endef
# Create a new ENV and optional bind values in it
# $(1): outer environment (set as a key named __outer__)
# $(2): list/vector object of bind forms
# $(3): space separated list of expressions to bind
ENV = $(strip $(foreach new_env,$(call _assoc!,$(call _hash_map),__outer__,$(if $(1),$(1),$(__nil))),$(if $(2),$(call BIND_ARGS,$(new_env),$(2),$(3)),$(new_env))))
ENV_FIND = $(strip \
$(if $(call _contains?,$(1),$(subst =,$(__equal),$(2))),\
$(1),\
$(if $(call _EQ,$(__nil),$(call _get,$(1),__outer__)),\
,\
$(call ENV_FIND,$(call _get,$(1),__outer__),$(2)))))
ENV_GET = $(foreach env,|$(call ENV_FIND,$(1),$(2))|,$(if $(call _EQ,||,$(env)),$(call _error,'$(2)' not found)$(__nil),$(call _get,$(strip $(subst |,,$(env))),$(subst =,$(__equal),$(2)))))
ENV_SET = $(if $(call _assoc!,$(1),$(subst =,$(__equal),$(2)),$(3)),$(1),)
endif