setup a simple lisp
This commit is contained in:
@@ -6,17 +6,17 @@ grammar;
|
|||||||
|
|
||||||
pub Term: Rc<Form> = {
|
pub Term: Rc<Form> = {
|
||||||
NUM => Rc::new(Form::Int(i32::from_str(<>).unwrap())),
|
NUM => Rc::new(Form::Int(i32::from_str(<>).unwrap())),
|
||||||
SYM => Rc::new(Form::Symbol(<>.to_owned())),
|
SYM => Rc::new(Form::Symbol(<>.to_owned(),None)),
|
||||||
"(" <ListInside?> ")" => <>.unwrap_or(Rc::new(Form::Nil)),
|
"(" <ListInside?> ")" => <>.unwrap_or(Rc::new(Form::Nil)),
|
||||||
"'" <Term> => Rc::new(Form::Pair(Rc::new(Form::Symbol("quote".to_owned())), Rc::new(Form::Pair(<>, Rc::new(Form::Nil))))),
|
"'" <Term> => Rc::new(Form::Pair(Rc::new(Form::Symbol("quote".to_owned(),None)), Rc::new(Form::Pair(<>, Rc::new(Form::Nil),None)),None)),
|
||||||
"!" <h: Term> <t: Term> => {
|
"!" <h: Term> <t: Term> => {
|
||||||
h.append(t).unwrap()
|
h.append(t).unwrap()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
ListInside: Rc<Form> = {
|
ListInside: Rc<Form> = {
|
||||||
<Term> => Rc::new(Form::Pair(<>, Rc::new(Form::Nil))),
|
<Term> => Rc::new(Form::Pair(<>, Rc::new(Form::Nil),None)),
|
||||||
<h: Term> <t: ListInside> => Rc::new(Form::Pair(h, t)),
|
<h: Term> <t: ListInside> => Rc::new(Form::Pair(h, t,None)),
|
||||||
<a: Term> "." <d: Term> => Rc::new(Form::Pair(a, d)),
|
<a: Term> "." <d: Term> => Rc::new(Form::Pair(a, d,None)),
|
||||||
}
|
}
|
||||||
match {
|
match {
|
||||||
"(",
|
"(",
|
||||||
|
|||||||
203
sl/src/lib.rs
203
sl/src/lib.rs
@@ -1,27 +1,52 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use anyhow::{anyhow,Result};
|
use anyhow::{anyhow,bail,Result};
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||||
|
pub struct ID {
|
||||||
|
id: i64
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Form {
|
pub enum Form {
|
||||||
Nil,
|
Nil,
|
||||||
Int(i32),
|
Int(i32),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Symbol(String),
|
Symbol(String, Option<RefCell<ID>>),
|
||||||
Pair(Rc<Form>,Rc<Form>),
|
Pair(Rc<Form>, Rc<Form>, Option<RefCell<ID>>),
|
||||||
|
Closure(Vec<String>, Rc<RefCell<Env>>, Rc<Form>, Option<RefCell<ID>>),
|
||||||
Prim(Prim),
|
Prim(Prim),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||||
pub enum Prim {
|
pub enum Prim {
|
||||||
Add,
|
Add,
|
||||||
|
Sub,
|
||||||
Mul,
|
Mul,
|
||||||
Eq,
|
Eq,
|
||||||
|
Cons,
|
||||||
|
Car,
|
||||||
|
Cdr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Form {
|
impl Form {
|
||||||
|
fn my_eq(&self, o: &Rc<Form>) -> bool {
|
||||||
|
match self {
|
||||||
|
Form::Nil => o.is_nil(),
|
||||||
|
Form::Int(i) => if let Ok(oi) = o.int() { *i == oi } else { false },
|
||||||
|
Form::Bool(b) => if let Ok(ob) = o.bool() { *b == ob } else { false },
|
||||||
|
Form::Symbol(s, _id) => if let Ok(os) = o.sym() { s == os } else { false },
|
||||||
|
Form::Pair(a,b,_id) => if let Ok((oa,ob)) = o.pair() { a.my_eq(&oa) && b.my_eq(&ob) } else { false },
|
||||||
|
Form::Closure(_, _, _, _) => false,
|
||||||
|
Form::Prim(p) => match &**o { Form::Prim(op) => p == op, _ => false },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn new_pair(car: Rc<Form>, cdr: Rc<Form>) -> Rc<Form> {
|
||||||
|
Rc::new(Form::Pair(car, cdr, None))
|
||||||
|
}
|
||||||
fn new_nil() -> Rc<Form> {
|
fn new_nil() -> Rc<Form> {
|
||||||
Rc::new(Form::Nil)
|
Rc::new(Form::Nil)
|
||||||
}
|
}
|
||||||
@@ -31,6 +56,9 @@ impl Form {
|
|||||||
fn new_bool(b: bool) -> Rc<Form> {
|
fn new_bool(b: bool) -> Rc<Form> {
|
||||||
Rc::new(Form::Bool(b))
|
Rc::new(Form::Bool(b))
|
||||||
}
|
}
|
||||||
|
fn new_closure(params: Vec<String>, env: Rc<RefCell<Env>>, body: Rc<Form>) -> Rc<Form> {
|
||||||
|
Rc::new(Form::Closure(params, env, body, None))
|
||||||
|
}
|
||||||
fn truthy(&self) -> bool {
|
fn truthy(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Form::Bool(b) => *b,
|
Form::Bool(b) => *b,
|
||||||
@@ -38,6 +66,12 @@ impl Form {
|
|||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn bool(&self) -> Result<bool> {
|
||||||
|
match self {
|
||||||
|
Form::Bool(b) => Ok(*b),
|
||||||
|
_ => Err(anyhow!("bool on not a bool")),
|
||||||
|
}
|
||||||
|
}
|
||||||
fn int(&self) -> Result<i32> {
|
fn int(&self) -> Result<i32> {
|
||||||
match self {
|
match self {
|
||||||
Form::Int(i) => Ok(*i),
|
Form::Int(i) => Ok(*i),
|
||||||
@@ -52,25 +86,25 @@ impl Form {
|
|||||||
}
|
}
|
||||||
fn sym(&self) -> Result<&str> {
|
fn sym(&self) -> Result<&str> {
|
||||||
match self {
|
match self {
|
||||||
Form::Symbol(s) => Ok(s),
|
Form::Symbol(s, _id) => Ok(s),
|
||||||
_ => Err(anyhow!("sym on not a sym")),
|
_ => Err(anyhow!("sym on not a sym")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn pair(&self) -> Result<(Rc<Form>,Rc<Form>)> {
|
fn pair(&self) -> Result<(Rc<Form>,Rc<Form>)> {
|
||||||
match self {
|
match self {
|
||||||
Form::Pair(car, cdr) => Ok((Rc::clone(car),Rc::clone(cdr))),
|
Form::Pair(car, cdr, _id) => Ok((Rc::clone(car),Rc::clone(cdr))),
|
||||||
_ => Err(anyhow!("pair on not a pair")),
|
_ => Err(anyhow!("pair on not a pair")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn car(&self) -> Result<Rc<Form>> {
|
fn car(&self) -> Result<Rc<Form>> {
|
||||||
match self {
|
match self {
|
||||||
Form::Pair(car, _cdr) => Ok(Rc::clone(car)),
|
Form::Pair(car, _cdr, _id) => Ok(Rc::clone(car)),
|
||||||
_ => Err(anyhow!("car on not a pair")),
|
_ => Err(anyhow!("car on not a pair")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn cdr(&self) -> Result<Rc<Form>> {
|
fn cdr(&self) -> Result<Rc<Form>> {
|
||||||
match self {
|
match self {
|
||||||
Form::Pair(_car, cdr) => Ok(Rc::clone(cdr)),
|
Form::Pair(_car, cdr, _id) => Ok(Rc::clone(cdr)),
|
||||||
_ => Err(anyhow!("cdr on not a pair")),
|
_ => Err(anyhow!("cdr on not a pair")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,52 +116,150 @@ impl Form {
|
|||||||
}
|
}
|
||||||
pub fn append(&self, x: Rc<Form>) -> Result<Rc<Form>> {
|
pub fn append(&self, x: Rc<Form>) -> Result<Rc<Form>> {
|
||||||
match self {
|
match self {
|
||||||
Form::Pair(car, cdr) => cdr.append(x).map(|x| Rc::new(Form::Pair(Rc::clone(car), x))),
|
Form::Pair(car, cdr, _id) => cdr.append(x).map(|x| Rc::new(Form::Pair(Rc::clone(car), x, None))),
|
||||||
Form::Nil => Ok(Rc::new(Form::Pair(x, Rc::new(Form::Nil)))),
|
Form::Nil => Ok(Rc::new(Form::Pair(x, Rc::new(Form::Nil), None))),
|
||||||
_ => Err(anyhow!("append to not a pair")),
|
_ => Err(anyhow!("append to not a pair")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Env {
|
pub struct Env {
|
||||||
|
u: Option<Rc<RefCell<Env>>>,
|
||||||
m: BTreeMap<String, Rc<Form>>
|
m: BTreeMap<String, Rc<Form>>
|
||||||
}
|
}
|
||||||
impl Env {
|
impl Env {
|
||||||
pub fn root_env() -> Env {
|
pub fn root_env() -> Rc<RefCell<Env>> {
|
||||||
Env {
|
Rc::new(RefCell::new(Env {
|
||||||
|
u: None,
|
||||||
m: [
|
m: [
|
||||||
("+", Rc::new(Form::Prim(Prim::Add))),
|
("+", Rc::new(Form::Prim(Prim::Add))),
|
||||||
|
("-", Rc::new(Form::Prim(Prim::Sub))),
|
||||||
("*", Rc::new(Form::Prim(Prim::Mul))),
|
("*", Rc::new(Form::Prim(Prim::Mul))),
|
||||||
|
("cons", Rc::new(Form::Prim(Prim::Cons))),
|
||||||
|
("cdr", Rc::new(Form::Prim(Prim::Cdr))),
|
||||||
|
("car", Rc::new(Form::Prim(Prim::Car))),
|
||||||
("=", Rc::new(Form::Prim(Prim::Eq))),
|
("=", Rc::new(Form::Prim(Prim::Eq))),
|
||||||
|
("nil", Form::new_nil()),
|
||||||
].into_iter().map(|(s,p)| (s.to_owned(), p)).collect()
|
].into_iter().map(|(s,p)| (s.to_owned(), p)).collect()
|
||||||
}
|
}))
|
||||||
|
}
|
||||||
|
pub fn chain(o: &Rc<RefCell<Env>>) -> Rc<RefCell<Env>> {
|
||||||
|
Rc::new(RefCell::new(Env {
|
||||||
|
u: Some(Rc::clone(o)),
|
||||||
|
m: BTreeMap::new(),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
pub fn lookup(&self, s: &str) -> Result<Rc<Form>> {
|
pub fn lookup(&self, s: &str) -> Result<Rc<Form>> {
|
||||||
Ok(Rc::clone(self.m.get(s).ok_or(anyhow!("lookup failed"))?))
|
if let Some(r) = self.m.get(s) {
|
||||||
|
Ok(Rc::clone(r))
|
||||||
|
} else if let Some(u) = &self.u {
|
||||||
|
u.borrow().lookup(s)
|
||||||
|
} else {
|
||||||
|
bail!("lookup of {s} failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn define(&mut self, s: String, v: Rc<Form>) {
|
||||||
|
self.m.insert(s, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tree_walker_eval(f: Rc<Form>, e: &mut Env) -> Result<Rc<Form>> {
|
// add functions
|
||||||
|
// variables
|
||||||
|
// optimized as a function based off side table of id keyed -> opt
|
||||||
|
// that id might be nice for debugging too
|
||||||
|
// Symbol ID's could actually be used for environment lookups
|
||||||
|
// this is just interning
|
||||||
|
|
||||||
|
pub fn tree_walker_eval(f: Rc<Form>, e: Rc<RefCell<Env>>) -> Result<Rc<Form>> {
|
||||||
|
println!("tree_walker_eval({f})");
|
||||||
Ok(match &*f {
|
Ok(match &*f {
|
||||||
Form::Symbol(s) => e.lookup(s)?,
|
Form::Symbol(s, _id) => e.borrow().lookup(s)?,
|
||||||
Form::Pair(car, cdr) => {
|
Form::Pair(car, cdr, _id) => {
|
||||||
match &**car {
|
match &**car {
|
||||||
Form::Symbol(s) if s == "if" => {
|
Form::Symbol(s, _id) if s == "if" => {
|
||||||
if tree_walker_eval(cdr.car()?, e)?.truthy() {
|
if tree_walker_eval(cdr.car()?, Rc::clone(&e))?.truthy() {
|
||||||
tree_walker_eval(cdr.cdr()?.car()?, e)?
|
tree_walker_eval(cdr.cdr()?.car()?, e)?
|
||||||
} else {
|
} else {
|
||||||
tree_walker_eval(cdr.cdr()?.cdr()?.car()?, e)?
|
tree_walker_eval(cdr.cdr()?.cdr()?.car()?, e)?
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Form::Symbol(s, _id) if s == "begin" => {
|
||||||
|
let mut last_result = Form::new_nil();
|
||||||
|
let mut traverse = Rc::clone(cdr);
|
||||||
|
while let Ok((ncar, ncdr)) = traverse.pair() {
|
||||||
|
traverse = ncdr;
|
||||||
|
last_result = tree_walker_eval(ncar, Rc::clone(&e))?;
|
||||||
|
}
|
||||||
|
last_result
|
||||||
|
|
||||||
|
}
|
||||||
|
Form::Symbol(s, _id) if s == "debug" => {
|
||||||
|
println!("debug: {}", tree_walker_eval(cdr.car()?, e)?);
|
||||||
|
Form::new_nil()
|
||||||
|
}
|
||||||
|
// This is a fast and loose ~simple lisp~, so just go for it
|
||||||
|
// and can have convention that this is always top levelish
|
||||||
|
Form::Symbol(s, _id) if s == "define" => {
|
||||||
|
let v = tree_walker_eval(cdr.cdr()?.car()?, Rc::clone(&e))?;
|
||||||
|
e.borrow_mut().define(cdr.car()?.sym()?.to_string(), v);
|
||||||
|
Form::new_nil()
|
||||||
|
}
|
||||||
|
Form::Symbol(s, _id) if s == "quote" => {
|
||||||
|
cdr.car()?
|
||||||
|
}
|
||||||
|
// (lambda (a b) body)
|
||||||
|
Form::Symbol(s, _id) if s == "lambda" => {
|
||||||
|
let mut params_vec = vec![];
|
||||||
|
let mut params = cdr.car()?;
|
||||||
|
while let Ok((ncar, ncdr)) = params.pair() {
|
||||||
|
params_vec.push(ncar.sym()?.to_string());
|
||||||
|
params = ncdr;
|
||||||
|
}
|
||||||
|
let body = cdr.cdr()?.car()?;
|
||||||
|
Form::new_closure(params_vec, Rc::clone(&e), body)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let comb = tree_walker_eval(Rc::clone(car), e)?;
|
let comb = tree_walker_eval(Rc::clone(car), Rc::clone(&e))?;
|
||||||
let a = tree_walker_eval(cdr.car()?, e)?;
|
match &*comb {
|
||||||
let b = tree_walker_eval(cdr.cdr()?.car()?, e)?;
|
Form::Closure(ps, ie, b, id) => {
|
||||||
match comb.prim().unwrap() {
|
let mut arguments_vec = vec![];
|
||||||
Prim::Add => Form::new_int(a.int()? + b.int()?),
|
let mut arguments = Rc::clone(cdr);
|
||||||
Prim::Mul => Form::new_int(a.int()? * b.int()?),
|
while let Ok((ncar, ncdr)) = arguments.pair() {
|
||||||
Prim::Eq => Form::new_bool(a == b),
|
arguments_vec.push(tree_walker_eval(ncar, Rc::clone(&e))?);
|
||||||
|
arguments = ncdr;
|
||||||
|
}
|
||||||
|
if ps.len() != arguments_vec.len() {
|
||||||
|
bail!("arguments length doesn't match");
|
||||||
|
}
|
||||||
|
let new_env = Env::chain(&e);
|
||||||
|
for (name, value) in ps.iter().zip(arguments_vec.into_iter()) {
|
||||||
|
new_env.borrow_mut().define(name.to_string(), value);
|
||||||
|
}
|
||||||
|
tree_walker_eval(Rc::clone(b), new_env)?
|
||||||
|
},
|
||||||
|
Form::Prim(p) => {
|
||||||
|
let a = tree_walker_eval(cdr.car()?, Rc::clone(&e))?;
|
||||||
|
match comb.prim().unwrap() {
|
||||||
|
Prim::Car => a.car()?,
|
||||||
|
Prim::Cdr => a.cdr()?,
|
||||||
|
_ => {
|
||||||
|
let b = tree_walker_eval(cdr.cdr()?.car()?, Rc::clone(&e))?;
|
||||||
|
match comb.prim().unwrap() {
|
||||||
|
Prim::Add => Form::new_int(a.int()? + b.int()?),
|
||||||
|
Prim::Sub => Form::new_int(a.int()? - b.int()?),
|
||||||
|
Prim::Mul => Form::new_int(a.int()? * b.int()?),
|
||||||
|
Prim::Cons => Form::new_pair(a, b),
|
||||||
|
Prim::Eq => Form::new_bool(a.my_eq(&b)),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
bail!("tried to call a non-comb {}", comb)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,13 +269,13 @@ pub fn tree_walker_eval(f: Rc<Form>, e: &mut Env) -> Result<Rc<Form>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// todo, strings not symbols?
|
// todo, strings not symbols?
|
||||||
impl From<String> for Form { fn from(item: String) -> Self { Form::Symbol(item) } }
|
impl From<String> for Form { fn from(item: String) -> Self { Form::Symbol(item, None) } }
|
||||||
impl From<&str> for Form { fn from(item: &str) -> Self { Form::Symbol(item.to_owned()) } }
|
impl From<&str> for Form { fn from(item: &str) -> Self { Form::Symbol(item.to_owned(), None) } }
|
||||||
impl From<i32> for Form { fn from(item: i32) -> Self { Form::Int(item) } }
|
impl From<i32> for Form { fn from(item: i32) -> Self { Form::Int(item) } }
|
||||||
impl From<bool> for Form { fn from(item: bool) -> Self { Form::Bool(item) } }
|
impl From<bool> for Form { fn from(item: bool) -> Self { Form::Bool(item) } }
|
||||||
impl<A: Into<Form>, B: Into<Form>> From<(A, B)> for Form {
|
impl<A: Into<Form>, B: Into<Form>> From<(A, B)> for Form {
|
||||||
fn from(item: (A, B)) -> Self {
|
fn from(item: (A, B)) -> Self {
|
||||||
Form::Pair(Rc::new(item.0.into()), Rc::new(item.1.into()))
|
Form::Pair(Rc::new(item.0.into()), Rc::new(item.1.into()), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,13 +285,13 @@ impl fmt::Display for Form {
|
|||||||
Form::Nil => write!(f, "nil"),
|
Form::Nil => write!(f, "nil"),
|
||||||
Form::Int(i) => write!(f, "{i}"),
|
Form::Int(i) => write!(f, "{i}"),
|
||||||
Form::Bool(b) => write!(f, "{b}"),
|
Form::Bool(b) => write!(f, "{b}"),
|
||||||
Form::Symbol(s) => write!(f, "'{s}"),
|
Form::Symbol(s, _id) => write!(f, "'{s}"),
|
||||||
Form::Pair(car, cdr) => {
|
Form::Pair(car, cdr, _id) => {
|
||||||
write!(f, "({}", car)?;
|
write!(f, "({}", car)?;
|
||||||
let mut traverse: Rc<Form> = Rc::clone(cdr);
|
let mut traverse: Rc<Form> = Rc::clone(cdr);
|
||||||
loop {
|
loop {
|
||||||
match &*traverse {
|
match &*traverse {
|
||||||
Form::Pair(ref carp, ref cdrp) => {
|
Form::Pair(ref carp, ref cdrp, ref _id) => {
|
||||||
write!(f, " {}", carp)?;
|
write!(f, " {}", carp)?;
|
||||||
traverse = Rc::clone(cdrp);
|
traverse = Rc::clone(cdrp);
|
||||||
},
|
},
|
||||||
@@ -174,10 +306,17 @@ impl fmt::Display for Form {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Form::Closure(params, inner_env, code, id) => {
|
||||||
|
write!(f, "<closure {:?}>", params)
|
||||||
|
}
|
||||||
Form::Prim(p) => {
|
Form::Prim(p) => {
|
||||||
match p {
|
match p {
|
||||||
Prim::Add => write!(f, "+"),
|
Prim::Add => write!(f, "+"),
|
||||||
|
Prim::Sub => write!(f, "-"),
|
||||||
Prim::Mul => write!(f, "*"),
|
Prim::Mul => write!(f, "*"),
|
||||||
|
Prim::Cons => write!(f, "cons"),
|
||||||
|
Prim::Car => write!(f, "car"),
|
||||||
|
Prim::Cdr => write!(f, "cdr"),
|
||||||
Prim::Eq => write!(f, "="),
|
Prim::Eq => write!(f, "="),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,29 @@ use anyhow::Result;
|
|||||||
use sl::{tree_walker_eval, Env};
|
use sl::{tree_walker_eval, Env};
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let input = "(if (= 1 2) (+ 2 3) (* 2 2))";
|
let input = "
|
||||||
|
(begin
|
||||||
|
(debug 1)
|
||||||
|
(debug (= 1 2))
|
||||||
|
(debug (+ 2 3))
|
||||||
|
(define a (+ 1 (* 3 4)))
|
||||||
|
(define fact (lambda (n) (if (= n 1) 1 (* n (fact (- n 1))))))
|
||||||
|
(debug 'gonna_fact_it)
|
||||||
|
(debug fact)
|
||||||
|
(debug (fact 5))
|
||||||
|
(debug a)
|
||||||
|
(define b (cons 1 (cons 2 (cons 3 nil))))
|
||||||
|
(debug b)
|
||||||
|
(debug (car b))
|
||||||
|
(debug (cdr b))
|
||||||
|
(if (= 1 2) (+ 2 3) (* 2 2))
|
||||||
|
)
|
||||||
|
";
|
||||||
let parsed_input = Rc::new(grammar::TermParser::new().parse(input)?);
|
let parsed_input = Rc::new(grammar::TermParser::new().parse(input)?);
|
||||||
//println!("Hello, world: {parsed_input:?}");
|
//println!("Hello, world: {parsed_input:?}");
|
||||||
println!("Hello, world: {parsed_input}");
|
println!("Hello, world: {parsed_input}");
|
||||||
let mut e = Env::root_env();
|
let e = Env::root_env();
|
||||||
let tree_walker_evaled = tree_walker_eval(Rc::clone(&parsed_input), &mut e)?;
|
let tree_walker_evaled = tree_walker_eval(Rc::clone(&parsed_input), e)?;
|
||||||
println!("tree walker evaled: {tree_walker_evaled}");
|
println!("tree walker evaled: {tree_walker_evaled}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user