ruschm/interpreter/
interpreter.rs

1#![allow(dead_code)]
2
3use crate::{import_library_direct, parser::*, values::Value};
4use error::SyntaxError;
5use itertools::Itertools;
6
7use crate::error::*;
8use crate::values::Procedure;
9use crate::{
10    environment::*, io::file_char_stream, library_factory::GenericLibraryFactory, library_name,
11    values::*,
12};
13
14#[cfg(test)]
15use crate::parser::pair::*;
16
17use std::{collections::HashMap, ops::Deref, path::Path, rc::Rc};
18use std::{collections::HashSet, iter::Iterator};
19use std::{marker::PhantomData, path::PathBuf};
20
21use super::Result;
22use super::{error::LogicError, library::native};
23use crate::interpreter::library::Library;
24use crate::parser::LibraryName;
25
26pub type LibraryFactory<'a, R> = GenericLibraryFactory<'a, Value<R>>;
27
28#[test]
29fn library_factory() -> Result<()> {
30    let mut it = Interpreter::<f32>::new();
31    it.register_library_factory(LibraryFactory::Native(
32        library_name!("foo"),
33        Box::new(|| vec![("a".to_string(), Value::Void)]),
34    ));
35    assert_eq!(
36        it.get_library(library_name!("foo").into()),
37        Ok(Library::new(
38            library_name!("foo").into(),
39            vec![("a".to_string(), Value::Void)]
40        ))
41    );
42    it.register_library_factory(LibraryFactory::from_char_stream(
43        &library_name!("foo"),
44        "(define-library (foo) (export a) (begin (define a 1)))".chars(),
45    )?);
46    assert_eq!(
47        it.get_library(library_name!("foo").into()),
48        Ok(Library::new(
49            library_name!("foo").into(),
50            vec![("a".to_string(), Value::Number(Number::Integer(1)))]
51        ))
52    );
53    Ok(())
54}
55
56#[derive(Debug, Clone, PartialEq)]
57enum TailExpressionResult<'a, R: RealNumberInternalTrait> {
58    TailCall(TailCall<'a, R>),
59    Value(Value<R>),
60}
61#[derive(Debug, Clone, PartialEq)]
62enum TailCall<'a, R: RealNumberInternalTrait> {
63    Ref(&'a Expression, &'a [Expression], Rc<Environment<R>>),
64    Owned(
65        Expression,
66        Vec<Expression>,
67        Rc<Environment<R>>,
68        PhantomData<R>,
69    ),
70}
71impl<'a, R: RealNumberInternalTrait> TailCall<'a, R> {
72    pub fn as_ref(&'a self) -> (&'a Expression, &'a [Expression], &Rc<Environment<R>>) {
73        match self {
74            TailCall::Ref(procedure_expr, arguments, env) => (procedure_expr, arguments, env),
75            TailCall::Owned(procedure_expr, arguments, env, _) => (procedure_expr, arguments, env),
76        }
77    }
78}
79pub struct LibraryLoader<'a, R: RealNumberInternalTrait> {
80    lib_factories: HashMap<LibraryName, Rc<LibraryFactory<'a, R>>>,
81}
82
83impl<'a, R: RealNumberInternalTrait> LibraryLoader<'a, R> {
84    pub fn new() -> Self {
85        Self {
86            lib_factories: HashMap::new(),
87        }
88    }
89    pub fn register_library_factory(&mut self, library_factory: LibraryFactory<'a, R>) {
90        self.lib_factories.insert(
91            library_factory.get_library_name().clone(),
92            Rc::new(library_factory),
93        );
94    }
95    pub fn with_lib_factory(mut self, library_factory: LibraryFactory<'a, R>) -> Self {
96        self.register_library_factory(library_factory);
97        self
98    }
99    /// iterate all registered library name in library loader
100    /// # Example
101    /// ```
102    /// use ruschm::library_name;
103    /// use ruschm::interpreter::{LibraryLoader, LibraryFactory};
104    /// use ruschm::parser::LibraryName;
105    /// use std::collections::HashSet;
106    /// let library_loader = LibraryLoader::<f32>::new()
107    ///     .with_lib_factory(LibraryFactory::Native(library_name!("foo"), Box::new(|| vec![])))
108    ///     .with_lib_factory(LibraryFactory::Native(
109    ///         library_name!("foo", "bar"),
110    ///         Box::new(|| vec![]),
111    ///     ))
112    ///     .with_lib_factory(LibraryFactory::Native(library_name!(0, "a"), Box::new(|| vec![])));
113    /// assert_eq!(
114    ///     library_loader.iter_library_names().collect::<HashSet<_>>(),
115    ///     vec![
116    ///         &library_name!("foo"),
117    ///         &library_name!("foo", "bar"),
118    ///         &library_name!(0, "a")
119    ///     ]
120    ///     .into_iter()
121    ///     .collect::<HashSet<_>>()
122    /// );
123    /// ```
124    pub fn iter_library_names(&self) -> impl Iterator<Item = &LibraryName> {
125        self.lib_factories.keys()
126    }
127}
128
129pub struct Interpreter<'a, R: RealNumberInternalTrait> {
130    pub env: Rc<Environment<R>>,
131    lib_loader: LibraryLoader<'a, R>,
132    imported_library: HashSet<LibraryName>,
133    import_end: bool, // indicate program's import declaration part end
134    pub program_directory: Option<PathBuf>,
135    _marker: PhantomData<R>,
136}
137
138impl<'a, R: RealNumberInternalTrait> Interpreter<'a, R> {
139    pub fn new() -> Self {
140        Self::with_environment(Rc::new(Environment::new()))
141    }
142
143    pub fn new_with_stdlib() -> Self {
144        let mut interpreter = Interpreter::<R>::new();
145        interpreter.import_stdlib();
146        interpreter
147    }
148
149    pub fn with_environment(environment: Rc<Environment<R>>) -> Self {
150        let mut interpreter = Self {
151            env: environment,
152            lib_loader: LibraryLoader::new(),
153            imported_library: HashSet::new(),
154            import_end: false,
155            program_directory: None,
156            _marker: PhantomData,
157        };
158        interpreter.register_stdlib_factories();
159        interpreter
160    }
161
162    pub fn import_stdlib(&mut self) {
163        self.eval_import(
164            &ImportDeclaration(vec![
165                import_library_direct!("scheme", "base"),
166                import_library_direct!("scheme", "write"),
167            ]),
168            self.env.clone(),
169        )
170        .unwrap();
171    }
172
173    pub fn get_lib_loader(&self) -> &LibraryLoader<R> {
174        &self.lib_loader
175    }
176    pub fn append_lib_loader(&mut self, lib_loader: LibraryLoader<'a, R>) {
177        self.lib_loader
178            .lib_factories
179            .extend(lib_loader.lib_factories.into_iter());
180    }
181    pub fn register_library_factory(&mut self, library_factory: LibraryFactory<'a, R>) {
182        self.lib_loader.register_library_factory(library_factory);
183    }
184
185    fn register_stdlib_factories(&mut self) {
186        self.register_library_factory(LibraryFactory::Native(
187            library_name!("ruschm", "base"),
188            Box::new(native::base::library_map),
189        ));
190        self.register_library_factory(LibraryFactory::Native(
191            library_name!("ruschm", "write"),
192            Box::new(native::write::library_map),
193        ));
194        self.register_library_factory(
195            LibraryFactory::from_char_stream(
196                &library_name!("scheme", "base"),
197                include_str!("library/include/scheme/base.sld").chars(),
198            )
199            .unwrap(),
200        );
201        self.register_library_factory(
202            LibraryFactory::from_char_stream(
203                &library_name!("scheme", "write"),
204                include_str!("library/include/scheme/write.sld").chars(),
205            )
206            .unwrap(),
207        );
208    }
209
210    fn apply_scheme_procedure<'b>(
211        formals: &ParameterFormals,
212        internal_definitions: &[Definition],
213        expressions: &'b [Expression],
214        closure: Rc<Environment<R>>,
215        args: ArgVec<R>,
216    ) -> Result<TailExpressionResult<'b, R>> {
217        let local_env = Rc::new(Environment::new_child(closure.clone()));
218        let mut arg_iter = args.into_iter();
219        match formals.iter_to_last(|formal| {
220            let arg = arg_iter.next().unwrap();
221            local_env.define(formal.as_name(), arg);
222        }) {
223            Some(variadic) => {
224                let list = arg_iter.collect::<Pair<R>>();
225                local_env.define(variadic.as_name(), Value::Pair(Box::new(list)));
226            }
227            None => {}
228        }
229        // if let Some(variadic) = &formals.1 {
230        //     let list = arg_iter.collect();
231        //     local_env.define(variadic.clone(), Value::Pair(list));
232        // }
233        for DefinitionBody(name, expr) in internal_definitions.into_iter().map(|d| &d.data) {
234            let value = Self::eval_expression(&expr, &local_env)?;
235            local_env.define(name.clone(), value)
236        }
237        match expressions.split_last() {
238            Some((last, other)) => {
239                for expr in other {
240                    Self::eval_expression(&expr, &local_env)?;
241                }
242                Self::eval_tail_expression(last, local_env)
243            }
244            None => unreachable!(),
245        }
246    }
247
248    pub(self) fn eval_root_expression(&self, expression: Expression) -> Result<Value<R>> {
249        Self::eval_expression(&expression, &self.env)
250    }
251
252    fn eval_procedure_call(
253        procedure_expr: &Expression,
254        arguments: &[Expression],
255        env: &Rc<Environment<R>>,
256    ) -> Result<(Procedure<R>, ArgVec<R>)> {
257        let first = Self::eval_expression(procedure_expr, env)?;
258        let evaluated_args_result = arguments
259            .iter()
260            .map(|arg| Self::eval_expression(arg, env))
261            .collect::<Result<ArgVec<_>>>()?;
262        Ok((first.expect_procedure()?, evaluated_args_result))
263    }
264
265    pub fn apply_procedure<'b>(
266        initial_procedure: &Procedure<R>,
267        mut args: ArgVec<R>,
268        env: &Rc<Environment<R>>,
269    ) -> Result<Value<R>> {
270        let formals = initial_procedure.get_parameters();
271        // let args = args.into_iter();
272        // formals.iter_to_last(|formal| args.next)
273        let (fixed_len, has_variadic) = formals.len();
274        if args.len() < fixed_len || (args.len() > fixed_len && !has_variadic) {
275            return error!(LogicError::ArgumentMissMatch(
276                formals.clone(),
277                format!("{}", args.iter().join(" "))
278            ));
279        }
280        let mut current_procedure = None;
281        loop {
282            match if current_procedure.is_none() {
283                initial_procedure
284            } else {
285                current_procedure.as_ref().unwrap()
286            } {
287                Procedure::Builtin(BuiltinProcedure { body, .. }) => {
288                    break body.apply(args, env);
289                }
290                Procedure::User(SchemeProcedure(formals, definitions, expressions), closure) => {
291                    let apply_result = Self::apply_scheme_procedure(
292                        formals,
293                        definitions,
294                        expressions,
295                        closure.clone(),
296                        args,
297                    )?;
298                    match apply_result {
299                        TailExpressionResult::TailCall(tail_call) => {
300                            let (tail_procedure_expr, tail_arguments, last_env) =
301                                tail_call.as_ref();
302                            let (tail_procedure, tail_args) = Self::eval_procedure_call(
303                                tail_procedure_expr,
304                                tail_arguments,
305                                &last_env,
306                            )?;
307                            current_procedure = Some(tail_procedure);
308                            args = tail_args;
309                        }
310                        TailExpressionResult::Value(return_value) => {
311                            break Ok(return_value);
312                        }
313                    };
314                }
315            };
316        }
317    }
318
319    fn eval_tail_expression<'b>(
320        expression: &'b Expression,
321        env: Rc<Environment<R>>,
322    ) -> Result<TailExpressionResult<'b, R>> {
323        Ok(match &expression.data {
324            ExpressionBody::ProcedureCall(procedure_expr, arguments) => {
325                TailExpressionResult::TailCall(TailCall::Ref(
326                    procedure_expr.as_ref(),
327                    arguments,
328                    env,
329                ))
330            }
331            ExpressionBody::Conditional(cond) => {
332                let (test, consequent, alternative) = cond.as_ref();
333                let condition = Self::eval_expression(&test, &env)?.as_boolean();
334                if condition {
335                    Self::eval_tail_expression(consequent, env)?
336                } else {
337                    match alternative {
338                        Some(alter) => Self::eval_tail_expression(alter, env)?,
339                        None => TailExpressionResult::Value(Value::Void),
340                    }
341                }
342            }
343            _ => TailExpressionResult::Value(Self::eval_expression(&expression, &env)?),
344        })
345    }
346    // during eval_tail_expression, some expression will expand to owned expression
347    // it has to repeat this logic for owned expression, no other workaround
348    fn eval_owned_tail_expression<'b>(
349        expression: Expression,
350        env: Rc<Environment<R>>,
351    ) -> Result<TailExpressionResult<'b, R>> {
352        Ok(match &expression.data {
353            ExpressionBody::ProcedureCall(..) | ExpressionBody::Conditional(_) => {
354                match expression.extract_data() {
355                    ExpressionBody::ProcedureCall(procedure_expr, arguments) => {
356                        TailExpressionResult::TailCall(TailCall::Owned(
357                            *procedure_expr,
358                            arguments,
359                            env,
360                            PhantomData,
361                        ))
362                    }
363                    ExpressionBody::Conditional(cond) => {
364                        let (test, consequent, alternative) = *cond;
365                        let condition = Self::eval_expression(&test, &env)?.as_boolean();
366                        if condition {
367                            Self::eval_owned_tail_expression(consequent, env)?
368                        } else {
369                            match alternative {
370                                Some(alter) => Self::eval_owned_tail_expression(alter, env)?,
371                                None => TailExpressionResult::Value(Value::Void),
372                            }
373                        }
374                    }
375                    _ => unreachable!(),
376                }
377            }
378            _ => TailExpressionResult::Value(Self::eval_expression(&expression, &env)?),
379        })
380    }
381    pub fn read_literal(datum: &Datum, env: &Rc<Environment<R>>) -> Result<Value<R>> {
382        match &datum.data {
383            DatumBody::Primitive(primitive) => Self::eval_primitive(&primitive),
384            DatumBody::Symbol(name) => Ok(Value::Symbol(name.clone())),
385            DatumBody::Pair(list) => Ok(Value::Pair(Box::new(
386                list.map_ok_ref(&mut |i| Self::read_literal(i, env))?,
387            ))),
388            DatumBody::Vector(vec) => Ok(Value::Vector(ValueReference::new_immutable(
389                vec.into_iter()
390                    .map(|i| Self::read_literal(i, env))
391                    .collect::<Result<_>>()?,
392            ))),
393        }
394    }
395
396    fn eval_primitive(datum: &Primitive) -> Result<Value<R>> {
397        Ok(match &datum {
398            Primitive::Character(c) => Value::Character(*c),
399            Primitive::String(string) => Value::String(string.clone()),
400            Primitive::Boolean(value) => Value::Boolean(*value),
401            Primitive::Integer(value) => Value::Number(Number::Integer(*value)),
402            Primitive::Real(number_literal) => Value::Number(Number::Real(
403                R::from(number_literal.parse::<f64>().unwrap()).unwrap(),
404            )),
405            // TODO: apply gcd here.
406            Primitive::Rational(a, b) => Value::Number(Number::Rational(*a, *b as i32)),
407        })
408    }
409
410    pub fn eval_expression(expression: &Expression, env: &Rc<Environment<R>>) -> Result<Value<R>> {
411        Ok(match &expression.data {
412            ExpressionBody::Primitive(datum) => Self::eval_primitive(datum)?,
413            ExpressionBody::Datum(datum) => Self::read_literal(datum, env)?,
414            ExpressionBody::ProcedureCall(procedure_expr, arguments) => {
415                let first = Self::eval_expression(procedure_expr, env)?;
416                let evaluated_args: Result<ArgVec<_>> = arguments
417                    .into_iter()
418                    .map(|arg| Self::eval_expression(arg, env))
419                    .collect();
420                match first {
421                    Value::Procedure(procedure) => {
422                        Self::apply_procedure(&procedure, evaluated_args?, env)?
423                    }
424                    other => {
425                        return located_error!(
426                            LogicError::TypeMisMatch(other.to_string(), Type::Procedure),
427                            procedure_expr.location
428                        )
429                    }
430                }
431            }
432            ExpressionBody::Period => {
433                return located_error!(
434                    LogicError::UnexpectedExpression(expression.clone()),
435                    expression.location
436                );
437            }
438            ExpressionBody::Assignment(name, value_expr) => {
439                let value = Self::eval_expression(value_expr, env)?;
440                env.set(name, value)?;
441                Value::Void
442            }
443            ExpressionBody::Procedure(scheme) => {
444                Value::Procedure(Procedure::User(scheme.clone(), env.clone()))
445            }
446            ExpressionBody::Conditional(cond) => {
447                let &(test, consequent, alternative) = &cond.as_ref();
448                if Self::eval_expression(&test, &env)?.as_boolean() {
449                    Self::eval_expression(&consequent, env)?
450                } else {
451                    match alternative {
452                        Some(alter) => Self::eval_expression(&alter, env)?,
453                        None => Value::Void,
454                    }
455                }
456            }
457            ExpressionBody::Quote(inner) => Self::read_literal(inner.as_ref(), env)?,
458
459            ExpressionBody::Symbol(ident) => match env.get(ident.as_str()) {
460                Some(value) => value.clone(),
461                None => {
462                    return located_error!(
463                        LogicError::UnboundedSymbol(ident.clone()),
464                        expression.location
465                    )
466                }
467            },
468        })
469    }
470
471    pub fn eval_import(
472        &mut self,
473        imports: &ImportDeclaration,
474        env: Rc<Environment<R>>,
475    ) -> Result<()> {
476        let mut definitions = HashMap::new();
477        for import in &imports.0 {
478            definitions.extend(self.eval_import_set(import)?.into_iter());
479        }
480        for (name, value) in definitions {
481            env.define(name, value);
482        }
483        Ok(())
484    }
485    fn file_library_factory(&self, name: &Located<LibraryName>) -> Result<LibraryFactory<'a, R>> {
486        let base_directory = if let Some(program_directory) = &self.program_directory {
487            program_directory.clone()
488        } else {
489            std::env::current_dir()?
490        };
491        // TODO: file extension, file system variants
492        let path = base_directory
493            .join(name.deref().path())
494            .with_extension("sld");
495        if path.exists() {
496            let char_stream = file_char_stream(&path)?;
497            LibraryFactory::from_char_stream(name.deref(), char_stream)
498        } else {
499            located_error!(
500                LogicError::LibraryNotFound(name.deref().clone()),
501                name.location.clone()
502            )
503        }
504    }
505    fn new_library(&mut self, factory: &LibraryFactory<R>) -> Result<Library<R>> {
506        match factory {
507            LibraryFactory::Native(name, f) => Ok(Library::new(name.clone().into(), f())),
508            LibraryFactory::AST(library_definition) => {
509                self.eval_library_definition(library_definition.deref())
510            }
511        }
512    }
513    pub fn get_library(&mut self, name: Located<LibraryName>) -> Result<Library<R>> {
514        let factory = match self.lib_loader.lib_factories.get(&name) {
515            Some(factory) => factory,
516            None => {
517                let new_factory = self.file_library_factory(&name)?;
518                self.lib_loader
519                    .lib_factories
520                    .entry(name.deref().clone())
521                    .or_insert(Rc::new(new_factory))
522            }
523        }
524        .clone();
525        self.new_library(&factory)
526    }
527    pub fn eval_import_set(&mut self, import: &ImportSet) -> Result<Vec<(String, Value<R>)>> {
528        match &import.data {
529            ImportSetBody::Direct(lib_name) => {
530                if self
531                    .imported_library
532                    .insert(lib_name.clone().extract_data())
533                {
534                    let library = self.get_library(lib_name.clone())?;
535                    self.imported_library.remove(lib_name);
536                    Ok(library
537                        .iter_definitions()
538                        .map(|(name, value)| (name.clone(), value.clone()))
539                        .collect())
540                } else {
541                    located_error!(
542                        LogicError::LibraryImportCyclic(lib_name.clone().extract_data()),
543                        lib_name.location
544                    )
545                }
546            }
547            ImportSetBody::Only(import_set, identifiers) => {
548                let id_set = identifiers.into_iter().collect::<HashSet<_>>();
549                Ok(self
550                    .eval_import_set(import_set.as_ref())?
551                    .into_iter()
552                    .filter(|(name, _)| id_set.contains(name))
553                    .collect())
554            }
555            ImportSetBody::Except(import_set, identifiers) => {
556                let id_set = identifiers.into_iter().collect::<HashSet<_>>();
557                Ok(self
558                    .eval_import_set(import_set.as_ref())?
559                    .into_iter()
560                    .filter(|(name, _)| !id_set.contains(name))
561                    .collect())
562            }
563            ImportSetBody::Prefix(import_set, prefix) => Ok(self
564                .eval_import_set(import_set.as_ref())?
565                .into_iter()
566                .map(|(name, value)| (format!("{}{}", prefix, name), value))
567                .collect()),
568            ImportSetBody::Rename(import_set, renames) => {
569                let id_map = renames
570                    .into_iter()
571                    .map(|(from, to)| (from, to))
572                    .collect::<HashMap<_, _>>();
573                Ok(self
574                    .eval_import_set(import_set.as_ref())?
575                    .into_iter()
576                    .map(|(name, value)| match id_map.get(&name) {
577                        Some(to) => ((*to).clone(), value),
578                        None => (name, value),
579                    })
580                    .collect())
581            }
582        }
583    }
584
585    pub fn eval_expression_or_definition(
586        &mut self,
587        statement: &Statement,
588        env: Rc<Environment<R>>,
589    ) -> Result<Option<Value<R>>> {
590        Ok(match statement {
591            Statement::Expression(expr) => Some(Self::eval_expression(&expr, &env)?),
592            Statement::Definition(Definition {
593                data: DefinitionBody(name, expr),
594                ..
595            }) => {
596                let value = Self::eval_expression(&expr, &env)?;
597                env.define(name.clone(), value);
598                None
599            }
600            Statement::SyntaxDefinition(syntax) => {
601                let SyntaxDefBody(name, value) = &syntax.data;
602                env.define(
603                    name.clone(),
604                    Value::Transformer(Transformer::Scheme(value.clone())),
605                );
606                None
607            }
608            _ => error!(SyntaxError::ExpectSomething(
609                "expression/definition".to_string(),
610                "other statement".to_string(),
611            ))?,
612        })
613    }
614
615    pub fn eval_ast(
616        &mut self,
617        ast: &Statement,
618        env: Rc<Environment<R>>,
619    ) -> Result<Option<Value<R>>> {
620        let ast_location = ast.location();
621        match self.eval_ast_error_no_location(ast, env) {
622            Ok(value) => Ok(value),
623            Err(Located { data, location }) => Err(data.locate(
624                // prevent loss accurate location
625                location.or(ast_location),
626            )),
627        }
628    }
629
630    pub fn eval_ast_error_no_location(
631        &mut self,
632        ast: &Statement,
633        env: Rc<Environment<R>>,
634    ) -> Result<Option<Value<R>>> {
635        if !self.import_end {
636            Ok(match ast {
637                Statement::ImportDeclaration(imports) => {
638                    self.eval_import(imports, env)?;
639                    None
640                }
641                Statement::LibraryDefinition(library_definition) => {
642                    return located_error!(
643                        SyntaxError::ExpectSomething(
644                            "import declaration/expression/definition".to_string(),
645                            "other statement".to_string(),
646                        ),
647                        library_definition.location.clone()
648                    );
649                }
650                other => {
651                    self.import_end = true;
652                    self.eval_expression_or_definition(other, env)?
653                }
654            })
655        } else {
656            self.eval_expression_or_definition(ast, env)
657        }
658    }
659
660    pub fn eval_root_ast(&mut self, ast: &Statement) -> Result<Option<Value<R>>> {
661        self.eval_ast(ast, self.env.clone())
662    }
663
664    pub fn eval_library_definition<'b>(
665        &mut self,
666        library_definition: &LibraryDefinition,
667    ) -> Result<Library<R>> {
668        let name = library_definition.0.clone();
669        let mut definitions = HashMap::new();
670        let mut final_exports = Vec::new();
671        let lib_env = Rc::new(Environment::new());
672        for declaration in &library_definition.1 {
673            match &declaration.data {
674                LibraryDeclaration::ImportDeclaration(imports) => {
675                    self.eval_import(imports, lib_env.clone())?;
676                }
677                LibraryDeclaration::Export(exports) => final_exports.extend(exports.iter()),
678                LibraryDeclaration::Begin(statements) => {
679                    for statement in statements.iter() {
680                        self.eval_expression_or_definition(statement, lib_env.clone())?;
681                    }
682                }
683            }
684        }
685        for export in final_exports {
686            let (from, to) = match &export.data {
687                ExportSpec::Direct(identifier) => (identifier, identifier),
688                ExportSpec::Rename(from, to) => (from, to),
689            };
690            match lib_env.get(from) {
691                Some(value) => {
692                    definitions.insert(to.clone(), value.clone());
693                }
694                None => located_error!(LogicError::UnboundedSymbol(from.clone()), export.location)?,
695            }
696        }
697        Ok(Library::new(name, definitions))
698    }
699    pub fn eval_program<'b>(
700        &mut self,
701        asts: impl IntoIterator<Item = &'b Statement>,
702    ) -> Result<Option<Value<R>>> {
703        asts.into_iter()
704            .try_fold(None, |_, ast| self.eval_root_ast(&ast))
705    }
706
707    pub fn eval(&mut self, char_stream: impl Iterator<Item = char>) -> Result<Option<Value<R>>> {
708        {
709            let lexer = Lexer::from_char_stream(char_stream);
710            let mut parser = Parser::from_lexer(lexer);
711            parser.try_fold(None, |_, statement| self.eval_root_ast(&statement?))
712        }
713    }
714    pub fn eval_file(&mut self, path: PathBuf) -> Result<Option<Value<R>>> {
715        self.program_directory = path.clone().parent().map(Path::to_owned);
716        self.eval(file_char_stream(&path)?)
717    }
718}
719
720#[test]
721fn number() -> Result<()> {
722    let interpreter = Interpreter::<f32>::new_with_stdlib();
723    assert_eq!(
724        interpreter
725            .eval_root_expression(ExpressionBody::Primitive(Primitive::Integer(-1)).into())?,
726        Value::Number(Number::Integer(-1))
727    );
728    assert_eq!(
729        interpreter
730            .eval_root_expression(ExpressionBody::Primitive(Primitive::Rational(1, 3)).into())?,
731        Value::Number(Number::Rational(1, 3))
732    );
733    assert_eq!(
734        interpreter.eval_root_expression(
735            ExpressionBody::Primitive(Primitive::Real("-3.45e-7".to_string()).into()).into()
736        )?,
737        Value::Number(Number::Real(-3.45e-7))
738    );
739    Ok(())
740}
741
742#[test]
743fn arithmetic() -> Result<()> {
744    let interpreter = Interpreter::<f32>::new_with_stdlib();
745
746    assert_eq!(
747        interpreter.eval_root_expression(Expression::from(ExpressionBody::ProcedureCall(
748            Box::new(Expression::from(ExpressionBody::Symbol("+".to_string()))),
749            vec![
750                ExpressionBody::Primitive(Primitive::Integer(1)).into(),
751                ExpressionBody::Primitive(Primitive::Integer(2)).into()
752            ]
753        )))?,
754        Value::Number(Number::Integer(3))
755    );
756
757    assert_eq!(
758        interpreter.eval_root_expression(Expression::from(ExpressionBody::ProcedureCall(
759            Box::new(Expression::from(ExpressionBody::Symbol("+".to_string()))),
760            vec![
761                ExpressionBody::Primitive(Primitive::Integer(1)).into(),
762                ExpressionBody::Primitive(Primitive::Rational(1, 2)).into()
763            ]
764        )))?,
765        Value::Number(Number::Rational(3, 2))
766    );
767
768    assert_eq!(
769        interpreter.eval_root_expression(Expression::from(ExpressionBody::ProcedureCall(
770            Box::new(Expression::from(ExpressionBody::Symbol("*".to_string()))),
771            vec![
772                ExpressionBody::Primitive(Primitive::Rational(1, 2)).into(),
773                ExpressionBody::Primitive(Primitive::Real("2.0".to_string()).into()).into(),
774            ]
775        )))?,
776        Value::Number(Number::Real(1.0)),
777    );
778
779    assert_eq!(
780        interpreter.eval_root_expression(Expression::from(ExpressionBody::ProcedureCall(
781            Box::new(Expression::from(ExpressionBody::Symbol("/".to_string()))),
782            vec![
783                ExpressionBody::Primitive(Primitive::Integer(1)).into(),
784                ExpressionBody::Primitive(Primitive::Integer(0)).into()
785            ]
786        ))),
787        Err(ErrorData::Logic(LogicError::DivisionByZero).no_locate()),
788    );
789
790    assert_eq!(
791        interpreter.eval_root_expression(Expression::from(ExpressionBody::ProcedureCall(
792            Box::new(Expression::from(ExpressionBody::Symbol("max".to_string()))),
793            vec![
794                ExpressionBody::Primitive(Primitive::Integer(1)).into(),
795                ExpressionBody::Primitive(Primitive::Real("1.3".to_string()).into()).into(),
796            ]
797        )))?,
798        Value::Number(Number::Real(1.3)),
799    );
800    assert_eq!(
801        interpreter.eval_root_expression(Expression::from(ExpressionBody::ProcedureCall(
802            Box::new(Expression::from(ExpressionBody::Symbol("min".to_string()))),
803            vec![
804                ExpressionBody::Primitive(Primitive::Integer(1)).into(),
805                ExpressionBody::Primitive(Primitive::Real("1.3".to_string()).into()).into(),
806            ]
807        )))?,
808        Value::Number(Number::Real(1.0)),
809    );
810    assert_eq!(
811        interpreter.eval_root_expression(Expression::from(ExpressionBody::ProcedureCall(
812            Box::new(Expression::from(ExpressionBody::Symbol("min".to_string()))),
813            vec![ExpressionBody::Primitive(Primitive::String("a".to_string()).into()).into()]
814        ))),
815        Err(ErrorData::Logic(LogicError::TypeMisMatch("a".to_string(), Type::Number)).no_locate()),
816    );
817
818    assert_eq!(
819        interpreter.eval_root_expression(Expression::from(ExpressionBody::ProcedureCall(
820            Box::new(Expression::from(ExpressionBody::Symbol("max".to_string()))),
821            vec![ExpressionBody::Primitive(Primitive::String("a".to_string()).into()).into()]
822        ))),
823        Err(ErrorData::Logic(LogicError::TypeMisMatch("a".to_string(), Type::Number)).no_locate()),
824    );
825
826    assert_eq!(
827        interpreter.eval_root_expression(Expression::from(ExpressionBody::ProcedureCall(
828            Box::new(Expression::from(ExpressionBody::Symbol("sqrt".to_string()))),
829            vec![ExpressionBody::Primitive(Primitive::Integer(4)).into()]
830        )))?,
831        Value::Number(Number::Real(2.0)),
832    );
833
834    match interpreter.eval_root_expression(Expression::from(ExpressionBody::ProcedureCall(
835        Box::new(Expression::from(ExpressionBody::Symbol("sqrt".to_string()))),
836        vec![ExpressionBody::Primitive(Primitive::Integer(-4)).into()],
837    )))? {
838        Value::Number(Number::Real(should_be_nan)) => {
839            assert!(num_traits::Float::is_nan(should_be_nan))
840        }
841        _ => panic!("sqrt result should be a number"),
842    }
843
844    for (cmp, result) in [">", "<", ">=", "<=", "="]
845        .iter()
846        .zip([false, false, true, true, true].iter())
847    {
848        assert_eq!(
849            interpreter.eval_root_expression(Expression::from(ExpressionBody::ProcedureCall(
850                Box::new(Expression::from(ExpressionBody::Symbol(cmp.to_string()))),
851                vec![
852                    ExpressionBody::Primitive(Primitive::Integer(1)).into(),
853                    ExpressionBody::Primitive(Primitive::Rational(1, 1)).into(),
854                    ExpressionBody::Primitive(Primitive::Real("1.0".to_string()).into()).into(),
855                ],
856            )))?,
857            Value::Boolean(*result)
858        )
859    }
860
861    Ok(())
862}
863
864#[test]
865fn undefined() -> Result<()> {
866    let interpreter = Interpreter::<f32>::new_with_stdlib();
867
868    assert_eq!(
869        interpreter
870            .eval_root_expression(Expression::from(ExpressionBody::Symbol("foo".to_string()))),
871        Err(ErrorData::Logic(LogicError::UnboundedSymbol("foo".to_string())).no_locate())
872    );
873    Ok(())
874}
875
876#[test]
877fn variable_definition() -> Result<()> {
878    let mut interpreter = Interpreter::<f32>::new();
879
880    let program = vec![
881        Statement::Definition(Definition::from(DefinitionBody(
882            "a".to_string(),
883            ExpressionBody::Primitive(Primitive::Integer(1)).into(),
884        ))),
885        Statement::Definition(Definition::from(DefinitionBody(
886            "b".to_string(),
887            Expression::from(ExpressionBody::Symbol("a".to_string())),
888        ))),
889        Statement::Expression(Expression::from(ExpressionBody::Symbol("b".to_string()))),
890    ];
891    assert_eq!(
892        interpreter.eval_program(program.iter())?,
893        Some(Value::Number(Number::Integer(1)))
894    );
895    Ok(())
896}
897
898#[test]
899fn variable_assignment() -> Result<()> {
900    let mut interpreter = Interpreter::<f32>::new();
901
902    let program = vec![
903        Statement::Definition(Definition::from(DefinitionBody(
904            "a".to_string(),
905            ExpressionBody::Primitive(Primitive::Integer(1)).into(),
906        ))),
907        Statement::Expression(Expression::from(ExpressionBody::Assignment(
908            "a".to_string(),
909            Box::new(ExpressionBody::Primitive(Primitive::Integer(2)).into()),
910        ))),
911        Statement::Expression(Expression::from(ExpressionBody::Symbol("a".to_string()))),
912    ];
913    assert_eq!(
914        interpreter.eval_program(program.iter())?,
915        Some(Value::Number(Number::Integer(2)))
916    );
917    Ok(())
918}
919
920#[test]
921fn builtin_procedural() -> Result<()> {
922    let mut interpreter = Interpreter::<f32>::new_with_stdlib();
923
924    let program = vec![
925        Statement::Definition(Definition::from(DefinitionBody(
926            "get-add".to_string(),
927            simple_procedure(
928                param_fixed![],
929                Expression::from(ExpressionBody::Symbol("+".to_string())),
930            ),
931        ))),
932        Statement::Expression(Expression::from(ExpressionBody::ProcedureCall(
933            Box::new(Expression::from(ExpressionBody::ProcedureCall(
934                Box::new(Expression::from(ExpressionBody::Symbol(
935                    "get-add".to_string(),
936                ))),
937                vec![],
938            ))),
939            vec![
940                ExpressionBody::Primitive(Primitive::Integer(1)).into(),
941                ExpressionBody::Primitive(Primitive::Integer(2)).into(),
942            ],
943        ))),
944    ];
945    assert_eq!(
946        interpreter.eval_program(program.iter())?,
947        Some(Value::Number(Number::Integer(3)))
948    );
949    Ok(())
950}
951
952#[test]
953fn procedure_definition() -> Result<()> {
954    let mut interpreter = Interpreter::<f32>::new_with_stdlib();
955
956    let program = vec![
957        Statement::Definition(Definition::from(DefinitionBody(
958            "add".to_string(),
959            simple_procedure(
960                param_fixed!["x", "y"],
961                Expression::from(ExpressionBody::ProcedureCall(
962                    Box::new(Expression::from(ExpressionBody::Symbol("+".to_string()))),
963                    vec![
964                        Expression::from(ExpressionBody::Symbol("x".to_string())),
965                        Expression::from(ExpressionBody::Symbol("y".to_string())),
966                    ],
967                )),
968            ),
969        ))),
970        Statement::Expression(Expression::from(ExpressionBody::ProcedureCall(
971            Box::new(Expression::from(ExpressionBody::Symbol("add".to_string()))),
972            vec![
973                ExpressionBody::Primitive(Primitive::Integer(1)).into(),
974                ExpressionBody::Primitive(Primitive::Integer(2)).into(),
975            ],
976        ))),
977    ];
978    assert_eq!(
979        interpreter.eval_program(program.iter())?,
980        Some(Value::Number(Number::Integer(3)))
981    );
982    Ok(())
983}
984
985#[test]
986fn procedure_debug() -> Result<()> {
987    let mut interpreter = Interpreter::<f32>::new();
988
989    let program = vec![Statement::Expression(simple_procedure(
990        param_fixed!["x".to_string(), "y".to_string()],
991        Expression::from(ExpressionBody::ProcedureCall(
992            Box::new(Expression::from(ExpressionBody::Symbol("+".to_string()))),
993            vec![
994                Expression::from(ExpressionBody::Symbol("x".to_string())),
995                Expression::from(ExpressionBody::Symbol("y".to_string())),
996            ],
997        )),
998    ))];
999    // If impl SchemeProcedure with default Debug, this println will end up with an infinite recursion
1000    println!("{:?}", interpreter.eval_program(program.iter())?);
1001    Ok(())
1002}
1003
1004#[test]
1005fn lambda_call() -> Result<()> {
1006    let mut interpreter = Interpreter::<f32>::new_with_stdlib();
1007
1008    let program = vec![Statement::Expression(Expression::from(
1009        ExpressionBody::ProcedureCall(
1010            Box::new(simple_procedure(
1011                append_variadic_param!(param_fixed!["x", "y"], "z"),
1012                Expression::from(ExpressionBody::ProcedureCall(
1013                    Box::new(Expression::from(ExpressionBody::Symbol("+".to_string()))),
1014                    vec![
1015                        Expression::from(ExpressionBody::Symbol("x".to_string())),
1016                        Expression::from(ExpressionBody::Symbol("y".to_string())),
1017                    ],
1018                )),
1019            )),
1020            vec![
1021                ExpressionBody::Primitive(Primitive::Integer(1)).into(),
1022                ExpressionBody::Primitive(Primitive::Integer(2)).into(),
1023                ExpressionBody::Primitive(Primitive::String("something-else".to_string()).into())
1024                    .into(),
1025            ],
1026        ),
1027    ))];
1028    assert_eq!(
1029        interpreter.eval_program(program.iter())?,
1030        Some(Value::Number(Number::Integer(3)))
1031    );
1032    Ok(())
1033}
1034
1035#[test]
1036fn closure() -> Result<()> {
1037    let mut interpreter = Interpreter::<f32>::new_with_stdlib();
1038
1039    let program = vec![
1040        Statement::Definition(Definition::from(DefinitionBody(
1041            "counter-creator".to_string(),
1042            Expression::from(ExpressionBody::Procedure(SchemeProcedure(
1043                param_fixed![],
1044                vec![Definition::from(DefinitionBody(
1045                    "current".to_string(),
1046                    ExpressionBody::Primitive(Primitive::Integer(0)).into(),
1047                ))],
1048                vec![Expression::from(ExpressionBody::Procedure(
1049                    SchemeProcedure(
1050                        param_fixed![],
1051                        vec![],
1052                        vec![
1053                            Expression::from(ExpressionBody::Assignment(
1054                                "current".to_string(),
1055                                Box::new(Expression::from(ExpressionBody::ProcedureCall(
1056                                    Box::new(Expression::from(ExpressionBody::Symbol(
1057                                        "+".to_string(),
1058                                    ))),
1059                                    vec![
1060                                        Expression::from(ExpressionBody::Symbol(
1061                                            "current".to_string(),
1062                                        )),
1063                                        ExpressionBody::Primitive(Primitive::Integer(1)).into(),
1064                                    ],
1065                                ))),
1066                            )),
1067                            Expression::from(ExpressionBody::Symbol("current".to_string())),
1068                        ],
1069                    ),
1070                ))],
1071            ))),
1072        ))),
1073        Statement::Definition(Definition::from(DefinitionBody(
1074            "counter".to_string(),
1075            Expression::from(ExpressionBody::ProcedureCall(
1076                Box::new(Expression::from(ExpressionBody::Symbol(
1077                    "counter-creator".to_string(),
1078                ))),
1079                vec![],
1080            )),
1081        ))),
1082        Statement::Expression(Expression::from(ExpressionBody::ProcedureCall(
1083            Box::new(Expression::from(ExpressionBody::Symbol(
1084                "counter".to_string(),
1085            ))),
1086            vec![],
1087        ))),
1088        Statement::Expression(Expression::from(ExpressionBody::ProcedureCall(
1089            Box::new(Expression::from(ExpressionBody::Symbol(
1090                "counter".to_string(),
1091            ))),
1092            vec![],
1093        ))),
1094    ];
1095    assert_eq!(
1096        interpreter.eval_program(program.iter())?,
1097        Some(Value::Number(Number::Integer(2)))
1098    );
1099    Ok(())
1100}
1101#[test]
1102fn condition() -> Result<()> {
1103    let mut interpreter = Interpreter::<f32>::new();
1104
1105    assert_eq!(
1106        interpreter.eval_program(
1107            vec![Statement::Expression(Expression::from(
1108                ExpressionBody::Conditional(Box::new((
1109                    ExpressionBody::Primitive(Primitive::Boolean(true)).into(),
1110                    ExpressionBody::Primitive(Primitive::Integer(1)).into(),
1111                    Some(ExpressionBody::Primitive(Primitive::Integer(2)).into()),
1112                ))),
1113            ))]
1114            .iter()
1115        )?,
1116        Some(Value::Number(Number::Integer(1)))
1117    );
1118    assert_eq!(
1119        interpreter.eval_program(
1120            vec![Statement::Expression(Expression::from(
1121                ExpressionBody::Conditional(Box::new((
1122                    ExpressionBody::Primitive(Primitive::Boolean(false)).into(),
1123                    ExpressionBody::Primitive(Primitive::Integer(1)).into(),
1124                    Some(ExpressionBody::Primitive(Primitive::Integer(2)).into()),
1125                ))),
1126            ))]
1127            .iter()
1128        )?,
1129        Some(Value::Number(Number::Integer(2)))
1130    );
1131    Ok(())
1132}
1133
1134#[test]
1135fn local_environment() -> Result<()> {
1136    let mut interpreter = Interpreter::<f32>::new_with_stdlib();
1137
1138    let program = vec![
1139        Statement::Definition(Definition::from(DefinitionBody(
1140            "adda".to_string(),
1141            simple_procedure(
1142                param_fixed![ParameterFormalsBody::Name("x".to_string())],
1143                Expression::from(ExpressionBody::ProcedureCall(
1144                    Box::new(Expression::from(ExpressionBody::Symbol("+".to_string()))),
1145                    vec![
1146                        Expression::from(ExpressionBody::Symbol("x".to_string())),
1147                        Expression::from(ExpressionBody::Symbol("a".to_string())),
1148                    ],
1149                )),
1150            ),
1151        ))),
1152        Statement::Definition(Definition::from(DefinitionBody(
1153            "a".to_string(),
1154            ExpressionBody::Primitive(Primitive::Integer(1)).into(),
1155        ))),
1156        Statement::Expression(Expression::from(ExpressionBody::ProcedureCall(
1157            Box::new(Expression::from(ExpressionBody::Symbol("adda".to_string()))),
1158            vec![ExpressionBody::Primitive(Primitive::Integer(2)).into()],
1159        ))),
1160    ];
1161    assert_eq!(
1162        interpreter.eval_program(program.iter())?,
1163        Some(Value::Number(Number::Integer(3)))
1164    );
1165    Ok(())
1166}
1167
1168#[test]
1169fn procedure_as_data() -> Result<()> {
1170    let mut interpreter = Interpreter::<f32>::new_with_stdlib();
1171
1172    let program = vec![
1173        Statement::Definition(Definition::from(DefinitionBody(
1174            "add".to_string(),
1175            simple_procedure(
1176                param_fixed!["x", "y"],
1177                Expression::from(ExpressionBody::ProcedureCall(
1178                    Box::new(Expression::from(ExpressionBody::Symbol("+".to_string()))),
1179                    vec![
1180                        Expression::from(ExpressionBody::Symbol("x".to_string())),
1181                        Expression::from(ExpressionBody::Symbol("y".to_string())),
1182                    ],
1183                )),
1184            ),
1185        ))),
1186        Statement::Definition(Definition::from(DefinitionBody(
1187            "apply-op".to_string(),
1188            simple_procedure(
1189                param_fixed!["op", "x", "y"],
1190                Expression::from(ExpressionBody::ProcedureCall(
1191                    Box::new(Expression::from(ExpressionBody::Symbol("op".to_string()))),
1192                    vec![
1193                        Expression::from(ExpressionBody::Symbol("x".to_string())),
1194                        Expression::from(ExpressionBody::Symbol("y".to_string())),
1195                    ],
1196                )),
1197            ),
1198        ))),
1199        Statement::Expression(Expression::from(ExpressionBody::ProcedureCall(
1200            Box::new(Expression::from(ExpressionBody::Symbol(
1201                "apply-op".to_string(),
1202            ))),
1203            vec![
1204                Expression::from(ExpressionBody::Symbol("add".to_string())),
1205                ExpressionBody::Primitive(Primitive::Integer(1)).into(),
1206                ExpressionBody::Primitive(Primitive::Integer(2)).into(),
1207            ],
1208        ))),
1209    ];
1210    assert_eq!(
1211        interpreter.eval_program(program.iter())?,
1212        Some(Value::Number(Number::Integer(3)))
1213    );
1214    Ok(())
1215}
1216
1217#[test]
1218fn eval_tail_expression() -> Result<()> {
1219    let expect_result = convert_located(vec![
1220        ExpressionBody::Primitive(Primitive::Integer(2)),
1221        ExpressionBody::Primitive(Primitive::Integer(5)),
1222    ]);
1223    let interpreter = Interpreter::<f32>::new_with_stdlib();
1224
1225    {
1226        let expression = ExpressionBody::Primitive(Primitive::Integer(3)).into();
1227        assert_eq!(
1228            Interpreter::eval_tail_expression(&expression, interpreter.env.clone())?,
1229            TailExpressionResult::Value(Value::Number(Number::Integer(3)))
1230        );
1231    }
1232    {
1233        let expression = Expression::from(ExpressionBody::ProcedureCall(
1234            Box::new(Expression::from(ExpressionBody::Symbol("+".to_string()))),
1235            expect_result.clone(),
1236        ));
1237        assert_eq!(
1238            Interpreter::eval_tail_expression(&expression, interpreter.env.clone())?,
1239            TailExpressionResult::TailCall(TailCall::Ref(
1240                &Expression::from(ExpressionBody::Symbol("+".to_string())),
1241                &expect_result,
1242                interpreter.env.clone()
1243            ))
1244        );
1245    }
1246    {
1247        let expression = Expression::from(ExpressionBody::Conditional(Box::new((
1248            ExpressionBody::Primitive(Primitive::Boolean(true)).into(),
1249            Expression::from(ExpressionBody::ProcedureCall(
1250                Box::new(Expression::from(ExpressionBody::Symbol("+".to_string()))),
1251                expect_result.clone(),
1252            )),
1253            None,
1254        ))));
1255        assert_eq!(
1256            Interpreter::eval_tail_expression(&expression, interpreter.env.clone())?,
1257            TailExpressionResult::TailCall(TailCall::Ref(
1258                &Expression::from(ExpressionBody::Symbol("+".to_string())),
1259                &expect_result,
1260                interpreter.env.clone()
1261            ))
1262        );
1263    }
1264    {
1265        let expression = Expression::from(ExpressionBody::Conditional(Box::new((
1266            ExpressionBody::Primitive(Primitive::Boolean(false)).into(),
1267            Expression::from(ExpressionBody::ProcedureCall(
1268                Box::new(Expression::from(ExpressionBody::Symbol("+".to_string()))),
1269                expect_result.clone(),
1270            )),
1271            Some(ExpressionBody::Primitive(Primitive::Integer(4)).into()),
1272        ))));
1273        assert_eq!(
1274            Interpreter::eval_tail_expression(&expression, interpreter.env.clone())?,
1275            TailExpressionResult::Value(Value::Number(Number::Integer(4)))
1276        );
1277    }
1278    {
1279        let expression = Expression::from(ExpressionBody::Conditional(Box::new((
1280            ExpressionBody::Primitive(Primitive::Boolean(false)).into(),
1281            ExpressionBody::Primitive(Primitive::Integer(4)).into(),
1282            Some(Expression::from(ExpressionBody::ProcedureCall(
1283                Box::new(Expression::from(ExpressionBody::Symbol("+".to_string()))),
1284                expect_result.clone(),
1285            ))),
1286        ))));
1287        assert_eq!(
1288            Interpreter::eval_tail_expression(&expression, interpreter.env.clone())?,
1289            TailExpressionResult::TailCall(TailCall::Ref(
1290                &Expression::from(ExpressionBody::Symbol("+".to_string())),
1291                &expect_result,
1292                interpreter.env.clone()
1293            ))
1294        );
1295    }
1296    Ok(())
1297}
1298
1299#[test]
1300fn datum_literal() -> Result<()> {
1301    let interpreter = Interpreter::<f32>::new();
1302
1303    assert_eq!(
1304        Interpreter::eval_expression(
1305            &ExpressionBody::Quote(Box::new(DatumBody::Primitive(Primitive::Integer(1)).into()))
1306                .into(),
1307            &interpreter.env,
1308        )?,
1309        1.into()
1310    );
1311    assert_eq!(
1312        Interpreter::eval_expression(
1313            &ExpressionBody::Quote(Box::new(DatumBody::Symbol("a".to_string()).into())).into(),
1314            &interpreter.env,
1315        )?,
1316        Value::Symbol("a".to_string())
1317    );
1318    assert_eq!(
1319        Interpreter::eval_expression(
1320            &ExpressionBody::Quote(
1321                Box::<Datum>::new(
1322                    DatumBody::Pair(Box::new(list![
1323                        DatumBody::Primitive(Primitive::Integer(1)).into()
1324                    ]))
1325                    .into()
1326                )
1327                .into()
1328            )
1329            .into(),
1330            &interpreter.env,
1331        )?,
1332        Box::new(Pair::Some(
1333            Value::Number(Number::Integer(1)),
1334            Value::from(Box::new(Pair::Empty))
1335        ))
1336        .into()
1337    );
1338    assert_eq!(
1339        Interpreter::eval_expression(
1340            &ExpressionBody::Quote(
1341                Box::<Datum>::new(
1342                    DatumBody::Vector(vec![DatumBody::Symbol("a".to_string()).into()]).into()
1343                )
1344                .into()
1345            )
1346            .into(),
1347            &interpreter.env,
1348        )?,
1349        Value::Vector(ValueReference::new_immutable(vec![Value::Symbol(
1350            "a".to_string()
1351        )]))
1352    );
1353    Ok(())
1354}
1355
1356#[test]
1357fn search_library() -> Result<()> {
1358    let mut interpreter = Interpreter::<f32>::new();
1359    {
1360        let library = interpreter.get_library(library_name!("scheme", "base").into())?;
1361        assert!(library
1362            .iter_definitions()
1363            .find(|(name, _)| name.as_str() == "+")
1364            .is_some());
1365    }
1366    {
1367        // not exist
1368        let library = interpreter.get_library(library_name!("lib", "not", "exist").into());
1369        assert_eq!(
1370            library,
1371            error!(LogicError::LibraryNotFound(library_name!(
1372                "lib", "not", "exist"
1373            )))
1374        );
1375    }
1376    let lib_not_exist_factory = LibraryFactory::Native(
1377        library_name!("lib", "not", "exist"),
1378        Box::new(|| vec![("a".to_string(), Value::Boolean(false))]),
1379    );
1380    // exist now
1381    interpreter.register_library_factory(lib_not_exist_factory);
1382    {
1383        let library = interpreter.get_library(library_name!("lib", "not", "exist").into())?;
1384        assert_eq!(
1385            library
1386                .iter_definitions()
1387                .find(|(name, _)| name.as_str() == "a"),
1388            Some((&"a".to_string(), &Value::Boolean(false)))
1389        );
1390    }
1391    Ok(())
1392}
1393
1394#[test]
1395fn import_set() -> Result<()> {
1396    let mut interpreter = Interpreter::<f32>::new();
1397    interpreter.register_library_factory(LibraryFactory::Native(
1398        library_name!("foo", "bar"),
1399        Box::new(|| {
1400            vec![
1401                ("a".to_string(), Value::String("father".to_string())),
1402                ("b".to_string(), Value::String("bob".to_string())),
1403            ]
1404        }),
1405    ));
1406    let direct = ImportSetBody::Direct(library_name!("foo", "bar").into());
1407    {
1408        let definitions = interpreter.eval_import_set(&direct.clone().into())?;
1409        assert!(definitions.len() == 2);
1410        assert!(definitions.contains(&("a".to_string(), Value::String("father".to_string()))));
1411        assert!(definitions.contains(&("b".to_string(), Value::String("bob".to_string()))));
1412    }
1413    {
1414        let only = ImportSetBody::Only(Box::new(direct.clone().into()), vec!["b".to_string()]);
1415        let definitions = interpreter.eval_import_set(&only.into())?;
1416        assert!(definitions.len() == 1);
1417        assert!(definitions.contains(&("b".to_string(), Value::String("bob".to_string()))));
1418    }
1419    let prefix = ImportSetBody::Prefix(Box::new(direct.clone().into()), "god-".to_string());
1420    {
1421        let definitions = interpreter.eval_import_set(&prefix.clone().into())?;
1422        assert!(definitions.len() == 2);
1423        assert!(definitions.contains(&("god-a".to_string(), Value::String("father".to_string()))));
1424        assert!(definitions.contains(&("god-b".to_string(), Value::String("bob".to_string()))));
1425    }
1426    {
1427        let except =
1428            ImportSetBody::Except(Box::new(prefix.clone().into()), vec!["god-b".to_string()]);
1429        let definitions = interpreter.eval_import_set(&except.into())?;
1430        assert!(definitions.len() == 1);
1431        assert!(definitions.contains(&("god-a".to_string(), Value::String("father".to_string()))));
1432    }
1433    {
1434        let rename = ImportSetBody::Rename(
1435            Box::new(prefix.clone().into()),
1436            vec![("god-b".to_string(), "human-a".to_string())],
1437        );
1438        let definitions = interpreter.eval_import_set(&rename.into())?;
1439        assert!(definitions.len() == 2);
1440        assert!(definitions.contains(&("god-a".to_string(), Value::String("father".to_string()))));
1441        assert!(definitions.contains(&("human-a".to_string(), Value::String("bob".to_string()))));
1442    }
1443    Ok(())
1444}
1445#[test]
1446fn import() -> Result<()> {
1447    let mut interpreter = Interpreter::<f32>::new();
1448    interpreter.register_library_factory(LibraryFactory::Native(
1449        library_name!("foo", "bar"),
1450        Box::new(|| {
1451            vec![
1452                ("a".to_string(), Value::String("father".to_string())),
1453                ("b".to_string(), Value::String("bob".to_string())),
1454            ]
1455        }),
1456    ));
1457    let import_declaration = ImportDeclaration(vec![
1458        ImportSetBody::Only(
1459            Box::new(ImportSetBody::Direct(library_name!("foo", "bar").into()).into()),
1460            vec!["b".to_string()],
1461        )
1462        .into(),
1463        ImportSetBody::Rename(
1464            Box::new(ImportSetBody::Direct(library_name!("foo", "bar").into()).into()),
1465            vec![("a".to_string(), "c".to_string())],
1466        )
1467        .into(),
1468    ]);
1469    use std::ops::Deref;
1470    interpreter.eval_import(&import_declaration, interpreter.env.clone())?;
1471    {
1472        let value = interpreter.env.get("b").unwrap();
1473        assert_eq!(value.deref(), &Value::String("bob".to_string()));
1474    }
1475    {
1476        let value = interpreter.env.get("c").unwrap();
1477        assert_eq!(value.deref(), &Value::String("father".to_string()));
1478    }
1479    Ok(())
1480}
1481
1482#[test]
1483fn library_definition() -> Result<()> {
1484    let mut interpreter = Interpreter::<f32>::new();
1485    interpreter.register_library_factory(LibraryFactory::Native(
1486        library_name!("foo", "bar"),
1487        Box::new(|| {
1488            vec![
1489                ("a".to_string(), Value::String("father".to_string())),
1490                ("b".to_string(), Value::String("bob".to_string())),
1491            ]
1492        }),
1493    ));
1494    {
1495        // empty library
1496        let library_definition = LibraryDefinition(library_name!("foo", "foo-bar").into(), vec![]);
1497        let library = interpreter.eval_library_definition(&library_definition)?;
1498        assert_eq!(
1499            library,
1500            Library::new(library_name!("foo", "foo-bar").into(), vec![])
1501        );
1502    }
1503    {
1504        // export direct
1505        let library_definition = LibraryDefinition(
1506            library_name!("foo", "foo-bar").into(),
1507            vec![
1508                LibraryDeclaration::ImportDeclaration(
1509                    ImportDeclaration(vec![ImportSetBody::Direct(
1510                        library_name!("foo", "bar").into(),
1511                    )
1512                    .into()])
1513                    .no_locate(),
1514                )
1515                .into(),
1516                LibraryDeclaration::Export(vec![ExportSpec::Direct("a".to_string()).into()]).into(),
1517            ],
1518        );
1519        let library = interpreter.eval_library_definition(&library_definition)?;
1520        assert_eq!(
1521            library,
1522            Library::new(
1523                library_name!("foo", "foo-bar").into(),
1524                vec![("a".to_string(), Value::String("father".to_string()))]
1525            )
1526        );
1527    }
1528    {
1529        // export direct and rename
1530        let library_definition = LibraryDefinition(
1531            library_name!("foo", "foo-bar").into(),
1532            vec![
1533                LibraryDeclaration::Export(vec![ExportSpec::Rename(
1534                    "b".to_string(),
1535                    "c".to_string(),
1536                )
1537                .into()])
1538                .into(),
1539                LibraryDeclaration::ImportDeclaration(
1540                    ImportDeclaration(vec![ImportSetBody::Direct(
1541                        library_name!("foo", "bar").into(),
1542                    )
1543                    .into()])
1544                    .no_locate(),
1545                )
1546                .into(),
1547                LibraryDeclaration::Export(vec![ExportSpec::Direct("a".to_string()).into()]).into(),
1548            ],
1549        );
1550        let library = interpreter.eval_library_definition(&library_definition)?;
1551        assert_eq!(
1552            library,
1553            Library::new(
1554                library_name!("foo", "foo-bar").into(),
1555                vec![
1556                    ("a".to_string(), Value::String("father".to_string())),
1557                    ("c".to_string(), Value::String("bob".to_string()))
1558                ]
1559            )
1560        );
1561    }
1562    {
1563        // export local define
1564        let library_definition = LibraryDefinition(
1565            library_name!("foo", "foo-bar").into(),
1566            vec![
1567                // define need (scheme base)
1568                LibraryDeclaration::ImportDeclaration(
1569                    ImportDeclaration(vec![ImportSetBody::Direct(
1570                        library_name!("scheme", "base").into(),
1571                    )
1572                    .into()])
1573                    .no_locate(),
1574                )
1575                .into(),
1576                LibraryDeclaration::Begin(vec![Statement::Definition(
1577                    DefinitionBody(
1578                        "a".to_string(),
1579                        ExpressionBody::Primitive(Primitive::Integer(5)).into(),
1580                    )
1581                    .into(),
1582                )])
1583                .into(),
1584                LibraryDeclaration::Export(vec![ExportSpec::Direct("a".to_string()).into()]).into(),
1585            ],
1586        );
1587        let library = interpreter.eval_library_definition(&library_definition)?;
1588        assert_eq!(
1589            library,
1590            Library::new(
1591                library_name!("foo", "foo-bar").into(),
1592                vec![("a".to_string(), Value::Number(Number::Integer(5))),]
1593            )
1594        );
1595    }
1596
1597    Ok(())
1598}
1599
1600#[test]
1601fn import_cyclic() -> Result<()> {
1602    let mut it = Interpreter::<f32>::new();
1603    it.register_library_factory(LibraryFactory::from_char_stream(
1604        &library_name!("foo"),
1605        "(define-library (foo) (import (foo)))".chars(),
1606    )?);
1607    let result = it.get_library(library_name!("foo").into());
1608    assert_eq!(
1609        result,
1610        error!(LogicError::LibraryImportCyclic(library_name!("foo")))
1611    );
1612    Ok(())
1613}
1614
1615#[test]
1616#[ignore]
1617fn transformer() -> Result<()> {
1618    let it = Interpreter::<f32>::new_with_stdlib();
1619    // transform to expression
1620    it.env.define(
1621        "foo".to_string(),
1622        Value::Transformer(Transformer::Native(|datum| {
1623            Ok(DatumBody::Pair(Box::new(GenericPair::cons(
1624                DatumBody::Symbol("+".to_string()).into(),
1625                datum.into(),
1626            )))
1627            .no_locate())
1628        })),
1629    );
1630    let env = it.env.clone();
1631    assert_eq!(
1632        Interpreter::eval_expression(
1633            &ExpressionBody::ProcedureCall(
1634                Box::new(ExpressionBody::Symbol("foo".to_string()).into()),
1635                vec![
1636                    ExpressionBody::Primitive(Primitive::Integer(1)).into(),
1637                    ExpressionBody::Primitive(Primitive::Integer(2)).into(),
1638                    ExpressionBody::Primitive(Primitive::Integer(3)).into(),
1639                ],
1640            )
1641            .into(),
1642            &env,
1643        ),
1644        Ok(Value::Number(Number::Integer(6)))
1645    );
1646    assert_eq!(
1647        Interpreter::eval_tail_expression(
1648            &ExpressionBody::ProcedureCall(
1649                Box::new(ExpressionBody::Symbol("foo".to_string()).into()),
1650                vec![
1651                    ExpressionBody::Primitive(Primitive::Integer(1)).into(),
1652                    ExpressionBody::Primitive(Primitive::Integer(2)).into(),
1653                    ExpressionBody::Primitive(Primitive::Integer(3)).into(),
1654                ],
1655            )
1656            .into(),
1657            env.clone(),
1658        ),
1659        Ok(TailExpressionResult::TailCall(TailCall::Owned(
1660            ExpressionBody::Symbol("+".to_string()).into(),
1661            vec![
1662                ExpressionBody::Primitive(Primitive::Integer(1)).into(),
1663                ExpressionBody::Primitive(Primitive::Integer(2)).into(),
1664                ExpressionBody::Primitive(Primitive::Integer(3)).into(),
1665            ],
1666            env,
1667            PhantomData
1668        )))
1669    );
1670
1671    Ok(())
1672}
1673
1674#[test]
1675fn ast_location() -> Result<()> {
1676    let mut interpreter = Interpreter::<f32>::new();
1677    assert_eq!(
1678        interpreter
1679            .eval_ast(
1680                &ExpressionBody::Symbol("foo".to_string())
1681                    .locate(Some([4, 6]))
1682                    .into(),
1683                Rc::new(Environment::new())
1684            )
1685            .unwrap_err()
1686            .location,
1687        Some([4, 6])
1688    );
1689    Ok(())
1690}