2021-12-16 22:24:31 +00:00
|
|
|
#![feature(let_else)]
|
2021-12-16 18:23:02 +00:00
|
|
|
|
2021-12-16 22:24:31 +00:00
|
|
|
mod grammar;
|
2021-12-16 18:23:02 +00:00
|
|
|
|
2021-12-16 20:30:28 +00:00
|
|
|
use rustyline::validate::{
|
|
|
|
MatchingBracketValidator, ValidationContext, ValidationResult, Validator,
|
|
|
|
};
|
2021-12-16 22:24:31 +00:00
|
|
|
use rustyline::Editor;
|
2021-12-16 20:30:28 +00:00
|
|
|
use rustyline_derive::{Completer, Helper, Highlighter, Hinter};
|
2021-12-16 22:24:31 +00:00
|
|
|
use std::collections::HashMap;
|
2021-12-16 18:23:02 +00:00
|
|
|
|
2021-12-16 20:30:28 +00:00
|
|
|
#[derive(Completer, Helper, Highlighter, Hinter)]
|
|
|
|
struct InputValidator {
|
|
|
|
brackets: MatchingBracketValidator,
|
2021-12-16 18:23:02 +00:00
|
|
|
}
|
|
|
|
|
2021-12-16 20:30:28 +00:00
|
|
|
impl Validator for InputValidator {
|
2021-12-16 22:24:31 +00:00
|
|
|
fn validate(&self, ctx: &mut ValidationContext) -> rustyline::Result<ValidationResult> {
|
2021-12-16 20:30:28 +00:00
|
|
|
self.brackets.validate(ctx)
|
2021-12-16 18:23:02 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-16 22:24:31 +00:00
|
|
|
use debug2::dbg;
|
2021-12-16 18:23:02 +00:00
|
|
|
|
2021-12-16 22:24:31 +00:00
|
|
|
#[derive(Debug, debug2::Debug, PartialEq)]
|
|
|
|
enum Tree {
|
|
|
|
Leaf(Literal),
|
2021-12-16 23:15:31 +00:00
|
|
|
Define(String, Box<Tree>),
|
2021-12-16 22:24:31 +00:00
|
|
|
Branch(Vec<Tree>),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, debug2::Debug, PartialEq)]
|
|
|
|
enum Literal {
|
|
|
|
Sym(String),
|
|
|
|
Num(f64),
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct RTError(String);
|
|
|
|
|
|
|
|
fn err<T>(s: String) -> Result<T, RTError> {
|
|
|
|
Err(RTError(s))
|
|
|
|
}
|
|
|
|
|
|
|
|
type Func = fn(&[Value]) -> Result<Value, RTError>;
|
|
|
|
|
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
enum Value {
|
|
|
|
Num(f64),
|
|
|
|
Func(Func),
|
2021-12-16 23:15:31 +00:00
|
|
|
NotAValue,
|
2021-12-16 22:24:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl std::fmt::Debug for Value {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
match self {
|
|
|
|
Self::Num(n) => n.fmt(f),
|
|
|
|
Self::Func(_) => f.write_str("#<procedure>"),
|
2021-12-16 23:15:31 +00:00
|
|
|
Self::NotAValue => Ok(()),
|
2021-12-16 22:24:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-16 18:23:02 +00:00
|
|
|
|
2021-12-16 22:24:31 +00:00
|
|
|
impl Value {
|
|
|
|
fn as_num(&self) -> Result<f64, RTError> {
|
|
|
|
if let Self::Num(n) = self {
|
|
|
|
Ok(*n)
|
|
|
|
} else {
|
|
|
|
Err(RTError("Expected a number".to_owned()))
|
|
|
|
}
|
|
|
|
}
|
2021-12-16 18:23:02 +00:00
|
|
|
|
2021-12-16 22:24:31 +00:00
|
|
|
fn as_func(&self) -> Result<Func, RTError> {
|
|
|
|
if let Self::Func(f) = self {
|
|
|
|
Ok(*f)
|
|
|
|
} else {
|
|
|
|
Err(RTError("Expected a function".to_owned()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-16 18:23:02 +00:00
|
|
|
|
2021-12-16 22:24:31 +00:00
|
|
|
struct Env {
|
|
|
|
vars: HashMap<String, Value>,
|
|
|
|
}
|
2021-12-16 18:23:02 +00:00
|
|
|
|
2021-12-16 22:24:31 +00:00
|
|
|
fn main() {
|
2021-12-16 20:30:28 +00:00
|
|
|
let mut rl = Editor::new();
|
|
|
|
rl.set_helper(Some(InputValidator {
|
|
|
|
brackets: MatchingBracketValidator::new(),
|
|
|
|
}));
|
2021-12-16 22:24:31 +00:00
|
|
|
|
|
|
|
let mut env = default_env();
|
|
|
|
|
2021-12-16 20:30:28 +00:00
|
|
|
while let Ok(line) = rl.readline("> ") {
|
|
|
|
rl.add_history_entry(&line);
|
2021-12-16 18:23:02 +00:00
|
|
|
|
2021-12-16 20:30:28 +00:00
|
|
|
let tree = grammar::TreeParser::new().parse(&line).unwrap();
|
|
|
|
dbg!(&tree);
|
2021-12-16 23:15:31 +00:00
|
|
|
println!("< {:?}", eval(&tree, &mut env))
|
2021-12-16 18:23:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-16 23:15:31 +00:00
|
|
|
fn eval(t: &Tree, env: &mut Env) -> Result<Value, RTError> {
|
2021-12-16 22:24:31 +00:00
|
|
|
Ok(match t {
|
|
|
|
Tree::Leaf(l) => match l {
|
|
|
|
Literal::Sym(s) => match env.vars.get(s) {
|
|
|
|
Some(&v) => v,
|
|
|
|
None => return err(format!("Undefined variable `{}`", s)),
|
|
|
|
},
|
|
|
|
Literal::Num(v) => Value::Num(*v),
|
|
|
|
},
|
|
|
|
Tree::Branch(args) => {
|
|
|
|
let Some(fun) = args.get(0) else { return err("No argument given".to_owned()) };
|
|
|
|
let fun = eval(fun, env)?.as_func()?;
|
|
|
|
let args = args
|
|
|
|
.iter()
|
|
|
|
.skip(1)
|
|
|
|
.map(|a| eval(a, env))
|
|
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
|
|
return fun(&args);
|
|
|
|
}
|
2021-12-16 23:15:31 +00:00
|
|
|
Tree::Define(name, to) => {
|
|
|
|
let val = eval(to, env)?;
|
|
|
|
env.vars.insert(name.to_owned(), val);
|
|
|
|
Value::NotAValue
|
|
|
|
}
|
2021-12-16 22:24:31 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// fn eval(t: &Tree) -> f64 {
|
|
|
|
// match t {
|
|
|
|
// Tree::Val(v) => *v,
|
|
|
|
// Tree::Add(vs) => vs.iter().map(eval).sum(),
|
|
|
|
// Tree::Mul(vs) => vs.iter().map(eval).product(),
|
|
|
|
// Tree::Sub(vs) => eval(&vs[0]) - vs[1..].iter().map(eval).sum::<f64>(),
|
|
|
|
// Tree::Div(vs) => eval(&vs[0]) / vs[1..].iter().map(eval).product::<f64>(),
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
fn default_env() -> Env {
|
|
|
|
let mut vars = HashMap::new();
|
|
|
|
// vars.insert("+".to_owned(), prims::add);
|
|
|
|
// vars.insert("-".to_owned(), prims::sub);
|
|
|
|
// vars.insert("*".to_owned(), prims::mul);
|
|
|
|
// vars.insert("/".to_owned(), prims::div);
|
|
|
|
|
|
|
|
for (name, fun) in [
|
|
|
|
("*", prims::mul as Func),
|
|
|
|
("+", prims::add as Func),
|
|
|
|
("-", prims::sub as Func),
|
|
|
|
("/", prims::div as Func),
|
|
|
|
] {
|
|
|
|
vars.insert(name.to_owned(), Value::Func(fun));
|
2021-12-16 20:30:28 +00:00
|
|
|
}
|
2021-12-16 22:24:31 +00:00
|
|
|
|
|
|
|
Env { vars }
|
2021-12-16 18:23:02 +00:00
|
|
|
}
|
|
|
|
|
2021-12-16 22:24:31 +00:00
|
|
|
mod prims {
|
|
|
|
use crate::{RTError, Value};
|
|
|
|
|
|
|
|
pub(crate) fn add(args: &[Value]) -> Result<Value, RTError> {
|
|
|
|
args.iter()
|
|
|
|
.map(Value::as_num)
|
|
|
|
.try_fold(0.0, |a, b| Ok(a + b?))
|
|
|
|
.map(Value::Num)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn mul(args: &[Value]) -> Result<Value, RTError> {
|
|
|
|
args.iter()
|
|
|
|
.map(Value::as_num)
|
|
|
|
.try_fold(1.0, |a, b| Ok(a * b?))
|
|
|
|
.map(Value::Num)
|
2021-12-16 20:30:28 +00:00
|
|
|
}
|
2021-12-16 18:23:02 +00:00
|
|
|
|
2021-12-16 22:24:31 +00:00
|
|
|
pub(crate) fn div(args: &[Value]) -> Result<Value, RTError> {
|
|
|
|
let init = args
|
|
|
|
.get(0)
|
|
|
|
.ok_or_else(|| RTError("`div` needs at least one argument".to_owned()))?
|
|
|
|
.as_num()?;
|
|
|
|
let rest = mul(&args[1..])?.as_num().unwrap();
|
|
|
|
Ok(Value::Num(init / rest))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn sub(args: &[Value]) -> Result<Value, RTError> {
|
|
|
|
let init = args
|
|
|
|
.get(0)
|
|
|
|
.ok_or_else(|| RTError("`sub` needs at least one argument".to_owned()))?
|
|
|
|
.as_num()?;
|
|
|
|
let rest = add(&args[1..])?.as_num().unwrap();
|
|
|
|
Ok(Value::Num(init - rest))
|
2021-12-16 18:23:02 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-16 22:24:31 +00:00
|
|
|
|
|
|
|
// #[cfg(test)]
|
|
|
|
// mod tests {
|
|
|
|
// use super::*;
|
|
|
|
|
|
|
|
// #[test]
|
|
|
|
// fn simple_math_space() {
|
|
|
|
// let t = grammar::TreeParser::new()
|
|
|
|
// .parse("( + 1 2 ( / 2 3 4 5) )")
|
|
|
|
// .unwrap();
|
|
|
|
// assert_eq!(
|
|
|
|
// t,
|
|
|
|
// Tree::Add(vec![
|
|
|
|
// Tree::Val(1.0),
|
|
|
|
// Tree::Val(2.0),
|
|
|
|
// Tree::Div(vec![
|
|
|
|
// Tree::Val(2.0),
|
|
|
|
// Tree::Val(3.0),
|
|
|
|
// Tree::Val(4.0),
|
|
|
|
// Tree::Val(5.0),
|
|
|
|
// ])
|
|
|
|
// ])
|
|
|
|
// );
|
|
|
|
// }
|
|
|
|
|
|
|
|
// #[test]
|
|
|
|
// fn simple_math_dence() {
|
|
|
|
// let t = grammar::TreeParser::new()
|
|
|
|
// .parse("(+ 1 2 (/ 2 3 4 5))")
|
|
|
|
// .unwrap();
|
|
|
|
// assert_eq!(
|
|
|
|
// t,
|
|
|
|
// Tree::Add(vec![
|
|
|
|
// Tree::Val(1.0),
|
|
|
|
// Tree::Val(2.0),
|
|
|
|
// Tree::Div(vec![
|
|
|
|
// Tree::Val(2.0),
|
|
|
|
// Tree::Val(3.0),
|
|
|
|
// Tree::Val(4.0),
|
|
|
|
// Tree::Val(5.0),
|
|
|
|
// ])
|
|
|
|
// ])
|
|
|
|
// );
|
|
|
|
// }
|
|
|
|
// }
|