conlang: Add constructor expression for structs!
grammar: - Add new rules `PathLike`, `Structor`, `Fielder` - Replace Path with PathLike in Primary expressions cl-ast: - Add nodes for Structor and Fielder cl-parser: - Add branch to path-expression parsing - Parse Structor bodies interpret: - Add TODO
This commit is contained in:
@@ -350,6 +350,8 @@ pub enum ExprKind {
|
||||
Unary(Unary),
|
||||
/// An Array [Index] expression: a[10, 20, 30]
|
||||
Index(Index),
|
||||
/// A [Struct creation](Structor) expression: [Path] `{` ([Fielder] `,`)* [Fielder]? `}`
|
||||
Structor(Structor),
|
||||
/// A [path expression](Path): `::`? [PathPart] (`::` [PathPart])*
|
||||
Path(Path),
|
||||
/// A [Literal]: 0x42, 1e123, 2.4, "Hello"
|
||||
@@ -466,6 +468,20 @@ pub struct Index {
|
||||
pub indices: Vec<Expr>,
|
||||
}
|
||||
|
||||
/// A [Struct creation](Structor) expression: [Path] `{` ([Fielder] `,`)* [Fielder]? `}`
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Structor {
|
||||
pub to: Path,
|
||||
pub init: Vec<Fielder>,
|
||||
}
|
||||
|
||||
/// A [Struct field initializer] expression: [Identifier] (`=` [Expr])?
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Fielder {
|
||||
pub name: Identifier,
|
||||
pub init: Option<Box<Expr>>,
|
||||
}
|
||||
|
||||
/// An [Array] literal: `[` [`Expr`] (`,` [`Expr`])\* `]`
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Array {
|
||||
|
||||
@@ -424,6 +424,7 @@ mod display {
|
||||
ExprKind::Binary(v) => v.fmt(f),
|
||||
ExprKind::Unary(v) => v.fmt(f),
|
||||
ExprKind::Index(v) => v.fmt(f),
|
||||
ExprKind::Structor(v) => v.fmt(f),
|
||||
ExprKind::Path(v) => v.fmt(f),
|
||||
ExprKind::Literal(v) => v.fmt(f),
|
||||
ExprKind::Array(v) => v.fmt(f),
|
||||
@@ -540,6 +541,25 @@ mod display {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Structor {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { to, init } = self;
|
||||
write!(f, "{to}: ")?;
|
||||
separate(init, ", ")(f.delimit(INLINE_BRACES))
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Fielder {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let Self { name, init } = self;
|
||||
write!(f, "{name}")?;
|
||||
if let Some(init) = init {
|
||||
write!(f, ": {init}")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Array {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
separate(&self.values, ", ")(f.delimit(INLINE_SQUARE))
|
||||
|
||||
@@ -269,6 +269,22 @@ pub trait Fold {
|
||||
indices: indices.into_iter().map(|e| self.fold_expr(e)).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_structor(&mut self, s: Structor) -> Structor {
|
||||
let Structor { to, init } = s;
|
||||
Structor {
|
||||
to: self.fold_path(to),
|
||||
init: init.into_iter().map(|f| self.fold_fielder(f)).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_fielder(&mut self, f: Fielder) -> Fielder {
|
||||
let Fielder { name, init } = f;
|
||||
Fielder {
|
||||
name: self.fold_identifier(name),
|
||||
init: init.map(|e| Box::new(self.fold_expr(*e))),
|
||||
}
|
||||
}
|
||||
fn fold_array(&mut self, a: Array) -> Array {
|
||||
let Array { values } = a;
|
||||
Array { values: values.into_iter().map(|e| self.fold_expr(e)).collect() }
|
||||
@@ -499,6 +515,7 @@ pub fn or_fold_expr_kind<F: Fold + ?Sized>(folder: &mut F, kind: ExprKind) -> Ex
|
||||
ExprKind::Binary(b) => ExprKind::Binary(folder.fold_binary(b)),
|
||||
ExprKind::Unary(u) => ExprKind::Unary(folder.fold_unary(u)),
|
||||
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)),
|
||||
ExprKind::Literal(l) => ExprKind::Literal(folder.fold_literal(l)),
|
||||
ExprKind::Array(a) => ExprKind::Array(folder.fold_array(a)),
|
||||
|
||||
@@ -228,6 +228,18 @@ pub trait Visit<'a>: Sized {
|
||||
self.visit_expr_kind(head);
|
||||
indices.iter().for_each(|e| self.visit_expr(e));
|
||||
}
|
||||
fn visit_structor(&mut self, s: &'a Structor) {
|
||||
let Structor { to, init } = s;
|
||||
self.visit_path(to);
|
||||
init.iter().for_each(|e| self.visit_fielder(e))
|
||||
}
|
||||
fn visit_fielder(&mut self, f: &'a Fielder) {
|
||||
let Fielder { name, init } = f;
|
||||
self.visit_identifier(name);
|
||||
if let Some(init) = init {
|
||||
self.visit_expr(init);
|
||||
}
|
||||
}
|
||||
fn visit_array(&mut self, a: &'a Array) {
|
||||
let Array { values } = a;
|
||||
values.iter().for_each(|e| self.visit_expr(e))
|
||||
@@ -415,6 +427,7 @@ pub fn or_visit_expr_kind<'a, V: Visit<'a>>(visitor: &mut V, e: &'a ExprKind) {
|
||||
ExprKind::Binary(b) => visitor.visit_binary(b),
|
||||
ExprKind::Unary(u) => visitor.visit_unary(u),
|
||||
ExprKind::Index(i) => visitor.visit_index(i),
|
||||
ExprKind::Structor(s) => visitor.visit_structor(s),
|
||||
ExprKind::Path(p) => visitor.visit_path(p),
|
||||
ExprKind::Literal(l) => visitor.visit_literal(l),
|
||||
ExprKind::Array(a) => visitor.visit_array(a),
|
||||
|
||||
Reference in New Issue
Block a user