All: move some fns to core. Major cleanup.
[jackhill/mal.git] / make / step7_quote.mk
CommitLineData
31690700
JM
1#
2# mal (Make Lisp)
3#
4_TOP_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
5include $(_TOP_DIR)types.mk
6include $(_TOP_DIR)reader.mk
ea81a808
JM
7include $(_TOP_DIR)printer.mk
8include $(_TOP_DIR)env.mk
9include $(_TOP_DIR)core.mk
31690700
JM
10
11SHELL := /bin/bash
12INTERACTIVE ?= yes
13EVAL_DEBUG ?=
14
15# READ: read and parse input
16define READ
17$(if $(READLINE_EOF)$(__ERROR),,$(call READ_STR,$(if $(1),$(1),$(call READLINE,"user> "))))
18endef
19
20# EVAL: evaluate the parameter
21IS_PAIR = $(if $(call _EQ,list,$(call _obj_type,$(1))),$(if $(call _EQ,0,$(call _count,$(1))),,true),)
22
23define QUASIQUOTE
24$(strip \
25 $(if $(call _NOT,$(call IS_PAIR,$(1))),\
ea81a808 26 $(call _list,$(call _symbol,quote) $(1)),\
31690700
JM
27 $(if $(call _EQ,unquote,$($(call _nth,$(1),0)_value)),\
28 $(call _nth,$(1),1),\
29 $(if $(and $(call IS_PAIR,$(call _nth,$(1),0)),$(call _EQ,splice-unquote,$($(call _nth,$(call _nth,$(1),0),0)_value))),\
ea81a808
JM
30 $(call _list,$(call _symbol,concat) $(call _nth,$(call _nth,$(1),0),1) $(call QUASIQUOTE,$(call srest,$(1)))),\
31 $(call _list,$(call _symbol,cons) $(call QUASIQUOTE,$(call _nth,$(1),0)) $(call QUASIQUOTE,$(call srest,$(1))))))))
31690700
JM
32endef
33
34define LET
35$(strip \
36 $(word 1,$(2) \
37 $(foreach var,$(call _nth,$(1),0),\
38 $(foreach val,$(call _nth,$(1),1),\
39 $(call ENV_SET,$(2),$($(var)_value),$(call EVAL,$(val),$(2)))\
40 $(foreach left,$(call srest,$(call srest,$(1))),
41 $(if $(call _EQ,0,$(call _count,$(left))),\
42 ,\
43 $(call LET,$(left),$(2))))))))
44endef
45
46define EVAL_AST
47$(strip \
48 $(and $(EVAL_DEBUG),$(info EVAL_AST: $(call _pr_str,$(1))))\
49 $(if $(call _symbol?,$(1)),\
50 $(foreach key,$($(1)_value),\
51 $(call ENV_GET,$(2),$(key))),\
52 $(if $(call _list?,$(1)),\
53 $(call _smap,EVAL,$(1),$(2)),\
54 $(if $(call _vector?,$(1)),\
55 $(call _smap_vec,EVAL,$(1),$(2)),\
56 $(if $(call _hash_map?,$(1)),\
57 $(foreach new_hmap,$(call __new_obj,hmap),\
58 $(foreach v,$(call __get_obj_values,$(1)),\
59 $(eval $(v:$(1)_%=$(new_hmap)_%) := $(call EVAL,$($(v)),$(2))))\
60 $(eval $(new_hmap)_size := $($(1)_size))\
61 $(new_hmap)),\
62 $(1))))))
63endef
64
65define EVAL_INVOKE
66$(if $(__ERROR),,\
67 $(and $(EVAL_DEBUG),$(info EVAL_INVOKE: $(call _pr_str,$(1))))
68 $(foreach a0,$(call _nth,$(1),0),\
69 $(if $(call _EQ,def!,$($(a0)_value)),\
70 $(foreach a1,$(call _nth,$(1),1),\
71 $(foreach a2,$(call _nth,$(1),2),\
72 $(foreach res,$(call EVAL,$(a2),$(2)),\
73 $(if $(call ENV_SET,$(2),$($(a1)_value),$(res)),$(res),)))),\
74 $(if $(call _EQ,let*,$($(a0)_value)),\
75 $(foreach a1,$(call _nth,$(1),1),\
76 $(foreach a2,$(call _nth,$(1),2),\
77 $(call EVAL,$(a2),$(call LET,$(a1),$(call ENV,$(2)))))),\
78 $(if $(call _EQ,quote,$($(a0)_value)),\
79 $(call _nth,$(1),1),\
80 $(if $(call _EQ,quasiquote,$($(a0)_value)),\
81 $(call EVAL,$(call QUASIQUOTE,$(call _nth,$(1),1)),$(2)),\
82 $(if $(call _EQ,do,$($(a0)_value)),\
83 $(call slast,$(call EVAL_AST,$(call srest,$(1)),$(2))),\
84 $(if $(call _EQ,if,$($(a0)_value)),\
85 $(foreach a1,$(call _nth,$(1),1),\
86 $(foreach a2,$(call _nth,$(1),2),\
87 $(foreach cond,$(call EVAL,$(a1),$(2)),\
88 $(if $(or $(call _EQ,$(__nil),$(cond)),$(call _EQ,$(__false),$(cond))),\
89 $(foreach a3,$(call _nth,$(1),3),$(call EVAL,$(a3),$(2))),\
90 $(call EVAL,$(a2),$(2)))))),\
91 $(if $(call _EQ,fn*,$($(a0)_value)),\
92 $(foreach a1,$(call _nth,$(1),1),\
93 $(foreach a2,$(call _nth,$(1),2),\
ea81a808 94 $(call _function,$$(call EVAL,$(a2),$$(call ENV,$(2),$(a1),$$1))))),\
31690700
JM
95 $(foreach el,$(call EVAL_AST,$(1),$(2)),\
96 $(and $(EVAL_DEBUG),$(info invoke: $(call _pr_str,$(el))))\
97 $(foreach f,$(call sfirst,$(el)),\
98 $(foreach args,$(call srest,$(el)),\
99 $(call apply,$(f),$(args))))))))))))))
100endef
101
102define EVAL
103$(strip $(if $(__ERROR),,\
104 $(and $(EVAL_DEBUG),$(info EVAL: $(call _pr_str,$(1))))\
105 $(if $(call _list?,$(1)),\
106 $(word 1,$(strip $(call EVAL_INVOKE,$(1),$(2)) $(__nil))),\
107 $(call EVAL_AST,$(1),$(2)))))
108endef
109
110
111# PRINT:
112define PRINT
113$(if $(__ERROR),Error: $(call _pr_str,$(__ERROR),yes),$(if $(1),$(call _pr_str,$(1),yes)))$(if $(__ERROR),$(eval __ERROR :=),)
114endef
115
116# REPL:
117REPL_ENV := $(call ENV)
118REP = $(call PRINT,$(strip $(call EVAL,$(strip $(call READ,$(1))),$(REPL_ENV))))
119REPL = $(info $(call REP,$(call READLINE,"user> ")))$(if $(READLINE_EOF),,$(call REPL))
120
8cb5cda4 121# core.mk: defined using Make
ea81a808 122_fref = $(eval REPL_ENV := $(call ENV_SET,$(REPL_ENV),$(1),$(call _function,$$(call $(2),$$1))))
ea81a808
JM
123_import_core = $(if $(strip $(1)),$(call _fref,$(word 1,$(1)),$(word 2,$(1)))$(call _import_core,$(wordlist 3,$(words $(1)),$(1))),)
124$(call _import_core,$(core_ns))
8cb5cda4 125REPL_ENV := $(call ENV_SET,$(REPL_ENV),eval,$(call _function,$$(call EVAL,$$(1),$$(REPL_ENV))))
31690700 126
8cb5cda4 127# core.mal: defined in terms of the language itself
31690700 128$(call do,$(call REP, (def! not (fn* (a) (if a false true))) ))
1617910a 129$(call do,$(call REP, (def! load-file (fn* (f) (eval (read-string (str "(do " (slurp f) ")"))))) ))
31690700
JM
130
131# Load and eval any files specified on the command line
132$(if $(MAKECMDGOALS),\
133 $(foreach file,$(MAKECMDGOALS),$(call do,$(call REP, (load-file "$(file)") )))\
134 $(eval INTERACTIVE :=),)
135.PHONY: none $(MAKECMDGOALS)
136none $(MAKECMDGOALS):
137 @true
138
139# Call the read-eval-print loop
140$(if $(strip $(INTERACTIVE)),$(call REPL))