add access syntax

This commit is contained in:
mehbark 2026-01-03 00:45:46 -05:00
parent 79c3113689
commit b06f2f052f
3 changed files with 90 additions and 6 deletions

View file

@ -72,6 +72,8 @@ pub enum Ast {
Num(f64),
/// `(println bla; 3) #=> 3`
Block(Vec<Ast>),
/// `std.println`
Access(Box<Ast>, Symbol),
}
impl fmt::Display for Ast {
@ -108,6 +110,9 @@ impl fmt::Display for Ast {
let body: Vec<_> = body.iter().map(|stmt| format!("{stmt}")).collect();
write!(f, "({})", body.join(" "))
}
Ast::Access(val, sym) => {
write!(f, "{val}.{sym}")
}
}
}
}

View file

@ -18,6 +18,9 @@ enum Token<'a> {
#[token(":")]
Colon,
#[token(".")]
Period,
#[token(",")]
Comma,
@ -64,6 +67,7 @@ impl fmt::Display for Token<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Token::Colon => write!(f, ":"),
Token::Period => write!(f, "."),
Token::Comma => write!(f, ","),
Token::Semicolon => write!(f, ";"),
Token::Set => write!(f, ":="),
@ -99,6 +103,8 @@ where
recursive(|expr| {
let expr = expr.labelled("expression");
let symbol = select! { Token::Var(s) => s.to_owned() };
let ident = choice((
just(Token::Return)
.ignore_then(select! {
@ -194,7 +200,7 @@ where
})
.labelled("standalone function");
let non_app = choice((
let e1 = choice((
set,
num,
standalone_func,
@ -202,18 +208,28 @@ where
ident.map(Ast::Var).labelled("variable"),
map,
block.map(Ast::Block),
));
))
.boxed();
let app = non_app
let access = e1
.clone()
.foldl(non_app.clone().repeated(), |f, x| {
.then_ignore(just(Token::Period))
.foldl(symbol.separated_by(just(Token::Period)), |a, b| {
Ast::Access(Box::new(a), b)
})
.labelled("access");
let e2 = access.or(e1);
let app = e2
.clone()
.foldl(e2.clone().repeated(), |f, x| {
Ast::App(Box::new(f), Box::new(x))
})
.labelled("function application");
let atom = app.or(non_app);
let atom = app.or(e2);
// %
atom.pratt((
infix(none(1), just(Token::BinOp("=")), |l, _, r, _| {
Ast::BinOp(Box::new(l), BinOp::Eq, Box::new(r))

View file

@ -134,3 +134,66 @@ foo := 3;
",
);
}
#[test]
fn oop() {
test(
"
fn make_counter([] [obj]) (
i := 0;
{
fn ^inc() (
i := i + 1;
);
fn ^dec() (
i := i - 1;
);
fn ^get([] [i]) ();
}
);
counter_a := make_counter {};
counter_b := make_counter {};
counter_a.inc {};
std.println(counter_a.get {});
counter_a.inc {};
std.println(counter_a.get {});
counter_a.inc {};
std.println(counter_a.get {});
counter_a.dec {};
std.println(counter_a.get {});
counter_b.inc {};
std.println(counter_b.get {});
counter_b.dec {};
",
"
(set! make_counter \
(fn ([] [obj]) \
(set! i 0) \
{\
(set! ^inc (fn ([] []) (set! i (i + 1)))) \
(set! ^dec (fn ([] []) (set! i (i - 1)))) \
(set! ^get (fn ([] [i])))\
}\
)\
);
(set! counter_a (make_counter {}));
(set! counter_b (make_counter {}));
(counter_a.inc {});
(std.println ((counter_a.get {})));
(counter_a.inc {});
(std.println ((counter_a.get {})));
(counter_a.inc {});
(std.println ((counter_a.get {})));
(counter_a.dec {});
(std.println ((counter_a.get {})));
(counter_b.inc {});
(std.println ((counter_b.get {})));
(counter_b.dec {})
",
);
}