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 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, 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 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 (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 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 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 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 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 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 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 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 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 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 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 let library_definition = LibraryDefinition(
1565 library_name!("foo", "foo-bar").into(),
1566 vec![
1567 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 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}