mirror of
https://github.com/teo3300/rust-mal.git
synced 2026-01-12 01:05:32 +01:00
Implemented Atom type
Only functions available - atom - deref (aliased as @) - reset!
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@ -7,4 +7,7 @@ src/#*
|
|||||||
src/*~
|
src/*~
|
||||||
|
|
||||||
# history file
|
# history file
|
||||||
.mal-history
|
.mal-history
|
||||||
|
|
||||||
|
# stupid macos
|
||||||
|
.DS_Store
|
||||||
|
|||||||
10
src/core.rs
10
src/core.rs
@ -1,5 +1,4 @@
|
|||||||
use std::env;
|
use std::{cell::RefCell, env, rc::Rc};
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use crate::env::{any_zero, arithmetic_op, car, comparison_op, env_new, env_set, mal_exit, Env};
|
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::printer::pr_str;
|
||||||
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, MalErr};
|
use crate::types::{mal_assert, mal_equals, reset_bang, MalErr};
|
||||||
|
|
||||||
pub fn ns_init() -> Env {
|
pub fn ns_init() -> Env {
|
||||||
env_init!(None,
|
env_init!(None,
|
||||||
@ -63,8 +62,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(car(a)?.clone()))), "Return an atom pointing to the given arg"),
|
"atom" => Fun(|a| Ok(Atom(Rc::new(RefCell::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"),
|
"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()?) {
|
"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),
|
||||||
|
|||||||
@ -53,7 +53,7 @@ pub fn pr_str(ast: &MalType, print_readably: bool) -> String {
|
|||||||
),
|
),
|
||||||
M::Fun(..) => "#<builtin>".to_string(),
|
M::Fun(..) => "#<builtin>".to_string(),
|
||||||
M::MalFun { .. } => "#<function>".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.read_form()?,
|
||||||
])))
|
])))
|
||||||
}
|
}
|
||||||
|
"@" => {
|
||||||
|
self.next()?;
|
||||||
|
Ok(List(Rc::new([
|
||||||
|
MalType::Sym("deref".into()),
|
||||||
|
self.read_form()?,
|
||||||
|
])))
|
||||||
|
}
|
||||||
_ => self.read_atom(),
|
_ => self.read_atom(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
56
src/types.rs
56
src/types.rs
@ -1,5 +1,5 @@
|
|||||||
use crate::env::{car_cdr, Env};
|
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 MalStr = Rc<str>;
|
||||||
pub type MalArgs = Rc<[MalType]>;
|
pub type MalArgs = Rc<[MalType]>;
|
||||||
@ -25,7 +25,7 @@ pub enum MalType {
|
|||||||
Str(MalStr),
|
Str(MalStr),
|
||||||
Int(isize),
|
Int(isize),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Atom(Rc<MalType>),
|
Atom(Rc<RefCell<MalType>>),
|
||||||
Nil,
|
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 {
|
pub fn label_type(&self) -> MalType {
|
||||||
Key(match self {
|
Key(("ʞ:".to_owned()
|
||||||
M::Nil => "ʞ:nil",
|
+ match self {
|
||||||
M::Bool(_) => "ʞ:bool",
|
M::Nil => "nil",
|
||||||
M::Int(_) => "ʞ:int",
|
M::Bool(_) => "bool",
|
||||||
M::Fun(_, _) | M::MalFun { .. } => "ʞ:lambda",
|
M::Int(_) => "int",
|
||||||
M::Key(_) => "ʞ:key",
|
M::Fun(_, _) | M::MalFun { .. } => "lambda",
|
||||||
M::Str(_) => "ʞ:string",
|
M::Key(_) => "key",
|
||||||
M::Sym(_) => "ʞ:symbol",
|
M::Str(_) => "string",
|
||||||
M::List(_) => "ʞ:list",
|
M::Sym(_) => "symbol",
|
||||||
M::Vector(_) => "ʞ:vector",
|
M::List(_) => "list",
|
||||||
M::Map(_) => "ʞ:map",
|
M::Vector(_) => "vector",
|
||||||
M::Atom(_) => "ʞ:atom",
|
M::Map(_) => "map",
|
||||||
}
|
M::Atom(_) => "atom",
|
||||||
|
})
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,6 +127,22 @@ pub fn mal_assert(args: &[MalType]) -> MalRet {
|
|||||||
Ok(M::Nil)
|
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)]
|
#[derive(PartialEq, Clone, Copy, Debug)]
|
||||||
pub enum Severity {
|
pub enum Severity {
|
||||||
Recoverable,
|
Recoverable,
|
||||||
|
|||||||
Reference in New Issue
Block a user