keep working on some things

This commit is contained in:
Scott Richmond 2024-11-07 18:57:01 -05:00
parent 0875ec2ab5
commit 28d1c7ab0c
3 changed files with 81 additions and 2 deletions

View File

@ -43,7 +43,7 @@ mod vm;
use crate::vm::*; use crate::vm::*;
pub fn main() { 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(); let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
if lex_errs.len() > 0 { if lex_errs.len() > 0 {
println!("{:?}", lex_errs); println!("{:?}", lex_errs);

View File

@ -197,6 +197,8 @@ where
Token::Boolean(b) => Pattern::Boolean(b), Token::Boolean(b) => Pattern::Boolean(b),
Token::Number(n) => Pattern::Number(n), Token::Number(n) => Pattern::Number(n),
Token::Keyword(k) => Pattern::Keyword(k), Token::Keyword(k) => Pattern::Keyword(k),
// todo: actual string patterns
Token::String(s) => Pattern::String(s)
} }
.map_with(|a, e| (a, e.span())); .map_with(|a, e| (a, e.span()));

View File

@ -5,7 +5,7 @@ use std::rc::Rc;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct LudusError { pub struct LudusError {
msg: String, msg: &'static str,
} }
// oy // oy
@ -19,6 +19,8 @@ pub struct LudusError {
// to work with a mutable borrow of ctx // to work with a mutable borrow of ctx
pub struct Ctx<'src> { pub struct Ctx<'src> {
pub locals: Vec<(&'src str, Value<'src>)>, pub locals: Vec<(&'src str, Value<'src>)>,
// pub names: Vec<&'src str>,
// pub values: Vec<Value<'src>>,
} }
impl<'src> Ctx<'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>( pub fn eval<'src, 'a>(
ast: &Ast<'src>, ast: &Ast<'src>,
ctx: &'a mut Vec<(&'src str, Value<'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::Keyword(k) => Ok(Value::Keyword(k)),
Ast::String(s) => Ok(Value::String(s)), Ast::String(s) => Ok(Value::String(s)),
Ast::Block(exprs) => { Ast::Block(exprs) => {
let to = ctx.len();
let mut result = Value::Nil; let mut result = Value::Nil;
for (expr, _) in exprs { for (expr, _) in exprs {
result = eval(expr, ctx)?; result = eval(expr, ctx)?;
} }
while ctx.len() > to {
ctx.pop();
}
Ok(result) Ok(result)
} }
Ast::If(cond, if_true, if_false) => { Ast::If(cond, if_true, if_false) => {
@ -82,6 +152,13 @@ pub fn eval<'src, 'a>(
}; };
Ok(val) 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!(), _ => todo!(),
} }
} }