aboutsummaryrefslogtreecommitdiff
path: root/make
diff options
context:
space:
mode:
Diffstat (limited to 'make')
-rw-r--r--make/Makefile3
-rw-r--r--make/core.mk255
-rw-r--r--make/env.mk50
-rw-r--r--make/printer.mk45
-rwxr-xr-xmake/reader.mk20
-rw-r--r--make/step1_read_print.mk1
-rw-r--r--make/step2_eval.mk2
-rw-r--r--make/step3_env.mk3
-rw-r--r--make/step4_if_fn_do.mk13
-rw-r--r--make/step6_file.mk21
-rw-r--r--make/step7_quote.mk27
-rw-r--r--make/step8_macros.mk27
-rw-r--r--make/step9_interop.mk27
-rw-r--r--make/stepA_more.mk31
-rw-r--r--make/tests/types.mk10
-rw-r--r--make/types.mk420
16 files changed, 537 insertions, 418 deletions
diff --git a/make/Makefile b/make/Makefile
index 1110397..2bb1e1e 100644
--- a/make/Makefile
+++ b/make/Makefile
@@ -1,7 +1,8 @@
TESTS = tests/types.mk tests/reader.mk tests/step9_interop.mk
-SOURCES = util.mk readline.mk gmsl.mk types.mk reader.mk stepA_more.mk
+SOURCES = util.mk readline.mk gmsl.mk types.mk reader.mk printer.mk \
+ env.mk core.mk stepA_more.mk
mal.mk: $(SOURCES)
echo "#!/usr/bin/make -f" > $@
diff --git a/make/core.mk b/make/core.mk
new file mode 100644
index 0000000..aaba3fd
--- /dev/null
+++ b/make/core.mk
@@ -0,0 +1,255 @@
+#
+# mal (Make a Lisp) Core functions
+#
+
+ifndef __mal_core_included
+__mal_core_included := true
+
+_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
+include $(_TOP_DIR)util.mk
+include $(_TOP_DIR)types.mk
+include $(_TOP_DIR)printer.mk
+
+
+# Errors/Exceptions
+throw = $(eval __ERROR := $(1))
+
+
+# General functions
+
+# Return the type of the object (or "make" if it's not a object
+obj_type = $(call _string,$(call _obj_type,$(1)))
+
+equal? = $(if $(call _equal?,$(word 1,$(1)),$(word 2,$(1))),$(__true),$(__false))
+
+
+# Scalar functions
+nil? = $(if $(call _nil?,$(1)),$(__true),$(__false))
+true? = $(if $(call _true?,$(1)),$(__true),$(__false))
+false? = $(if $(call _false?,$(1)),$(__true),$(__false))
+
+
+# Symbol functions
+symbol? = $(if $(call _symbol?,$(1)),$(__true),$(__false))
+
+
+# Number functions
+number? = $(if $(call _number?,$(1)),$(__true),$(__false))
+
+number_lt = $(if $(call int_lt,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
+number_lte = $(if $(call int_lte,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
+number_gt = $(if $(call int_gt,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
+number_gte = $(if $(call int_gte,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
+
+number_plus = $(call _pnumber,$(call int_plus,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
+number_subtract = $(call _pnumber,$(call int_subtract,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
+number_multiply = $(call _pnumber,$(call int_multiply,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
+number_divide = $(call _pnumber,$(call int_divide,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
+
+
+# String functions
+
+pr_str = $(call _string,$(call _pr_str_mult,$(1),yes, ))
+str = $(call _string,$(call _pr_str_mult,$(1),,))
+prn = $(info $(call _pr_str_mult,$(1),yes, ))
+println = $(info $(subst \n,$(NEWLINE),$(call _pr_str_mult,$(1),, )))
+
+string? = $(if $(call _string?,$(1)),$(__true),$(__false))
+
+subs = $(strip \
+ $(foreach start,$(call gmsl_plus,1,$(call int_decode,$($(word 2,$(1))_value))),\
+ $(foreach end,$(if $(3),$(call int_decode,$($(3)_value)),$(words $($(word 1,$(1))_value))),\
+ $(call _string,$(wordlist $(start),$(end),$($(word 1,$(1))_value))))))
+
+
+
+# Function functions
+function? = $(if $(call _function?,$(1)),$(__true),$(__false))
+
+
+# List functions
+list? = $(if $(call _list?,$(1)),$(__true),$(__false))
+
+
+# Vector functions
+vector? = $(if $(call _vector?,$(1)),$(__true),$(__false))
+
+
+# Hash map (associative array) functions
+hash_map? = $(if $(call _hash_map?,$(1)),$(__true),$(__false))
+
+# set a key/value in a copy of the hash map
+assoc = $(word 1,\
+ $(foreach hm,$(call _clone_obj,$(word 1,$(1))),\
+ $(hm) \
+ $(call _assoc_seq!,$(hm),$(wordlist 2,$(words $(1)),$(1)))))
+
+# unset keys in a copy of the hash map
+# TODO: this could be made more efficient by copying only the
+# keys that not being removed.
+dissoc = $(word 1,\
+ $(foreach hm,$(call _clone_obj,$(word 1,$(1))),\
+ $(hm) \
+ $(foreach key,$(wordlist 2,$(words $(1)),$(1)),\
+ $(call _dissoc!,$(hm),$(call str_decode,$($(key)_value))))))
+
+keys = $(foreach new_list,$(call _list),$(new_list)$(eval $(new_list)_value := $(foreach v,$(call __get_obj_values,$(1)),$(call _string,$(word 4,$(subst _, ,$(v)))))))
+
+vals = $(foreach new_list,$(call _list),$(new_list)$(eval $(new_list)_value := $(foreach v,$(call __get_obj_values,$(1)),$($(v)))))
+
+# Hash map and vector functions
+
+# retrieve the value of a string key object from the hash map, or
+# retrive a vector by number object index
+get = $(strip \
+ $(if $(call _hash_map?,$(word 1,$(1))),\
+ $(call _get,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),\
+ $(call _get,$(word 1,$(1)),$(call int_decode,$($(word 2,$(1))_value)))))
+
+contains? = $(if $(call _contains?,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),$(__true),$(__false))
+
+
+# sequence operations
+
+sequential? = $(if $(call _sequential?,$(1)),$(__true),$(__false))
+
+cons = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $(strip $(word 1,$(1)) $(call __get_obj_values,$(word 2,$(1)))))))
+
+concat = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $(strip $(foreach lst,$1,$(call __get_obj_values,$(lst)))))))
+
+nth = $(word $(call gmsl_plus,1,$(call int_decode,$($(word 2,$(1))_value))),$($(word 1,$(1))_value))
+
+sfirst = $(word 1,$($(1)_value))
+
+slast = $(word $(words $($(1)_value)),$($(1)_value))
+
+empty? = $(if $(call _EQ,0,$(if $(call _hash_map?,$(1)),$($(1)_size),$(words $($(1)_value)))),$(__true),$(__false))
+
+count = $(call _number,$(call _count,$(1)))
+
+conj = $(word 1,$(foreach new_list,$(call __new_obj_like,$(word 1,$(1))),\
+ $(new_list) \
+ $(eval $(new_list)_value := $(strip $($(word 1,$(1))_value))) \
+ $(if $(call _list?,$(new_list)),\
+ $(foreach elem,$(wordlist 2,$(words $(1)),$(1)),\
+ $(eval $(new_list)_value := $(strip $(elem) $($(new_list)_value)))),\
+ $(eval $(new_list)_value := $(strip $($(new_list)_value) $(wordlist 2,$(words $(1)),$(1)))))))
+
+# Creates a new vector/list of the everything after but the first
+# element
+srest = $(word 1,$(foreach new_list,$(call _list),\
+ $(new_list) \
+ $(eval $(new_list)_value := $(wordlist 2,$(words $($(1)_value)),$($(1)_value)))))
+
+# Takes a space separated arguments and invokes the first argument
+# (function object) using the remaining arguments.
+sapply = $(call $(word 1,$(1))_value,\
+ $(strip \
+ $(wordlist 2,$(call gmsl_subtract,$(words $(1)),1),$(1)) \
+ $($(word $(words $(1)),$(1))_value)))
+
+# Map a function object over a list object
+smap = $(strip\
+ $(foreach func,$(word 1,$(1)),\
+ $(foreach lst,$(word 2,$(1)),\
+ $(foreach type,$(word 2,$(subst _, ,$(lst))),\
+ $(foreach new_hcode,$(call __new_obj_hash_code),\
+ $(foreach sz,$(words $(call __get_obj_values,$(lst))),\
+ $(eval $(__obj_magic)_$(type)_$(new_hcode)_value := $(strip \
+ $(foreach val,$(call __get_obj_values,$(lst)),\
+ $(call $(func)_value,$(val))))))\
+ $(__obj_magic)_$(type)_$(new_hcode))))))
+
+
+# Metadata functions
+
+with_meta = $(strip \
+ $(foreach new_obj,$(call _clone_obj,$(word 1,$(1))),\
+ $(eval $(new_obj)_meta := $(strip $(word 2,$(1))))\
+ $(new_obj)))
+
+meta = $(strip $($(1)_meta))
+
+
+# Atom functions
+
+atom = $(strip \
+ $(foreach hcode,$(call __new_obj_hash_code),\
+ $(foreach new_atom,$(__obj_magic)_atom_$(hcode),\
+ $(new_atom)\
+ $(eval $(new_atom)_value := $(1)))))
+atom? = $(if $(call _atom?,$(1)),$(__true),$(__false))
+
+deref = $($(1)_value)
+
+reset! = $(eval $(word 1,$(1))_value := $(word 2,$(1)))$(word 2,$(1))
+
+swap! = $(foreach resp,$(call $(word 2,$(1))_value,$($(word 1,$(1))_value) $(wordlist 3,$(words $(1)),$(1))),\
+ $(eval $(word 1,$(1))_value := $(resp))\
+ $(resp))
+
+
+
+
+# Namespace of core functions
+
+core_ns = type obj_type \
+ = equal? \
+ throw throw \
+ nil? nil? \
+ true? true? \
+ false? false? \
+ symbol _symbol \
+ symbol? symbol? \
+ function? function? \
+ string? string? \
+ pr-str pr_str \
+ str str \
+ prn prn \
+ println println \
+ subs subs \
+ number? number? \
+ < number_lt \
+ <= number_lte \
+ > number_gt \
+ >= number_gte \
+ + number_plus \
+ - number_subtract \
+ * number_multiply \
+ / number_divide \
+ \
+ list _list \
+ list? list? \
+ vector _vector \
+ vector? vector? \
+ hash-map _hash_map \
+ map? hash_map? \
+ assoc assoc \
+ dissoc dissoc \
+ get get \
+ contains? contains? \
+ keys keys \
+ vals vals \
+ \
+ sequential? sequential? \
+ cons cons \
+ concat concat \
+ nth nth \
+ first sfirst \
+ rest srest \
+ last slast \
+ empty? empty? \
+ count count \
+ conj conj \
+ apply sapply \
+ map smap \
+ \
+ with-meta with_meta \
+ meta meta \
+ atom atom \
+ atom? atom? \
+ deref deref \
+ reset! reset! \
+ swap! swap!
+
+endif
diff --git a/make/env.mk b/make/env.mk
new file mode 100644
index 0000000..d508283
--- /dev/null
+++ b/make/env.mk
@@ -0,0 +1,50 @@
+#
+# 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),$(call _get,$(strip $(subst |,,$(env))),$(subst =,$(__equal),$(2)))))
+
+ENV_SET = $(if $(call _assoc!,$(1),$(subst =,$(__equal),$(2)),$(3)),$(1),)
+
+endif
diff --git a/make/printer.mk b/make/printer.mk
new file mode 100644
index 0000000..a1f2559
--- /dev/null
+++ b/make/printer.mk
@@ -0,0 +1,45 @@
+#
+# mal (Make a Lisp) printer
+#
+
+ifndef __mal_printer_included
+__mal_printer_included := true
+
+_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
+include $(_TOP_DIR)util.mk
+include $(_TOP_DIR)types.mk
+
+# return a printable form of the argument, the second parameter is
+# 'print_readably' which backslashes quotes in string values
+_pr_str = $(if $(1),$(foreach ot,$(call _obj_type,$(1)),$(if $(call _EQ,make,$(ot)),$(call _error,_pr_str failed on $(1)),$(call $(ot)_pr_str,$(1),$(2)))),)
+
+# Like _pr_str but takes multiple values in first argument, the second
+# parameter is 'print_readably' which backslashes quotes in string
+# values, the third parameter is the delimeter to use between each
+# _pr_str'd value
+_pr_str_mult = $(call _pr_str,$(word 1,$(1)),$(2))$(if $(word 2,$(1)),$(3)$(call _pr_str_mult,$(wordlist 2,$(words $(1)),$(1)),$(2),$(3)),)
+
+
+# Type specific printing
+
+nil_pr_str = nil
+true_pr_str = true
+false_pr_str = false
+
+number_pr_str = $(call int_decode,$($(1)_value))
+
+symbol_pr_str = $($(1)_value)
+
+string_pr_str = $(if $(2),"$(subst $(DQUOTE),$(ESC_DQUOTE),$(subst $(SLASH),$(SLASH)$(SLASH),$(call str_decode,$($(1)_value))))",$(call str_decode,$($(1)_value)))
+
+function_pr_str = <$(if $(word 6,$(value $(1)_value)),$(wordlist 1,5,$(value $(1)_value))...,$(value $(1)_value))>
+
+list_pr_str = ($(foreach v,$(call __get_obj_values,$(1)),$(call _pr_str,$(v),$(2))))
+
+vector_pr_str = [$(foreach v,$(call __get_obj_values,$(1)),$(call _pr_str,$(v),$(2)))]
+
+hash_map_pr_str = {$(foreach v,$(call __get_obj_values,$(1)),"$(foreach hcode,$(word 3,$(subst _, ,$(1))),$(patsubst $(1)_%,%,$(v:%_value=%)))" $(call _pr_str,$($(v)),$(2)))}
+
+atom_pr_str = (atom $(call _pr_str,$($(1)_value),$(2)))
+
+endif
diff --git a/make/reader.mk b/make/reader.mk
index ce3b078..8d04596 100755
--- a/make/reader.mk
+++ b/make/reader.mk
@@ -55,10 +55,10 @@ endef
define READ_ATOM
$(foreach ch,$(word 1,$($(1))),\
$(if $(filter $(NUMBERS),$(ch)),\
- $(call number,$(call READ_NUMBER,$(1))),\
+ $(call _number,$(call READ_NUMBER,$(1))),\
$(if $(filter $(DQUOTE),$(ch)),\
$(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
- $(call _string,$(strip $(call READ_STRING,$(1))))\
+ $(call __string,$(strip $(call READ_STRING,$(1))))\
$(eval $(if $(filter $(DQUOTE),$(word 1,$($(1)))),\
$(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1)))),\
$(call _error,Expected '$(DQUOTE)' in; $($(1))))),\
@@ -69,7 +69,7 @@ $(foreach ch,$(word 1,$($(1))),\
$(__true),\
$(if $(call _EQ,false,$(sym)),\
$(__false),\
- $(call symbol,$(sym)))))))))
+ $(call _symbol,$(sym)))))))))
endef
# read and return tokens until $(2) found
@@ -111,28 +111,28 @@ $(foreach ch,$(word 1,$($(1))),\
$(call DROP_UNTIL,$(1),$(_NL)),\
$(if $(filter $(SQUOTE),$(ch)),\
$(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
- $(call list,$(call symbol,quote) $(strip $(call READ_FORM,$(1)))),\
+ $(call _list,$(call _symbol,quote) $(strip $(call READ_FORM,$(1)))),\
$(if $(filter $(QQUOTE),$(ch)),\
$(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
- $(call list,$(call symbol,quasiquote) $(strip $(call READ_FORM,$(1)))),\
+ $(call _list,$(call _symbol,quasiquote) $(strip $(call READ_FORM,$(1)))),\
$(if $(filter $(UNQUOTE),$(ch)),\
$(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
- $(call list,$(call symbol,unquote) $(strip $(call READ_FORM,$(1)))),\
+ $(call _list,$(call _symbol,unquote) $(strip $(call READ_FORM,$(1)))),\
$(if $(filter $(_SUQ),$(ch)),\
$(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
- $(call list,$(call symbol,splice-unquote) $(strip $(call READ_FORM,$(1)))),\
+ $(call _list,$(call _symbol,splice-unquote) $(strip $(call READ_FORM,$(1)))),\
$(if $(filter $(CARET),$(ch)),\
$(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
$(foreach meta,$(strip $(call READ_FORM,$(1))),\
- $(call list,$(call symbol,with-meta) $(strip $(call READ_FORM,$(1))) $(meta))),\
+ $(call _list,$(call _symbol,with-meta) $(strip $(call READ_FORM,$(1))) $(meta))),\
$(if $(filter $(ATSIGN),$(ch)),\
$(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
- $(call list,$(call symbol,deref) $(strip $(call READ_FORM,$(1)))),\
+ $(call _list,$(call _symbol,deref) $(strip $(call READ_FORM,$(1)))),\
$(if $(filter $(_RC),$(ch)),\
$(call _error,Unexpected '$(RCURLY)'),\
$(if $(filter $(_LC),$(ch)),\
$(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1))))\
- $(foreach thm,$(call hash_map),\
+ $(foreach thm,$(call _hash_map),\
$(call do,$(call _assoc_seq!,$(thm),$(strip $(call READ_UNTIL,$(1),$(_RC),$(RCURLY)))))\
$(eval $(if $(filter $(_RC),$(word 1,$($(1)))),\
$(eval $(1) := $(wordlist 2,$(words $($(1))),$($(1)))),\
diff --git a/make/step1_read_print.mk b/make/step1_read_print.mk
index 710cd1d..a5fe2d2 100644
--- a/make/step1_read_print.mk
+++ b/make/step1_read_print.mk
@@ -4,6 +4,7 @@
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(_TOP_DIR)types.mk
include $(_TOP_DIR)reader.mk
+include $(_TOP_DIR)printer.mk
SHELL := /bin/bash
INTERACTIVE ?= yes
diff --git a/make/step2_eval.mk b/make/step2_eval.mk
index 62cd415..96cd98f 100644
--- a/make/step2_eval.mk
+++ b/make/step2_eval.mk
@@ -4,6 +4,8 @@
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(_TOP_DIR)types.mk
include $(_TOP_DIR)reader.mk
+include $(_TOP_DIR)printer.mk
+include $(_TOP_DIR)core.mk
SHELL := /bin/bash
INTERACTIVE ?= yes
diff --git a/make/step3_env.mk b/make/step3_env.mk
index 4f3f070..7c505cf 100644
--- a/make/step3_env.mk
+++ b/make/step3_env.mk
@@ -4,6 +4,9 @@
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(_TOP_DIR)types.mk
include $(_TOP_DIR)reader.mk
+include $(_TOP_DIR)printer.mk
+include $(_TOP_DIR)env.mk
+include $(_TOP_DIR)core.mk
SHELL := /bin/bash
INTERACTIVE ?= yes
diff --git a/make/step4_if_fn_do.mk b/make/step4_if_fn_do.mk
index d08998d..f45cfa9 100644
--- a/make/step4_if_fn_do.mk
+++ b/make/step4_if_fn_do.mk
@@ -4,6 +4,9 @@
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(_TOP_DIR)types.mk
include $(_TOP_DIR)reader.mk
+include $(_TOP_DIR)printer.mk
+include $(_TOP_DIR)env.mk
+include $(_TOP_DIR)core.mk
SHELL := /bin/bash
INTERACTIVE ?= yes
@@ -71,7 +74,7 @@ $(if $(__ERROR),,\
$(if $(call _EQ,fn*,$($(a0)_value)),\
$(foreach a1,$(call _nth,$(1),1),\
$(foreach a2,$(call _nth,$(1),2),\
- $(call function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
+ $(call _function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
$(foreach el,$(call EVAL_AST,$(1),$(2)),\
$(and $(EVAL_DEBUG),$(info invoke: $(call _pr_str,$(el))))\
$(foreach f,$(call sfirst,$(el)),\
@@ -99,11 +102,11 @@ REP = $(call PRINT,$(strip $(call EVAL,$(strip $(call READ,$(1))),$(REPL_ENV))))
REPL = $(info $(call REP,$(call READLINE,"user> ")))$(if $(READLINE_EOF),,$(call REPL))
# Setup the environment
-_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call function,$$(call $(2),$$1))))
+_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call _function,$$(call $(2),$$1))))
-# Import types functions
-_import_types = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_types,$(wordlist 3,$(words $(1)),$(1))),)
-$(call _import_types,$(types_ns))
+# Import core namespace
+_import_core = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_core,$(wordlist 3,$(words $(1)),$(1))),)
+$(call _import_core,$(core_ns))
# Defined in terms of the language itself
$(call do,$(call REP, (def! not (fn* (a) (if a false true))) ))
diff --git a/make/step6_file.mk b/make/step6_file.mk
index 0c72a9c..c791b33 100644
--- a/make/step6_file.mk
+++ b/make/step6_file.mk
@@ -4,6 +4,9 @@
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(_TOP_DIR)types.mk
include $(_TOP_DIR)reader.mk
+include $(_TOP_DIR)printer.mk
+include $(_TOP_DIR)env.mk
+include $(_TOP_DIR)core.mk
SHELL := /bin/bash
INTERACTIVE ?= yes
@@ -71,7 +74,7 @@ $(if $(__ERROR),,\
$(if $(call _EQ,fn*,$($(a0)_value)),\
$(foreach a1,$(call _nth,$(1),1),\
$(foreach a2,$(call _nth,$(1),2),\
- $(call function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
+ $(call _function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
$(foreach el,$(call EVAL_AST,$(1),$(2)),\
$(and $(EVAL_DEBUG),$(info invoke: $(call _pr_str,$(el))))\
$(foreach f,$(call sfirst,$(el)),\
@@ -100,17 +103,17 @@ REPL = $(info $(call REP,$(call READLINE,"user> ")))$(if $(READLINE_EOF),,$(call
# Setup the environment
_ref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(if $(2),$(2),$(1))))
-_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call function,$$(call $(2),$$1))))
+_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call _function,$$(call $(2),$$1))))
-# Import types functions
-_import_types = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_types,$(wordlist 3,$(words $(1)),$(1))),)
-$(call _import_types,$(types_ns))
+# Import core namespace
+_import_core = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_core,$(wordlist 3,$(words $(1)),$(1))),)
+$(call _import_core,$(core_ns))
-$(call _ref,read-string,$(call function,$$(call READ_STR,$$(1))))
-$(call _ref,eval,$(call function,$$(call EVAL,$$(1),$$(REPL_ENV))))
+$(call _ref,read-string,$(call _function,$$(call READ_STR,$$(1))))
+$(call _ref,eval,$(call _function,$$(call EVAL,$$(1),$$(REPL_ENV))))
-_slurp = $(call string,$(call _read_file,$(1)))
-$(call _ref,slurp,$(call function,$$(call _slurp,$$(call str_decode,$$($$(1)_value)))))
+_slurp = $(call _string,$(call _read_file,$(1)))
+$(call _ref,slurp,$(call _function,$$(call _slurp,$$(call str_decode,$$($$(1)_value)))))
# Defined in terms of the language itself
$(call do,$(call REP, (def! not (fn* (a) (if a false true))) ))
diff --git a/make/step7_quote.mk b/make/step7_quote.mk
index 2a14c11..46e5130 100644
--- a/make/step7_quote.mk
+++ b/make/step7_quote.mk
@@ -4,6 +4,9 @@
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(_TOP_DIR)types.mk
include $(_TOP_DIR)reader.mk
+include $(_TOP_DIR)printer.mk
+include $(_TOP_DIR)env.mk
+include $(_TOP_DIR)core.mk
SHELL := /bin/bash
INTERACTIVE ?= yes
@@ -20,12 +23,12 @@ IS_PAIR = $(if $(call _EQ,list,$(call _obj_type,$(1))),$(if $(call _EQ,0,$(call
define QUASIQUOTE
$(strip \
$(if $(call _NOT,$(call IS_PAIR,$(1))),\
- $(call list,$(call symbol,quote) $(1)),\
+ $(call _list,$(call _symbol,quote) $(1)),\
$(if $(call _EQ,unquote,$($(call _nth,$(1),0)_value)),\
$(call _nth,$(1),1),\
$(if $(and $(call IS_PAIR,$(call _nth,$(1),0)),$(call _EQ,splice-unquote,$($(call _nth,$(call _nth,$(1),0),0)_value))),\
- $(call list,$(call symbol,concat) $(call _nth,$(call _nth,$(1),0),1) $(call QUASIQUOTE,$(call srest,$(1)))),\
- $(call list,$(call symbol,cons) $(call QUASIQUOTE,$(call _nth,$(1),0)) $(call QUASIQUOTE,$(call srest,$(1))))))))
+ $(call _list,$(call _symbol,concat) $(call _nth,$(call _nth,$(1),0),1) $(call QUASIQUOTE,$(call srest,$(1)))),\
+ $(call _list,$(call _symbol,cons) $(call QUASIQUOTE,$(call _nth,$(1),0)) $(call QUASIQUOTE,$(call srest,$(1))))))))
endef
define LET
@@ -88,7 +91,7 @@ $(if $(__ERROR),,\
$(if $(call _EQ,fn*,$($(a0)_value)),\
$(foreach a1,$(call _nth,$(1),1),\
$(foreach a2,$(call _nth,$(1),2),\
- $(call function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
+ $(call _function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
$(foreach el,$(call EVAL_AST,$(1),$(2)),\
$(and $(EVAL_DEBUG),$(info invoke: $(call _pr_str,$(el))))\
$(foreach f,$(call sfirst,$(el)),\
@@ -117,17 +120,17 @@ REPL = $(info $(call REP,$(call READLINE,"user> ")))$(if $(READLINE_EOF),,$(call
# Setup the environment
_ref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(if $(2),$(2),$(1))))
-_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call function,$$(call $(2),$$1))))
+_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call _function,$$(call $(2),$$1))))
-# Import types functions
-_import_types = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_types,$(wordlist 3,$(words $(1)),$(1))),)
-$(call _import_types,$(types_ns))
+# Import core namespace
+_import_core = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_core,$(wordlist 3,$(words $(1)),$(1))),)
+$(call _import_core,$(core_ns))
-$(call _ref,read-string,$(call function,$$(call READ_STR,$$(1))))
-$(call _ref,eval,$(call function,$$(call EVAL,$$(1),$$(REPL_ENV))))
+$(call _ref,read-string,$(call _function,$$(call READ_STR,$$(1))))
+$(call _ref,eval,$(call _function,$$(call EVAL,$$(1),$$(REPL_ENV))))
-_slurp = $(call string,$(call _read_file,$(1)))
-$(call _ref,slurp,$(call function,$$(call _slurp,$$(call str_decode,$$($$(1)_value)))))
+_slurp = $(call _string,$(call _read_file,$(1)))
+$(call _ref,slurp,$(call _function,$$(call _slurp,$$(call str_decode,$$($$(1)_value)))))
# Defined in terms of the language itself
$(call do,$(call REP, (def! not (fn* (a) (if a false true))) ))
diff --git a/make/step8_macros.mk b/make/step8_macros.mk
index 910acb0..fee4bb0 100644
--- a/make/step8_macros.mk
+++ b/make/step8_macros.mk
@@ -4,6 +4,9 @@
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(_TOP_DIR)types.mk
include $(_TOP_DIR)reader.mk
+include $(_TOP_DIR)printer.mk
+include $(_TOP_DIR)env.mk
+include $(_TOP_DIR)core.mk
SHELL := /bin/bash
INTERACTIVE ?= yes
@@ -20,12 +23,12 @@ IS_PAIR = $(if $(call _EQ,list,$(call _obj_type,$(1))),$(if $(call _EQ,0,$(call
define QUASIQUOTE
$(strip \
$(if $(call _NOT,$(call IS_PAIR,$(1))),\
- $(call list,$(call symbol,quote) $(1)),\
+ $(call _list,$(call _symbol,quote) $(1)),\
$(if $(call _EQ,unquote,$($(call _nth,$(1),0)_value)),\
$(call _nth,$(1),1),\
$(if $(and $(call IS_PAIR,$(call _nth,$(1),0)),$(call _EQ,splice-unquote,$($(call _nth,$(call _nth,$(1),0),0)_value))),\
- $(call list,$(call symbol,concat) $(call _nth,$(call _nth,$(1),0),1) $(call QUASIQUOTE,$(call srest,$(1)))),\
- $(call list,$(call symbol,cons) $(call QUASIQUOTE,$(call _nth,$(1),0)) $(call QUASIQUOTE,$(call srest,$(1))))))))
+ $(call _list,$(call _symbol,concat) $(call _nth,$(call _nth,$(1),0),1) $(call QUASIQUOTE,$(call srest,$(1)))),\
+ $(call _list,$(call _symbol,cons) $(call QUASIQUOTE,$(call _nth,$(1),0)) $(call QUASIQUOTE,$(call srest,$(1))))))))
endef
define IS_MACRO_CALL
@@ -108,7 +111,7 @@ $(if $(__ERROR),,\
$(if $(call _EQ,fn*,$($(a0)_value)),\
$(foreach a1,$(call _nth,$(1),1),\
$(foreach a2,$(call _nth,$(1),2),\
- $(call function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
+ $(call _function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
$(foreach el,$(call EVAL_AST,$(1),$(2)),\
$(and $(EVAL_DEBUG),$(info invoke: $(call _pr_str,$(el))))\
$(foreach f,$(call sfirst,$(el)),\
@@ -140,17 +143,17 @@ REPL = $(info $(call REP,$(call READLINE,"user> ")))$(if $(READLINE_EOF),,$(call
# Setup the environment
_ref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(if $(2),$(2),$(1))))
-_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call function,$$(call $(2),$$1))))
+_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call _function,$$(call $(2),$$1))))
-# Import types functions
-_import_types = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_types,$(wordlist 3,$(words $(1)),$(1))),)
-$(call _import_types,$(types_ns))
+# Import core namespace
+_import_core = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_core,$(wordlist 3,$(words $(1)),$(1))),)
+$(call _import_core,$(core_ns))
-$(call _ref,read-string,$(call function,$$(call READ_STR,$$(1))))
-$(call _ref,eval,$(call function,$$(call EVAL,$$(1),$$(REPL_ENV))))
+$(call _ref,read-string,$(call _function,$$(call READ_STR,$$(1))))
+$(call _ref,eval,$(call _function,$$(call EVAL,$$(1),$$(REPL_ENV))))
-_slurp = $(call string,$(call _read_file,$(1)))
-$(call _ref,slurp,$(call function,$$(call _slurp,$$(call str_decode,$$($$(1)_value)))))
+_slurp = $(call _string,$(call _read_file,$(1)))
+$(call _ref,slurp,$(call _function,$$(call _slurp,$$(call str_decode,$$($$(1)_value)))))
# Defined in terms of the language itself
$(call do,$(call REP, (def! not (fn* (a) (if a false true))) ))
diff --git a/make/step9_interop.mk b/make/step9_interop.mk
index 6de228d..4b7eaff 100644
--- a/make/step9_interop.mk
+++ b/make/step9_interop.mk
@@ -4,6 +4,9 @@
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(_TOP_DIR)types.mk
include $(_TOP_DIR)reader.mk
+include $(_TOP_DIR)printer.mk
+include $(_TOP_DIR)env.mk
+include $(_TOP_DIR)core.mk
SHELL := /bin/bash
INTERACTIVE ?= yes
@@ -20,12 +23,12 @@ IS_PAIR = $(if $(call _EQ,list,$(call _obj_type,$(1))),$(if $(call _EQ,0,$(call
define QUASIQUOTE
$(strip \
$(if $(call _NOT,$(call IS_PAIR,$(1))),\
- $(call list,$(call symbol,quote) $(1)),\
+ $(call _list,$(call _symbol,quote) $(1)),\
$(if $(call _EQ,unquote,$($(call _nth,$(1),0)_value)),\
$(call _nth,$(1),1),\
$(if $(and $(call IS_PAIR,$(call _nth,$(1),0)),$(call _EQ,splice-unquote,$($(call _nth,$(call _nth,$(1),0),0)_value))),\
- $(call list,$(call symbol,concat) $(call _nth,$(call _nth,$(1),0),1) $(call QUASIQUOTE,$(call srest,$(1)))),\
- $(call list,$(call symbol,cons) $(call QUASIQUOTE,$(call _nth,$(1),0)) $(call QUASIQUOTE,$(call srest,$(1))))))))
+ $(call _list,$(call _symbol,concat) $(call _nth,$(call _nth,$(1),0),1) $(call QUASIQUOTE,$(call srest,$(1)))),\
+ $(call _list,$(call _symbol,cons) $(call QUASIQUOTE,$(call _nth,$(1),0)) $(call QUASIQUOTE,$(call srest,$(1))))))))
endef
define IS_MACRO_CALL
@@ -112,7 +115,7 @@ $(if $(__ERROR),,\
$(if $(call _EQ,fn*,$($(a0)_value)),\
$(foreach a1,$(call _nth,$(1),1),\
$(foreach a2,$(call _nth,$(1),2),\
- $(call function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
+ $(call _function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
$(foreach el,$(call EVAL_AST,$(1),$(2)),\
$(and $(EVAL_DEBUG),$(info invoke: $(call _pr_str,$(el))))\
$(foreach f,$(call sfirst,$(el)),\
@@ -144,17 +147,17 @@ REPL = $(info $(call REP,$(call READLINE,"user> ")))$(if $(READLINE_EOF),,$(call
# Setup the environment
_ref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(if $(2),$(2),$(1))))
-_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call function,$$(call $(2),$$1))))
+_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call _function,$$(call $(2),$$1))))
-# Import types functions
-_import_types = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_types,$(wordlist 3,$(words $(1)),$(1))),)
-$(call _import_types,$(types_ns))
+# Import core namespace
+_import_core = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_core,$(wordlist 3,$(words $(1)),$(1))),)
+$(call _import_core,$(core_ns))
-$(call _ref,read-string,$(call function,$$(call READ_STR,$$(1))))
-$(call _ref,eval,$(call function,$$(call EVAL,$$(1),$$(REPL_ENV))))
+$(call _ref,read-string,$(call _function,$$(call READ_STR,$$(1))))
+$(call _ref,eval,$(call _function,$$(call EVAL,$$(1),$$(REPL_ENV))))
-_slurp = $(call string,$(call _read_file,$(1)))
-$(call _ref,slurp,$(call function,$$(call _slurp,$$(call str_decode,$$($$(1)_value)))))
+_slurp = $(call _string,$(call _read_file,$(1)))
+$(call _ref,slurp,$(call _function,$$(call _slurp,$$(call str_decode,$$($$(1)_value)))))
# Defined in terms of the language itself
$(call do,$(call REP, (def! not (fn* (a) (if a false true))) ))
diff --git a/make/stepA_more.mk b/make/stepA_more.mk
index 48c0cb2..3cd0d2a 100644
--- a/make/stepA_more.mk
+++ b/make/stepA_more.mk
@@ -4,6 +4,9 @@
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(_TOP_DIR)types.mk
include $(_TOP_DIR)reader.mk
+include $(_TOP_DIR)printer.mk
+include $(_TOP_DIR)env.mk
+include $(_TOP_DIR)core.mk
SHELL := /bin/bash
INTERACTIVE ?= yes
@@ -20,12 +23,12 @@ IS_PAIR = $(if $(call _EQ,list,$(call _obj_type,$(1))),$(if $(call _EQ,0,$(call
define QUASIQUOTE
$(strip \
$(if $(call _NOT,$(call IS_PAIR,$(1))),\
- $(call list,$(call symbol,quote) $(1)),\
+ $(call _list,$(call _symbol,quote) $(1)),\
$(if $(call _EQ,unquote,$($(call _nth,$(1),0)_value)),\
$(call _nth,$(1),1),\
$(if $(and $(call IS_PAIR,$(call _nth,$(1),0)),$(call _EQ,splice-unquote,$($(call _nth,$(call _nth,$(1),0),0)_value))),\
- $(call list,$(call symbol,concat) $(call _nth,$(call _nth,$(1),0),1) $(call QUASIQUOTE,$(call srest,$(1)))),\
- $(call list,$(call symbol,cons) $(call QUASIQUOTE,$(call _nth,$(1),0)) $(call QUASIQUOTE,$(call srest,$(1))))))))
+ $(call _list,$(call _symbol,concat) $(call _nth,$(call _nth,$(1),0),1) $(call QUASIQUOTE,$(call srest,$(1)))),\
+ $(call _list,$(call _symbol,cons) $(call QUASIQUOTE,$(call _nth,$(1),0)) $(call QUASIQUOTE,$(call srest,$(1))))))))
endef
define IS_MACRO_CALL
@@ -109,7 +112,7 @@ $(if $(__ERROR),,\
$(if $(call _EQ,catch*,$($(a20)_value)),\
$(foreach a21,$(call _nth,$(a2),1),\
$(foreach a22,$(call _nth,$(a2),2),\
- $(foreach binds,$(call list,$(a21)),\
+ $(foreach binds,$(call _list,$(a21)),\
$(foreach catch_env,$(call ENV,$(2),$(binds),$(__ERROR)),\
$(eval __ERROR :=)\
$(call EVAL,$(a22),$(catch_env)))))),\
@@ -127,7 +130,7 @@ $(if $(__ERROR),,\
$(if $(call _EQ,fn*,$($(a0)_value)),\
$(foreach a1,$(call _nth,$(1),1),\
$(foreach a2,$(call _nth,$(1),2),\
- $(call function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
+ $(call _function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
$(foreach el,$(call EVAL_AST,$(1),$(2)),\
$(and $(EVAL_DEBUG),$(info invoke: $(call _pr_str,$(el))))\
$(foreach f,$(call sfirst,$(el)),\
@@ -159,18 +162,18 @@ REPL = $(info $(call REP,$(call READLINE,"user> ")))$(if $(READLINE_EOF),,$(call
# Setup the environment
_ref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(if $(2),$(2),$(1))))
-_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call function,$$(call $(2),$$1))))
+_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call _function,$$(call $(2),$$1))))
-# Import types functions
-_import_types = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_types,$(wordlist 3,$(words $(1)),$(1))),)
-$(call _import_types,$(types_ns))
+# Import core namespace
+_import_core = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_core,$(wordlist 3,$(words $(1)),$(1))),)
+$(call _import_core,$(core_ns))
-$(call _ref,readline,$(call function,$$(foreach res,$$(call string,$$(call READLINE,"$$(call str_decode,$$($$(1)_value))")),$$(if $$(READLINE_EOF),$$(__nil),$$(res)))))
-$(call _ref,read-string,$(call function,$$(call READ_STR,$$(1))))
-$(call _ref,eval,$(call function,$$(call EVAL,$$(1),$$(REPL_ENV))))
+$(call _ref,readline,$(call _function,$$(foreach res,$$(call _string,$$(call READLINE,"$$(call str_decode,$$($$(1)_value))")),$$(if $$(READLINE_EOF),$$(__nil),$$(res)))))
+$(call _ref,read-string,$(call _function,$$(call READ_STR,$$(1))))
+$(call _ref,eval,$(call _function,$$(call EVAL,$$(1),$$(REPL_ENV))))
-_slurp = $(call string,$(call _read_file,$(1)))
-$(call _ref,slurp,$(call function,$$(call _slurp,$$(call str_decode,$$($$(1)_value)))))
+_slurp = $(call _string,$(call _read_file,$(1)))
+$(call _ref,slurp,$(call _function,$$(call _slurp,$$(call str_decode,$$($$(1)_value)))))
# Defined in terms of the language itself
$(call do,$(call REP, (def! not (fn* (a) (if a false true))) ))
diff --git a/make/tests/types.mk b/make/tests/types.mk
index c1c1849..a100afe 100644
--- a/make/tests/types.mk
+++ b/make/tests/types.mk
@@ -63,9 +63,9 @@ $(call assert_eq,a string value - a string (with parens),$(call str_decode,$($(c
$(info Testing function objects)
-$(call assert_eq,function,$(call _obj_type,$(call function,abc)),\
+$(call assert_eq,function,$(call _obj_type,$(call _function,abc)),\
(type (function abc)) is not 'function')
-FN1 := $(call function,arg1:'$$(word 1,$$(1))' arg2:'$$(word 2,$$(1))')
+FN1 := $(call _function,arg1:'$$(word 1,$$(1))' arg2:'$$(word 2,$$(1))')
$(call assert_eq,$(__true),$(call function?,$(FN1)))
$(call assert_eq,arg1:'A' arg2:'B',$(call apply,$(FN1),$(call list,A B)))
@@ -113,7 +113,7 @@ $(call assert_eq,A,$(call sfirst,$(call _nth,$(L4),1)),\
$(info Testing hash_maps)
-X := $(call hash_map)
+X := $(call _hash_map)
$(call assert_eq,$(__true),$(call hash_map?,$(X)),\
(hash_map? $$(X)))
$(call assert_eq,$(__false),$(call vector?,$(X)),\
@@ -130,7 +130,7 @@ $(call assert_eq,value of X a,$(call _get,$(X),a),\
$(call assert_eq,$(__true),$(call contains?,$(X) $(mykey)),\
(contains? $$(X),a))
-Y := $(call hash_map)
+Y := $(call _hash_map)
$(call assert_eq,0,$(call _count,$(Y)),\
(_count $$(Y)))
$(call do,$(call _assoc!,$(Y),a,value of Y a))
@@ -241,7 +241,7 @@ $(info Testing smap function)
L5 := $(call _conj!,$(call list),$(call number,1) $(call number,2) $(call number,3))
inc = $(call number_plus,$(call number,1) $(1))
$(call assert_eq,(2 3 4),$(call _pr_str,$(call _smap,inc,$(L5))))
-inc_func := $(call function,$$(call number_plus,$$(call number,1) $$(1)))
+inc_func := $(call _function,$$(call number_plus,$$(call number,1) $$(1)))
$(call assert_eq,(2 3 4),$(call _pr_str,$(call smap,$(inc_func) $(L5))))
diff --git a/make/types.mk b/make/types.mk
index 9f03530..b971fb1 100644
--- a/make/types.mk
+++ b/make/types.mk
@@ -1,5 +1,5 @@
#
-# mal (Make Lisp) Object Types and Functions
+# mal (Make a Lisp) object types
#
ifndef __mal_types_included
@@ -8,6 +8,9 @@ __mal_types_included := true
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
include $(_TOP_DIR)util.mk
+
+# Low-level type implemenation
+
# magic is \u2344 \u204a
__obj_magic = ⍄⁊
# \u2256
@@ -25,11 +28,54 @@ __get_obj_values = $(strip \
$(sort $(foreach v,$(filter %_value,$(filter $(1)_%,$(.VARIABLES))),$(if $(call _undefined?,$(v)),,$(v)))),\
$($(1)_value)))
+
+# Visualize Objects in memory
+__var_name = $(word 2,$(subst _, ,$(1)))_$(word 3,$(subst _, ,$(1)))
+__var_idx := 0
+__var_print = $(foreach v,$(1),\
+ $(foreach var,$(call __var_name,$(v)),\
+ $(if $(or $(call _list?,$(v)),$(call _vector?,$(v))),\
+ $(info $(2)$(var):)\
+ $(eval __var_idx := $(call gmsl_plus,1,$(__var_idx)))\
+ $(foreach lidx,__lidx_$(__var_idx),\
+ $(eval $(lidx) := 0)\
+ $(foreach val,$($(v)_value),\
+ $(call __var_print,$(val),$(2)$(SPACE)$(SPACE)$($(lidx)): )\
+ $(eval $(lidx) := $(call gmsl_plus,1,$($(lidx)))))),\
+ $(if $(call _hash_map?,$(v)),\
+ $(info $(2)$(var):)\
+ $(foreach vkey,$(filter $(v)_%,$(.VARIABLES)),\
+ $(foreach key,$(word 4,$(subst _, ,$(vkey))),\
+ $(info $(2)$(SPACE)$(SPACE)$(subst $(__equal),=,$(key)): )\
+ $(call __var_print,$($(vkey)),$(2)$(SPACE)$(SPACE)$(SPACE)$(SPACE)))),\
+ $(if $(call _symbol?,$(v)),\
+ $(info $(2)$(var): $($(v)_value)),\
+ $(if $(call _number?,$(v)),\
+ $(info $(2)$(var): $(call int_decode,$($(v)_value))),\
+ $(if $(call _nil?,$(v)),\
+ $(info $(2)nil),\
+ $(if $(call _function?,$(v)),\
+ $(if $(word 6,$(value $(v)_value)),\
+ $(info $(2)$(var): $(wordlist 1,5,$(value $(v)_value))...),\
+ $(info $(2)$(var): $(value $(v)_value))),\
+ $(info $(2)$(var): ...)))))))))
+
+_visualize_memory = $(foreach var,$(sort $(foreach vv,$(filter $(__obj_magic)_%,$(.VARIABLES)),$(call __var_name,$(vv)))),$(call __var_print,$(__obj_magic)_$(var)))
+
+
+# Errors/Exceptions
__ERROR :=
+_error = $(eval __ERROR := $(call _string,$(1)))
+
+
+# Constant atomic values
+__undefined = $(__obj_magic)_undf_0
+__nil = $(__obj_magic)__nil_0
+__true = $(__obj_magic)_true_0
+__false = $(__obj_magic)_fals_0
+
-#
# General functions
-#
# Return the type of the object (or "make" if it's not a object
_obj_type = $(strip \
@@ -46,22 +92,6 @@ _obj_type = $(strip \
$(if $(filter $(__obj_magic)_hmap_%,$(1)),hash_map,\
$(if $(filter $(__obj_magic)_undf_%,$(1)),undefined,\
make)))))))))))))
-obj_type = $(call string,$(call _obj_type,$(1)))
-
-# return a printable form of the argument, the second parameter is
-# 'print_readably' which backslashes quotes in string values
-_pr_str = $(if $(1),$(foreach ot,$(call _obj_type,$(1)),$(if $(call _EQ,make,$(ot)),$(call _error,_pr_str failed on $(1)),$(call $(ot)_pr_str,$(1),$(2)))),)
-
-# Like _pr_str but takes multiple values in first argument, the second
-# parameter is 'print_readably' which backslashes quotes in string
-# values, the third parameter is the delimeter to use between each
-# _pr_str'd value
-_pr_str_mult = $(call _pr_str,$(word 1,$(1)),$(2))$(if $(word 2,$(1)),$(3)$(call _pr_str_mult,$(wordlist 2,$(words $(1)),$(1)),$(2),$(3)),)
-
-pr_str = $(call string,$(call _pr_str_mult,$(1),yes, ))
-str = $(call string,$(call _pr_str_mult,$(1),,))
-prn = $(info $(call _pr_str_mult,$(1),yes, ))
-println = $(info $(subst \n,$(NEWLINE),$(call _pr_str_mult,$(1),, )))
_clone_obj = $(strip \
$(foreach new_hcode,$(call __new_obj_hash_code),\
@@ -75,101 +105,50 @@ _clone_obj = $(strip \
$(eval $(new_obj)_value := $(strip $($(1)_value)))))\
$(new_obj))))
-with_meta = $(strip \
- $(foreach new_obj,$(call _clone_obj,$(word 1,$(1))),\
- $(eval $(new_obj)_meta := $(strip $(word 2,$(1))))\
- $(new_obj)))
-
-meta = $(strip $($(1)_meta))
-
-
-#
-# Special atomic values
-#
-__undefined = $(__obj_magic)_undf_0
-__nil = $(__obj_magic)__nil_0
-__true = $(__obj_magic)_true_0
-__false = $(__obj_magic)_fals_0
+_equal? = $(strip \
+ $(foreach ot1,$(call _obj_type,$(1)),$(foreach ot2,$(call _obj_type,$(2)),\
+ $(if $(or $(call _EQ,$(ot1),$(ot2)),\
+ $(and $(call _sequential?,$(1)),$(call _sequential?,$(2)))),\
+ $(if $(or $(call _string?,$(1)),$(call _symbol?,$(1)),$(call _number?,$(1))),\
+ $(call _EQ,$($(1)_value),$($(2)_value)),\
+ $(if $(or $(call _vector?,$(1)),$(call _list?,$(1)),$(call _hash_map?,$(1))),\
+ $(if $(and $(call _EQ,$(call _count,$(1)),$(call _count,$(2))),\
+ $(call _EQ,$(call _count,$(1)),$(words $(call gmsl_pairmap,_equal?,$(call __get_obj_values,$(1)),$(call __get_obj_values,$(2)))))),$(__true),),\
+ $(call _EQ,$(1),$(2))))))))
_undefined? = $(or $(call _EQ,undefined,$(origin $(1))),$(filter $(__undefined),$($(1))))
-undefined? = $(if $(call _undefined?,$(1)),$(__true),$(__false))
_nil? = $(if $(filter $(__obj_magic)__nil_%,$(1)),$(__true),)
-nil? = $(if $(call _nil?,$(1)),$(__true),$(__false))
-nil_pr_str = nil
_true? = $(if $(filter $(__obj_magic)_true_%,$(1)),$(__true),)
-true? = $(if $(call _true?,$(1)),$(__true),$(__false))
-true_pr_str = true
_false? = $(if $(filter $(__obj_magic)_fals_%,$(1)),$(__true),)
-false? = $(if $(call _false?,$(1)),$(__true),$(__false))
-false_pr_str = false
-#
-# Numbers
-#
+# Symbols
+_symbol = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_symb_$(hcode)$(eval $(__obj_magic)_symb_$(hcode)_value := $(1)))
+_symbol? = $(if $(filter $(__obj_magic)_symb_%,$(1)),$(__true),)
-_pnumber = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_numb_$(hcode)$(eval $(__obj_magic)_numb_$(hcode)_value := $(1)))
-number = $(call _pnumber,$(call int_encode,$(1)))
+# Numbers
+_pnumber = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_numb_$(hcode)$(eval $(__obj_magic)_numb_$(hcode)_value := $(1)))
+_number = $(call _pnumber,$(call int_encode,$(1)))
_number? = $(if $(filter $(__obj_magic)_numb_%,$(1)),$(__true),)
-number? = $(if $(call _number?,$(1)),$(__true),$(__false))
-
-number_pr_str = $(call int_decode,$($(1)_value))
-
-number_plus = $(call _pnumber,$(call int_plus,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
-number_subtract = $(call _pnumber,$(call int_subtract,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
-number_multiply = $(call _pnumber,$(call int_multiply,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
-number_divide = $(call _pnumber,$(call int_divide,$($(word 1,$(1))_value),$($(word 2,$(1))_value)))
-number_gt = $(if $(call int_gt,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
-number_gte = $(if $(call int_gte,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
-number_lt = $(if $(call int_lt,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
-number_lte = $(if $(call int_lte,$($(word 1,$(1))_value),$($(word 2,$(1))_value)),$(__true),$(__false))
-
-#
-# Symbols
-#
-symbol = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_symb_$(hcode)$(eval $(__obj_magic)_symb_$(hcode)_value := $(1)))
-
-_symbol? = $(if $(filter $(__obj_magic)_symb_%,$(1)),$(__true),)
-symbol? = $(if $(call _symbol?,$(1)),$(__true),$(__false))
-
-symbol_pr_str = $($(1)_value)
-
-#
# Strings
-#
-_string = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_strn_$(hcode)$(eval $(__obj_magic)_strn_$(hcode)_value := $(1)))
-string = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_strn_$(hcode)$(eval $(__obj_magic)_strn_$(hcode)_value := $(call str_encode,$(1))))
-
+__string = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_strn_$(hcode)$(eval $(__obj_magic)_strn_$(hcode)_value := $(1)))
+_string = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_strn_$(hcode)$(eval $(__obj_magic)_strn_$(hcode)_value := $(call str_encode,$(1))))
_string? = $(if $(filter $(__obj_magic)_strn_%,$(1)),$(__true),)
-string? = $(if $(call _string?,$(1)),$(__true),$(__false))
-
-string_pr_str = $(if $(2),"$(subst $(DQUOTE),$(ESC_DQUOTE),$(subst $(SLASH),$(SLASH)$(SLASH),$(call str_decode,$($(1)_value))))",$(call str_decode,$($(1)_value)))
-
-subs = $(strip \
- $(foreach start,$(call gmsl_plus,1,$(call int_decode,$($(word 2,$(1))_value))),\
- $(foreach end,$(if $(3),$(call int_decode,$($(3)_value)),$(words $($(word 1,$(1))_value))),\
- $(call _string,$(wordlist $(start),$(end),$($(word 1,$(1))_value))))))
-#
-# Function objects
-#
+# Functions
# Return a function object. The first parameter is the
# function/macro 'source'. Note that any $ must be escaped as $$ to be
# preserved and become positional arguments for when the
# function/macro is later invoked.
-function = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_func_$(hcode)$(eval $(__obj_magic)_func_$(hcode)_value = $(1)))
-
+_function = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_func_$(hcode)$(eval $(__obj_magic)_func_$(hcode)_value = $(1)))
_function? = $(if $(filter $(__obj_magic)_func_%,$(1)),$(__true),)
-function? = $(if $(call _function?,$(1)),$(__true),$(__false))
-
-function_pr_str = <$(if $(word 6,$(value $(1)_value)),$(wordlist 1,5,$(value $(1)_value))...,$(value $(1)_value))>
# Takes a function name and a list object of arguments and invokes
# the function with space separated arguments
@@ -179,25 +158,20 @@ _apply = $(call $(1),$($(2)_value))
# the function with space separated arguments
apply = $(call $(1)_value,$($(2)_value))
-# Takes a space separated arguments and invokes the first argument
-# (function object) using the remaining arguments.
-sapply = $(call $(word 1,$(1))_value,\
- $(strip \
- $(wordlist 2,$(call gmsl_subtract,$(words $(1)),1),$(1)) \
- $($(word $(words $(1)),$(1))_value)))
-#
-# hash maps (associative arrays)
-#
+# Lists
+_list = $(word 1,$(foreach new_list,$(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_list_$(hcode)),$(new_list) $(eval $(new_list)_value := $1)))
+_list? = $(if $(filter $(__obj_magic)_list_%,$(1)),$(__true),)
-# create a new anonymous empty hash map
-_hash_map = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_hmap_$(hcode)$(eval $(__obj_magic)_hmap_$(hcode)_size := 0))
-hash_map = $(word 1,$(foreach new_hmap,$(call _hash_map),$(new_hmap) $(if $(1),$(call _assoc_seq!,$(new_hmap),$(1)))))
-_hash_map? = $(if $(filter $(__obj_magic)_hmap_%,$(1)),$(__true),)
-hash_map? = $(if $(call _hash_map?,$(1)),$(__true),$(__false))
+# Vectors (same as lists for now)
+_vector = $(word 1,$(foreach new_vect,$(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_vect_$(hcode)),$(new_vect) $(eval $(new_vect)_value := $1)))
+_vector? = $(if $(filter $(__obj_magic)_vect_%,$(1)),$(__true),)
+
-hash_map_pr_str = {$(foreach v,$(call __get_obj_values,$(1)),"$(foreach hcode,$(word 3,$(subst _, ,$(1))),$(patsubst $(1)_%,%,$(v:%_value=%)))" $(call _pr_str,$($(v)),$(2)))}
+# Hash maps (associative arrays)
+_hash_map = $(word 1,$(foreach hcode,$(call __new_obj_hash_code),$(foreach new_hmap,$(__obj_magic)_hmap_$(hcode),$(new_hmap) $(eval $(new_hmap)_size := 0) $(if $(1),$(call _assoc_seq!,$(new_hmap),$(1))))))
+_hash_map? = $(if $(filter $(__obj_magic)_hmap_%,$(1)),$(__true),)
# Set multiple key/values in a map
_assoc_seq! = $(call _assoc!,$(1),$(call str_decode,$($(word 1,$(2))_value)),$(word 2,$(2)))$(if $(word 3,$(2)),$(call _assoc_seq!,$(1),$(wordlist 3,$(words $(2)),$(2))),)
@@ -205,30 +179,9 @@ _assoc_seq! = $(call _assoc!,$(1),$(call str_decode,$($(word 1,$(2))_value)),$(w
# set a key/value in the hash map
_assoc! = $(foreach k,$(subst =,$(__equal),$(2)),$(if $(call _undefined?,$(1)_$(k)_value),$(eval $(1)_size := $(call gmsl_plus,$($(1)_size),1)),)$(eval $(1)_$(k)_value := $(3))$(1))
-# set a key/value in a copy of the hash map
-assoc = $(word 1,\
- $(foreach hm,$(call _clone_obj,$(word 1,$(1))),\
- $(hm) \
- $(call _assoc_seq!,$(hm),$(wordlist 2,$(words $(1)),$(1)))))
-
# unset a key in the hash map
_dissoc! = $(foreach k,$(subst =,$(__equal),$(2)),$(if $(call _undefined?,$(1)_$(k)_value),,$(eval $(1)_$(k)_value := $(__undefined))$(eval $(1)_size := $(call gmsl_subtract,$($(1)_size),1))))$(1)
-# unset keys in a copy of the hash map
-# TODO: this could be made more efficient by copying only the
-# keys that not being removed.
-dissoc = $(word 1,\
- $(foreach hm,$(call _clone_obj,$(word 1,$(1))),\
- $(hm) \
- $(foreach key,$(wordlist 2,$(words $(1)),$(1)),\
- $(call _dissoc!,$(hm),$(call str_decode,$($(key)_value))))))
-
-keys = $(foreach new_list,$(call _list),$(new_list)$(eval $(new_list)_value := $(foreach v,$(call __get_obj_values,$(1)),$(call string,$(word 4,$(subst _, ,$(v)))))))
-
-vals = $(foreach new_list,$(call _list),$(new_list)$(eval $(new_list)_value := $(foreach v,$(call __get_obj_values,$(1)),$($(v)))))
-
-
-
# Hash map and vector functions
# retrieve the value of a plain string key from the hash map, or
@@ -240,104 +193,20 @@ _get = $(strip \
$(word $(call gmsl_plus,1,$(2)),$($(1)_value)),\
,)))
-# retrieve the value of a string key object from the hash map, or
-# retrive a vector by number object index
-get = $(strip \
- $(if $(call _hash_map?,$(word 1,$(1))),\
- $(call _get,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),\
- $(call _get,$(word 1,$(1)),$(call number_pr_str,$(word 2,$(1))))))
-
_contains? = $(strip \
$(if $(call _hash_map?,$(1)),\
$(foreach k,$(subst =,$(__equal),$(2)),$(if $(call _undefined?,$(1)_$(k)_value),,$(__true))),\
$(if $(call _vector?,$(1)),\
$(if $(word $(call gmsl_plus,1,$(2)),$($(1)_value)),$(__true),),\
,)))
-contains? = $(if $(call _contains?,$(word 1,$(1)),$(call str_decode,$($(word 2,$(1))_value))),$(__true),$(__false))
-
-
-#
-# Errors/Exceptions
-#
-_error = $(eval __ERROR := $(call string,$(1)))
-throw = $(eval __ERROR := $(1))
-
-
-#
-# vectors
-#
-
-_vector = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_vect_$(hcode))
-vector = $(word 1,$(foreach new_vect,$(call _vector),$(new_vect) $(eval $(new_vect)_value := $1)))
-
-_vector? = $(if $(filter $(__obj_magic)_vect_%,$(1)),$(__true),)
-vector? = $(if $(call _vector?,$(1)),$(__true),$(__false))
-
-vector_pr_str = [$(foreach v,$(call __get_obj_values,$(1)),$(call _pr_str,$(v),$(2)))]
-
-#
-# list (same as vectors for now)
-#
-
-_list = $(foreach hcode,$(call __new_obj_hash_code),$(__obj_magic)_list_$(hcode))
-list = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $1)))
-
-_list? = $(if $(filter $(__obj_magic)_list_%,$(1)),$(__true),)
-list? = $(if $(call _list?,$(1)),$(__true),$(__false))
-
-list_pr_str = ($(foreach v,$(call __get_obj_values,$(1)),$(call _pr_str,$(v),$(2))))
-
-cons = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $(strip $(word 1,$(1)) $(call __get_obj_values,$(word 2,$(1)))))))
-#
-# atoms
-#
-atom = $(strip \
- $(foreach hcode,$(call __new_obj_hash_code),\
- $(foreach new_atom,$(__obj_magic)_atom_$(hcode),\
- $(new_atom)\
- $(eval $(new_atom)_value := $(1)))))
-
-_atom? = $(if $(filter $(__obj_magic)_atom_%,$(1)),$(__true),)
-atom? = $(if $(call _atom?,$(1)),$(__true),$(__false))
-
-atom_pr_str = (atom $(call _pr_str,$($(1)_value),$(2)))
-
-deref = $($(1)_value)
-
-reset! = $(eval $(word 1,$(1))_value := $(word 2,$(1)))$(word 2,$(1))
-
-swap! = $(foreach resp,$(call $(word 2,$(1))_value,$($(word 1,$(1))_value) $(wordlist 3,$(words $(1)),$(1))),\
- $(eval $(word 1,$(1))_value := $(resp))\
- $(resp))
-
-
-#
# sequence operations
-#
_sequential? = $(if $(filter $(__obj_magic)_list_% $(__obj_magic)_vect_%,$(1)),$(__true),)
-sequential? = $(if $(call _sequential?,$(1)),$(__true),$(__false))
-
-raw_flat = $(foreach val,$(call __get_obj_values,$(1)),$($(val)))
_nth = $(word $(call gmsl_plus,1,$(2)),$($(1)_value))
-nth = $(word $(call gmsl_plus,1,$(call int_decode,$($(word 2,$(1))_value))),$($(word 1,$(1))_value))
-
-empty? = $(if $(call _EQ,0,$(if $(call _hash_map?,$(1)),$($(1)_size),$(words $($(1)_value)))),$(__true),$(__false))
-
-concat = $(word 1,$(foreach new_list,$(call _list),$(new_list) $(eval $(new_list)_value := $(strip $(foreach lst,$1,$(call __get_obj_values,$(lst)))))))
-
-conj = $(word 1,$(foreach new_list,$(call __new_obj_like,$(word 1,$(1))),\
- $(new_list) \
- $(eval $(new_list)_value := $(strip $($(word 1,$(1))_value))) \
- $(if $(call _list?,$(new_list)),\
- $(foreach elem,$(wordlist 2,$(words $(1)),$(1)),\
- $(eval $(new_list)_value := $(strip $(elem) $($(new_list)_value)))),\
- $(eval $(new_list)_value := $(strip $($(new_list)_value) $(wordlist 2,$(words $(1)),$(1)))))))
-
# conj that mutates a sequence in-place to append the call arguments
_conj! = $(eval $(1)_value := $(strip $($(1)_value) $2 $3 $4 $5 $6 $7 $8 $9 $(10) $(11) $(12) $(13) $(14) $(15) $(16) $(17) $(18) $(19) $(20)))$(1)
@@ -345,11 +214,6 @@ _count = $(strip \
$(if $(call _hash_map?,$(1)),\
$($(1)_size),\
$(words $($(1)_value))))
-count = $(call number,$(call _count,$(1)))
-
-sfirst = $(word 1,$($(1)_value))
-
-slast = $(word $(words $($(1)_value)),$($(1)_value))
# Creates a new vector/list of the everything after but the first
# element
@@ -366,135 +230,15 @@ _smap = $(word 1,\
# Same as _smap but returns a vector
_smap_vec = $(word 1,\
- $(foreach new_vector,$(call vector),\
+ $(foreach new_vector,$(call _vector),\
$(new_vector)\
$(foreach v,$(call __get_obj_values,$(2)),\
$(call _conj!,$(new_vector),$(call $(1),$(v),$(3),$(4))))))
-# Map a function object over a list object
-smap = $(strip\
- $(foreach func,$(word 1,$(1)),\
- $(foreach lst,$(word 2,$(1)),\
- $(foreach type,$(word 2,$(subst _, ,$(lst))),\
- $(foreach new_hcode,$(call __new_obj_hash_code),\
- $(foreach sz,$(words $(call __get_obj_values,$(lst))),\
- $(eval $(__obj_magic)_$(type)_$(new_hcode)_value := $(strip \
- $(foreach val,$(call __get_obj_values,$(lst)),\
- $(call $(func)_value,$(val))))))\
- $(__obj_magic)_$(type)_$(new_hcode))))))
-
-
-
-_equal? = $(strip \
- $(foreach ot1,$(call _obj_type,$(1)),$(foreach ot2,$(call _obj_type,$(2)),\
- $(if $(or $(call _EQ,$(ot1),$(ot2)),\
- $(and $(call _sequential?,$(1)),$(call _sequential?,$(2)))),\
- $(if $(or $(call _string?,$(1)),$(call _symbol?,$(1)),$(call _number?,$(1))),\
- $(call _EQ,$($(1)_value),$($(2)_value)),\
- $(if $(or $(call _vector?,$(1)),$(call _list?,$(1)),$(call _hash_map?,$(1))),\
- $(if $(and $(call _EQ,$(call _count,$(1)),$(call _count,$(2))),\
- $(call _EQ,$(call _count,$(1)),$(words $(call gmsl_pairmap,_equal?,$(call __get_obj_values,$(1)),$(call __get_obj_values,$(2)))))),$(__true),),\
- $(call _EQ,$(1),$(2))))))))
-
-equal? = $(if $(call _equal?,$(word 1,$(1)),$(word 2,$(1))),$(__true),$(__false))
-
-#
-# 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),$(call _get,$(strip $(subst |,,$(env))),$(subst =,$(__equal),$(2)))))
-
-ENV_SET = $(if $(call _assoc!,$(1),$(subst =,$(__equal),$(2)),$(3)),$(1),)
-
-#
-# Visualize Objects in memory
-#
-
-__var_name = $(word 2,$(subst _, ,$(1)))_$(word 3,$(subst _, ,$(1)))
-__var_idx := 0
-__var_print = $(foreach v,$(1),\
- $(foreach var,$(call __var_name,$(v)),\
- $(if $(or $(call _list?,$(v)),$(call _vector?,$(v))),\
- $(info $(2)$(var):)\
- $(eval __var_idx := $(call gmsl_plus,1,$(__var_idx)))\
- $(foreach lidx,__lidx_$(__var_idx),\
- $(eval $(lidx) := 0)\
- $(foreach val,$($(v)_value),\
- $(call __var_print,$(val),$(2)$(SPACE)$(SPACE)$($(lidx)): )\
- $(eval $(lidx) := $(call gmsl_plus,1,$($(lidx)))))),\
- $(if $(call _hash_map?,$(v)),\
- $(info $(2)$(var):)\
- $(foreach vkey,$(filter $(v)_%,$(.VARIABLES)),\
- $(foreach key,$(word 4,$(subst _, ,$(vkey))),\
- $(info $(2)$(SPACE)$(SPACE)$(subst $(__equal),=,$(key)): )\
- $(call __var_print,$($(vkey)),$(2)$(SPACE)$(SPACE)$(SPACE)$(SPACE)))),\
- $(if $(call _symbol?,$(v)),\
- $(info $(2)$(var): $($(v)_value)),\
- $(if $(call _number?,$(v)),\
- $(info $(2)$(var): $(call int_decode,$($(v)_value))),\
- $(if $(call _nil?,$(v)),\
- $(info $(2)nil),\
- $(if $(call _function?,$(v)),\
- $(if $(word 6,$(value $(v)_value)),\
- $(info $(2)$(var): $(wordlist 1,5,$(value $(v)_value))...),\
- $(info $(2)$(var): $(value $(v)_value))),\
- $(info $(2)$(var): ...)))))))))
+# atoms
-visualize_memory = $(foreach var,$(sort $(foreach vv,$(filter $(__obj_magic)_%,$(.VARIABLES)),$(call __var_name,$(vv)))),$(call __var_print,$(__obj_magic)_$(var)))
+_atom? = $(if $(filter $(__obj_magic)_atom_%,$(1)),$(__true),)
-#
-# Namespace of type functions
-#
-types_ns = pr-str pr_str str str prn prn println println \
- with-meta with_meta meta meta \
- type obj_type = equal? \
- nil? nil? true? true? false? false? \
- number? number? \
- > number_gt >= number_gte < number_lt <= number_lte \
- + number_plus - number_subtract * number_multiply / number_divide \
- symbol? symbol? function? function? \
- string? string? subs subs \
- hash-map hash_map map? hash_map? assoc assoc dissoc dissoc \
- get get contains? contains? keys keys vals vals \
- throw throw \
- list list list? list? \
- vector vector vector? vector? \
- atom atom atom? atom? deref deref reset! reset! swap! swap! \
- sequential? sequential? \
- cons cons nth nth empty? empty? count count concat concat \
- conj conj first sfirst last slast rest srest \
- apply sapply map smap \
endif