mirror of
https://github.com/teo3300/rust-mal.git
synced 2026-01-12 09:15:32 +01:00
Implemented Atom type
Only functions available - atom - deref (aliased as @) - reset!
This commit is contained in:
10
src/core.rs
10
src/core.rs
@ -1,5 +1,4 @@
|
||||
use std::env;
|
||||
use std::rc::Rc;
|
||||
use std::{cell::RefCell, env, rc::Rc};
|
||||
|
||||
use crate::env::{any_zero, arithmetic_op, car, comparison_op, env_new, env_set, mal_exit, Env};
|
||||
|
||||
@ -36,7 +35,7 @@ use crate::parse_tools::read_file;
|
||||
use crate::printer::pr_str;
|
||||
use crate::reader::{read_str, Reader};
|
||||
use crate::types::MalType::{Atom, Fun, Int, List, Nil, Str};
|
||||
use crate::types::{mal_assert, mal_equals, MalErr};
|
||||
use crate::types::{mal_assert, mal_equals, reset_bang, MalErr};
|
||||
|
||||
pub fn ns_init() -> Env {
|
||||
env_init!(None,
|
||||
@ -63,8 +62,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(car(a)?.clone()))), "Return an atom pointing to the given arg"),
|
||||
"deref" => Fun(|a| Ok(car(a)?.if_atom()?.clone()), "Return the content of the atom argumet"),
|
||||
"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"),
|
||||
"env" => Fun(|a| match env::var(car(a)?.if_string()?) {
|
||||
Ok(s) => Ok(Str(s.into())),
|
||||
_ => Ok(Nil),
|
||||
|
||||
@ -53,7 +53,7 @@ pub fn pr_str(ast: &MalType, print_readably: bool) -> String {
|
||||
),
|
||||
M::Fun(..) => "#<builtin>".to_string(),
|
||||
M::MalFun { .. } => "#<function>".to_string(),
|
||||
M::Atom(sub) => format!("Atom({})", pr_str(sub, print_readably)),
|
||||
M::Atom(sub) => format!("Atom({})", pr_str(&sub.borrow(), print_readably)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -133,6 +133,13 @@ impl Reader {
|
||||
self.read_form()?,
|
||||
])))
|
||||
}
|
||||
"@" => {
|
||||
self.next()?;
|
||||
Ok(List(Rc::new([
|
||||
MalType::Sym("deref".into()),
|
||||
self.read_form()?,
|
||||
])))
|
||||
}
|
||||
_ => self.read_atom(),
|
||||
}
|
||||
}
|
||||
|
||||
56
src/types.rs
56
src/types.rs
@ -1,5 +1,5 @@
|
||||
use crate::env::{car_cdr, Env};
|
||||
use std::{collections::HashMap, rc::Rc};
|
||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||
|
||||
pub type MalStr = Rc<str>;
|
||||
pub type MalArgs = Rc<[MalType]>;
|
||||
@ -25,7 +25,7 @@ pub enum MalType {
|
||||
Str(MalStr),
|
||||
Int(isize),
|
||||
Bool(bool),
|
||||
Atom(Rc<MalType>),
|
||||
Atom(Rc<RefCell<MalType>>),
|
||||
Nil,
|
||||
}
|
||||
|
||||
@ -75,29 +75,21 @@ impl MalType {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn if_atom(&self) -> Result<&MalType, MalErr> {
|
||||
match self {
|
||||
Self::Atom(sym) => Ok(sym),
|
||||
_ => Err(MalErr::unrecoverable(
|
||||
format!("{:?} is not an atom", prt(self)).as_str(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn label_type(&self) -> MalType {
|
||||
Key(match self {
|
||||
M::Nil => "ʞ:nil",
|
||||
M::Bool(_) => "ʞ:bool",
|
||||
M::Int(_) => "ʞ:int",
|
||||
M::Fun(_, _) | M::MalFun { .. } => "ʞ:lambda",
|
||||
M::Key(_) => "ʞ:key",
|
||||
M::Str(_) => "ʞ:string",
|
||||
M::Sym(_) => "ʞ:symbol",
|
||||
M::List(_) => "ʞ:list",
|
||||
M::Vector(_) => "ʞ:vector",
|
||||
M::Map(_) => "ʞ:map",
|
||||
M::Atom(_) => "ʞ:atom",
|
||||
}
|
||||
Key(("ʞ:".to_owned()
|
||||
+ match self {
|
||||
M::Nil => "nil",
|
||||
M::Bool(_) => "bool",
|
||||
M::Int(_) => "int",
|
||||
M::Fun(_, _) | M::MalFun { .. } => "lambda",
|
||||
M::Key(_) => "key",
|
||||
M::Str(_) => "string",
|
||||
M::Sym(_) => "symbol",
|
||||
M::List(_) => "list",
|
||||
M::Vector(_) => "vector",
|
||||
M::Map(_) => "map",
|
||||
M::Atom(_) => "atom",
|
||||
})
|
||||
.into())
|
||||
}
|
||||
}
|
||||
@ -135,6 +127,22 @@ pub fn mal_assert(args: &[MalType]) -> MalRet {
|
||||
Ok(M::Nil)
|
||||
}
|
||||
|
||||
pub fn reset_bang(args: &[MalType]) -> MalRet {
|
||||
if args.len() < 2 {
|
||||
return Err(MalErr::unrecoverable("reset requires two arguments"));
|
||||
}
|
||||
let val = &args[1];
|
||||
match &args[0] {
|
||||
M::Atom(sym) => {
|
||||
*std::cell::RefCell::<_>::borrow_mut(sym) = val.clone();
|
||||
Ok(val.clone())
|
||||
}
|
||||
_ => Err(MalErr::unrecoverable(
|
||||
format!("{:?} is not an atom", prt(&args[1])).as_str(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||
pub enum Severity {
|
||||
Recoverable,
|
||||
|
||||
Reference in New Issue
Block a user