keep working on some things
This commit is contained in:
parent
0875ec2ab5
commit
28d1c7ab0c
|
@ -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);
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
||||||
|
|
79
src/vm.rs
79
src/vm.rs
|
@ -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!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user