conlang: Struct, tuple member accesses, member function call syntax
Currently uses UFCS in the interpreter. This may change after type checking?
This commit is contained in:
@@ -352,6 +352,8 @@ pub enum ExprKind {
|
||||
Binary(Binary),
|
||||
/// A [Unary] expression: [`UnaryKind`]\* [`Expr`]
|
||||
Unary(Unary),
|
||||
/// A [Member] access expression: [`Expr`] [`MemberKind`]\*
|
||||
Member(Member),
|
||||
/// An Array [Index] expression: a[10, 20, 30]
|
||||
Index(Index),
|
||||
/// A [Struct creation](Structor) expression: [Path] `{` ([Fielder] `,`)* [Fielder]? `}`
|
||||
@@ -443,7 +445,6 @@ pub enum BinaryKind {
|
||||
Mul,
|
||||
Div,
|
||||
Rem,
|
||||
Dot,
|
||||
Call,
|
||||
}
|
||||
|
||||
@@ -465,6 +466,22 @@ pub enum UnaryKind {
|
||||
/// Unused
|
||||
Tilde,
|
||||
}
|
||||
|
||||
/// A [Member] access expression: [`Expr`] [`MemberKind`]\*
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Member {
|
||||
pub head: Box<ExprKind>,
|
||||
pub kind: MemberKind,
|
||||
}
|
||||
|
||||
/// The kind of [Member] access
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum MemberKind {
|
||||
Call(Identifier, Tuple),
|
||||
Struct(Identifier),
|
||||
Tuple(Literal),
|
||||
}
|
||||
|
||||
/// A repeated [Index] expression: a[10, 20, 30][40, 50, 60]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Index {
|
||||
|
||||
@@ -422,6 +422,7 @@ mod display {
|
||||
ExprKind::Assign(v) => v.fmt(f),
|
||||
ExprKind::Binary(v) => v.fmt(f),
|
||||
ExprKind::Unary(v) => v.fmt(f),
|
||||
ExprKind::Member(v) => v.fmt(f),
|
||||
ExprKind::Index(v) => v.fmt(f),
|
||||
ExprKind::Structor(v) => v.fmt(f),
|
||||
ExprKind::Path(v) => v.fmt(f),
|
||||
@@ -474,7 +475,6 @@ mod display {
|
||||
let Self { kind, parts } = self;
|
||||
let (head, tail) = parts.borrow();
|
||||
match kind {
|
||||
BinaryKind::Dot => write!(f, "{head}{kind}{tail}"),
|
||||
BinaryKind::Call => write!(f, "{head}{tail}"),
|
||||
_ => write!(f, "{head} {kind} {tail}"),
|
||||
}
|
||||
@@ -505,7 +505,6 @@ mod display {
|
||||
BinaryKind::Mul => "*",
|
||||
BinaryKind::Div => "/",
|
||||
BinaryKind::Rem => "%",
|
||||
BinaryKind::Dot => ".",
|
||||
BinaryKind::Call => "()",
|
||||
}
|
||||
.fmt(f)
|
||||
@@ -532,6 +531,23 @@ mod display {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Member {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { head, kind } = self;
|
||||
write!(f, "{head}.{kind}")
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for MemberKind {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MemberKind::Call(name, args) => write!(f, "{name}{args}"),
|
||||
MemberKind::Struct(name) => write!(f, "{name}"),
|
||||
MemberKind::Tuple(name) => write!(f, "{name}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Index {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { head, indices } = self;
|
||||
@@ -735,6 +751,7 @@ mod convert {
|
||||
Assign => ExprKind::Assign,
|
||||
Binary => ExprKind::Binary,
|
||||
Unary => ExprKind::Unary,
|
||||
Member => ExprKind::Member,
|
||||
Index => ExprKind::Index,
|
||||
Path => ExprKind::Path,
|
||||
Literal => ExprKind::Literal,
|
||||
|
||||
@@ -262,6 +262,13 @@ pub trait Fold {
|
||||
fn fold_unary_kind(&mut self, kind: UnaryKind) -> UnaryKind {
|
||||
kind
|
||||
}
|
||||
fn fold_member(&mut self, m: Member) -> Member {
|
||||
let Member { head, kind } = m;
|
||||
Member { head: Box::new(self.fold_expr_kind(*head)), kind: self.fold_member_kind(kind) }
|
||||
}
|
||||
fn fold_member_kind(&mut self, kind: MemberKind) -> MemberKind {
|
||||
or_fold_member_kind(self, kind)
|
||||
}
|
||||
fn fold_index(&mut self, i: Index) -> Index {
|
||||
let Index { head, indices } = i;
|
||||
Index {
|
||||
@@ -517,6 +524,7 @@ pub fn or_fold_expr_kind<F: Fold + ?Sized>(folder: &mut F, kind: ExprKind) -> Ex
|
||||
ExprKind::Assign(a) => ExprKind::Assign(folder.fold_assign(a)),
|
||||
ExprKind::Binary(b) => ExprKind::Binary(folder.fold_binary(b)),
|
||||
ExprKind::Unary(u) => ExprKind::Unary(folder.fold_unary(u)),
|
||||
ExprKind::Member(m) => ExprKind::Member(folder.fold_member(m)),
|
||||
ExprKind::Index(i) => ExprKind::Index(folder.fold_index(i)),
|
||||
ExprKind::Structor(s) => ExprKind::Structor(folder.fold_structor(s)),
|
||||
ExprKind::Path(p) => ExprKind::Path(folder.fold_path(p)),
|
||||
@@ -536,3 +544,12 @@ pub fn or_fold_expr_kind<F: Fold + ?Sized>(folder: &mut F, kind: ExprKind) -> Ex
|
||||
ExprKind::Continue(c) => ExprKind::Continue(folder.fold_continue(c)),
|
||||
}
|
||||
}
|
||||
pub fn or_fold_member_kind<F: Fold + ?Sized>(folder: &mut F, kind: MemberKind) -> MemberKind {
|
||||
match kind {
|
||||
MemberKind::Call(name, args) => {
|
||||
MemberKind::Call(folder.fold_identifier(name), folder.fold_tuple(args))
|
||||
}
|
||||
MemberKind::Struct(name) => MemberKind::Struct(folder.fold_identifier(name)),
|
||||
MemberKind::Tuple(name) => MemberKind::Tuple(folder.fold_literal(name)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,6 +223,14 @@ pub trait Visit<'a>: Sized {
|
||||
self.visit_expr_kind(tail);
|
||||
}
|
||||
fn visit_unary_kind(&mut self, _kind: &'a UnaryKind) {}
|
||||
fn visit_member(&mut self, m: &'a Member) {
|
||||
let Member { head, kind } = m;
|
||||
self.visit_expr_kind(head);
|
||||
self.visit_member_kind(kind);
|
||||
}
|
||||
fn visit_member_kind(&mut self, kind: &'a MemberKind) {
|
||||
or_visit_member_kind(self, kind)
|
||||
}
|
||||
fn visit_index(&mut self, i: &'a Index) {
|
||||
let Index { head, indices } = i;
|
||||
self.visit_expr_kind(head);
|
||||
@@ -431,6 +439,7 @@ pub fn or_visit_expr_kind<'a, V: Visit<'a>>(visitor: &mut V, e: &'a ExprKind) {
|
||||
ExprKind::Assign(a) => visitor.visit_assign(a),
|
||||
ExprKind::Binary(b) => visitor.visit_binary(b),
|
||||
ExprKind::Unary(u) => visitor.visit_unary(u),
|
||||
ExprKind::Member(m) => visitor.visit_member(m),
|
||||
ExprKind::Index(i) => visitor.visit_index(i),
|
||||
ExprKind::Structor(s) => visitor.visit_structor(s),
|
||||
ExprKind::Path(p) => visitor.visit_path(p),
|
||||
@@ -450,3 +459,13 @@ pub fn or_visit_expr_kind<'a, V: Visit<'a>>(visitor: &mut V, e: &'a ExprKind) {
|
||||
ExprKind::Continue(c) => visitor.visit_continue(c),
|
||||
}
|
||||
}
|
||||
pub fn or_visit_member_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a MemberKind) {
|
||||
match kind {
|
||||
MemberKind::Call(field, args) => {
|
||||
visitor.visit_identifier(field);
|
||||
visitor.visit_tuple(args);
|
||||
}
|
||||
MemberKind::Struct(field) => visitor.visit_identifier(field),
|
||||
MemberKind::Tuple(field) => visitor.visit_literal(field),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user