1 set_path
, get_env
("YORICK_MAL_PATH") + ":" + get_path
()
15 return
((type
== MalList
) ||
(type
== MalVector
)) && count(ast) > 0
20 if
(!is_pair
(ast
)) return MalList
(val
=&[&MalSymbol(val="quote"), &ast])
23 if
(structof
(ast1
) == MalSymbol
&& ast1.val == "unquote") return *lst(2)
25 ast11
= *((*ast1.val
)(1))
26 if
(structof
(ast11
) == MalSymbol
&& ast11.val == "splice-unquote") {
27 return MalList
(val
=&[&MalSymbol(val="concat"), (*ast1.val)(2), &quasiquote(rest(ast))])
30 return MalList
(val
=&[&MalSymbol(val="cons"), &quasiquote(ast1), &quasiquote(rest(ast))])
33 func eval_ast
(ast
, env
)
36 if
(type
== MalSymbol
) {
37 return env_get
(env
, ast.val
)
38 } else if
(type
== MalList
) {
40 if
(numberof
(seq
) == 0) return ast
41 res
= array
(pointer
, numberof
(seq
))
42 for
(i
= 1; i
<= numberof
(seq
); ++i
) {
43 e
= EVAL
(*seq
(i
), env
)
44 if
(structof
(e
) == MalError
) return e
47 return MalList
(val
=&res)
48 } else if
(type
== MalVector
) {
50 if
(numberof
(seq
) == 0) return ast
51 res
= array
(pointer
, numberof
(seq
))
52 for
(i
= 1; i
<= numberof
(seq
); ++i
) {
53 e
= EVAL
(*seq
(i
), env
)
54 if
(structof
(e
) == MalError
) return e
57 return MalVector
(val
=&res)
58 } else if
(type
== MalHashmap
) {
60 if
(numberof
(*h.keys
) == 0) return ast
62 for
(i
= 1; i
<= numberof
(*h.keys
); ++i
) {
63 new_key
= EVAL
(hashmap_key_to_obj
((*h.keys
)(i
)), env
)
64 if
(structof
(new_key
) == MalError
) return new_key
65 new_val
= EVAL
(*((*h.vals
)(i
)), env
)
66 if
(structof
(new_val
) == MalError
) return new_val
67 hash_set
, res
, hashmap_obj_to_key
(new_key
), new_val
69 return MalHashmap
(val
=&res)
76 if
(structof
(ast
) == MalError
) return ast
77 if
(structof
(ast
) != MalList
) return eval_ast
(ast
, env
)
79 if
(numberof
(lst
) == 0) return ast
82 new_value
= EVAL
(*lst
(3), env
)
83 if
(structof
(new_value
) == MalError
) return new_value
84 return env_set
(env
, lst
(2)->val
, new_value
)
85 } else if
(a1
== "let*") {
86 let_env
= env_new
(&env)
87 args_lst
= *(lst
(2)->val
)
88 for
(i
= 1; i
<= numberof
(args_lst
); i
+= 2) {
89 var_name
= args_lst
(i
)->val
90 var_value
= EVAL
(*args_lst
(i
+ 1), let_env
)
91 if
(structof
(var_value
) == MalError
) return var_value
92 env_set
, let_env
, var_name
, var_value
97 } else if
(a1
== "quote") {
99 } else if
(a1
== "quasiquote") {
100 ast
= quasiquote
(*lst
(2)) // TCO
101 } else if
(a1
== "do") {
102 for
(i
= 2; i
< numberof
(lst
); ++i
) {
103 ret
= EVAL
(*lst
(i
), env
)
104 if
(structof
(ret
) == MalError
) return ret
106 ast
= *lst
(numberof
(lst
))
108 } else if
(a1
== "if") {
109 cond_val
= EVAL
(*lst
(2), env
)
110 if
(structof
(cond_val
) == MalError
) return cond_val
111 if
((structof
(cond_val
) == MalNil
) ||
(structof
(cond_val
) == MalFalse
)) {
112 if
(numberof
(lst
) > 3) {
121 } else if
(a1
== "fn*") {
122 return MalFunction
(env
=&env, binds=lst(2)->val, ast=lst(3))
124 el
= eval_ast
(ast
, env
)
125 if
(structof
(el
) == MalError
) return el
127 if
(structof
(*seq
(1)) == MalNativeFunction
) {
128 args
= (numberof
(seq
) > 1) ? seq
(2:) : []
129 return call_core_fn
(seq
(1)->val
, args
)
130 } else if
(structof
(*seq
(1)) == MalFunction
) {
132 exprs
= numberof
(seq
) > 1 ? seq
(2:) : []
133 fn_env
= env_new
(fn.env
, binds
=*fn.binds
, exprs
=exprs
)
138 return MalError
(message
="Unknown function type")
146 if
(structof
(exp
) == MalError
) return exp
147 return pr_str
(exp
, 1)
152 return EVAL
(READ(str
), env
)
157 return PRINT
(EVAL
(READ(str
), env
))
160 func get_command_line
(void
)
161 // Force quiet mode
(-q
) to prevent Yorick from printing its banner
164 return numberof
(argv
) > 1 ? grow
([argv
(1), "-q"], argv
(2:)) : [argv
(1), "-q"]
167 func prepare_argv_list
(args
)
169 if
(numberof
(args
) <= 1) return MalList
(val
=&[])
170 str_lst
= array
(pointer
, numberof
(args
) - 1)
171 for
(i
= 2; i
<= numberof
(args
); ++i
) {
172 str_lst
(i
- 1) = &MalString(val=args(i))
174 return MalList
(val
=&str_lst)
182 repl_env
= env_new
(pointer
(0))
184 // core.i
: defined using Yorick
185 core_symbols
= h_keys
(core_ns
)
186 for
(i
= 1; i
<= numberof
(core_symbols
); ++i
) {
187 env_set
, repl_env
, core_symbols
(i
), MalNativeFunction
(val
=core_symbols
(i
))
189 command_line_args
= process_argv
()
190 env_set
, repl_env
, "*ARGV*", prepare_argv_list
(command_line_args
)
192 // core.mal
: defined using the language itself
193 RE
, "(def! not (fn* (a) (if a false true)))", repl_env
194 RE
, "(def! load-file (fn* (f) (eval (read-string (str \"(do \
" (slurp f) \")\
")))))", repl_env
196 if
(numberof
(command_line_args
) > 0) {
197 RE
, "(load-file \"" + command_line_args(1) + "\
")", repl_env
201 stdin_file
= open
("/dev/stdin", "r")
203 write
, format
="%s", "user> "
204 line
= rdline
(stdin_file
, prompt
="")
206 if
(strlen
(line
) > 0) {
207 result
= REP
(line
, repl_env
)
208 if
(structof
(result
) == MalError
) write
, format
="Error: %s\n", result.message
209 else write
, format
="%s\n", result