diff --git a/src/lib.rs b/src/lib.rs index 680eb6b..c7c8334 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,4 +38,5 @@ pub mod stdlib { pub use crate::stl::{get_stdlib}; pub use crate::str::{get_echo, get_concat}; pub use crate::append::{get_append}; + pub use crate::vars::{get_export}; } diff --git a/src/stl.rs b/src/stl.rs index 4f19ecf..1dca9fa 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -18,6 +18,7 @@ use crate::str::{get_echo, get_concat}; use crate::append::get_append; use crate::func::{FTable, func_declare}; +use crate::vars::{get_export}; use std::rc::Rc; use std::cell::RefCell; @@ -32,6 +33,9 @@ pub fn get_stdlib() -> Result>, String> { if let Some(s) = func_declare(ft.clone(), Rc::new(RefCell::new(get_concat()))) { return Err(s) } + if let Some(s) = func_declare(ft.clone(), Rc::new(RefCell::new(get_export()))) { + return Err(s) + } return Ok(ft) } diff --git a/src/test_lib_vars.rs b/src/test_lib_vars.rs new file mode 100644 index 0000000..cd96e67 --- /dev/null +++ b/src/test_lib_vars.rs @@ -0,0 +1,67 @@ +mod str_lib_tests { + use relish::stdlib::{get_stdlib}; + use relish::ast::{lex, eval, ast_to_string, VTable, FTable, Ctr}; + use std::rc::Rc; + use std::cell::RefCell; + + #[test] + fn test_variable_export_and_lookup() { + let doc1 = "(export test 1)"; + let doc2 = "(echo test)"; + let result = "1"; + let vt = Rc::new(RefCell::new(VTable::new())); + let ft: Rc>; + match get_stdlib() { + Ok(f) => ft = f, + Err(s) => { + ft = Rc::new(RefCell::new(FTable::new())); + println!("Couldnt get stdlib: {}!", s); + assert!(false); + } + } + + match lex(doc1.to_string()) { + Err(s) => { + println!("Couldnt lex {}: {}", doc1, s); + assert!(false); + }, + + Ok(tree) => { + match eval(tree, vt.clone(), ft.clone(), false) { + Err(s) => { + println!("Couldnt eval {}: {}", doc2, s); + assert!(false); + }, + + Ok(ctr) => { + Ctr::None => assert!(true), + _ => assert!(false) + } + } + } + } + + match lex(doc2.to_string()) { + Err(s) => { + println!("Couldnt lex {}: {}", doc2, s); + assert!(false); + }, + + Ok(tree) => { + match eval(tree, vt.clone(), ft.clone(), false) { + Err(s) => { + println!("Couldnt eval {}: {}", doc2, s); + assert!(false); + }, + + Ok(ctr) => { + match ctr { + Ctr::String(s) => assert_eq!(s, result), + _ => assert!(false) + } + } + } + } + } + } +} diff --git a/src/vars.rs b/src/vars.rs index fc0784b..2813c2b 100644 --- a/src/vars.rs +++ b/src/vars.rs @@ -18,8 +18,8 @@ use std::cell::RefCell; use std::rc::Rc; use std::collections::HashMap; -use crate::segment::{Ctr}; - +use crate::segment::{Ctr, Ast}; +use crate::func::{Function, Operation, Args, FTable}; /* Mapping between a string token and a tree of Segments * The string token can be found in any Ctr::Symbol value * it is expected that the trees stored are already evaluated @@ -36,3 +36,27 @@ pub fn define( drop(rc_segment); } } + +pub fn get_export() -> Function { + return Function{ + name: String::from("export"), + loose_syms: true, + eval_lazy: false, + args: Args::Lazy(2), + function: Operation::Internal( + |a: Ast, b: Rc>, _c: Rc>| -> Ctr { + let inner = a.borrow_mut(); + match &inner.car { + Ctr::Symbol(identifier) => { + define(b, identifier.to_string(), Rc::new(inner.cdr.clone())); + return Ctr::None; + }, + _ => { + eprintln!("first argument to export must be a symbol"); + return Ctr::None; + } + } + } + ) + }; +} diff --git a/tests/test_lib_str.rs b/tests/test_lib_str.rs index b568628..2cad97d 100644 --- a/tests/test_lib_str.rs +++ b/tests/test_lib_str.rs @@ -1,11 +1,11 @@ mod str_lib_tests { use relish::stdlib::{get_stdlib}; - use relish::ast::{lex, eval, ast_to_string, VTable, FTable, Ctr}; + use relish::ast::{lex, eval, VTable, FTable, Ctr}; use std::rc::Rc; use std::cell::RefCell; #[test] - fn test_simple_echo() { + fn test_simple_concat() { let document = "(concat 'test')"; let result = "test"; let vt = Rc::new(RefCell::new(VTable::new())); @@ -49,7 +49,7 @@ mod str_lib_tests { } #[test] - fn test_poly_echo() { + fn test_poly_concat() { let document = "(concat 'test' 1 2 3)"; let result = "test123"; let vt = Rc::new(RefCell::new(VTable::new())); @@ -93,7 +93,7 @@ mod str_lib_tests { } #[test] - fn test_empty_echo() { + fn test_empty_concat() { let document = "(concat)"; let result = ""; let vt = Rc::new(RefCell::new(VTable::new()));