1use crate::{
2 context::{
3 self,
4 Context,
5 },
6 data::{
7 functions::{
8 Functions,
9 Scope,
10 },
11 types as t,
12 value::{
13 self,
14 Compute as _,
15 Value as _,
16 },
17 },
18 function::Function,
19};
20
21
22pub type Result = std::result::Result<(), context::Error>;
23
24
25macro_rules! builtins {
26 ($($name:expr, $fn:ident, ($($arg:expr,)*);)*) => {
27 pub fn builtins<Host>(functions: &mut Functions<Function<Host>>) {
28 let scope = functions.root_scope();
29
30 functions
31 $(
32 .define(
33 scope,
34 String::from($name),
35 &[$(&$arg,)*],
36 Function::Builtin($fn),
37 )
38 .expect("Failed to define builtin")
39 )*;
40 }
41 }
42}
43
44builtins!(
45 "print", print, (t::Any,);
46 "define", define, (t::List, t::Symbol,);
47 "define", define_s, (t::List, t::Symbol, t::Scope,);
48 "caller", caller, ();
49 "fail", fail, ();
50 "eval", eval, (t::List,);
51 "load", load, (t::String,);
52 "to_list", to_list, (t::Symbol,);
53
54 "drop", drop, (t::Any,);
55 "clone", clone, (t::Any,);
56 "swap", swap, (t::Any, t::Any,);
57 "dig", dig, (t::Any, t::List,);
58
59 "if", r#if, (t::List, t::List,);
60
61 "map", map, (t::List, t::List,);
62 "wrap", wrap, (t::Any,);
63 "unwrap", unwrap, (t::List,);
64 "prepend", prepend, (t::List, t::Any,);
65 "append", append, (t::List, t::Any,);
66
67 "+", add_n, (t::Number, t::Number,);
68 "*", mul_n, (t::Number, t::Number,);
69 "/", div_n, (t::Number, t::Number,);
70 ">", gt_n, (t::Number, t::Number,);
71
72 "+", add_f, (t::Float, t::Float,);
73 "*", mul_f, (t::Float, t::Float,);
74 ">", gt_f, (t::Float, t::Float,);
75
76 "=", eq, (t::Any, t::Any,);
77 "not", not, (t::Bool,);
78);
79
80
81fn print<Host>(
82 _: &mut Host,
83 context: &mut dyn Context<Host>,
84 _: Scope,
85)
86 -> Result
87{
88 let expression = context.stack().pop(&t::Any);
89 write!(context.output(), "{}", expression.kind)?;
90
91 Ok(())
92}
93
94fn define<Host>(
95 _: &mut Host,
96 context: &mut dyn Context<Host>,
97 scope: Scope,
98)
99 -> Result
100{
101 let (body, name) = context.stack()
102 .pop((&t::List, &t::Symbol));
103
104 context.functions().define(
105 scope,
106 name.inner,
107 &[],
108 Function::UserDefined { body },
109 )?;
110
111 Ok(())
112}
113
114fn define_s<Host>(
115 _: &mut Host,
116 context: &mut dyn Context<Host>,
117 _: Scope,
118)
119 -> Result
120{
121 let (body, name, scope) = context.stack()
122 .pop((&t::List, &t::Symbol, &t::Scope));
123
124 context.functions().define(
125 scope.inner,
126 name.inner,
127 &[],
128 Function::UserDefined { body },
129 )?;
130
131 Ok(())
132}
133
134fn caller<Host>(
135 _: &mut Host,
136 context: &mut dyn Context<Host>,
137 _: Scope,
138)
139 -> Result
140{
141 let caller = match context.call_stack().caller() {
142 Some(caller) => caller.clone(),
143 None => return Err(context::Error::Caller),
144 };
145
146 context.stack().push(value::Scope::new(caller.scope, caller.span));
147
148 Ok(())
149}
150
151fn fail<Host>(
152 _: &mut Host,
153 _: &mut dyn Context<Host>,
154 _: Scope,
155)
156 -> Result
157{
158 Err(context::Error::Failure)
159}
160
161fn eval<Host>(
162 host: &mut Host,
163 context: &mut dyn Context<Host>,
164 scope: Scope,
165)
166 -> Result
167{
168 let list = context.stack().pop(&t::List);
169 let span = context.call_stack().operator().clone().span.merge(&list.span);
170
171 context.stack().create_substack();
172
173 context.evaluate_list(
174 host,
175 list,
176 )?;
177
178 let items = context.stack().destroy_substack();
179
180 let list = value::List::new(
181 value::ListInner::from_values(
182 items,
183 context.functions().new_scope(scope, "list"),
184 ),
185 span,
186 );
187 context.stack().push(list);
188
189 Ok(())
190}
191
192fn load<Host>(
193 _: &mut Host,
194 context: &mut dyn Context<Host>,
195 scope: Scope,
196)
197 -> Result
198{
199 let path = context.stack().pop(&t::String);
200
201 let list = context.load(path, scope)?;
202 context.stack().push(list);
203 Ok(())
204}
205
206fn to_list<Host>(
207 _: &mut Host,
208 context: &mut dyn Context<Host>,
209 scope: Scope,
210)
211 -> Result
212{
213 let symbol = context.stack().pop(&t::Symbol);
214
215 let (word, span) = symbol.open();
216 let list_span = context.call_stack().operator().span.clone().merge(&span);
217 let word = value::Any::new(value::Kind::Word(word), span);
218
219 let list = value::List::new(
220 value::ListInner::from_values(
221 vec![word],
222 context.functions().new_scope(scope, "list"),
223 ),
224 list_span,
225 );
226 context.stack().push(list);
227
228 Ok(())
229}
230
231
232fn drop<Host>(
233 _: &mut Host,
234 context: &mut dyn Context<Host>,
235 _: Scope,
236)
237 -> Result
238{
239 context.stack().pop(&t::Any);
240 Ok(())
241}
242
243fn clone<Host>(
244 _: &mut Host,
245 context: &mut dyn Context<Host>,
246 _: Scope,
247)
248 -> Result
249{
250 let mut expression = context.stack().pop(&t::Any);
251
252 expression.span = context.call_stack().operator().span.clone().merge(&expression.span);
253
254 context.stack().push((expression.clone(), expression));
255
256 Ok(())
257}
258
259fn swap<Host>(
260 _: &mut Host,
261 context: &mut dyn Context<Host>,
262 _: Scope,
263)
264 -> Result
265{
266 let (a, b) = context.stack().pop((&t::Any, &t::Any));
267 context.stack().push((b, a));
268
269 Ok(())
270}
271
272fn dig<Host>(
273 host: &mut Host,
274 context: &mut dyn Context<Host>,
275 _: Scope,
276)
277 -> Result
278{
279 let (item, f) = context.stack().pop((&t::Any, &t::List));
280 context.evaluate_list(host, f)?;
281 context.stack().push(item);
282 Ok(())
283}
284
285
286fn r#if<Host>(
287 host: &mut Host,
288 context: &mut dyn Context<Host>,
289 _: Scope,
290)
291 -> Result
292{
293 let (function, condition) =context.stack()
294 .pop((&t::List, &t::List));
295
296 context.evaluate_list(host, condition)?;
297
298 let evaluated_condition = context.stack().pop(&t::Bool);
299
300 if evaluated_condition.inner {
301 context.evaluate_list(
302 host,
303 function,
304 )?;
305 }
306
307 Ok(())
308}
309
310
311fn map<Host>(
312 host: &mut Host,
313 context: &mut dyn Context<Host>,
314 _: Scope,
315)
316 -> Result
317{
318 let (list, function) = context.stack()
319 .pop((&t::List, &t::List));
320
321 context.stack().create_substack();
322
323 for item in list.inner.items {
324 context.stack().push(item);
325 context.evaluate_list(
326 host,
327 function.clone(),
328 )?;
329 }
330
331 let result = context.stack().destroy_substack();
332
333 let data = value::List::new(
334 value::ListInner::from_values(
335 result,
336 context.functions().new_scope(list.inner.scope, "list"),
337 ),
338 context.call_stack().operator().span.clone().merge(&list.span).merge(&function.span),
339 );
340 context.stack().push(data);
341
342 Ok(())
343}
344
345fn wrap<Host>(
346 _: &mut Host,
347 context: &mut dyn Context<Host>,
348 scope: Scope,
349)
350 -> Result
351{
352 let arg = context.stack().pop(&t::Any);
353
354 let span = context.call_stack().operator().span.clone().merge(&arg.span);
355 let list = value::List::new(
356 value::ListInner::from_values(
357 vec![arg],
358 context.functions().new_scope(scope, "list"),
359 ),
360 span,
361 );
362
363 context.stack().push(list);
364
365 Ok(())
366}
367
368fn unwrap<Host>(
369 _: &mut Host,
370 context: &mut dyn Context<Host>,
371 _: Scope,
372)
373 -> Result
374{
375 let list = context.stack().pop(&t::List);
376
377 for value in list.inner.items {
378 context.stack().push(value);
379 }
380
381 Ok(())
382}
383
384fn prepend<Host>(
385 _: &mut Host,
386 context: &mut dyn Context<Host>,
387 _: Scope,
388)
389 -> Result
390{
391 let (mut list, arg) = context.stack().pop((&t::List, &t::Any));
392
393 list.span = context.call_stack().operator().span.clone().merge(&list.span).merge(&arg.span);
394 list.inner.items.insert(0, arg);
395
396 context.stack().push(list);
397
398 Ok(())
399}
400
401fn append<Host>(
402 _: &mut Host,
403 context: &mut dyn Context<Host>,
404 _: Scope,
405)
406 -> Result
407{
408 let (mut list, arg) = context.stack().pop((&t::List, &t::Any));
409
410 list.span = context.call_stack().operator().span.clone().merge(&list.span).merge(&arg.span);
411 list.inner.items.push(arg);
412
413 context.stack().push(list);
414
415 Ok(())
416}
417
418
419fn add_n<Host>(
420 _: &mut Host,
421 context: &mut dyn Context<Host>,
422 _: Scope,
423)
424 -> Result
425{
426 let sum = context.stack()
427 .pop((&t::Number, &t::Number))
428 .compute::<value::Number, _, _>(|(a, b)| a + b);
429
430 context.stack().push(sum);
431
432 Ok(())
433}
434
435fn mul_n<Host>(
436 _: &mut Host,
437 context: &mut dyn Context<Host>,
438 _: Scope,
439)
440 -> Result
441{
442 let product = context.stack()
443 .pop((&t::Number, &t::Number))
444 .compute::<value::Number, _, _>(|(a, b)| a * b);
445
446 context.stack().push(product);
447
448 Ok(())
449}
450
451fn div_n<Host>(
452 _: &mut Host,
453 context: &mut dyn Context<Host>,
454 _: Scope,
455)
456 -> Result
457{
458 let quotient = context.stack()
459 .pop((&t::Number, &t::Number))
460 .compute::<value::Number, _, _>(|(a, b)| a / b);
461
462 context.stack().push(quotient);
463
464 Ok(())
465}
466
467fn gt_n<Host>(
468 _: &mut Host,
469 context: &mut dyn Context<Host>,
470 _: Scope,
471)
472 -> Result
473{
474 let is_greater = context.stack()
475 .pop((&t::Number, &t::Number))
476 .compute::<value::Bool, _, _>(|(a, b)| a > b);
477
478 context.stack().push(is_greater);
479
480 Ok(())
481}
482
483
484fn add_f<Host>(
485 _: &mut Host,
486 context: &mut dyn Context<Host>,
487 _: Scope,
488)
489 -> Result
490{
491 let sum = context.stack()
492 .pop((&t::Float, &t::Float))
493 .compute::<value::Float, _, _>(|(a, b)| a + b);
494
495 context.stack().push(sum);
496
497 Ok(())
498}
499
500fn mul_f<Host>(
501 _: &mut Host,
502 context: &mut dyn Context<Host>,
503 _: Scope,
504)
505 -> Result
506{
507 let product = context.stack()
508 .pop((&t::Float, &t::Float))
509 .compute::<value::Float, _, _>(|(a, b)| a * b);
510
511 context.stack().push(product);
512
513 Ok(())
514}
515
516fn gt_f<Host>(
517 _: &mut Host,
518 context: &mut dyn Context<Host>,
519 _: Scope,
520)
521 -> Result
522{
523 let is_greater = context.stack()
524 .pop((&t::Float, &t::Float))
525 .compute::<value::Bool, _, _>(|(a, b)| a > b);
526
527 context.stack().push(is_greater);
528
529 Ok(())
530}
531
532
533fn eq<Host>(
534 _: &mut Host,
535 context: &mut dyn Context<Host>,
536 _: Scope,
537)
538 -> Result
539{
540 let is_equal = context.stack()
541 .pop((&t::Any, &t::Any))
542 .compute::<value::Bool, _, _>(|(a, b)| a == b);
543
544 context.stack().push(is_equal);
545
546 Ok(())
547}
548
549fn not<Host>(
550 _: &mut Host,
551 context: &mut dyn Context<Host>,
552 _: Scope,
553)
554 -> Result
555{
556 let inverted = context.stack()
557 .pop(&t::Bool)
558 .compute::<value::Bool, _, _>(|b| !b);
559
560 context.stack().push(inverted);
561
562 Ok(())
563}