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))))))))
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
))),\
43 $(call LET
,$(left
),$(2))))))))
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
))\
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)),\
74 $(if
$(call ENV_SET
,$(2),$($(a1
)_value
),$(res
)),$(res
),))))),\
75 $(if
$(call _EQ
,let
*,$($(a0
)_value
)),\
76 $(foreach a1
,$(call _nth
,$(1),1),\
77 $(foreach a2
,$(call _nth
,$(1),2),\
78 $(call EVAL
,$(a2
),$(call LET
,$(a1
),$(call ENV
,$(2)))))),\
79 $(if
$(call _EQ
,quote
,$($(a0
)_value
)),\
81 $(if
$(call _EQ
,quasiquote
,$($(a0
)_value
)),\
82 $(call EVAL
,$(call QUASIQUOTE
,$(call _nth
,$(1),1)),$(2)),\
83 $(if
$(call _EQ
,do
,$($(a0
)_value
)),\
84 $(call slast
,$(call EVAL_AST
,$(call srest
,$(1)),$(2))),\
85 $(if
$(call _EQ
,if
,$($(a0
)_value
)),\
86 $(foreach a1
,$(call _nth
,$(1),1),\
87 $(foreach a2
,$(call _nth
,$(1),2),\
88 $(foreach cond
,$(call EVAL
,$(a1
),$(2)),\
89 $(if
$(or
$(call _EQ
,$(__nil
),$(cond
)),$(call _EQ
,$(__false
),$(cond
))),\
90 $(foreach a3
,$(call _nth
,$(1),3),$(call EVAL
,$(a3
),$(2))),\
91 $(call EVAL
,$(a2
),$(2)))))),\
92 $(if
$(call _EQ
,fn
*,$($(a0
)_value
)),\
93 $(foreach a1
,$(call _nth
,$(1),1),\
94 $(foreach a2
,$(call _nth
,$(1),2),\
95 $(call _function
,$$(call EVAL
,$(a2
),$$(call ENV
,$(2),$(a1
),$$1))))),\
96 $(foreach el
,$(call EVAL_AST
,$(1),$(2)),\
97 $(and
$(EVAL_DEBUG
),$(info invoke
: $(call _pr_str
,$(el
))))\
98 $(foreach f
,$(call sfirst
,$(el
)),\
99 $(foreach args
,$(call srest
,$(el
)),\
100 $(call apply
,$(f
),$(args
))))))))))))))
104 $(strip $(if
$(__ERROR
),,\
105 $(and
$(EVAL_DEBUG
),$(info EVAL
: $(call _pr_str
,$(1))))\
106 $(if
$(call _list?
,$(1)),\
107 $(if
$(call _EQ
,0,$(call _count
,$(1))),\
109 $(word 1,$(strip $(call EVAL_INVOKE
,$(1),$(2)) $(__nil
)))),\
110 $(call EVAL_AST
,$(1),$(2)))))
116 $(if
$(__ERROR
),Error
: $(call _pr_str
,$(__ERROR
),yes
),$(if
$(1),$(call _pr_str
,$(1),yes
)))$(if
$(__ERROR
),$(eval __ERROR
:=),)
120 REPL_ENV
:= $(call ENV
)
121 REP
= $(call PRINT
,$(strip $(call EVAL
,$(strip $(call READ
,$(1))),$(REPL_ENV
))))
122 REPL
= $(info $(call REP
,$(call READLINE
,"user> ")))$(if
$(READLINE_EOF
),,$(call REPL
))
124 # core.mk: defined using Make
125 _fref
= $(eval REPL_ENV
:= $(call ENV_SET
,$(REPL_ENV
),$(1),$(call _function
,$$(call
$(2),$$1))))
126 _import_core
= $(if
$(strip $(1)),$(call _fref
,$(word 1,$(1)),$(word 2,$(1)))$(call _import_core
,$(wordlist
3,$(words $(1)),$(1))),)
127 $(call _import_core
,$(core_ns
))
128 REPL_ENV
:= $(call ENV_SET
,$(REPL_ENV
),eval
,$(call _function
,$$(call EVAL
,$$(1),$$(REPL_ENV
))))
129 _argv
:= $(call _list
)
130 REPL_ENV
:= $(call ENV_SET
,$(REPL_ENV
),*ARGV
*,$(_argv
))
132 # core.mal: defined in terms of the language itself
133 $(call do
,$(call REP
, (def
! not
(fn
* (a
) (if a false true
))) ))
134 $(call do
,$(call REP
, (def
! load-file
(fn
* (f
) (eval
(read-string
(str
"(do " (slurp f
) "\nnil)"))))) ))
136 # Load and eval any files specified on the command line
137 $(if
$(MAKECMDGOALS
),\
138 $(foreach arg
,$(wordlist
2,$(words $(MAKECMDGOALS
)),$(MAKECMDGOALS
)),\
139 $(call do
,$(call _conj
!,$(_argv
),$(call _string
,$(arg
)))))\
140 $(call do
,$(call REP
, (load-file
"$(word 1,$(MAKECMDGOALS))") )) \
141 $(eval INTERACTIVE
:=),)
144 $(if
$(strip $(INTERACTIVE
)),$(call REPL
))
146 .PHONY
: none
$(MAKECMDGOALS
)
147 none
$(MAKECMDGOALS
):