Skip to content

Instantly share code, notes, and snippets.

@aripiprazole
Created July 5, 2023 20:02
Show Gist options
  • Save aripiprazole/4073479eb08dc2709dd77754eea2f8d8 to your computer and use it in GitHub Desktop.
Save aripiprazole/4073479eb08dc2709dd77754eea2f8d8 to your computer and use it in GitHub Desktop.
expr.rs a very cute file
/// Accessor expression, is an expression that is an accessor to a field in a struct, it can be
/// represented by [GlobalId], since it can hold `.` too.
///
/// # Examples
///
/// The syntax is like:
/// ```haskell
/// person.data
/// ```
#[derive(Default, Node, Clone)]
pub struct Accessor(GreenTree);
#[ast_of]
impl Accessor {
#[ast_leaf]
pub fn receiver(&self) -> Expr {
self.filter().first()
}
#[ast_leaf]
pub fn segments(&self) -> Vec<AccessorSegment> {
self.filter()
}
/// Represents the module canonical path of the module that contains this accessor.
pub fn compute_receiver_paths(&self) -> ReceiverPaths {
let Expr::LocalExpr(receiver) = self.receiver() else {
let receiver = Receiver::Expr(self.receiver());
return ReceiverPaths { receiver, segments: self.segments() };
};
let mut path = vec![];
let mut remaining_segments = vec![];
let mut should_skip_path = false;
for argument in self.segments().iter() {
if should_skip_path {
remaining_segments.push(argument.clone());
} else {
path.push(argument.name());
}
if !argument.arguments().is_empty() {
should_skip_path = true;
remaining_segments.push(argument.clone());
}
}
ReceiverPaths {
receiver: Receiver::Path(QualifiedPath::of(path)),
segments: remaining_segments,
}
}
}
#[derive(Debug)]
pub enum Receiver {
Expr(Expr),
Path(QualifiedPath),
}
#[derive(Debug)]
pub struct ReceiverPaths {
pub receiver: Receiver,
pub segments: Vec<AccessorSegment>,
}
impl Listenable for Receiver {
type Listener<'a> = &'a mut dyn AsenaListener<()>;
fn listen(&self, listener: &mut Self::Listener<'_>) {
match self {
Receiver::Expr(expr) => expr.listen(listener),
Receiver::Path(path) => path.listen(listener),
}
}
}
impl Walkable for Receiver {
type Walker<'a> = &'a mut dyn AsenaVisitor<()>;
fn walk(&self, walker: &mut Self::Walker<'_>) {
match self {
Receiver::Expr(expr) => expr.walk(walker),
Receiver::Path(path) => path.walk(walker),
}
}
}
impl Listenable for ReceiverPaths {
type Listener<'a> = &'a mut dyn AsenaListener<()>;
fn listen(&self, walker: &mut Self::Listener<'_>) {
self.receiver.listen(walker);
self.segments.listen(walker);
}
}
impl Walkable for ReceiverPaths {
type Walker<'a> = &'a mut dyn AsenaVisitor<()>;
fn walk(&self, walker: &mut Self::Walker<'_>) {
self.receiver.walk(walker);
self.segments.walk(walker);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment