forked from kanaka/mal
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcore.fs
246 lines (209 loc) · 6.26 KB
/
core.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
require env.fs
0 MalEnv. constant core
: args-as-native { argv argc -- entry*argc... }
argc 0 ?do
argv i cells + @ as-native
loop ;
: defcore* ( sym xt )
MalNativeFn. core env/set ;
: defcore
parse-allot-name MalSymbol. ( xt )
['] defcore* :noname ;
defcore + args-as-native + MalInt. ;;
defcore - args-as-native - MalInt. ;;
defcore * args-as-native * MalInt. ;;
defcore / args-as-native / MalInt. ;;
defcore < args-as-native < mal-bool ;;
defcore > args-as-native > mal-bool ;;
defcore <= args-as-native <= mal-bool ;;
defcore >= args-as-native >= mal-bool ;;
defcore list { argv argc }
argc cells allocate throw { start }
argv start argc cells cmove
start argc MalList. ;;
defcore vector { argv argc }
argc cells allocate throw { start }
argv start argc cells cmove
start argc MalList.
MalVector new swap over MalVector/list ! ;;
defcore empty? drop @ empty? ;;
defcore count drop @ mal-count ;;
defcore = drop dup @ swap cell+ @ swap m= mal-bool ;;
defcore not
drop @
dup mal-nil = if
drop mal-true
else
mal-false = if
mal-true
else
mal-false
endif
endif ;;
: pr-str-multi ( readably? argv argc )
?dup 0= if drop 0 0
else
{ argv argc }
new-str
argv @ pr-buf
argc 1 ?do
a-space
argv i cells + @ pr-buf
loop
endif ;
defcore prn true -rot pr-str-multi type cr drop mal-nil ;;
defcore pr-str true -rot pr-str-multi MalString. nip ;;
defcore println false -rot pr-str-multi type cr drop mal-nil ;;
defcore str ( argv argc )
dup 0= if
MalString.
else
{ argv argc }
false new-str
argc 0 ?do
argv i cells + @ pr-buf
loop
MalString. nip
endif ;;
defcore read-string drop @ unpack-str read-str ;;
defcore slurp drop @ unpack-str slurp-file MalString. ;;
defcore cons ( argv[item,coll] argc )
drop dup @ swap cell+ @ ( item coll )
to-list conj ;;
defcore concat { lists argc }
MalList new
lists over MalList/start !
argc over MalList/count !
MalList/concat ;;
defcore conj { argv argc }
argv @ ( coll )
argc 1 ?do
argv i cells + @ swap conj
loop ;;
defcore seq drop @ seq ;;
defcore assoc { argv argc }
argv @ ( coll )
argv argc cells + argv cell+ +do
i @ \ key
i cell+ @ \ val
rot assoc
2 cells +loop ;;
defcore keys ( argv argc )
drop @ MalMap/list @
dup MalList/start @ swap MalList/count @ { start count }
here
start count cells + start +do
i @ ,
2 cells +loop
here>MalList ;;
defcore vals ( argv argc )
drop @ MalMap/list @
dup MalList/start @ swap MalList/count @ { start count }
here
start count cells + start cell+ +do
i @ ,
2 cells +loop
here>MalList ;;
defcore dissoc { argv argc }
argv @ \ coll
argv argc cells + argv cell+ +do
i @ swap dissoc
cell +loop ;;
defcore hash-map { argv argc }
MalMap/Empty
argc cells argv + argv +do
i @ i cell+ @ rot assoc
2 cells +loop ;;
defcore get { argv argc }
argc 3 < if mal-nil else argv cell+ cell+ @ endif
argv cell+ @ \ key
argv @ \ coll
get ;;
defcore contains? { argv argc }
0
argv cell+ @ \ key
argv @ \ coll
get 0 <> mal-bool ;;
defcore nth ( argv[coll,i] argc )
drop dup @ to-list ( argv list )
swap cell+ @ MalInt/int @ ( list i )
over MalList/count @ ( list i count )
2dup >= if { i count }
0 0
new-str i int>str str-append s\" \040>= " count int>str
s" nth out of bounds: " ...throw-str
endif drop ( list i )
cells swap ( c-offset list )
MalList/start @ + @ ;;
defcore first ( argv[coll] argc )
drop @ to-list
dup MalList/count @ 0= if
drop mal-nil
else
MalList/start @ @
endif ;;
defcore rest ( argv[coll] argc )
drop @ to-list MalList/rest ;;
defcore meta ( argv[obj] argc )
drop @ mal-meta @
?dup 0= if mal-nil endif ;;
defcore with-meta ( argv[obj,meta] argc )
drop ( argv )
dup cell+ @ swap @ ( meta obj )
dup mal-type @ MalTypeType-struct @ ( meta obj obj-size )
dup allocate throw { new-obj } ( meta obj obj-size )
new-obj swap cmove ( meta )
new-obj mal-meta ! ( )
new-obj ;;
defcore atom ( argv[val] argc )
drop @ Atom. ;;
defcore deref ( argv[atom] argc )
drop @ Atom/val @ ;;
defcore reset! ( argv[atom,val] argc )
drop dup cell+ @ ( argv val )
dup -rot swap @ Atom/val ! ;;
defcore apply { argv argc -- val }
\ argv is (fn args... more-args)
argv argc 1- cells + @ to-list { more-args }
argc 2 - { list0len }
more-args MalList/count @ list0len + { final-argc }
final-argc cells allocate throw { final-argv }
argv cell+ final-argv list0len cells cmove
more-args MalList/start @ final-argv list0len cells + final-argc list0len - cells cmove
final-argv final-argc argv @ invoke ;;
defcore throw ( argv argc -- )
drop @ to exception-object
1 throw ;;
defcore map? drop @ mal-type @ MalMap = mal-bool ;;
defcore list? drop @ mal-type @ MalList = mal-bool ;;
defcore vector? drop @ mal-type @ MalVector = mal-bool ;;
defcore keyword? drop @ mal-type @ MalKeyword = mal-bool ;;
defcore symbol? drop @ mal-type @ MalSymbol = mal-bool ;;
defcore string? drop @ mal-type @ MalString = mal-bool ;;
defcore atom? drop @ mal-type @ Atom = mal-bool ;;
defcore true? drop @ mal-true = mal-bool ;;
defcore false? drop @ mal-false = mal-bool ;;
defcore nil? drop @ mal-nil = mal-bool ;;
defcore number? drop @ mal-type @ MalInt = mal-bool ;;
defcore fn?
drop @
dup mal-type @ MalUserFn = if
MalUserFn/is-macro? @ if
mal-false
else
mal-true
endif
else
mal-type @ MalNativeFn = if
mal-true
else
mal-false
endif
endif ;;
defcore macro? drop @ dup mal-type @ MalUserFn =
swap MalUserFn/is-macro? @
and mal-bool ;;
defcore sequential? drop @ sequential? ;;
defcore keyword drop @ unpack-str MalKeyword. ;;
defcore symbol drop @ unpack-str MalSymbol. ;;
defcore time-ms 2drop utime d>s 1000 / MalInt. ;;