1
1
mirror of https://github.com/kanaka/mal.git synced 2024-10-27 22:58:00 +03:00
mal/impls/make/util.mk

130 lines
2.9 KiB
Makefile
Raw Normal View History

#
# 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 := η
SEMI := ;
COMMA := ,
COLON := :
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
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)
MINUS := -
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)
# 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))
#$(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
# 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
# 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
endif