add access syntax
This commit is contained in:
parent
79c3113689
commit
b06f2f052f
3 changed files with 90 additions and 6 deletions
|
|
@ -72,6 +72,8 @@ pub enum Ast {
|
||||||
Num(f64),
|
Num(f64),
|
||||||
/// `(println bla; 3) #=> 3`
|
/// `(println bla; 3) #=> 3`
|
||||||
Block(Vec<Ast>),
|
Block(Vec<Ast>),
|
||||||
|
/// `std.println`
|
||||||
|
Access(Box<Ast>, Symbol),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Ast {
|
impl fmt::Display for Ast {
|
||||||
|
|
@ -108,6 +110,9 @@ impl fmt::Display for Ast {
|
||||||
let body: Vec<_> = body.iter().map(|stmt| format!("{stmt}")).collect();
|
let body: Vec<_> = body.iter().map(|stmt| format!("{stmt}")).collect();
|
||||||
write!(f, "({})", body.join(" "))
|
write!(f, "({})", body.join(" "))
|
||||||
}
|
}
|
||||||
|
Ast::Access(val, sym) => {
|
||||||
|
write!(f, "{val}.{sym}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ enum Token<'a> {
|
||||||
#[token(":")]
|
#[token(":")]
|
||||||
Colon,
|
Colon,
|
||||||
|
|
||||||
|
#[token(".")]
|
||||||
|
Period,
|
||||||
|
|
||||||
#[token(",")]
|
#[token(",")]
|
||||||
Comma,
|
Comma,
|
||||||
|
|
||||||
|
|
@ -64,6 +67,7 @@ impl fmt::Display for Token<'_> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Token::Colon => write!(f, ":"),
|
Token::Colon => write!(f, ":"),
|
||||||
|
Token::Period => write!(f, "."),
|
||||||
Token::Comma => write!(f, ","),
|
Token::Comma => write!(f, ","),
|
||||||
Token::Semicolon => write!(f, ";"),
|
Token::Semicolon => write!(f, ";"),
|
||||||
Token::Set => write!(f, ":="),
|
Token::Set => write!(f, ":="),
|
||||||
|
|
@ -99,6 +103,8 @@ where
|
||||||
recursive(|expr| {
|
recursive(|expr| {
|
||||||
let expr = expr.labelled("expression");
|
let expr = expr.labelled("expression");
|
||||||
|
|
||||||
|
let symbol = select! { Token::Var(s) => s.to_owned() };
|
||||||
|
|
||||||
let ident = choice((
|
let ident = choice((
|
||||||
just(Token::Return)
|
just(Token::Return)
|
||||||
.ignore_then(select! {
|
.ignore_then(select! {
|
||||||
|
|
@ -194,7 +200,7 @@ where
|
||||||
})
|
})
|
||||||
.labelled("standalone function");
|
.labelled("standalone function");
|
||||||
|
|
||||||
let non_app = choice((
|
let e1 = choice((
|
||||||
set,
|
set,
|
||||||
num,
|
num,
|
||||||
standalone_func,
|
standalone_func,
|
||||||
|
|
@ -202,18 +208,28 @@ where
|
||||||
ident.map(Ast::Var).labelled("variable"),
|
ident.map(Ast::Var).labelled("variable"),
|
||||||
map,
|
map,
|
||||||
block.map(Ast::Block),
|
block.map(Ast::Block),
|
||||||
));
|
))
|
||||||
|
.boxed();
|
||||||
|
|
||||||
let app = non_app
|
let access = e1
|
||||||
.clone()
|
.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))
|
Ast::App(Box::new(f), Box::new(x))
|
||||||
})
|
})
|
||||||
.labelled("function application");
|
.labelled("function application");
|
||||||
|
|
||||||
let atom = app.or(non_app);
|
let atom = app.or(e2);
|
||||||
|
|
||||||
// %
|
|
||||||
atom.pratt((
|
atom.pratt((
|
||||||
infix(none(1), just(Token::BinOp("=")), |l, _, r, _| {
|
infix(none(1), just(Token::BinOp("=")), |l, _, r, _| {
|
||||||
Ast::BinOp(Box::new(l), BinOp::Eq, Box::new(r))
|
Ast::BinOp(Box::new(l), BinOp::Eq, Box::new(r))
|
||||||
|
|
|
||||||
|
|
@ -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 {})
|
||||||
|
",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue