keep working on some things
This commit is contained in:
parent
0875ec2ab5
commit
28d1c7ab0c
|
@ -43,7 +43,7 @@ mod vm;
|
|||
use crate::vm::*;
|
||||
|
||||
pub fn main() {
|
||||
let src = "[1, 2, 3]";
|
||||
let src = "let (x, 2) = (1, 2); x";
|
||||
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
||||
if lex_errs.len() > 0 {
|
||||
println!("{:?}", lex_errs);
|
||||
|
|
|
@ -197,6 +197,8 @@ where
|
|||
Token::Boolean(b) => Pattern::Boolean(b),
|
||||
Token::Number(n) => Pattern::Number(n),
|
||||
Token::Keyword(k) => Pattern::Keyword(k),
|
||||
// todo: actual string patterns
|
||||
Token::String(s) => Pattern::String(s)
|
||||
}
|
||||
.map_with(|a, e| (a, e.span()));
|
||||
|
||||
|
|
79
src/vm.rs
79
src/vm.rs
|
@ -5,7 +5,7 @@ use std::rc::Rc;
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct LudusError {
|
||||
msg: String,
|
||||
msg: &'static str,
|
||||
}
|
||||
|
||||
// oy
|
||||
|
@ -19,6 +19,8 @@ pub struct LudusError {
|
|||
// to work with a mutable borrow of ctx
|
||||
pub struct Ctx<'src> {
|
||||
pub locals: Vec<(&'src str, Value<'src>)>,
|
||||
// pub names: Vec<&'src str>,
|
||||
// pub values: Vec<Value<'src>>,
|
||||
}
|
||||
|
||||
impl<'src> Ctx<'src> {
|
||||
|
@ -35,6 +37,70 @@ impl<'src> Ctx<'src> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn match_eq<T, U>(x: T, y: T, z: U) -> Option<U>
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
if x == y {
|
||||
Some(z)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn matchh<'src, 'a>(
|
||||
patt: &Pattern<'src>,
|
||||
val: &Value<'src>,
|
||||
ctx: &'a mut Vec<(&'src str, Value<'src>)>,
|
||||
) -> Option<&'a mut Vec<(&'src str, Value<'src>)>> {
|
||||
match (patt, val) {
|
||||
(Pattern::Nil, Value::Nil) => Some(ctx),
|
||||
(Pattern::Placeholder, _) => Some(ctx),
|
||||
(Pattern::Number(x), Value::Number(y)) => match_eq(x, y, ctx),
|
||||
(Pattern::Boolean(x), Value::Boolean(y)) => match_eq(x, y, ctx),
|
||||
(Pattern::Keyword(x), Value::Keyword(y)) => match_eq(x, y, ctx),
|
||||
(Pattern::String(x), Value::String(y)) => match_eq(x, y, ctx),
|
||||
(Pattern::Word(w), val) => {
|
||||
ctx.push((w, val.clone()));
|
||||
Some(ctx)
|
||||
}
|
||||
// todo: add splats to these match clauses
|
||||
(Pattern::Tuple(x), Value::Tuple(y)) => {
|
||||
if x.len() != y.len() {
|
||||
return None;
|
||||
};
|
||||
let to = ctx.len();
|
||||
for i in 0..x.len() {
|
||||
if let None = matchh(&x[i].0, &y[i], ctx) {
|
||||
while ctx.len() > to {
|
||||
ctx.pop();
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(ctx)
|
||||
}
|
||||
(Pattern::List(x), Value::List(y)) => {
|
||||
if x.len() != y.len() {
|
||||
return None;
|
||||
};
|
||||
let to = ctx.len();
|
||||
for i in 0..x.len() {
|
||||
if let None = matchh(&x[i].0, y.get(i).unwrap(), ctx) {
|
||||
while ctx.len() > to {
|
||||
ctx.pop();
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
Some(ctx)
|
||||
}
|
||||
(Pattern::Pair(_, _), _) => todo!("dictionary patterns still to do"),
|
||||
(Pattern::Dict(_), _) => todo!("dictionary patterns still to do"),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval<'src, 'a>(
|
||||
ast: &Ast<'src>,
|
||||
ctx: &'a mut Vec<(&'src str, Value<'src>)>,
|
||||
|
@ -46,10 +112,14 @@ pub fn eval<'src, 'a>(
|
|||
Ast::Keyword(k) => Ok(Value::Keyword(k)),
|
||||
Ast::String(s) => Ok(Value::String(s)),
|
||||
Ast::Block(exprs) => {
|
||||
let to = ctx.len();
|
||||
let mut result = Value::Nil;
|
||||
for (expr, _) in exprs {
|
||||
result = eval(expr, ctx)?;
|
||||
}
|
||||
while ctx.len() > to {
|
||||
ctx.pop();
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
Ast::If(cond, if_true, if_false) => {
|
||||
|
@ -82,6 +152,13 @@ pub fn eval<'src, 'a>(
|
|||
};
|
||||
Ok(val)
|
||||
}
|
||||
Ast::Let(patt, expr) => {
|
||||
let val = eval(&expr.0, ctx)?;
|
||||
match matchh(&patt.0, &val, ctx) {
|
||||
Some(_) => Ok(val),
|
||||
None => Err(LudusError { msg: "No match" }),
|
||||
}
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user