actually remove catchall pattern in eval
This commit is contained in:
parent
fd55604608
commit
32ab5f7944
|
@ -43,7 +43,7 @@ mod vm;
|
|||
use crate::vm::*;
|
||||
|
||||
pub fn main() {
|
||||
let src = "let (x, 2) = (1, 2); x";
|
||||
let src = "when { false -> :false, true -> :true}";
|
||||
let (tokens, lex_errs) = lexer().parse(src).into_output_errors();
|
||||
if lex_errs.len() > 0 {
|
||||
println!("{:?}", lex_errs);
|
||||
|
|
|
@ -3,6 +3,12 @@ use crate::spans::*;
|
|||
use chumsky::{input::ValueInput, prelude::*, recursive::Recursive};
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct WhenClause<'src> {
|
||||
pub cond: Spanned<Ast<'src>>,
|
||||
pub body: Spanned<Ast<'src>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Ast<'src> {
|
||||
Error,
|
||||
|
@ -23,8 +29,7 @@ pub enum Ast<'src> {
|
|||
Let(Box<Spanned<Pattern<'src>>>, Box<Spanned<Self>>),
|
||||
Box(&'src str, Box<Spanned<Self>>),
|
||||
Synthetic(Box<Spanned<Self>>, Box<Spanned<Self>>, Vec<Spanned<Self>>),
|
||||
WhenClause(Box<Spanned<Self>>, Box<Spanned<Self>>),
|
||||
When(Vec<Spanned<Self>>),
|
||||
When(Vec<Spanned<WhenClause<'src>>>),
|
||||
MatchClause(Box<Spanned<Pattern<'src>>>, Box<Spanned<Self>>),
|
||||
Match(Box<Spanned<Self>>, Vec<Spanned<Self>>),
|
||||
FnClause(Box<Spanned<Pattern<'src>>>, Box<Spanned<Self>>),
|
||||
|
@ -382,7 +387,7 @@ where
|
|||
.clone()
|
||||
.then_ignore(just(Token::Punctuation("->")))
|
||||
.then(expr.clone())
|
||||
.map_with(|(cond, body), e| (Ast::WhenClause(Box::new(cond), Box::new(body)), e.span()));
|
||||
.map_with(|(cond, body), e| (WhenClause { cond, body }, e.span()));
|
||||
|
||||
let when = just(Token::Reserved("when"))
|
||||
.ignore_then(
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::parser::*;
|
||||
use crate::spans::*;
|
||||
use imbl::*;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -31,6 +32,7 @@ pub enum Value<'src> {
|
|||
List(Rc<Vector<Self>>),
|
||||
// ref-counted, immutable, persistent
|
||||
Dict(Rc<HashMap<&'src str, Self>>),
|
||||
Box(&'src str, Box<Self>),
|
||||
// Fn(Rc<Fn<'src>>),
|
||||
// Set(HashSet<Self>),
|
||||
// Sets are hard
|
||||
|
@ -55,6 +57,7 @@ impl<'src> Clone for Value<'src> {
|
|||
Value::Tuple(t) => Value::Tuple(t.clone()),
|
||||
Value::List(l) => Value::List(l.clone()),
|
||||
Value::Dict(d) => Value::Dict(d.clone()),
|
||||
Value::Box(name, b) => Value::Box(name, b.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,6 +88,7 @@ impl<'src> fmt::Display for Value<'src> {
|
|||
.join(", ")
|
||||
),
|
||||
Value::Dict(d) => write!(f, "#{{{:?}}}", d),
|
||||
Value::Box(name, b) => write!(f, "box {} [ {} ]", name, b),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
44
src/vm.rs
44
src/vm.rs
|
@ -5,7 +5,7 @@ use std::rc::Rc;
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct LudusError {
|
||||
msg: &'static str,
|
||||
msg: String,
|
||||
}
|
||||
|
||||
// oy
|
||||
|
@ -156,7 +156,9 @@ pub fn eval<'src, 'a>(
|
|||
let val = eval(&expr.0, ctx)?;
|
||||
match matchh(&patt.0, &val, ctx) {
|
||||
Some(_) => Ok(val),
|
||||
None => Err(LudusError { msg: "No match" }),
|
||||
None => Err(LudusError {
|
||||
msg: "No match".to_string(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
Ast::Placeholder => todo!(),
|
||||
|
@ -166,15 +168,45 @@ pub fn eval<'src, 'a>(
|
|||
Ast::Pair(_, _) => todo!(),
|
||||
Ast::Box(_, _) => todo!(),
|
||||
Ast::Synthetic(_, _, _) => todo!(),
|
||||
Ast::When(_) => todo!(),
|
||||
Ast::WhenClause(_, _) => todo!(),
|
||||
Ast::When(clauses) => {
|
||||
for clause in clauses.iter() {
|
||||
let WhenClause { cond, body } = &clause.0;
|
||||
if eval(&cond.0, ctx)?.bool() {
|
||||
return eval(&body.0, ctx);
|
||||
};
|
||||
}
|
||||
return Err(LudusError {
|
||||
msg: "no match".to_string(),
|
||||
});
|
||||
}
|
||||
Ast::Match(_, _) => todo!(),
|
||||
Ast::MatchClause(_, _) => todo!(),
|
||||
Ast::Fn(_, _) => todo!(),
|
||||
Ast::FnDeclaration(_) => todo!(),
|
||||
Ast::FnClause(_, _) => todo!(),
|
||||
Ast::Panic(_) => todo!(),
|
||||
Ast::Repeat(_, _) => todo!(),
|
||||
Ast::Panic(msg) => {
|
||||
let msg = eval(&msg.0, ctx)?;
|
||||
Err(LudusError {
|
||||
msg: msg.to_string(),
|
||||
})
|
||||
}
|
||||
Ast::Repeat(times, body) => {
|
||||
let mut times_num = 0;
|
||||
match eval(×.0, ctx) {
|
||||
Ok(Value::Number(n)) => {
|
||||
times_num = n as usize;
|
||||
}
|
||||
_ => {
|
||||
return Err(LudusError {
|
||||
msg: "repeat may only take numbers".to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
for _ in 0..times_num {
|
||||
let _ = eval(&body.0, ctx)?;
|
||||
}
|
||||
Ok(Value::Nil)
|
||||
}
|
||||
Ast::Do(_) => todo!(),
|
||||
Ast::Loop(_, _) => todo!(),
|
||||
Ast::Recur(_) => todo!(),
|
||||
|
|
Loading…
Reference in New Issue
Block a user