bebop_lang/lisp/
mod.rs

1pub mod builtin;
2pub mod env;
3pub mod eval;
4pub mod parser;
5
6use env::{Lenv, Lookup};
7use std::{error::Error, fmt};
8
9#[derive(Clone)]
10pub enum Lval {
11    Sym(String),
12    Num(f64),
13    Sexpr(Vec<Lval>),
14    Qexpr(Vec<Lval>),
15    Fun(Lfun),
16    Lambda(Llambda),
17    Str(String),
18}
19
20impl PartialEq for Lval {
21    fn eq(&self, other: &Self) -> bool {
22        match self {
23            Lval::Sym(a) => match other {
24                Lval::Sym(b) => a == b,
25                _ => false,
26            },
27            Lval::Num(a) => match other {
28                Lval::Num(b) => a == b,
29                _ => false,
30            },
31            Lval::Sexpr(a) => match other {
32                Lval::Sexpr(b) => a == b,
33                _ => false,
34            },
35            Lval::Qexpr(a) => match other {
36                Lval::Qexpr(b) => a == b,
37                _ => false,
38            },
39            Lval::Fun(_) => match other {
40                Lval::Fun(_) => true,
41                _ => false,
42            },
43            Lval::Str(_) => match other {
44                Lval::Str(_) => true,
45                _ => false,
46            },
47            Lval::Lambda(a) => match other {
48                Lval::Lambda(b) => a.body == b.body && a.args == b.args,
49                _ => false,
50            },
51        }
52    }
53}
54
55impl fmt::Debug for Lval {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        match &self {
58            Lval::Sym(s) => write!(f, "{}", s),
59            Lval::Num(n) => write!(f, "{}", n),
60            Lval::Sexpr(s) => write!(
61                f,
62                "({})",
63                s.into_iter()
64                    .map(|x| match x {
65                        Lval::Sym(sym) => format!("{}", sym),
66                        _ => format!("{:?}", x),
67                    })
68                    .collect::<Vec<String>>()
69                    .join(" ")
70            ),
71            Lval::Qexpr(q) => write!(
72                f,
73                "[{}]",
74                q.into_iter()
75                    .map(|x| match x {
76                        Lval::Sym(sym) => format!("{}", sym),
77                        _ => format!("{:?}", x),
78                    })
79                    .collect::<Vec<String>>()
80                    .join(" ")
81            ),
82            Lval::Fun(_) => write!(f, "builtin"),
83            Lval::Str(s) => write!(f, "{}", s),
84            Lval::Lambda(l) => write!(
85                f,
86                "(\\ [{}] [{}])",
87                l.args.join(" "),
88                l.body
89                    .to_owned()
90                    .into_iter()
91                    .map(|x| match x {
92                        Lval::Sym(sym) => format!("{}", sym),
93                        _ => format!("{:?}", x),
94                    })
95                    .collect::<Vec<String>>()
96                    .join(" ")
97            ),
98        }
99    }
100}
101
102#[derive(Clone)]
103pub struct Llambda {
104    args: Vec<String>,
105    body: Vec<Lval>,
106    env: Lenv,
107}
108
109impl Llambda {
110    fn new(args: Vec<String>, body: Vec<Lval>, lookup: Lookup) -> Self {
111        let mut lenv = Lenv::new();
112        lenv.push(lookup);
113        Llambda {
114            args,
115            body,
116            env: lenv,
117        }
118    }
119}
120
121#[derive(Clone, PartialEq)]
122pub struct Lerr {
123    etype: LerrType,
124    details: String,
125    message: String,
126}
127
128impl Lerr {
129    fn new(etype: LerrType, message: String) -> Lerr {
130        let msg = match &etype {
131            LerrType::DivZero => "Cannot Divide By Zero",
132            LerrType::BadOp => "Invalid Operator",
133            LerrType::BadNum => "Invalid Operand",
134            LerrType::IncorrectParamCount => "Incorrect Number of Params passed to function",
135            LerrType::WrongType => "Incorrect Data Type used",
136            LerrType::EmptyList => "Empty List passed to function",
137            LerrType::UnboundSymbol => "This Symbol has not been Defined",
138            LerrType::Interrupt => "User defined Error",
139        };
140
141        Lerr {
142            details: msg.to_string(),
143            message,
144            etype,
145        }
146    }
147}
148
149impl fmt::Debug for Lerr {
150    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151        write!(
152            f,
153            "Error: {:?} - {}; {}",
154            self.etype, self.details, self.message
155        )
156    }
157}
158
159impl fmt::Display for Lerr {
160    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
161        write!(f, "{}", self.details)
162    }
163}
164
165impl Error for Lerr {
166    fn description(&self) -> &str {
167        &self.details
168    }
169}
170
171#[derive(Clone, Debug, PartialEq)]
172pub enum LerrType {
173    DivZero,
174    BadOp,
175    BadNum,
176    IncorrectParamCount,
177    EmptyList,
178    WrongType,
179    UnboundSymbol,
180    Interrupt,
181}
182
183pub type Lfun = fn(&mut Lenv, Vec<Lval>) -> Result<Lval, Lerr>;
184
185pub fn add_builtin(env: &mut Lenv, sym: &str, fun: Lfun) {
186    env.insert(sym, Lval::Fun(fun));
187}
188
189fn to_num(expr: Lval) -> Option<f64> {
190    if let Lval::Num(n) = expr {
191        Some(n)
192    } else {
193        None
194    }
195}
196
197fn to_sym(expr: Lval) -> Option<String> {
198    if let Lval::Sym(s) = expr {
199        Some(s.clone())
200    } else {
201        None
202    }
203}
204
205fn to_str(expr: Lval) -> Option<String> {
206    if let Lval::Str(s) = expr {
207        Some(s.clone())
208    } else {
209        None
210    }
211}
212
213fn to_qexpr(expr: Lval) -> Option<Vec<Lval>> {
214    if let Lval::Qexpr(s) = expr {
215        Some(s.clone())
216    } else {
217        None
218    }
219}
220
221#[cfg(test)]
222fn to_lambda(expr: &Lval) -> Option<Llambda> {
223    if let Lval::Lambda(s) = expr {
224        Some(s.clone())
225    } else {
226        None
227    }
228}
229
230pub fn lisp(env: &mut Lenv, input: &str) -> String {
231    if "env" == input {
232        return format!("{:#?}", env.peek().unwrap());
233    }
234
235    let ast = parser::parse(input);
236    match ast {
237        Ok(tree) => match eval::eval(env, tree.1) {
238            Ok(r) => format!("{:?}", r),
239            Err(r) => format!("{:?}", r),
240        },
241        Err(e) => format!("Error: Parsing Error - Could not parse the input; {}", e),
242    }
243}