[fine] Improvements to classes

- Classes are defined lazily
- Member access is via environment
- Member access is just a binary expression with a weird environment
- Slot loads look like variable loads now
- Associativity in the parser (ugh)
This commit is contained in:
John Doty 2024-01-22 23:17:02 -08:00
parent 0d48bfb113
commit 2839b43f6d
5 changed files with 286 additions and 123 deletions

View file

@ -129,6 +129,8 @@ pub enum TreeKind {
ConditionalExpression,
ExpressionStatement,
FieldDecl,
FieldList,
FieldValue,
File,
ForStatement,
FunctionDecl,
@ -139,18 +141,18 @@ pub enum TreeKind {
ListConstructor,
ListConstructorElement,
LiteralExpression,
MemberAccess,
NewObjectExpression,
ParamList,
Parameter,
ReturnStatement,
ReturnType,
SelfParameter,
SelfReference,
TypeExpression,
TypeParameter,
TypeParameterList,
UnaryExpression,
FieldList,
NewObjectExpression,
FieldValue,
MemberAccess,
}
pub struct Tree<'a> {
@ -606,6 +608,8 @@ fn param_list(p: &mut CParser) {
while !p.at(TokenKind::RightParen) && !p.eof() {
if p.at(TokenKind::Identifier) {
parameter(p);
} else if p.at(TokenKind::Selff) {
self_parameter(p);
} else {
if p.at_any(PARAM_LIST_RECOVERY) {
break;
@ -632,6 +636,21 @@ fn parameter(p: &mut CParser) {
p.end(m, TreeKind::Parameter);
}
fn self_parameter(p: &mut CParser) {
let m = p.start();
p.expect_start(TokenKind::Selff);
if p.eat(TokenKind::Colon) {
p.error("self parameters cannot have explicit types");
type_expr(p);
}
if !p.at(TokenKind::RightParen) {
p.expect(TokenKind::Comma, "expected a comma between parameters");
}
p.end(m, TreeKind::SelfParameter);
}
fn return_type(p: &mut CParser) {
let m = p.start();
@ -780,31 +799,27 @@ fn expression(p: &mut CParser) {
expression_with_power(p, 0)
}
// BINDING POWERS. When parsing expressions we only accept expressions that
// meet a minimum binding power. (This is like "precedence" but I just super
// don't like that terminology.)
const ASSIGNMENT_POWER: u8 = 0; // =
const OR_POWER: u8 = 1; // or
const AND_POWER: u8 = 2; // and
const EQUALITY_POWER: u8 = 3; // == !=
const COMPARISON_POWER: u8 = 4; // < > <= >=
const TERM_POWER: u8 = 5; // + -
const FACTOR_POWER: u8 = 6; // * /
const UNARY_POWER: u8 = 7; // ! -
const UNARY_POWER: u8 = 14;
// const PRIMARY_POWER: u8 = 9;
fn token_power<'a>(token: TokenKind) -> Option<u8> {
fn infix_power(token: TokenKind) -> Option<(u8, u8)> {
// A dumb thing: the pair controls associativity.
//
// If lhs < rhs then it's left-associative, otherwise it's
// right-associative.
match token {
TokenKind::Equal => Some(ASSIGNMENT_POWER),
TokenKind::Or => Some(OR_POWER),
TokenKind::And => Some(AND_POWER),
TokenKind::EqualEqual | TokenKind::BangEqual => Some(EQUALITY_POWER),
TokenKind::Equal => Some((1, 0)),
TokenKind::Or => Some((2, 3)),
TokenKind::And => Some((4, 5)),
TokenKind::EqualEqual | TokenKind::BangEqual => Some((6, 7)),
TokenKind::Less | TokenKind::Greater | TokenKind::GreaterEqual | TokenKind::LessEqual => {
Some(COMPARISON_POWER)
Some((8, 9))
}
TokenKind::Plus | TokenKind::Minus => Some(TERM_POWER),
TokenKind::Star | TokenKind::Slash => Some(FACTOR_POWER),
TokenKind::Plus | TokenKind::Minus => Some((10, 11)),
TokenKind::Star | TokenKind::Slash => Some((12, 13)),
//
// UNARY_POWER goes here.
//
TokenKind::Dot => Some((16, 17)),
_ => None,
}
}
@ -818,10 +833,11 @@ fn expression_with_power(p: &mut CParser, minimum_power: u8) {
}
loop {
let Some(power) = token_power(p.peek()) else {
let token = p.peek();
let Some((lp, rp)) = infix_power(token) else {
break;
};
if power < minimum_power {
if lp < minimum_power {
break;
}
@ -829,18 +845,15 @@ fn expression_with_power(p: &mut CParser, minimum_power: u8) {
// see won't we.
let m = p.start_before(expr);
p.advance(); // Consume the operator
expression_with_power(p, power);
expr = p.end(m, TreeKind::BinaryExpression);
}
while p.at(TokenKind::Dot) {
let m = p.start_before(expr);
p.advance(); // Consume the dot
p.expect(
TokenKind::Identifier,
"expected an identifier for member access",
expression_with_power(p, rp);
expr = p.end(
m,
if token == TokenKind::Dot {
TreeKind::MemberAccess
} else {
TreeKind::BinaryExpression
},
);
expr = p.end(m, TreeKind::MemberAccess);
}
}
@ -885,6 +898,7 @@ fn prefix_expression(p: &mut CParser) -> MarkClosed {
TokenKind::If => conditional(p),
TokenKind::Identifier => identifier(p),
TokenKind::Selff => self_reference(p),
TokenKind::LeftBracket => list_constructor(p),
@ -946,6 +960,15 @@ fn identifier(p: &mut CParser) -> MarkClosed {
p.end(m, TreeKind::Identifier)
}
fn self_reference(p: &mut CParser) -> MarkClosed {
assert!(p.at(TokenKind::Selff));
let m = p.start();
p.advance();
p.end(m, TreeKind::SelfReference)
}
fn list_constructor(p: &mut CParser) -> MarkClosed {
let m = p.start();