4 _TOP_DIR
:= $(dir $(lastword
$(MAKEFILE_LIST
)))
5 include $(_TOP_DIR
)types.mk
6 include $(_TOP_DIR
)reader.mk
7 include $(_TOP_DIR
)printer.mk
8 include $(_TOP_DIR
)env.mk
9 include $(_TOP_DIR
)core.mk
15 # READ: read and parse input
17 $(if
$(READLINE_EOF
)$(__ERROR
),,$(call READ_STR
,$(if
$(1),$(1),$(call READLINE
,"user> "))))
20 # EVAL: evaluate the parameter
21 IS_PAIR
= $(if
$(call _sequential?
,$(1)),$(if
$(call _EQ
,0,$(call _count
,$(1))),,true
),)
25 $(if
$(call _NOT
,$(call IS_PAIR
,$(1))),\
26 $(call _list
,$(call _symbol
,quote
) $(1)),\
27 $(if
$(call _EQ
,unquote
,$($(call _nth
,$(1),0)_value
)),\
29 $(if
$(and
$(call IS_PAIR
,$(call _nth
,$(1),0)),$(call _EQ
,splice-unquote
,$($(call _nth
,$(call _nth
,$(1),0),0)_value
))),\
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))))))))
35 $(if
$(call _list?
,$(1)),$(if
$(call ENV_FIND
,$(2),$($(call _nth
,$(1),0)_value
)),$(_macro_
$(call ENV_GET
,$(2),$($(call _nth
,$(1),0)_value
))),),)
39 $(strip $(if
$(__ERROR
),,\
40 $(if
$(call IS_MACRO_CALL
,$(1),$(2)),\
41 $(foreach mac
,$(call ENV_GET
,$(2),$($(call _nth
,$(1),0)_value
)),\
42 $(call MACROEXPAND
,$(call apply
,$(mac
),$(call srest
,$(1))),$(2))),\
49 $(foreach var
,$(call _nth
,$(1),0),\
50 $(foreach val
,$(call _nth
,$(1),1),\
51 $(call ENV_SET
,$(2),$($(var
)_value
),$(call EVAL
,$(val
),$(2)))\
52 $(foreach left
,$(call srest
,$(call srest
,$(1))),
53 $(if
$(call _EQ
,0,$(call _count
,$(left
))),\
55 $(call LET
,$(left
),$(2))))))))
60 $(and
$(EVAL_DEBUG
),$(info EVAL_AST
: $(call _pr_str
,$(1))))\
61 $(if
$(call _symbol?
,$(1)),\
62 $(foreach key
,$($(1)_value
),\
63 $(call ENV_GET
,$(2),$(key
))),\
64 $(if
$(call _list?
,$(1)),\
65 $(call _smap
,EVAL
,$(1),$(2)),\
66 $(if
$(call _vector?
,$(1)),\
67 $(call _smap_vec
,EVAL
,$(1),$(2)),\
68 $(if
$(call _hash_map?
,$(1)),\
69 $(foreach new_hmap
,$(call __new_obj
,hmap
),\
70 $(foreach v
,$(call __get_obj_values
,$(1)),\
71 $(eval
$(v
:$(1)_
%=$(new_hmap
)_
%) := $(call EVAL
,$($(v
)),$(2))))\
72 $(eval
$(new_hmap
)_size
:= $($(1)_size
))\
79 $(and
$(EVAL_DEBUG
),$(info EVAL_INVOKE
: $(call _pr_str
,$(1))))
80 $(foreach a0
,$(call _nth
,$(1),0),\
81 $(if
$(call _EQ
,def
!,$($(a0
)_value
)),\
82 $(foreach a1
,$(call _nth
,$(1),1),\
83 $(foreach a2
,$(call _nth
,$(1),2),\
84 $(foreach res
,$(call EVAL
,$(a2
),$(2)),\
86 $(if
$(call ENV_SET
,$(2),$($(a1
)_value
),$(res
)),$(res
),))))),\
87 $(if
$(call _EQ
,let
*,$($(a0
)_value
)),\
88 $(foreach a1
,$(call _nth
,$(1),1),\
89 $(foreach a2
,$(call _nth
,$(1),2),\
90 $(call EVAL
,$(a2
),$(call LET
,$(a1
),$(call ENV
,$(2)))))),\
91 $(if
$(call _EQ
,quote
,$($(a0
)_value
)),\
93 $(if
$(call _EQ
,quasiquote
,$($(a0
)_value
)),\
94 $(call EVAL
,$(call QUASIQUOTE
,$(call _nth
,$(1),1)),$(2)),\
95 $(if
$(call _EQ
,defmacro
!,$($(a0
)_value
)),\
96 $(foreach a1
,$(call _nth
,$(1),1),\
97 $(foreach a2
,$(call _nth
,$(1),2),\
98 $(foreach res
,$(call EVAL
,$(a2
),$(2)),\
99 $(eval _macro_
$(res
) = true
)\
100 $(if
$(call ENV_SET
,$(2),$($(a1
)_value
),$(res
)),$(res
),)))),\
101 $(if
$(call _EQ
,macroexpand
,$($(a0
)_value
)),\
102 $(call MACROEXPAND
,$(call _nth
,$(1),1),$(2)),\
103 $(if
$(call _EQ
,try
*,$($(a0
)_value
)),\
104 $(foreach a1
,$(call _nth
,$(1),1),\
105 $(foreach res
,$(call EVAL
,$(a1
),$(2)),\
107 $(foreach a2
,$(call _nth
,$(1),2),\
108 $(foreach a20
,$(call _nth
,$(a2
),0),\
109 $(if
$(call _EQ
,catch
*,$($(a20
)_value
)),\
110 $(foreach a21
,$(call _nth
,$(a2
),1),\
111 $(foreach a22
,$(call _nth
,$(a2
),2),\
112 $(foreach binds
,$(call _list
,$(a21
)),\
113 $(foreach catch_env
,$(call ENV
,$(2),$(binds
),$(__ERROR
)),\
115 $(call EVAL
,$(a22
),$(catch_env
)))))),\
118 $(if
$(call _EQ
,do
,$($(a0
)_value
)),\
119 $(call slast
,$(call EVAL_AST
,$(call srest
,$(1)),$(2))),\
120 $(if
$(call _EQ
,if
,$($(a0
)_value
)),\
121 $(foreach a1
,$(call _nth
,$(1),1),\
122 $(foreach a2
,$(call _nth
,$(1),2),\
123 $(foreach cond
,$(call EVAL
,$(a1
),$(2)),\
124 $(if
$(or
$(call _EQ
,$(__nil
),$(cond
)),$(call _EQ
,$(__false
),$(cond
))),\
125 $(foreach a3
,$(call _nth
,$(1),3),$(call EVAL
,$(a3
),$(2))),\
126 $(call EVAL
,$(a2
),$(2)))))),\
127 $(if
$(call _EQ
,fn
*,$($(a0
)_value
)),\
128 $(foreach a1
,$(call _nth
,$(1),1),\
129 $(foreach a2
,$(call _nth
,$(1),2),\
130 $(call _function
,$$(call EVAL
,$(a2
),$$(call ENV
,$(2),$(a1
),$$1))))),\
131 $(foreach el
,$(call EVAL_AST
,$(1),$(2)),\
132 $(and
$(EVAL_DEBUG
),$(info invoke
: $(call _pr_str
,$(el
))))\
133 $(foreach f
,$(call sfirst
,$(el
)),\
134 $(foreach args
,$(call srest
,$(el
)),\
135 $(call apply
,$(f
),$(args
)))))))))))))))))
139 $(strip $(if
$(__ERROR
),,\
140 $(and
$(EVAL_DEBUG
),$(info EVAL
: $(call _pr_str
,$(1))))\
141 $(if
$(call _list?
,$(1)),\
142 $(foreach ast
,$(call MACROEXPAND
,$(1),$(2)),
143 $(if
$(call _list?
,$(ast
)),\
144 $(if
$(call _EQ
,0,$(call _count
,$(ast
))),\
146 $(word 1,$(strip $(call EVAL_INVOKE
,$(ast
),$(2)) $(__nil
)))),\
147 $(call EVAL_AST
,$(ast
),$(2)))),\
148 $(call EVAL_AST
,$(1),$(2)))))
154 $(if
$(__ERROR
),Error
: $(call _pr_str
,$(__ERROR
),yes
),$(if
$(1),$(call _pr_str
,$(1),yes
)))$(if
$(__ERROR
),$(eval __ERROR
:=),)
158 REPL_ENV
:= $(call ENV
)
159 REP
= $(call PRINT
,$(strip $(call EVAL
,$(strip $(call READ
,$(1))),$(REPL_ENV
))))
160 REPL
= $(info $(call REP
,$(call READLINE
,"user> ")))$(if
$(READLINE_EOF
),,$(call REPL
))
162 # core.mk: defined using Make
163 _fref
= $(eval REPL_ENV
:= $(call ENV_SET
,$(REPL_ENV
),$(1),$(call _function
,$$(call
$(2),$$1))))
164 _import_core
= $(if
$(strip $(1)),$(call _fref
,$(word 1,$(1)),$(word 2,$(1)))$(call _import_core
,$(wordlist
3,$(words $(1)),$(1))),)
165 $(call _import_core
,$(core_ns
))
166 REPL_ENV
:= $(call ENV_SET
,$(REPL_ENV
),eval
,$(call _function
,$$(call EVAL
,$$(1),$$(REPL_ENV
))))
167 _argv
:= $(call _list
)
168 REPL_ENV
:= $(call ENV_SET
,$(REPL_ENV
),*ARGV
*,$(_argv
))
170 # core.mal: defined in terms of the language itself
171 $(call do
,$(call REP
, (def
! not
(fn
* (a
) (if a false true
))) ))
172 $(call do
,$(call REP
, (def
! load-file
(fn
* (f
) (eval
(read-string
(str
"(do " (slurp f
) "\nnil)"))))) ))
173 $(call do
,$(call REP
, (defmacro
! cond
(fn
* (& xs
) (if
(> (count xs
) 0) (list
'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw "odd number of forms to cond")) (cons 'cond
(rest
(rest xs
))))))) ))
175 # Load and eval any files specified on the command line
176 $(if
$(MAKECMDGOALS
),\
177 $(foreach arg
,$(wordlist
2,$(words $(MAKECMDGOALS
)),$(MAKECMDGOALS
)),\
178 $(call do
,$(call _conj
!,$(_argv
),$(call _string
,$(arg
)))))\
179 $(call do
,$(call REP
, (load-file
"$(word 1,$(MAKECMDGOALS))") )) \
180 $(eval INTERACTIVE
:=),)
183 $(if
$(strip $(INTERACTIVE
)),$(call REPL
))
185 .PHONY
: none
$(MAKECMDGOALS
)
186 none
$(MAKECMDGOALS
):