1use crate::r#macro;
2
3use super::{parser, semantics, LispErr, Pos};
4use alloc::{
5 boxed::Box,
6 collections::{btree_map::BTreeMap, linked_list::LinkedList, vec_deque::VecDeque},
7 format,
8 string::{String, ToString},
9 vec,
10 vec::Vec,
11};
12use core::{
13 cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
14 ops::{Shl, Shr},
15 pin::Pin,
16 ptr::{read_volatile, write_volatile},
17};
18use num_bigint::BigInt;
19use num_traits::{ToPrimitive, Zero};
20
21type Expr = semantics::LangExpr;
22type Pattern = semantics::Pattern;
23
24struct RuntimeErr {
25 msg: String,
26 pos: Pos,
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
30pub struct Variables {
31 vars: VecDeque<BTreeMap<String, RTData>>,
32}
33
34impl Variables {
35 fn new() -> Variables {
36 let mut list = VecDeque::new();
37 list.push_back(BTreeMap::new());
38 Variables { vars: list }
39 }
40
41 fn push(&mut self) {
42 self.vars.push_back(BTreeMap::new());
43 }
44
45 fn pop(&mut self) {
46 self.vars.pop_back();
47 }
48
49 fn insert(&mut self, id: String, data: RTData) {
50 let m = self.vars.back_mut().unwrap();
51 m.insert(id, data);
52 }
53
54 fn get(&mut self, id: &str) -> Option<&RTData> {
55 for m in self.vars.iter().rev() {
56 if let Some(val) = m.get(id) {
57 return Some(val);
58 }
59 }
60 None
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
65pub enum TCall {
66 Defun(String),
67 Lambda(u64),
68}
69
70#[derive(Eq, Debug, Clone)]
71pub struct IntType(*mut (BigInt, bool));
72
73impl IntType {
74 fn get_int(&self) -> &BigInt {
75 unsafe { &(*self.0).0 }
76 }
77
78 fn get_ref(&mut self) -> &mut bool {
79 unsafe { &mut (*self.0).1 }
80 }
81}
82
83impl Ord for IntType {
84 fn cmp(&self, other: &Self) -> Ordering {
85 let s1 = self.get_int();
86 let s2 = other.get_int();
87 s1.cmp(s2)
88 }
89}
90
91impl PartialOrd for IntType {
92 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
93 let s1 = self.get_int();
94 let s2 = other.get_int();
95 Some(s1.cmp(s2))
96 }
97}
98
99impl PartialEq for IntType {
100 fn eq(&self, other: &Self) -> bool {
101 let s1 = self.get_int();
102 let s2 = other.get_int();
103 s1 == s2
104 }
105}
106
107#[derive(Eq, Debug, Clone)]
108pub struct StrType(*mut (String, bool));
109
110impl StrType {
111 fn get_string(&self) -> &String {
112 unsafe { &(*self.0).0 }
113 }
114
115 fn get_ref(&mut self) -> &mut bool {
116 unsafe { &mut (*self.0).1 }
117 }
118}
119
120impl Ord for StrType {
121 fn cmp(&self, other: &Self) -> Ordering {
122 let s1 = self.get_string();
123 let s2 = other.get_string();
124 s1.cmp(s2)
125 }
126}
127
128impl PartialOrd for StrType {
129 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
130 let s1 = self.get_string();
131 let s2 = other.get_string();
132 Some(s1.cmp(s2))
133 }
134}
135
136impl PartialEq for StrType {
137 fn eq(&self, other: &Self) -> bool {
138 let s1 = self.get_string();
139 let s2 = other.get_string();
140 s1 == s2
141 }
142}
143
144#[derive(Eq, Debug, Clone)]
145pub struct ClojureType(*mut (Clojure, bool));
146
147impl ClojureType {
148 fn get_clojure(&self) -> &Clojure {
149 unsafe { &(*self.0).0 }
150 }
151
152 fn get_clojure_mut(&mut self) -> &mut Clojure {
153 unsafe { &mut (*self.0).0 }
154 }
155
156 fn get_ref(&mut self) -> &mut bool {
157 unsafe { &mut (*self.0).1 }
158 }
159}
160
161impl Ord for ClojureType {
162 fn cmp(&self, other: &Self) -> Ordering {
163 let s1 = self.get_clojure();
164 let s2 = other.get_clojure();
165 s1.cmp(s2)
166 }
167}
168
169impl PartialOrd for ClojureType {
170 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
171 let s1 = self.get_clojure();
172 let s2 = other.get_clojure();
173 Some(s1.cmp(s2))
174 }
175}
176
177impl PartialEq for ClojureType {
178 fn eq(&self, other: &Self) -> bool {
179 let s1 = self.get_clojure();
180 let s2 = other.get_clojure();
181 s1 == s2
182 }
183}
184
185#[derive(Eq, Debug, Clone)]
186pub struct LDataType(*mut (LabeledData, bool));
187
188impl LDataType {
189 fn get_ldata(&self) -> &LabeledData {
190 unsafe { &(*self.0).0 }
191 }
192
193 fn get_ldata_mut(&mut self) -> &mut LabeledData {
194 unsafe { &mut (*self.0).0 }
195 }
196
197 fn get_ref(&mut self) -> &mut bool {
198 unsafe { &mut (*self.0).1 }
199 }
200}
201
202impl Ord for LDataType {
203 fn cmp(&self, other: &Self) -> Ordering {
204 let s1 = self.get_ldata();
205 let s2 = other.get_ldata();
206 s1.cmp(s2)
207 }
208}
209
210impl PartialOrd for LDataType {
211 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
212 let s1 = self.get_ldata();
213 let s2 = other.get_ldata();
214 Some(s1.cmp(s2))
215 }
216}
217
218impl PartialEq for LDataType {
219 fn eq(&self, other: &Self) -> bool {
220 let s1 = self.get_ldata();
221 let s2 = other.get_ldata();
222 s1 == s2
223 }
224}
225
226#[derive(Debug, Clone, Ord, PartialOrd, PartialEq, Eq)]
227pub enum RTData {
228 Str(StrType),
229 Char(char),
230 Int(IntType),
231 Bool(bool),
232 Defun(String),
233 Lambda(ClojureType),
234 LData(LDataType),
235 TailCall(TCall, Variables),
236}
237
238fn escape_char(c: char) -> String {
239 match c {
240 '\n' => "\\n".to_string(),
241 '\r' => "\\r".to_string(),
242 '\t' => "\\t".to_string(),
243 '\0' => "\\0".to_string(),
244 _ => c.to_string(),
245 }
246}
247
248impl RTData {
249 fn get_in_lisp(&self, list_head: bool) -> String {
250 match self {
251 RTData::Str(n) => {
252 let mut str = "\"".to_string();
253 for s in n.get_string().chars() {
254 if s == '"' {
255 str.push_str("\\\"");
256 } else {
257 str.push_str(&escape_char(s));
258 }
259 }
260 str.push('"');
261 str
262 }
263 RTData::Char(c) => {
264 if *c == '`' {
265 "`\\``".to_string()
266 } else {
267 let s = escape_char(*c);
268 format!("`{}`", s)
269 }
270 }
271 RTData::Int(n) => {
272 format!("{}", n.get_int())
273 }
274 RTData::Bool(n) => n.to_string(),
275 RTData::Defun(n) => n.to_string(),
276 RTData::Lambda(n) => format!("(Lambda {})", n.get_clojure().ident),
277 RTData::LData(n) => {
278 let label = &n.get_ldata().label;
279 if label == "Cons" {
280 let e1;
281 let e2;
282 match n.get_ldata().data.as_ref() {
283 Some(ld) => {
284 e1 = ld[0].get_in_lisp(true);
285 e2 = ld[1].get_in_lisp(false);
286 }
287 None => panic!("invalid list"),
288 }
289 if list_head {
290 if e2.is_empty() {
291 format!("'({})", e1)
292 } else {
293 format!("'({} {})", e1, e2)
294 }
295 } else if e2.is_empty() {
296 e1
297 } else {
298 format!("{} {}", e1, e2)
299 }
300 } else if label == "Nil" {
301 if list_head {
302 "'()".to_string()
303 } else {
304 "".to_string()
305 }
306 } else if label == "Tuple" {
307 match n.get_ldata().data.as_ref() {
308 Some(ld) => {
309 let mut msg = "".to_string();
310 let len = (*ld).len();
311 let mut i = 1;
312 for d in ld.iter() {
313 if i == len {
314 msg = format!("{}{}", msg, d.get_in_lisp(true));
315 } else {
316 msg = format!("{}{} ", msg, d.get_in_lisp(true));
317 }
318 i += 1;
319 }
320 format!("[{}]", msg)
321 }
322 None => "[]".to_string(),
323 }
324 } else {
325 match n.get_ldata().data.as_ref() {
326 Some(ld) => {
327 let mut msg = format!("({}", label);
328 for d in ld.iter() {
329 msg = format!("{} {}", msg, d.get_in_lisp(true));
330 }
331 format!("{})", msg)
332 }
333 None => label.to_string(),
334 }
335 }
336 }
337 RTData::TailCall(TCall::Defun(f), _) => format!("(TailCall (Defun {}))", f),
338 RTData::TailCall(TCall::Lambda(f), _) => format!("(TailCall (Lambda {}))", f),
339 }
340 }
341}
342
343#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
344struct LabeledData {
345 label: String,
346 data: Option<Vec<RTData>>,
347}
348
349#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
350struct Clojure {
351 ident: u64,
352 data: Option<BTreeMap<String, RTData>>,
353}
354
355const MIN_GC_NUM: usize = 1024;
356
357#[derive(Debug)]
358pub(crate) struct RootObject {
359 objects: LinkedList<Pin<Box<(LabeledData, bool)>>>,
360 clojure: LinkedList<Pin<Box<(Clojure, bool)>>>,
361 integers: LinkedList<Pin<Box<(BigInt, bool)>>>,
362 strings: LinkedList<Pin<Box<(String, bool)>>>,
363 threshold: usize,
364}
365
366impl RootObject {
367 fn new() -> RootObject {
368 RootObject {
369 objects: LinkedList::new(),
370 clojure: LinkedList::new(),
371 integers: LinkedList::new(),
372 strings: LinkedList::new(),
373 threshold: MIN_GC_NUM,
374 }
375 }
376
377 fn len(&self) -> usize {
378 self.objects.len() + self.clojure.len() + self.integers.len() + self.strings.len()
379 }
380
381 fn make_int(&mut self, n: BigInt) -> IntType {
382 self.integers.push_back(Box::pin((n, false)));
383 let ptr = self.integers.back_mut().unwrap();
384 IntType(unsafe { ptr.as_mut().get_unchecked_mut() as *mut (BigInt, bool) })
385 }
386
387 fn make_str(&mut self, str: String) -> StrType {
388 self.strings.push_back(Box::pin((str, false)));
389 let ptr = self.strings.back_mut().unwrap();
390 StrType(unsafe { ptr.as_mut().get_unchecked_mut() as *mut (String, bool) })
391 }
392
393 fn make_obj(&mut self, label: String, data: Option<Vec<RTData>>) -> LDataType {
394 let obj = LabeledData { label, data };
395 self.objects.push_back(Box::pin((obj, false)));
396 let ptr = self.objects.back_mut().unwrap();
397 LDataType(unsafe { ptr.as_mut().get_unchecked_mut() as *mut (LabeledData, bool) })
398 }
399
400 fn make_clojure(&mut self, ident: u64, data: Option<BTreeMap<String, RTData>>) -> ClojureType {
401 let obj = Clojure { ident, data };
402 self.clojure.push_back(Box::pin((obj, false)));
403 let ptr = self.clojure.back_mut().unwrap();
404 ClojureType(unsafe { ptr.as_mut().get_unchecked_mut() as *mut (Clojure, bool) })
405 }
406}
407
408pub struct Environment<'a> {
409 pub(crate) ctx: &'a semantics::Context,
410 pub(crate) lambda: &'a BTreeMap<u64, semantics::Lambda>,
411 pub(crate) root: &'a mut RootObject,
412 pub(crate) vars: &'a mut VecDeque<Variables>,
413}
414
415pub(crate) fn eval(
416 code: &str,
417 ctx: &semantics::Context,
418) -> Result<LinkedList<Result<String, String>>, LispErr> {
419 let mut ps = parser::Parser::new(code, crate::FileType::Eval);
420 let mut exprs: LinkedList<parser::Expr> = match ps.parse() {
421 Ok(e) => e,
422 Err(e) => {
423 let msg = format!("Syntax Error: {}", e.msg);
424 return Err(LispErr { msg, pos: e.pos });
425 }
426 };
427
428 if let Err(e) = r#macro::process_macros(&mut exprs) {
429 let msg = format!("Macro Error: {}", e.msg);
430 return Err(LispErr::new(msg, e.pos));
431 }
432
433 for expr in exprs.iter_mut() {
434 if let Err(e) = r#macro::apply(expr, &ctx.macros) {
435 let msg: String = format!("Macro Error: {}", e.msg);
436 return Err(LispErr { msg, pos: e.pos });
437 }
438 }
439
440 let mut typed_exprs = LinkedList::new();
441 for expr in &exprs {
442 match semantics::typing_expr(expr, ctx) {
443 Ok(e) => {
444 typed_exprs.push_back(e);
445 }
446 Err(e) => {
447 let msg = format!("Typing Error: {}", e.msg);
448 return Err(LispErr { msg, pos: e.pos });
449 }
450 }
451 }
452
453 let mut root = RootObject::new();
454 let mut result = LinkedList::new();
455 for (expr, lambda) in &typed_exprs {
456 let mut vars = VecDeque::new();
457 vars.push_back(Variables::new());
458
459 let mut env = Environment {
460 ctx,
461 lambda,
462 root: &mut root,
463 vars: &mut vars,
464 };
465
466 match eval_expr(expr, &mut env) {
467 Ok(val) => {
468 result.push_back(Ok(val.get_in_lisp(true)));
469 }
470 Err(e) => {
471 let msg = format!(
472 "(RuntimeErr [{} (Pos {} {})])",
473 e.msg, e.pos.line, e.pos.column
474 );
475 result.push_back(Err(msg));
476 return Ok(result);
477 }
478 }
479 }
480
481 Ok(result)
482}
483
484fn get_data_of_id(id: &str, vars: &mut VecDeque<Variables>) -> RTData {
485 match vars.back_mut().unwrap().get(id) {
486 Some(data) => data.clone(),
487 None => RTData::Defun(id.to_string()),
488 }
489}
490
491fn eval_expr(expr: &Expr, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {
492 match expr {
493 Expr::LitStr(e) => Ok(RTData::Str(env.root.make_str(e.str.clone()))),
494 Expr::LitNum(e) => Ok(RTData::Int(env.root.make_int(e.num.clone()))),
495 Expr::LitChar(e) => Ok(RTData::Char(e.c)),
496 Expr::LitBool(e) => Ok(RTData::Bool(e.val)),
497 Expr::IfExpr(e) => eval_if(e, env),
498 Expr::DataExpr(e) => eval_data(e, env),
499 Expr::ListExpr(e) => eval_list(e, env),
500 Expr::LetExpr(e) => eval_let(e, env),
501 Expr::MatchExpr(e) => eval_match(e, env),
502 Expr::IDExpr(e) => Ok(eval_id(e, env.vars)),
503 Expr::ApplyExpr(e) => eval_apply(e, env),
504 Expr::TupleExpr(e) => eval_tuple(e, env),
505 Expr::LambdaExpr(e) => Ok(eval_lambda(e, env)),
506 }
507}
508
509fn eval_lambda(expr: &semantics::Lambda, env: &mut Environment<'_>) -> RTData {
510 let data = if !expr.vars.is_empty() {
511 let mut m = BTreeMap::new();
512 for v in &expr.vars {
513 m.insert(v.to_string(), get_data_of_id(v, env.vars));
514 }
515 Some(m)
516 } else {
517 None
518 };
519
520 let ptr = env.root.make_clojure(expr.ident, data);
521 RTData::Lambda(ptr)
522}
523
524fn eval_tuple(expr: &semantics::Exprs, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {
525 let mut v = Vec::new();
526 for e in expr.exprs.iter() {
527 v.push(eval_expr(e, env)?);
528 }
529
530 let ptr = env.root.make_obj("Tuple".to_string(), Some(v));
531
532 Ok(RTData::LData(ptr))
533}
534
535fn get_fun<'a>(
536 ctx: &'a semantics::Context,
537 fun_name: &str,
538 expr: &Expr,
539) -> Result<&'a semantics::Defun, RuntimeErr> {
540 let fun = match ctx.funs.get(fun_name) {
541 Some(f) => f,
542 None => {
543 let pos = expr.get_pos();
544 let msg = format!("{} is not defined", fun_name);
545 return Err(RuntimeErr { msg, pos });
546 }
547 };
548
549 Ok(fun)
550}
551
552fn get_lambda<'a>(
553 ctx: &'a semantics::Context,
554 lambda: &'a BTreeMap<u64, semantics::Lambda>,
555 id: u64,
556 expr: &Expr,
557) -> Result<&'a semantics::Lambda, RuntimeErr> {
558 let fun;
559 match ctx.lambda.get(&id) {
560 Some(f) => {
561 fun = f;
562 }
563 None => match lambda.get(&id) {
564 Some(f) => {
565 fun = f;
566 }
567 None => {
568 let pos = expr.get_pos();
569 let msg = format!("could not find (Lambda {})", id);
570 return Err(RuntimeErr { msg, pos });
571 }
572 },
573 }
574
575 Ok(fun)
576}
577
578fn call_lambda(
579 expr: &semantics::Apply,
580 env: &mut Environment<'_>,
581 cloj: &Clojure,
582 iter: core::slice::Iter<semantics::LangExpr>,
583 fun_expr: &semantics::LangExpr,
584) -> Result<RTData, RuntimeErr> {
585 let ident = cloj.ident;
587 let fun = get_lambda(env.ctx, env.lambda, ident, fun_expr)?;
588
589 let mut vars_fun = Variables::new();
591 for (e, arg) in iter.zip(fun.args.iter()) {
592 let data = eval_expr(e, env)?;
593 vars_fun.insert(arg.id.to_string(), data);
594 }
595
596 match &cloj.data {
598 Some(d) => {
599 for (key, val) in d {
600 vars_fun.insert(key.to_string(), val.clone());
601 }
602 }
603 None => (),
604 }
605
606 if expr.is_tail {
608 Ok(RTData::TailCall(TCall::Lambda(ident), vars_fun))
609 } else {
610 env.vars.push_back(vars_fun);
611 let result = eval_tail_call(&fun.expr, env);
612 env.vars.pop_back();
613 result
614 }
615}
616
617fn eval_apply(expr: &semantics::Apply, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {
618 let mut iter = expr.exprs.iter();
619 let fun_expr = match iter.next() {
620 Some(e) => e,
621 None => {
622 let pos = expr.pos;
623 return Err(RuntimeErr {
624 msg: "empty application".to_string(),
625 pos,
626 });
627 }
628 };
629
630 match eval_expr(fun_expr, env)? {
631 RTData::Defun(fun_name) => {
632 if env.ctx.built_in.contains(&fun_name) {
634 let mut v = Vec::new();
635 for e in iter {
636 let data = eval_expr(e, env)?;
637 v.push(data);
638 }
639 return eval_built_in(fun_name, &v, expr.pos, env);
640 }
641
642 if let Some(ffi) = env.ctx.ext_ffi.get(fun_name.as_str()) {
643 let mut v = Vec::new();
644 for e in iter {
645 let data = eval_expr(e, env)?;
646 v.push(data);
647 }
648 return Ok(ffi(env, &v));
649 }
650
651 if let Ok(fun) = get_fun(env.ctx, &fun_name, fun_expr) {
653 let mut vars_fun = Variables::new();
655 for (e, arg) in iter.zip(fun.args.iter()) {
656 let data = eval_expr(e, env)?;
657 vars_fun.insert(arg.id.to_string(), data);
658 }
659
660 if expr.is_tail {
662 Ok(RTData::TailCall(TCall::Defun(fun_name), vars_fun))
663 } else {
664 env.vars.push_back(vars_fun);
665 let result = eval_tail_call(&fun.expr, env)?;
666 env.vars.pop_back();
667 Ok(result)
668 }
669 } else {
670 if let Some(RTData::Lambda(cloj)) = env.vars.back_mut().unwrap().get(&fun_name) {
672 let c = cloj.clone();
673 return call_lambda(expr, env, c.get_clojure(), iter, fun_expr);
674 }
675
676 let pos = fun_expr.get_pos();
678 let msg = format!("{} is not defined", fun_name);
679 Err(RuntimeErr { msg, pos })
680 }
681 }
682 RTData::Lambda(f) => {
683 let f = f.get_clojure();
684 call_lambda(expr, env, f, iter, fun_expr)
685 }
686 _ => {
687 let pos = fun_expr.get_pos();
688 Err(RuntimeErr {
689 msg: "not function".to_string(),
690 pos,
691 })
692 }
693 }
694}
695
696fn eval_tail_call<'a>(
697 mut expr: &'a Expr,
698 env: &'a mut Environment<'_>,
699) -> Result<RTData, RuntimeErr> {
700 loop {
701 match eval_expr(expr, env)? {
702 RTData::TailCall(TCall::Defun(fun_name), vars_fun) => {
703 let fun = get_fun(env.ctx, &fun_name, expr)?;
704 expr = &fun.expr;
705 env.vars.pop_back();
706 env.vars.push_back(vars_fun);
707 collect_garbage(env.vars, env.root); }
709 RTData::TailCall(TCall::Lambda(id), vars_fun) => {
710 let fun = get_lambda(env.ctx, env.lambda, id, expr)?;
711 expr = &fun.expr;
712 env.vars.pop_back();
713 env.vars.push_back(vars_fun);
714 collect_garbage(env.vars, env.root); }
716 x => {
717 return Ok(x);
718 }
719 }
720 }
721}
722
723fn get_int(args: &[RTData], pos: Pos) -> Result<*const BigInt, RuntimeErr> {
724 match &args[0] {
725 RTData::Int(n) => Ok(n.get_int()),
726 _ => Err(RuntimeErr {
727 msg: "there must be exactly 2 integers".to_string(),
728 pos,
729 }),
730 }
731}
732
733fn get_int_int(args: &[RTData], pos: Pos) -> Result<(*const BigInt, *const BigInt), RuntimeErr> {
734 match (&args[0], &args[1]) {
735 (RTData::Int(n1), RTData::Int(n2)) => Ok((n1.get_int(), n2.get_int())),
736 _ => Err(RuntimeErr {
737 msg: "there must be exactly 2 integers".to_string(),
738 pos,
739 }),
740 }
741}
742
743fn get_int_int_int(
744 args: &[RTData],
745 pos: Pos,
746) -> Result<(*const BigInt, *const BigInt, *const BigInt), RuntimeErr> {
747 match (&args[0], &args[1], &args[2]) {
748 (RTData::Int(n1), RTData::Int(n2), RTData::Int(n3)) => {
749 Ok((n1.get_int(), n2.get_int(), n3.get_int()))
750 }
751 _ => Err(RuntimeErr {
752 msg: "there must be exactly 3 integers".to_string(),
753 pos,
754 }),
755 }
756}
757
758fn get_bool_bool(args: &[RTData], pos: Pos) -> Result<(bool, bool), RuntimeErr> {
759 match (args[0].clone(), args[1].clone()) {
760 (RTData::Bool(n1), RTData::Bool(n2)) => Ok((n1, n2)),
761 _ => Err(RuntimeErr {
762 msg: "there must be exactly 2 boolean values".to_string(),
763 pos,
764 }),
765 }
766}
767
768fn get_bool(args: &[RTData], pos: Pos) -> Result<bool, RuntimeErr> {
769 match args[0].clone() {
770 RTData::Bool(n) => Ok(n),
771 _ => Err(RuntimeErr {
772 msg: "there must be exactly 1 boolean value".to_string(),
773 pos,
774 }),
775 }
776}
777
778fn eval_built_in(
779 fun_name: String,
780 args: &[RTData],
781 pos: Pos,
782 env: &mut Environment<'_>,
783) -> Result<RTData, RuntimeErr> {
784 match fun_name.as_str() {
785 "+" => {
786 let (n1, n2) = get_int_int(args, pos)?;
787 let n = unsafe { &*n1 + &*n2 };
788 Ok(RTData::Int(env.root.make_int(n)))
789 }
790 "-" => {
791 let (n1, n2) = get_int_int(args, pos)?;
792 let n = unsafe { &*n1 - &*n2 };
793 Ok(RTData::Int(env.root.make_int(n)))
794 }
795 "*" => {
796 let (n1, n2) = get_int_int(args, pos)?;
797 let n = unsafe { &*n1 * &*n2 };
798 Ok(RTData::Int(env.root.make_int(n)))
799 }
800 "/" => {
801 let (n1, n2) = get_int_int(args, pos)?;
802 let n = unsafe { &*n1 / &*n2 };
803 Ok(RTData::Int(env.root.make_int(n)))
804 }
805 "%" => {
806 let (n1, n2) = get_int_int(args, pos)?;
807 let n = unsafe { &*n1 % &*n2 };
808 Ok(RTData::Int(env.root.make_int(n)))
809 }
810 "=" | "eq" => Ok(RTData::Bool(args[0] == args[1])),
811 "!=" | "neq" => Ok(RTData::Bool(args[0] != args[1])),
812 "<=" | "leq" => Ok(RTData::Bool(args[0] <= args[1])),
813 ">=" | "geq" => Ok(RTData::Bool(args[0] >= args[1])),
814 ">" | "gt" => Ok(RTData::Bool(args[0] > args[1])),
815 "<" | "lt" => Ok(RTData::Bool(args[0] < args[1])),
816 "and" => {
817 let (n1, n2) = get_bool_bool(args, pos)?;
818 Ok(RTData::Bool(n1 && n2))
819 }
820 "or" => {
821 let (n1, n2) = get_bool_bool(args, pos)?;
822 Ok(RTData::Bool(n1 || n2))
823 }
824 "xor" => {
825 let (n1, n2) = get_bool_bool(args, pos)?;
826 Ok(RTData::Bool(n1 ^ n2))
827 }
828 "not" => {
829 let n = get_bool(args, pos)?;
830 Ok(RTData::Bool(!n))
831 }
832 "band" => {
833 let (n1, n2) = get_int_int(args, pos)?;
834 let n = unsafe { &*n1 & &*n2 };
835 Ok(RTData::Int(env.root.make_int(n)))
836 }
837 "bor" => {
838 let (n1, n2) = get_int_int(args, pos)?;
839 let n = unsafe { &*n1 | &*n2 };
840 Ok(RTData::Int(env.root.make_int(n)))
841 }
842 "bxor" => {
843 let (n1, n2) = get_int_int(args, pos)?;
844 let n = unsafe { &*n1 ^ &*n2 };
845 Ok(RTData::Int(env.root.make_int(n)))
846 }
847 "sqrt" => {
848 let n = get_int(args, pos)?;
849 if unsafe { (*n) >= Zero::zero() } {
850 let n = unsafe { (*n).sqrt() };
851 let n = RTData::Int(env.root.make_int(n));
852 let ptr = env.root.make_obj("Some".to_string(), Some(vec![n]));
853 Ok(RTData::LData(ptr))
854 } else {
855 let ptr = env.root.make_obj("None".to_string(), None);
856 Ok(RTData::LData(ptr))
857 }
858 }
859 "pow" => {
860 let (n1, n2) = get_int_int(args, pos)?;
861 if let Some(e) = unsafe { (*n2).to_u32() } {
862 let n = unsafe { (*n1).pow(e) };
863 let n = RTData::Int(env.root.make_int(n));
864 let ptr = env.root.make_obj("Some".to_string(), Some(vec![n]));
865 Ok(RTData::LData(ptr))
866 } else {
867 let ptr = env.root.make_obj("None".to_string(), None);
868 Ok(RTData::LData(ptr))
869 }
870 }
871 ">>" => {
872 let (n1, n2) = get_int_int(args, pos)?;
873 if let Some(e) = unsafe { (*n2).to_u64() } {
874 let n = unsafe { (*n1).clone() };
875 let n = n.shr(e);
876 let n = RTData::Int(env.root.make_int(n));
877 let ptr = env.root.make_obj("Some".to_string(), Some(vec![n]));
878 Ok(RTData::LData(ptr))
879 } else {
880 let ptr = env.root.make_obj("None".to_string(), None);
881 Ok(RTData::LData(ptr))
882 }
883 }
884 "<<" => {
885 let (n1, n2) = get_int_int(args, pos)?;
886 if let Some(e) = unsafe { (*n2).to_u64() } {
887 let n = unsafe { (*n1).clone() };
888 let n = n.shl(e);
889 let n = RTData::Int(env.root.make_int(n));
890 let ptr = env.root.make_obj("Some".to_string(), Some(vec![n]));
891 Ok(RTData::LData(ptr))
892 } else {
893 let ptr = env.root.make_obj("None".to_string(), None);
894 Ok(RTData::LData(ptr))
895 }
896 }
897 "chars" => {
898 let mut tail = RTData::LData(env.root.make_obj("Nil".to_string(), None));
899 if let RTData::Str(st) = &args[0] {
900 let s = st.get_string();
901 for c in s.chars().rev() {
902 let c = RTData::Char(c);
903 let cons =
904 RTData::LData(env.root.make_obj("Cons".to_string(), Some(vec![c, tail])));
905 tail = cons;
906 }
907 }
908 Ok(tail)
909 }
910 "str" => {
911 let mut head = &args[0];
912 let mut s = "".to_string();
913 loop {
914 if let RTData::LData(data) = head {
915 if data.get_ldata().label == "Cons" {
916 if let Some(d) = &data.get_ldata().data {
917 if let RTData::Char(c) = &d[0] {
918 s.push(*c);
919 head = &d[1];
920 } else {
921 return Err(RuntimeErr {
922 msg: "not char".to_string(),
923 pos,
924 });
925 }
926 } else {
927 return Err(RuntimeErr {
928 msg: "invalid cons".to_string(),
929 pos,
930 });
931 }
932 } else if data.get_ldata().label == "Nil" {
933 break;
934 } else {
935 return Err(RuntimeErr {
936 msg: "not list".to_string(),
937 pos,
938 });
939 }
940 }
941 }
942 let ptr = env.root.make_str(s);
943 Ok(RTData::Str(ptr))
944 }
945 "call-rust" => {
946 let (n1, n2, n3) = get_int_int_int(args, pos)?;
947 let n = unsafe { (env.ctx.callback)(&*n1, &*n2, &*n3) };
948 if let Some(n) = n {
949 let n = RTData::Int(env.root.make_int(n));
950 let ptr = env.root.make_obj("Some".to_string(), Some(vec![n]));
951 Ok(RTData::LData(ptr))
952 } else {
953 let ptr = env.root.make_obj("None".to_string(), None);
954 Ok(RTData::LData(ptr))
955 }
956 }
957 _ => Err(RuntimeErr {
958 msg: "unknown built-in function".to_string(),
959 pos,
960 }),
961 }
962}
963
964fn eval_match(
965 expr: &semantics::MatchNode,
966 env: &mut Environment<'_>,
967) -> Result<RTData, RuntimeErr> {
968 let data = eval_expr(&expr.expr, env)?;
969
970 for c in &expr.cases {
971 env.vars.back_mut().unwrap().push();
972 if eval_pat(&c.pattern, data.clone(), env.vars) {
973 let retval = eval_expr(&c.expr, env)?;
974 env.vars.back_mut().unwrap().pop();
975 return Ok(retval);
976 }
977 env.vars.back_mut().unwrap().pop();
978 }
979
980 let pos = expr.pos;
981 Err(RuntimeErr {
982 msg: "pattern-matching is not exhaustive".to_string(),
983 pos,
984 })
985}
986
987fn eval_id(expr: &semantics::IDNode, vars: &mut VecDeque<Variables>) -> RTData {
988 let id = expr.id.to_string();
989 get_data_of_id(&id, vars)
990}
991
992fn eval_list(expr: &semantics::Exprs, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {
993 let mut elm = env.root.make_obj("Nil".to_string(), None);
994 for e in expr.exprs.iter().rev() {
995 let val = eval_expr(e, env)?;
996 elm = env
997 .root
998 .make_obj("Cons".to_string(), Some(vec![val, RTData::LData(elm)]));
999 }
1000
1001 Ok(RTData::LData(elm))
1002}
1003
1004fn eval_if(expr: &semantics::IfNode, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {
1005 let cond = eval_expr(&expr.cond_expr, env)?;
1006 let flag = match cond {
1007 RTData::Bool(e) => e,
1008 _ => {
1009 let pos = expr.cond_expr.get_pos();
1010 return Err(RuntimeErr {
1011 msg: "type mismatched".to_string(),
1012 pos,
1013 });
1014 }
1015 };
1016
1017 if flag {
1018 eval_expr(&expr.then_expr, env)
1019 } else {
1020 eval_expr(&expr.else_expr, env)
1021 }
1022}
1023
1024fn eval_data(expr: &semantics::DataNode, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {
1025 let data = if expr.exprs.is_empty() {
1026 None
1027 } else {
1028 let mut v = Vec::new();
1029 for e in &expr.exprs {
1030 v.push(eval_expr(e, env)?);
1031 }
1032 Some(v)
1033 };
1034
1035 let ptr = env.root.make_obj(expr.label.id.to_string(), data);
1036
1037 Ok(RTData::LData(ptr))
1038}
1039
1040fn eval_let(expr: &semantics::LetNode, env: &mut Environment<'_>) -> Result<RTData, RuntimeErr> {
1041 env.vars.back_mut().unwrap().push();
1042
1043 for def in &expr.def_vars {
1044 let data = eval_expr(&def.expr, env)?;
1045 if !eval_pat(&def.pattern, data, env.vars) {
1046 let pos = def.pattern.get_pos();
1047 return Err(RuntimeErr {
1048 msg: "failed pattern matching".to_string(),
1049 pos,
1050 });
1051 }
1052 }
1053
1054 let result = eval_expr(&expr.expr, env)?;
1055 env.vars.back_mut().unwrap().pop();
1056
1057 Ok(result)
1058}
1059
1060fn eval_pat(pat: &Pattern, data: RTData, vars: &mut VecDeque<Variables>) -> bool {
1061 match pat {
1062 Pattern::PatID(p) => {
1063 vars.back_mut().unwrap().insert(p.id.to_string(), data);
1064 true
1065 }
1066 Pattern::PatStr(p) => match data {
1067 RTData::Str(n) => n.get_string() == &p.str,
1068 _ => false,
1069 },
1070 Pattern::PatChar(p) => match data {
1071 RTData::Char(n) => n == p.c,
1072 _ => false,
1073 },
1074 Pattern::PatNum(p) => match data {
1075 RTData::Int(n) => n.get_int() == &p.num,
1076 _ => false,
1077 },
1078 Pattern::PatBool(p) => match data {
1079 RTData::Bool(n) => n == p.val,
1080 _ => false,
1081 },
1082 Pattern::PatNil(_) => match data {
1083 RTData::LData(ptr) => ptr.get_ldata().label == "Nil",
1084 _ => false,
1085 },
1086 Pattern::PatTuple(p) => match data {
1087 RTData::LData(ptr) => {
1088 if ptr.get_ldata().label != "Tuple" {
1089 return false;
1090 }
1091
1092 match &ptr.get_ldata().data {
1093 Some(rds) => {
1094 for (pat2, rd) in p.pattern.iter().zip(rds.iter()) {
1095 if !eval_pat(pat2, rd.clone(), vars) {
1096 return false;
1097 }
1098 }
1099 true
1100 }
1101 None => true,
1102 }
1103 }
1104 _ => false,
1105 },
1106 Pattern::PatData(p) => match data {
1107 RTData::LData(ptr) => {
1108 if ptr.get_ldata().label != p.label.id {
1109 return false;
1110 }
1111
1112 match &ptr.get_ldata().data {
1113 Some(rds) => {
1114 for (pat2, rd) in p.pattern.iter().zip(rds.iter()) {
1115 if !eval_pat(pat2, rd.clone(), vars) {
1116 return false;
1117 }
1118 }
1119 true
1120 }
1121 None => true,
1122 }
1123 }
1124 _ => false,
1125 },
1126 }
1127}
1128
1129fn collect_garbage(vars: &mut VecDeque<Variables>, root: &mut RootObject) {
1131 let n = root.len();
1132 if n < root.threshold {
1133 return;
1134 }
1135
1136 mark(vars);
1137 sweep(&mut root.clojure);
1138 sweep(&mut root.objects);
1139 sweep(&mut root.integers);
1140 sweep(&mut root.strings);
1141
1142 let n = root.len();
1143 root.threshold = n * 2;
1144 if root.threshold < (MIN_GC_NUM >> 1) {
1145 root.threshold = MIN_GC_NUM;
1146 }
1147}
1148
1149fn mark(vars: &mut VecDeque<Variables>) {
1151 for v in vars.iter_mut() {
1152 for var in v.vars.iter_mut() {
1153 for (_, v) in var.iter_mut() {
1154 mark_obj(v);
1155 }
1156 }
1157 }
1158}
1159
1160fn mark_obj(data: &mut RTData) {
1162 match data {
1163 RTData::Str(ptr) => unsafe {
1164 write_volatile(ptr.get_ref(), true);
1165 },
1166 RTData::Int(ptr) => unsafe {
1167 write_volatile(ptr.get_ref(), true);
1168 },
1169 RTData::Lambda(ptr) => unsafe {
1170 if !read_volatile(ptr.get_ref()) {
1171 write_volatile(ptr.get_ref(), true);
1172 if let Some(data) = &mut ptr.get_clojure_mut().data {
1173 for (_, v) in data.iter_mut() {
1174 mark_obj(v);
1175 }
1176 }
1177 }
1178 },
1179 RTData::LData(ptr) => unsafe {
1180 if !read_volatile(ptr.get_ref()) {
1181 write_volatile(ptr.get_ref(), true);
1182 if let Some(data) = &mut ptr.get_ldata_mut().data {
1183 for v in data.iter_mut() {
1184 mark_obj(v);
1185 }
1186 }
1187 }
1188 },
1189 _ => (),
1190 }
1191}
1192
1193fn sweep<T>(root: &mut LinkedList<Pin<Box<(T, bool)>>>) {
1195 let mut tail = root.split_off(0);
1196 loop {
1197 if tail.is_empty() {
1198 break;
1199 }
1200
1201 let mut head;
1203 if tail.len() == 1 {
1204 head = tail.split_off(0);
1205 } else {
1206 let tmp = tail.split_off(1);
1207 head = tail;
1208 tail = tmp;
1209 };
1210
1211 let h = head.front_mut().unwrap();
1213 let marked = unsafe { read_volatile(&h.as_ref().1) };
1214 let flag = if marked {
1215 let h = h.as_mut();
1217 unsafe {
1218 h.get_unchecked_mut().1 = false;
1219 }
1220 true
1221 } else {
1222 false
1224 };
1225
1226 if flag {
1228 root.append(&mut head);
1229 }
1230 }
1231}
1232
1233pub trait RTDataToRust<T> {
1234 fn into(&self) -> T;
1235}
1236
1237impl RTDataToRust<BigInt> for RTData {
1239 fn into(&self) -> BigInt {
1240 if let RTData::Int(data) = self {
1241 data.get_int().clone()
1242 } else {
1243 panic!("data is not BigInt");
1244 }
1245 }
1246}
1247
1248impl RTDataToRust<char> for RTData {
1250 fn into(&self) -> char {
1251 if let RTData::Char(data) = self {
1252 *data
1253 } else {
1254 panic!("data is not Char");
1255 }
1256 }
1257}
1258
1259impl RTDataToRust<String> for RTData {
1261 fn into(&self) -> String {
1262 if let RTData::Str(data) = self {
1263 data.get_string().clone()
1264 } else {
1265 panic!("data is not String");
1266 }
1267 }
1268}
1269
1270impl RTDataToRust<bool> for RTData {
1272 fn into(&self) -> bool {
1273 if let RTData::Bool(data) = self {
1274 *data
1275 } else {
1276 panic!("data is not Bool");
1277 }
1278 }
1279}
1280
1281impl<T> RTDataToRust<Vec<T>> for RTData
1283where
1284 RTData: RTDataToRust<T>,
1285{
1286 fn into(&self) -> Vec<T> {
1287 if let RTData::LData(data) = self {
1288 let ldata = data.get_ldata();
1289 let mut result = Vec::new();
1290 list_to_vec(ldata, &mut result);
1291
1292 return result;
1293 }
1294
1295 panic!("data is not List");
1296 }
1297}
1298
1299impl<T> RTDataToRust<Option<T>> for RTData
1301where
1302 RTData: RTDataToRust<T>,
1303{
1304 fn into(&self) -> Option<T> {
1305 if let RTData::LData(data) = self {
1306 let ldata = data.get_ldata();
1307 match ldata.label.as_str() {
1308 "Some" => {
1309 if let Some(v) = &ldata.data {
1310 let e: T = RTDataToRust::into(&v[0]);
1311 Some(e)
1312 } else {
1313 panic!("invalid Some")
1314 }
1315 }
1316 "None" => None,
1317 _ => panic!("label is neither Some nor None"),
1318 }
1319 } else {
1320 panic!("data is not Option");
1321 }
1322 }
1323}
1324
1325fn list_to_vec<T>(mut ldata: &LabeledData, result: &mut Vec<T>)
1327where
1328 RTData: RTDataToRust<T>,
1329{
1330 loop {
1331 match ldata.label.as_str() {
1332 "Cons" => {
1333 if let Some(v) = &ldata.data {
1334 let e: T = RTDataToRust::into(&v[0]);
1335 result.push(e);
1336
1337 if let RTData::LData(data) = &v[1] {
1338 ldata = data.get_ldata();
1339 } else {
1340 panic!("no next in Cons")
1341 }
1342 } else {
1343 panic!("invalid Cons");
1344 }
1345 }
1346 "Nil" => break,
1347 _ => panic!("label is neither Cons nor Nil"),
1348 }
1349 }
1350}
1351
1352impl<T, E> RTDataToRust<Result<T, E>> for RTData
1354where
1355 RTData: RTDataToRust<T> + RTDataToRust<E>,
1356{
1357 fn into(&self) -> Result<T, E> {
1358 if let RTData::LData(data) = self {
1359 let ldata = data.get_ldata();
1360 match ldata.label.as_str() {
1361 "Ok" => {
1362 if let Some(v) = &ldata.data {
1363 let e: T = RTDataToRust::into(&v[0]);
1364 Ok(e)
1365 } else {
1366 panic!("invalid Ok")
1367 }
1368 }
1369 "Err" => {
1370 if let Some(v) = &ldata.data {
1371 let e: E = RTDataToRust::into(&v[0]);
1372 Err(e)
1373 } else {
1374 panic!("invalid Err")
1375 }
1376 }
1377 _ => panic!("label is neither Ok nor Err"),
1378 }
1379 } else {
1380 panic!("data is not Result");
1381 }
1382 }
1383}
1384
1385macro_rules! impl_rt_data_to_rust_tuple {
1386 ($($(#[$impl_attrs:meta])*
1387 [ $(($index:literal, $name_snake:ident, $name_pascal:ident)),+ $(,)? ]),+ $(,)?) => {
1388 $($(#[$impl_attrs])*
1389 impl<$($name_pascal),*> RTDataToRust<($($name_pascal),*)> for RTData
1390 where $(RTData: RTDataToRust<$name_pascal>),* {
1391 fn into(&self) -> ($($name_pascal),*) {
1392 if let RTData::LData(data) = self {
1393 let ldata = data.get_ldata();
1394 if ldata.label.as_str() == "Tuple" {
1395 if let Some(v) = &ldata.data {
1396 $(let $name_snake: $name_pascal = RTDataToRust::into(&v[$index]);)*
1397
1398 ($($name_snake),*)
1399 } else {
1400 panic!("invalid Tuple")
1401 }
1402 } else {
1403 panic!("label is not Tuple")
1404 }
1405 } else {
1406 panic!("data is not a Tuple")
1407 }
1408 }
1409 })*
1410 }
1411}
1412impl_rt_data_to_rust_tuple![
1413 [
1416 (0, v0, T0),
1417 (1, v1, T1),
1418 ],
1419 [
1422 (0, v0, T0),
1423 (1, v1, T1),
1424 (2, v2, T2),
1425 ],
1426 [
1429 (0, v0, T0),
1430 (1, v1, T1),
1431 (2, v2, T2),
1432 (3, v3, T3),
1433 ],
1434 [
1437 (0, v0, T0),
1438 (1, v1, T1),
1439 (2, v2, T2),
1440 (3, v3, T3),
1441 (4, v4, T4),
1442 ],
1443 [
1446 (0, v0, T0),
1447 (1, v1, T1),
1448 (2, v2, T2),
1449 (3, v3, T3),
1450 (4, v4, T4),
1451 (5, v5, T5),
1452 ],
1453 [
1456 (0, v0, T0),
1457 (1, v1, T1),
1458 (2, v2, T2),
1459 (3, v3, T3),
1460 (4, v4, T4),
1461 (5, v5, T5),
1462 (6, v6, T6),
1463 ],
1464 [
1467 (0, v0, T0),
1468 (1, v1, T1),
1469 (2, v2, T2),
1470 (3, v3, T3),
1471 (4, v4, T4),
1472 (5, v5, T5),
1473 (6, v6, T6),
1474 (7, v7, T7),
1475 ],
1476 [
1479 (0, v0, T0),
1480 (1, v1, T1),
1481 (2, v2, T2),
1482 (3, v3, T3),
1483 (4, v4, T4),
1484 (5, v5, T5),
1485 (6, v6, T6),
1486 (7, v7, T7),
1487 (8, v8, T8),
1488 ],
1489 [
1492 (0, v0, T0),
1493 (1, v1, T1),
1494 (2, v2, T2),
1495 (3, v3, T3),
1496 (4, v4, T4),
1497 (5, v5, T5),
1498 (6, v6, T6),
1499 (7, v7, T7),
1500 (8, v8, T8),
1501 (9, v9, T9),
1502 ],
1503 [
1506 (0, v0, T0),
1507 (1, v1, T1),
1508 (2, v2, T2),
1509 (3, v3, T3),
1510 (4, v4, T4),
1511 (5, v5, T5),
1512 (6, v6, T6),
1513 (7, v7, T7),
1514 (8, v8, T8),
1515 (9, v9, T9),
1516 (10, v10, T10),
1517 ],
1518 [
1521 (0, v0, T0),
1522 (1, v1, T1),
1523 (2, v2, T2),
1524 (3, v3, T3),
1525 (4, v4, T4),
1526 (5, v5, T5),
1527 (6, v6, T6),
1528 (7, v7, T7),
1529 (8, v8, T8),
1530 (9, v9, T9),
1531 (10, v10, T10),
1532 (11, v11, T11),
1533 ],
1534];
1535
1536pub trait RustToRTData<T> {
1537 fn from(env: &mut Environment<'_>, value: T) -> Self;
1538}
1539
1540impl RustToRTData<BigInt> for RTData {
1541 fn from(env: &mut Environment<'_>, value: BigInt) -> Self {
1542 RTData::Int(env.root.make_int(value))
1543 }
1544}
1545
1546impl RustToRTData<char> for RTData {
1547 fn from(_env: &mut Environment<'_>, value: char) -> Self {
1548 RTData::Char(value)
1549 }
1550}
1551
1552impl RustToRTData<bool> for RTData {
1553 fn from(_env: &mut Environment<'_>, value: bool) -> Self {
1554 RTData::Bool(value)
1555 }
1556}
1557
1558impl RustToRTData<String> for RTData {
1559 fn from(env: &mut Environment<'_>, value: String) -> Self {
1560 RTData::Str(env.root.make_str(value))
1561 }
1562}
1563
1564impl<T> RustToRTData<Option<T>> for RTData
1565where
1566 RTData: RustToRTData<T>,
1567{
1568 fn from(env: &mut Environment<'_>, value: Option<T>) -> Self {
1569 if let Some(value) = value {
1570 let value = RustToRTData::from(env, value);
1571 RTData::LData(env.root.make_obj("Some".to_string(), Some(vec![value])))
1572 } else {
1573 RTData::LData(env.root.make_obj("None".to_string(), None))
1574 }
1575 }
1576}
1577
1578impl<T, E> RustToRTData<Result<T, E>> for RTData
1579where
1580 RTData: RustToRTData<T> + RustToRTData<E>,
1581{
1582 fn from(env: &mut Environment<'_>, value: Result<T, E>) -> Self {
1583 match value {
1584 Ok(value) => {
1585 let value = RustToRTData::from(env, value);
1586 RTData::LData(env.root.make_obj("Ok".to_string(), Some(vec![value])))
1587 }
1588 Err(value) => {
1589 let value = RustToRTData::from(env, value);
1590 RTData::LData(env.root.make_obj("Err".to_string(), Some(vec![value])))
1591 }
1592 }
1593 }
1594}
1595
1596impl RustToRTData<()> for RTData {
1597 fn from(env: &mut Environment<'_>, _: ()) -> Self {
1598 RTData::LData(env.root.make_obj("Tuple".to_string(), Some(vec![])))
1599 }
1600}
1601
1602macro_rules! impl_rust_to_rt_data_tuple {
1603 ($([ $(($name_snake:ident, $name_pascal:ident)),+ $(,)? ]),+ $(,)?) => {
1604 $(impl<$($name_pascal),*> RustToRTData<($($name_pascal),*)> for RTData
1605 where $(RTData: RustToRTData<$name_pascal>),* {
1606 fn from(env: &mut Environment<'_>, ($($name_snake),*): ($($name_pascal),*)) -> Self {
1607 $(let $name_snake = <RTData as RustToRTData<$name_pascal>>::from(env, $name_snake);)*
1608 RTData::LData(env.root.make_obj("Tuple".to_string(), Some(vec![$($name_snake),*])))
1609 }
1610 })*
1611 }
1612}
1613impl_rust_to_rt_data_tuple![
1614 [(v0, V0), (v1, V1),],
1615 [(v0, V0), (v1, V1), (v2, V2),],
1616 [(v0, V0), (v1, V1), (v2, V2), (v3, V3),],
1617 [(v0, V0), (v1, V1), (v2, V2), (v3, V3), (v4, V4),],
1618 [(v0, V0), (v1, V1), (v2, V2), (v3, V3), (v4, V4), (v5, V5),],
1619 [
1620 (v0, V0),
1621 (v1, V1),
1622 (v2, V2),
1623 (v3, V3),
1624 (v4, V4),
1625 (v5, V5),
1626 (v6, V6),
1627 ],
1628 [
1629 (v0, V0),
1630 (v1, V1),
1631 (v2, V2),
1632 (v3, V3),
1633 (v4, V4),
1634 (v5, V5),
1635 (v6, V6),
1636 (v7, V7),
1637 ],
1638 [
1639 (v0, V0),
1640 (v1, V1),
1641 (v2, V2),
1642 (v3, V3),
1643 (v4, V4),
1644 (v5, V5),
1645 (v6, V6),
1646 (v7, V7),
1647 (v8, V8),
1648 ],
1649 [
1650 (v0, V0),
1651 (v1, V1),
1652 (v2, V2),
1653 (v3, V3),
1654 (v4, V4),
1655 (v5, V5),
1656 (v6, V6),
1657 (v7, V7),
1658 (v8, V8),
1659 (v9, V9),
1660 ],
1661 [
1662 (v0, V0),
1663 (v1, V1),
1664 (v2, V2),
1665 (v3, V3),
1666 (v4, V4),
1667 (v5, V5),
1668 (v6, V6),
1669 (v7, V7),
1670 (v8, V8),
1671 (v9, V9),
1672 (v10, V10),
1673 ],
1674 [
1675 (v0, V0),
1676 (v1, V1),
1677 (v2, V2),
1678 (v3, V3),
1679 (v4, V4),
1680 (v5, V5),
1681 (v6, V6),
1682 (v7, V7),
1683 (v8, V8),
1684 (v9, V9),
1685 (v10, V10),
1686 (v11, V11),
1687 ],
1688];
1689
1690impl<T> RustToRTData<Vec<T>> for RTData
1691where
1692 RTData: RustToRTData<T>,
1693{
1694 fn from(env: &mut Environment<'_>, vec: Vec<T>) -> Self {
1695 Self::LData(collection_to_list(env, vec.into_iter()))
1696 }
1697}
1698impl<T, const N: usize> RustToRTData<[T; N]> for RTData
1699where
1700 RTData: RustToRTData<T>,
1701{
1702 fn from(env: &mut Environment<'_>, slice: [T; N]) -> Self {
1703 Self::LData(collection_to_list(env, slice.into_iter()))
1704 }
1705}
1706
1707fn collection_to_list<I, T>(env: &mut Environment<'_>, iter: I) -> LDataType
1709where
1710 I: DoubleEndedIterator<Item = T>,
1711 RTData: RustToRTData<T>,
1712{
1713 let mut iter = iter
1714 .map(|item| {
1715 (
1716 "Cons".to_string(),
1717 Some(vec![<RTData as RustToRTData<T>>::from(env, item)]),
1718 )
1719 })
1720 .chain([("Nil".to_string(), None)].into_iter())
1721 .collect::<Vec<_>>()
1722 .into_iter()
1723 .map(|(label, data)| env.root.make_obj(label, data))
1724 .rev()
1725 .peekable();
1726
1727 let mut root_cons = None;
1728 while let Some(item) = iter.next() {
1729 match iter.peek_mut() {
1730 Some(next) => {
1731 next.get_ldata_mut()
1732 .data
1733 .as_mut()
1734 .expect("all items after a nil should contain a value")
1735 .push(RTData::LData(item));
1736 }
1737 None => {
1738 root_cons = Some(item);
1739 }
1740 }
1741 }
1742
1743 root_cons.expect("chaining a nil should ensure that the iterator always has a value")
1744}
1745
1746pub trait FFI {
1747 fn blisp_extern(&self) -> &'static str;
1749
1750 fn ffi(&self) -> fn(env: &mut Environment<'_>, args: &[RTData]) -> RTData;
1752
1753 fn name(&self) -> &'static str;
1755}