mirror of
https://github.com/teo3300/rust-mal.git
synced 2026-01-12 09:15:32 +01:00
Fixing some atom functions
This commit is contained in:
@ -46,9 +46,11 @@
|
|||||||
(= (count l) 0)))
|
(= (count l) 0)))
|
||||||
|
|
||||||
(def! assert-eq (fn* [a b]
|
(def! assert-eq (fn* [a b]
|
||||||
|
"returns an error if arguments are not equals, NIL otherwise"
|
||||||
(assert (= a b))))
|
(assert (= a b))))
|
||||||
|
|
||||||
(def! assert-fail (fn* [x]
|
(def! assert-fail (fn* [x]
|
||||||
|
"returns NIL if evaluation of argument fails, error otherwise"
|
||||||
(assert (not (ok? (eval x))))))
|
(assert (not (ok? (eval x))))))
|
||||||
|
|
||||||
;; Since thread safety is not required, I will leave it like this,
|
;; Since thread safety is not required, I will leave it like this,
|
||||||
@ -58,13 +60,16 @@
|
|||||||
|
|
||||||
;; File-interaction functions
|
;; File-interaction functions
|
||||||
(def! load-file (fn* [f]
|
(def! load-file (fn* [f]
|
||||||
|
"open a mal file and evaluate its content"
|
||||||
(eval (read-string (str "(do " (slurp f) "\nnil)")))))
|
(eval (read-string (str "(do " (slurp f) "\nnil)")))))
|
||||||
|
|
||||||
(def! conf-reload (fn* []
|
(def! conf-reload (fn* []
|
||||||
|
"reload mal config file"
|
||||||
(load-file (str MAL_HOME "/" "config.mal"))))
|
(load-file (str MAL_HOME "/" "config.mal"))))
|
||||||
|
|
||||||
;; Shorthand
|
;; Shorthand
|
||||||
(def! quit (fn* []
|
(def! quit (fn* []
|
||||||
|
"Quit the program with status '0'"
|
||||||
(exit 0)))
|
(exit 0)))
|
||||||
|
|
||||||
;; variables
|
;; variables
|
||||||
@ -132,5 +137,3 @@
|
|||||||
"; (help <symbol>) : print information about a symbol\n"
|
"; (help <symbol>) : print information about a symbol\n"
|
||||||
";\n"
|
";\n"
|
||||||
"; enjoy ^.^\n"))
|
"; enjoy ^.^\n"))
|
||||||
|
|
||||||
(println BANNER)
|
|
||||||
|
|||||||
19
src/core.rs
19
src/core.rs
@ -34,11 +34,22 @@ macro_rules! env_init {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use crate::parse_tools::read_file;
|
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::reader::{read_str, Reader};
|
||||||
use crate::types::MalType::{Atom, Fun, Int, List, Nil, Str};
|
use crate::types::MalType::{Atom, Fun, Int, List, Nil, Str};
|
||||||
use crate::types::{mal_assert, mal_equals, reset_bang, MalErr};
|
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 {
|
pub fn ns_init() -> Env {
|
||||||
env_init!(None,
|
env_init!(None,
|
||||||
// That's it, you are all going to be simpler functions
|
// 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"),
|
"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"),
|
"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"),
|
"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"),
|
"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| match car(a)? { Atom(a) => Ok(a.borrow().clone()), _ => todo!("Cacca suprema") }, "Return the content of the atom argumet"),
|
"deref" => Fun(|a| if_atom!(car(a)?), "Return the content of the atom argumet"),
|
||||||
"reset!" => Fun(reset_bang, "Set the value of the first argument to the second argument"),
|
"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()?) {
|
"env" => Fun(|a| match env::var(car(a)?.if_string()?) {
|
||||||
Ok(s) => Ok(Str(s.into())),
|
Ok(s) => Ok(Str(s.into())),
|
||||||
_ => Ok(Nil),
|
_ => Ok(Nil),
|
||||||
|
|||||||
@ -103,7 +103,7 @@ pub fn call_func(func: &MalType, args: &[MalType]) -> CallRet {
|
|||||||
eval(x, inner_env.clone())?;
|
eval(x, inner_env.clone())?;
|
||||||
}
|
}
|
||||||
Ok(CallFunc::MalFun(
|
Ok(CallFunc::MalFun(
|
||||||
list.last().unwrap_or(&Nil).clone(),
|
list.last().unwrap_or_default().clone(),
|
||||||
inner_env,
|
inner_env,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ mod step6_file;
|
|||||||
mod types;
|
mod types;
|
||||||
|
|
||||||
use core::ns_init;
|
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() {
|
fn main() {
|
||||||
// Initialize ns environment
|
// Initialize ns environment
|
||||||
@ -33,5 +33,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
print_banner(&reply_env);
|
||||||
|
|
||||||
interactive(reply_env);
|
interactive(reply_env);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,10 @@ pub fn set_home_path(env: &Env) {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_banner(env: &Env) {
|
||||||
|
let _ = eval_str("(prn BANNER)", env);
|
||||||
|
}
|
||||||
|
|
||||||
fn get_home_path(env: &Env) -> Result<String, MalErr> {
|
fn get_home_path(env: &Env) -> Result<String, MalErr> {
|
||||||
Ok(eval_str("MAL_HOME", env)?.if_string()?.to_string())
|
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
|
// // Read line to compose program input
|
||||||
// let mut line = String::new();
|
// let mut line = String::new();
|
||||||
// io::stdin().read_line(&mut line).unwrap();
|
// io::stdin().read_line(&mut line).unwrap();
|
||||||
let line = rl.readline("; user> ");
|
let line = rl.readline("; mal> ");
|
||||||
|
|
||||||
match line {
|
match line {
|
||||||
Ok(line) => {
|
Ok(line) => {
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
// input, thus this can be referenced by the previous step without the need
|
// input, thus this can be referenced by the previous step without the need
|
||||||
// to allocate more memory
|
// to allocate more memory
|
||||||
|
|
||||||
|
// FIXME: (?) multiple sentences per line, only last is kept
|
||||||
|
|
||||||
use crate::env::Env;
|
use crate::env::Env;
|
||||||
use crate::eval::eval;
|
use crate::eval::eval;
|
||||||
use crate::printer::pr_str;
|
use crate::printer::pr_str;
|
||||||
|
|||||||
@ -29,6 +29,12 @@ pub enum MalType {
|
|||||||
Nil,
|
Nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for &MalType {
|
||||||
|
fn default() -> Self {
|
||||||
|
&MalType::Nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MalType {
|
impl MalType {
|
||||||
pub fn if_number(&self) -> Result<isize, MalErr> {
|
pub fn if_number(&self) -> Result<isize, MalErr> {
|
||||||
match self {
|
match self {
|
||||||
|
|||||||
Reference in New Issue
Block a user