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
24 $(foreach var
,$(call _nth
,$(1),0),\
25 $(foreach val
,$(call _nth
,$(1),1),\
26 $(call ENV_SET
,$(2),$($(var
)_value
),$(call EVAL
,$(val
),$(2)))\
27 $(foreach left
,$(call srest
,$(call srest
,$(1))),
28 $(if
$(call _EQ
,0,$(call _count
,$(left
))),\
30 $(call LET
,$(left
),$(2))))))))
35 $(and
$(EVAL_DEBUG
),$(info EVAL_AST
: $(call _pr_str
,$(1))))\
36 $(if
$(call _symbol?
,$(1)),\
37 $(foreach key
,$($(1)_value
),\
38 $(call ENV_GET
,$(2),$(key
))),\
39 $(if
$(call _list?
,$(1)),\
40 $(call _smap
,EVAL
,$(1),$(2)),\
41 $(if
$(call _vector?
,$(1)),\
42 $(call _smap_vec
,EVAL
,$(1),$(2)),\
43 $(if
$(call _hash_map?
,$(1)),\
44 $(foreach new_hmap
,$(call __new_obj
,hmap
),\
45 $(foreach v
,$(call __get_obj_values
,$(1)),\
46 $(eval
$(v
:$(1)_
%=$(new_hmap
)_
%) := $(call EVAL
,$($(v
)),$(2))))\
47 $(eval
$(new_hmap
)_size
:= $($(1)_size
))\
54 $(and
$(EVAL_DEBUG
),$(info EVAL_INVOKE
: $(call _pr_str
,$(1))))
55 $(foreach a0
,$(call _nth
,$(1),0),\
56 $(if
$(call _EQ
,def
!,$($(a0
)_value
)),\
57 $(foreach a1
,$(call _nth
,$(1),1),\
58 $(foreach a2
,$(call _nth
,$(1),2),\
59 $(foreach res
,$(call EVAL
,$(a2
),$(2)),\
61 $(if
$(call ENV_SET
,$(2),$($(a1
)_value
),$(res
)),$(res
),))))),\
62 $(if
$(call _EQ
,let
*,$($(a0
)_value
)),\
63 $(foreach a1
,$(call _nth
,$(1),1),\
64 $(foreach a2
,$(call _nth
,$(1),2),\
65 $(call EVAL
,$(a2
),$(call LET
,$(a1
),$(call ENV
,$(2)))))),\
66 $(if
$(call _EQ
,do
,$($(a0
)_value
)),\
67 $(call slast
,$(call EVAL_AST
,$(call srest
,$(1)),$(2))),\
68 $(if
$(call _EQ
,if
,$($(a0
)_value
)),\
69 $(foreach a1
,$(call _nth
,$(1),1),\
70 $(foreach a2
,$(call _nth
,$(1),2),\
71 $(foreach cond
,$(call EVAL
,$(a1
),$(2)),\
72 $(if
$(or
$(call _EQ
,$(__nil
),$(cond
)),$(call _EQ
,$(__false
),$(cond
))),\
73 $(foreach a3
,$(call _nth
,$(1),3),$(call EVAL
,$(a3
),$(2))),\
74 $(call EVAL
,$(a2
),$(2)))))),\
75 $(if
$(call _EQ
,fn
*,$($(a0
)_value
)),\
76 $(foreach a1
,$(call _nth
,$(1),1),\
77 $(foreach a2
,$(call _nth
,$(1),2),\
78 $(call _function
,$$(call EVAL
,$(a2
),$$(call ENV
,$(2),$(a1
),$$1))))),\
79 $(foreach el
,$(call EVAL_AST
,$(1),$(2)),\
80 $(and
$(EVAL_DEBUG
),$(info invoke
: $(call _pr_str
,$(el
))))\
81 $(foreach f
,$(call sfirst
,$(el
)),\
82 $(foreach args
,$(call srest
,$(el
)),\
83 $(call apply
,$(f
),$(args
))))))))))))
87 $(strip $(if
$(__ERROR
),,\
88 $(and
$(EVAL_DEBUG
),$(info EVAL
: $(call _pr_str
,$(1))))\
89 $(if
$(call _list?
,$(1)),\
90 $(word 1,$(strip $(call EVAL_INVOKE
,$(1),$(2)) $(__nil
))),\
91 $(call EVAL_AST
,$(1),$(2)))))
97 $(if
$(__ERROR
),Error
: $(call _pr_str
,$(__ERROR
),yes
),$(if
$(1),$(call _pr_str
,$(1),yes
)))$(if
$(__ERROR
),$(eval __ERROR
:=),)
101 REPL_ENV
:= $(call ENV
)
102 REP
= $(call PRINT
,$(strip $(call EVAL
,$(strip $(call READ
,$(1))),$(REPL_ENV
))))
103 REPL
= $(info $(call REP
,$(call READLINE
,"user> ")))$(if
$(READLINE_EOF
),,$(call REPL
))
105 # core.mk: defined using Make
106 _fref
= $(eval REPL_ENV
:= $(call ENV_SET
,$(REPL_ENV
),$(1),$(call _function
,$$(call
$(2),$$1))))
107 _import_core
= $(if
$(strip $(1)),$(call _fref
,$(word 1,$(1)),$(word 2,$(1)))$(call _import_core
,$(wordlist
3,$(words $(1)),$(1))),)
108 $(call _import_core
,$(core_ns
))
109 REPL_ENV
:= $(call ENV_SET
,$(REPL_ENV
),eval
,$(call _function
,$$(call EVAL
,$$(1),$$(REPL_ENV
))))
110 _argv
:= $(call _list
)
111 REPL_ENV
:= $(call ENV_SET
,$(REPL_ENV
),*ARGV
*,$(_argv
))
113 # core.mal: defined in terms of the language itself
114 $(call do
,$(call REP
, (def
! not
(fn
* (a
) (if a false true
))) ))
115 $(call do
,$(call REP
, (def
! load-file
(fn
* (f
) (eval
(read-string
(str
"(do " (slurp f
) ")"))))) ))
117 # Load and eval any files specified on the command line
118 $(if
$(MAKECMDGOALS
),\
119 $(foreach arg
,$(wordlist
2,$(words $(MAKECMDGOALS
)),$(MAKECMDGOALS
)),\
120 $(call do
,$(call _conj
!,$(_argv
),$(call _string
,$(arg
)))))\
121 $(call do
,$(call REP
, (load-file
"$(word 1,$(MAKECMDGOALS))") )) \
122 $(eval INTERACTIVE
:=),)
125 $(if
$(strip $(INTERACTIVE
)),$(call REPL
))
127 .PHONY
: none
$(MAKECMDGOALS
)
128 none
$(MAKECMDGOALS
):