From 1f2007957190283e29fe7f459adfd9df2e6fbf39 Mon Sep 17 00:00:00 2001 From: teo3300 Date: Wed, 29 May 2024 08:51:38 +0900 Subject: [PATCH] Fixing some atom functions --- core/core.mal | 7 +++++-- src/core.rs | 19 +++++++++++++++---- src/env.rs | 2 +- src/main.rs | 4 +++- src/parse_tools.rs | 6 +++++- src/step6_file.rs | 2 ++ src/types.rs | 6 ++++++ 7 files changed, 37 insertions(+), 9 deletions(-) diff --git a/core/core.mal b/core/core.mal index 4f198c3..746d148 100644 --- a/core/core.mal +++ b/core/core.mal @@ -46,9 +46,11 @@ (= (count l) 0))) (def! assert-eq (fn* [a b] + "returns an error if arguments are not equals, NIL otherwise" (assert (= a b)))) (def! assert-fail (fn* [x] + "returns NIL if evaluation of argument fails, error otherwise" (assert (not (ok? (eval x)))))) ;; Since thread safety is not required, I will leave it like this, @@ -58,13 +60,16 @@ ;; File-interaction functions (def! load-file (fn* [f] + "open a mal file and evaluate its content" (eval (read-string (str "(do " (slurp f) "\nnil)"))))) (def! conf-reload (fn* [] + "reload mal config file" (load-file (str MAL_HOME "/" "config.mal")))) ;; Shorthand (def! quit (fn* [] + "Quit the program with status '0'" (exit 0))) ;; variables @@ -132,5 +137,3 @@ "; (help ) : print information about a symbol\n" ";\n" "; enjoy ^.^\n")) - -(println BANNER) diff --git a/src/core.rs b/src/core.rs index 44683c2..fa8a286 100644 --- a/src/core.rs +++ b/src/core.rs @@ -34,11 +34,22 @@ macro_rules! env_init { } use crate::parse_tools::read_file; -use crate::printer::pr_str; +use crate::printer::{pr_str, prt}; use crate::reader::{read_str, Reader}; use crate::types::MalType::{Atom, Fun, Int, List, Nil, Str}; use crate::types::{mal_assert, mal_equals, reset_bang, MalErr}; +macro_rules! if_atom { + ($val:expr) => {{ + match $val { + Atom(a) => Ok(a.borrow().clone()), + _ => Err(MalErr::unrecoverable( + format!("{:?} is not an atom", prt($val)).as_str(), + )), + } + }}; +} + pub fn ns_init() -> Env { env_init!(None, // That's it, you are all going to be simpler functions @@ -66,9 +77,9 @@ pub fn ns_init() -> Env { "assert" => Fun(mal_assert, "Return an error if assertion fails"), "read-string" => Fun(|a| read_str(Reader::new().push(car(a)?.if_string()?)).map_err(MalErr::severe), "Tokenize and read the first argument"), "slurp" => Fun(|a| Ok(Str(read_file(car(a)?.if_string()?)?)), "Read a file and return the content as a string"), - "atom" => Fun(|a| Ok(Atom(Rc::new(RefCell::new(car(a)?.clone())))), "Return an atom pointing to the given arg"), - "deref" => Fun(|a| match car(a)? { Atom(a) => Ok(a.borrow().clone()), _ => todo!("Cacca suprema") }, "Return the content of the atom argumet"), - "reset!" => Fun(reset_bang, "Set the value of the first argument to the second argument"), + "atom" => Fun(|a| Ok(Atom(Rc::new(RefCell::new(car(a).unwrap_or_default().clone())))), "Return an atom pointing to the given arg"), + "deref" => Fun(|a| if_atom!(car(a)?), "Return the content of the atom argumet"), + "reset!" => Fun(reset_bang, "Change the value of the Atom (frist argument) to the second argument"), "env" => Fun(|a| match env::var(car(a)?.if_string()?) { Ok(s) => Ok(Str(s.into())), _ => Ok(Nil), diff --git a/src/env.rs b/src/env.rs index 1e746ec..04d5839 100644 --- a/src/env.rs +++ b/src/env.rs @@ -103,7 +103,7 @@ pub fn call_func(func: &MalType, args: &[MalType]) -> CallRet { eval(x, inner_env.clone())?; } Ok(CallFunc::MalFun( - list.last().unwrap_or(&Nil).clone(), + list.last().unwrap_or_default().clone(), inner_env, )) } diff --git a/src/main.rs b/src/main.rs index 67cf52c..93cce8b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,7 +12,7 @@ mod step6_file; mod types; use core::ns_init; -use parse_tools::{interactive, load_file, load_home_file, set_home_path}; +use parse_tools::{interactive, load_file, load_home_file, print_banner, set_home_path}; fn main() { // Initialize ns environment @@ -33,5 +33,7 @@ fn main() { } }); + print_banner(&reply_env); + interactive(reply_env); } diff --git a/src/parse_tools.rs b/src/parse_tools.rs index 129649a..ea0cc78 100644 --- a/src/parse_tools.rs +++ b/src/parse_tools.rs @@ -22,6 +22,10 @@ pub fn set_home_path(env: &Env) { .unwrap(); } +pub fn print_banner(env: &Env) { + let _ = eval_str("(prn BANNER)", env); +} + fn get_home_path(env: &Env) -> Result { Ok(eval_str("MAL_HOME", env)?.if_string()?.to_string()) } @@ -92,7 +96,7 @@ pub fn interactive(env: Env) { // // Read line to compose program input // let mut line = String::new(); // io::stdin().read_line(&mut line).unwrap(); - let line = rl.readline("; user> "); + let line = rl.readline("; mal> "); match line { Ok(line) => { diff --git a/src/step6_file.rs b/src/step6_file.rs index 86a5e47..d8105ac 100644 --- a/src/step6_file.rs +++ b/src/step6_file.rs @@ -4,6 +4,8 @@ // input, thus this can be referenced by the previous step without the need // to allocate more memory +// FIXME: (?) multiple sentences per line, only last is kept + use crate::env::Env; use crate::eval::eval; use crate::printer::pr_str; diff --git a/src/types.rs b/src/types.rs index c05be7a..251ffd0 100644 --- a/src/types.rs +++ b/src/types.rs @@ -29,6 +29,12 @@ pub enum MalType { Nil, } +impl Default for &MalType { + fn default() -> Self { + &MalType::Nil + } +} + impl MalType { pub fn if_number(&self) -> Result { match self {