2014-03-25 01:32:24 +04:00
|
|
|
#
|
|
|
|
# mal (Make Lisp) utility functions/definitions
|
|
|
|
#
|
|
|
|
|
|
|
|
ifndef __mal_util_included
|
|
|
|
__mal_util_included := true
|
|
|
|
|
|
|
|
_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
|
|
|
|
include $(_TOP_DIR)gmsl.mk
|
|
|
|
|
make: improve efficiency and encapsulation
Readability
* Use implicit parameter transmission ($(_list?) instead of $(call
_list?,$1),
first/lastword instead of word 1/words,
$1 instead of $(1).
* Use an undefined $(rem) macro and some automatic stripping (if,
foreach) to indent code with less calls to `strip` functions.
* Name the Make macro implementing a MAL core function exactly like the
function (modulo the encoding above) and simplify core_ns accordingly.
* Replace empty results representing `nil` with explicit MAL values.
* Implement large conditionals with a computed variable name, as already
done in printer.mk. For QUASIQUOTE and EVAL, this reduces a lot the
diff between steps.
* Represent the reader state as an explicit global variable instead of
passing the same name as argument again and again.
* Merge read-atom into read-form so that the switch on first character
is more visible.
Encapsulation
* Hide most representations into types.mk.
* Implement the type as a suffix in order to avoid a conditional in
_obj_type.
* Implement _error with throw.
* Create distinct types for keywords and macros.
* Move most metadata and atom stuff from core.mk to types.mk.
* Move parameter association from env to types because it hides more
about the representation of functions.
Representation
* Encode Make special characters in all strings/keywords/symbols, so
they can be used directly as spaced words and/or variable names for
map keys. (The encoding adding separating characters is kept for
read-string and seq).
* Change representation of numbers/strings/keywords/symbols, reducing
the number of Make variables.
Various
* Allow keyword argument for keyword core function.
* Shorten time-mes,slurp,readline...
* Remove obsolete stuff:
* `get` and `contains?` for vectors
* `count` for hash-maps
* `_join` from util.mk.
* `type` from core.mk.
* Add a function listing env_keys for DEBUG-EVAL.
* Fix some includes.
2022-02-01 20:06:57 +03:00
|
|
|
encoded_equal := Ξ
|
|
|
|
encoded_colon := κ
|
|
|
|
encoded_slash := λ
|
|
|
|
raw_hash := \#
|
|
|
|
encoded_hash := η
|
|
|
|
|
2014-03-25 01:32:24 +04:00
|
|
|
SEMI := ;
|
|
|
|
COMMA := ,
|
2014-12-19 05:33:49 +03:00
|
|
|
COLON := :
|
2014-03-25 01:32:24 +04:00
|
|
|
LCURLY := {
|
|
|
|
RCURLY := }
|
|
|
|
LPAREN := (
|
|
|
|
RPAREN := )
|
|
|
|
LBRACKET := [
|
|
|
|
RBRACKET := ]
|
|
|
|
DQUOTE := "# "
|
|
|
|
SLASH := $(strip \ )
|
make: improve efficiency and encapsulation
Readability
* Use implicit parameter transmission ($(_list?) instead of $(call
_list?,$1),
first/lastword instead of word 1/words,
$1 instead of $(1).
* Use an undefined $(rem) macro and some automatic stripping (if,
foreach) to indent code with less calls to `strip` functions.
* Name the Make macro implementing a MAL core function exactly like the
function (modulo the encoding above) and simplify core_ns accordingly.
* Replace empty results representing `nil` with explicit MAL values.
* Implement large conditionals with a computed variable name, as already
done in printer.mk. For QUASIQUOTE and EVAL, this reduces a lot the
diff between steps.
* Represent the reader state as an explicit global variable instead of
passing the same name as argument again and again.
* Merge read-atom into read-form so that the switch on first character
is more visible.
Encapsulation
* Hide most representations into types.mk.
* Implement the type as a suffix in order to avoid a conditional in
_obj_type.
* Implement _error with throw.
* Create distinct types for keywords and macros.
* Move most metadata and atom stuff from core.mk to types.mk.
* Move parameter association from env to types because it hides more
about the representation of functions.
Representation
* Encode Make special characters in all strings/keywords/symbols, so
they can be used directly as spaced words and/or variable names for
map keys. (The encoding adding separating characters is kept for
read-string and seq).
* Change representation of numbers/strings/keywords/symbols, reducing
the number of Make variables.
Various
* Allow keyword argument for keyword core function.
* Shorten time-mes,slurp,readline...
* Remove obsolete stuff:
* `get` and `contains?` for vectors
* `count` for hash-maps
* `_join` from util.mk.
* `type` from core.mk.
* Add a function listing env_keys for DEBUG-EVAL.
* Fix some includes.
2022-02-01 20:06:57 +03:00
|
|
|
ESC_DQUOTE := $(encoded_slash)$(DQUOTE)
|
|
|
|
ESC_N := $(encoded_slash)n
|
2014-03-25 01:32:24 +04:00
|
|
|
SQUOTE := '# '
|
|
|
|
QQUOTE := `# `
|
make: improve efficiency and encapsulation
Readability
* Use implicit parameter transmission ($(_list?) instead of $(call
_list?,$1),
first/lastword instead of word 1/words,
$1 instead of $(1).
* Use an undefined $(rem) macro and some automatic stripping (if,
foreach) to indent code with less calls to `strip` functions.
* Name the Make macro implementing a MAL core function exactly like the
function (modulo the encoding above) and simplify core_ns accordingly.
* Replace empty results representing `nil` with explicit MAL values.
* Implement large conditionals with a computed variable name, as already
done in printer.mk. For QUASIQUOTE and EVAL, this reduces a lot the
diff between steps.
* Represent the reader state as an explicit global variable instead of
passing the same name as argument again and again.
* Merge read-atom into read-form so that the switch on first character
is more visible.
Encapsulation
* Hide most representations into types.mk.
* Implement the type as a suffix in order to avoid a conditional in
_obj_type.
* Implement _error with throw.
* Create distinct types for keywords and macros.
* Move most metadata and atom stuff from core.mk to types.mk.
* Move parameter association from env to types because it hides more
about the representation of functions.
Representation
* Encode Make special characters in all strings/keywords/symbols, so
they can be used directly as spaced words and/or variable names for
map keys. (The encoding adding separating characters is kept for
read-string and seq).
* Change representation of numbers/strings/keywords/symbols, reducing
the number of Make variables.
Various
* Allow keyword argument for keyword core function.
* Shorten time-mes,slurp,readline...
* Remove obsolete stuff:
* `get` and `contains?` for vectors
* `count` for hash-maps
* `_join` from util.mk.
* `type` from core.mk.
* Add a function listing env_keys for DEBUG-EVAL.
* Fix some includes.
2022-02-01 20:06:57 +03:00
|
|
|
SPACE :=
|
|
|
|
SPACE := $(SPACE) $(SPACE)
|
2016-02-26 08:09:14 +03:00
|
|
|
MINUS := -
|
2014-03-25 01:32:24 +04:00
|
|
|
NUMBERS := 0 1 2 3 4 5 6 7 8 9
|
|
|
|
UNQUOTE := ~
|
|
|
|
define NEWLINE
|
|
|
|
|
|
|
|
|
|
|
|
endef
|
|
|
|
CARET := ^
|
|
|
|
ATSIGN := @
|
|
|
|
|
|
|
|
# \u00ab
|
|
|
|
_LP := «
|
|
|
|
# \u00bb
|
|
|
|
_RP := »
|
|
|
|
## \u00a7
|
|
|
|
_SP := §
|
|
|
|
## \u00ae
|
|
|
|
_DOL := Ş
|
|
|
|
## \u00b6
|
|
|
|
_NL := ¶
|
|
|
|
## \u00a8
|
|
|
|
###_EDQ := ¨
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
# Utility functions
|
|
|
|
#
|
|
|
|
|
|
|
|
_EQ = $(if $(subst x$1,,x$2)$(subst x$2,,x$1),,true)
|
|
|
|
|
2015-01-05 00:47:20 +03:00
|
|
|
# reverse list of words
|
make: improve efficiency and encapsulation
Readability
* Use implicit parameter transmission ($(_list?) instead of $(call
_list?,$1),
first/lastword instead of word 1/words,
$1 instead of $(1).
* Use an undefined $(rem) macro and some automatic stripping (if,
foreach) to indent code with less calls to `strip` functions.
* Name the Make macro implementing a MAL core function exactly like the
function (modulo the encoding above) and simplify core_ns accordingly.
* Replace empty results representing `nil` with explicit MAL values.
* Implement large conditionals with a computed variable name, as already
done in printer.mk. For QUASIQUOTE and EVAL, this reduces a lot the
diff between steps.
* Represent the reader state as an explicit global variable instead of
passing the same name as argument again and again.
* Merge read-atom into read-form so that the switch on first character
is more visible.
Encapsulation
* Hide most representations into types.mk.
* Implement the type as a suffix in order to avoid a conditional in
_obj_type.
* Implement _error with throw.
* Create distinct types for keywords and macros.
* Move most metadata and atom stuff from core.mk to types.mk.
* Move parameter association from env to types because it hides more
about the representation of functions.
Representation
* Encode Make special characters in all strings/keywords/symbols, so
they can be used directly as spaced words and/or variable names for
map keys. (The encoding adding separating characters is kept for
read-string and seq).
* Change representation of numbers/strings/keywords/symbols, reducing
the number of Make variables.
Various
* Allow keyword argument for keyword core function.
* Shorten time-mes,slurp,readline...
* Remove obsolete stuff:
* `get` and `contains?` for vectors
* `count` for hash-maps
* `_join` from util.mk.
* `type` from core.mk.
* Add a function listing env_keys for DEBUG-EVAL.
* Fix some includes.
2022-02-01 20:06:57 +03:00
|
|
|
_reverse = $(if $1,$(call _reverse,$(_rest)) $(firstword $1))
|
|
|
|
|
2015-01-05 00:47:20 +03:00
|
|
|
|
|
|
|
#$(info reverse(1 2 3 4 5): $(call reverse,1 2 3 4 5))
|
|
|
|
|
|
|
|
# str_encode: take a string and return an encoded version of it with
|
|
|
|
# every character separated by a space and special characters replaced
|
|
|
|
# with special Unicode characters
|
make: improve efficiency and encapsulation
Readability
* Use implicit parameter transmission ($(_list?) instead of $(call
_list?,$1),
first/lastword instead of word 1/words,
$1 instead of $(1).
* Use an undefined $(rem) macro and some automatic stripping (if,
foreach) to indent code with less calls to `strip` functions.
* Name the Make macro implementing a MAL core function exactly like the
function (modulo the encoding above) and simplify core_ns accordingly.
* Replace empty results representing `nil` with explicit MAL values.
* Implement large conditionals with a computed variable name, as already
done in printer.mk. For QUASIQUOTE and EVAL, this reduces a lot the
diff between steps.
* Represent the reader state as an explicit global variable instead of
passing the same name as argument again and again.
* Merge read-atom into read-form so that the switch on first character
is more visible.
Encapsulation
* Hide most representations into types.mk.
* Implement the type as a suffix in order to avoid a conditional in
_obj_type.
* Implement _error with throw.
* Create distinct types for keywords and macros.
* Move most metadata and atom stuff from core.mk to types.mk.
* Move parameter association from env to types because it hides more
about the representation of functions.
Representation
* Encode Make special characters in all strings/keywords/symbols, so
they can be used directly as spaced words and/or variable names for
map keys. (The encoding adding separating characters is kept for
read-string and seq).
* Change representation of numbers/strings/keywords/symbols, reducing
the number of Make variables.
Various
* Allow keyword argument for keyword core function.
* Shorten time-mes,slurp,readline...
* Remove obsolete stuff:
* `get` and `contains?` for vectors
* `count` for hash-maps
* `_join` from util.mk.
* `type` from core.mk.
* Add a function listing env_keys for DEBUG-EVAL.
* Fix some includes.
2022-02-01 20:06:57 +03:00
|
|
|
define str_encode
|
|
|
|
$(eval __temp := $1)$(rem \
|
|
|
|
)$(foreach a,$(encoded_slash) $(_DOL) $(_LP) $(_RP) $(_NL) \
|
|
|
|
$(encoded_hash) $(encoded_colon) $(_SP) $(encoded_equal) $(gmsl_characters)\
|
|
|
|
,$(eval __temp := $$(subst $$a,$$a$$(SPACE),$(__temp))))$(rem \
|
|
|
|
)$(__temp)
|
|
|
|
endef
|
2015-01-05 00:47:20 +03:00
|
|
|
|
|
|
|
# str_decode: take an encoded string an return an unencoded version of
|
|
|
|
# it by replacing the special Unicode charactes with the real
|
|
|
|
# characters and with all characters joined into a regular string
|
make: improve efficiency and encapsulation
Readability
* Use implicit parameter transmission ($(_list?) instead of $(call
_list?,$1),
first/lastword instead of word 1/words,
$1 instead of $(1).
* Use an undefined $(rem) macro and some automatic stripping (if,
foreach) to indent code with less calls to `strip` functions.
* Name the Make macro implementing a MAL core function exactly like the
function (modulo the encoding above) and simplify core_ns accordingly.
* Replace empty results representing `nil` with explicit MAL values.
* Implement large conditionals with a computed variable name, as already
done in printer.mk. For QUASIQUOTE and EVAL, this reduces a lot the
diff between steps.
* Represent the reader state as an explicit global variable instead of
passing the same name as argument again and again.
* Merge read-atom into read-form so that the switch on first character
is more visible.
Encapsulation
* Hide most representations into types.mk.
* Implement the type as a suffix in order to avoid a conditional in
_obj_type.
* Implement _error with throw.
* Create distinct types for keywords and macros.
* Move most metadata and atom stuff from core.mk to types.mk.
* Move parameter association from env to types because it hides more
about the representation of functions.
Representation
* Encode Make special characters in all strings/keywords/symbols, so
they can be used directly as spaced words and/or variable names for
map keys. (The encoding adding separating characters is kept for
read-string and seq).
* Change representation of numbers/strings/keywords/symbols, reducing
the number of Make variables.
Various
* Allow keyword argument for keyword core function.
* Shorten time-mes,slurp,readline...
* Remove obsolete stuff:
* `get` and `contains?` for vectors
* `count` for hash-maps
* `_join` from util.mk.
* `type` from core.mk.
* Add a function listing env_keys for DEBUG-EVAL.
* Fix some includes.
2022-02-01 20:06:57 +03:00
|
|
|
str_decode = $(subst $(SPACE),,$1)
|
|
|
|
|
|
|
|
define str_encode_nospace
|
|
|
|
$(subst $(SLASH),$(encoded_slash),$(rem \
|
|
|
|
)$(subst $$,$(_DOL),$(rem \
|
|
|
|
)$(subst $(LPAREN),$(_LP),$(rem \
|
|
|
|
)$(subst $(RPAREN),$(_RP),$(rem \
|
|
|
|
)$(subst $(NEWLINE),$(_NL),$(rem \
|
|
|
|
)$(subst $(raw_hash),$(encoded_hash),$(rem \
|
|
|
|
)$(subst $(COLON),$(encoded_colon),$(rem \
|
|
|
|
)$(subst $(SPACE),$(_SP),$(rem \
|
|
|
|
)$(subst =,$(encoded_equal),$(rem \
|
|
|
|
)$1)))))))))
|
|
|
|
endef
|
|
|
|
|
|
|
|
define str_decode_nospace
|
|
|
|
$(subst $(encoded_slash),$(SLASH),$(rem \
|
|
|
|
)$(subst $(_DOL),$$,$(rem \
|
|
|
|
)$(subst $(_LP),$(LPAREN),$(rem \
|
|
|
|
)$(subst $(_RP),$(RPAREN),$(rem \
|
|
|
|
)$(subst $(_NL),$(NEWLINE),$(rem \
|
|
|
|
)$(subst $(encoded_hash),$(raw_hash),$(rem \
|
|
|
|
)$(subst $(encoded_colon),$(COLON),$(rem \
|
|
|
|
)$(subst $(_SP),$(SPACE),$(rem \
|
|
|
|
)$(subst $(encoded_equal),=,$1)))))))))
|
|
|
|
endef
|
2014-03-25 01:32:24 +04:00
|
|
|
|
|
|
|
# Read a whole file substituting newlines with $(_NL)
|
make: improve efficiency and encapsulation
Readability
* Use implicit parameter transmission ($(_list?) instead of $(call
_list?,$1),
first/lastword instead of word 1/words,
$1 instead of $(1).
* Use an undefined $(rem) macro and some automatic stripping (if,
foreach) to indent code with less calls to `strip` functions.
* Name the Make macro implementing a MAL core function exactly like the
function (modulo the encoding above) and simplify core_ns accordingly.
* Replace empty results representing `nil` with explicit MAL values.
* Implement large conditionals with a computed variable name, as already
done in printer.mk. For QUASIQUOTE and EVAL, this reduces a lot the
diff between steps.
* Represent the reader state as an explicit global variable instead of
passing the same name as argument again and again.
* Merge read-atom into read-form so that the switch on first character
is more visible.
Encapsulation
* Hide most representations into types.mk.
* Implement the type as a suffix in order to avoid a conditional in
_obj_type.
* Implement _error with throw.
* Create distinct types for keywords and macros.
* Move most metadata and atom stuff from core.mk to types.mk.
* Move parameter association from env to types because it hides more
about the representation of functions.
Representation
* Encode Make special characters in all strings/keywords/symbols, so
they can be used directly as spaced words and/or variable names for
map keys. (The encoding adding separating characters is kept for
read-string and seq).
* Change representation of numbers/strings/keywords/symbols, reducing
the number of Make variables.
Various
* Allow keyword argument for keyword core function.
* Shorten time-mes,slurp,readline...
* Remove obsolete stuff:
* `get` and `contains?` for vectors
* `count` for hash-maps
* `_join` from util.mk.
* `type` from core.mk.
* Add a function listing env_keys for DEBUG-EVAL.
* Fix some includes.
2022-02-01 20:06:57 +03:00
|
|
|
_read_file = $(call str_encode_nospace,$(shell \
|
|
|
|
sed -z 's/\n/$(_NL)/g' '$(str_decode_nospace)'))
|
|
|
|
|
|
|
|
print = $(info $(str_decode_nospace))
|
|
|
|
|
|
|
|
_rest = $(wordlist 2,$(words $1),$1)
|
|
|
|
_rest2 = $(wordlist 3,$(words $1),$1)
|
|
|
|
|
|
|
|
# Evaluate $3 repeatedly with $k and $v set to key/value pairs from $1.
|
|
|
|
define _foreach2
|
|
|
|
$(if $1\
|
|
|
|
,$(foreach k,$(firstword $1)\
|
|
|
|
,$(foreach v,$(word 2,$1)\
|
|
|
|
,$(eval $2)))$(rem \
|
|
|
|
)$(call _foreach2,$(_rest2),$2))
|
|
|
|
endef
|
2014-03-25 01:32:24 +04:00
|
|
|
|
|
|
|
endif
|