Compilation aided syntax highlighting

This commit is contained in:
Mia
2026-03-09 11:07:24 +01:00
parent 63890e46d9
commit dc94090976
11 changed files with 798 additions and 280 deletions
+23 -14
View File
@@ -22,6 +22,7 @@ pub enum BinaryOperator {
#[derive(Debug, Deref, Clone)]
pub struct AstNode<T> {
pub path: Arc<[u32]>,
pub range: Range<usize>,
#[deref]
pub node: T,
@@ -30,27 +31,27 @@ pub struct AstNode<T> {
#[derive(Debug, Clone)]
pub struct Number {
pub number: Range<usize>,
pub ty: Option<Range<usize>>,
pub ty: Option<AstNode<()>>,
}
#[derive(Debug, Clone)]
pub enum Expr {
Number(Number),
String(Range<usize>),
Ident(Range<usize>),
Ident,
Uninit(Range<usize>),
If(Box<If>),
If(Box<AstNode<If>>),
Func(Arc<AstNode<Function>>),
While(Box<While>),
While(Box<AstNode<While>>),
Block(Arc<AstNode<Block>>),
VarDecl(Box<VarDecl>),
ConstDecl(Box<ConstDecl>),
VarDecl(Box<AstNode<VarDecl>>),
ConstDecl(Box<AstNode<ConstDecl>>),
List(Vec<AstNode<Expr>>),
Tuple(Vec<AstNode<Expr>>),
Access {
value: Box<AstNode<Expr>>,
operator: Range<usize>,
field: Range<usize>,
field: AstNode<()>,
},
Deref {
value: Box<AstNode<Expr>>,
@@ -97,7 +98,7 @@ pub struct Import {
#[derive(Debug, Clone)]
pub struct Field {
pub name: Range<usize>,
pub name: AstNode<()>,
pub ty: AstNode<Expr>,
pub public: Option<Range<usize>>,
pub mutable: Option<Range<usize>>,
@@ -105,19 +106,27 @@ pub struct Field {
#[derive(Debug, Clone)]
pub enum NamePattern {
Single(Range<usize>),
Tuple(Vec<Range<usize>>),
List(Vec<Range<usize>>),
Single(AstNode<()>),
Tuple(Vec<AstNode<()>>),
List(Vec<AstNode<()>>),
}
impl NamePattern {
pub fn as_slice(&self) -> &[Range<usize>] {
pub fn as_slice(&self) -> &[AstNode<()>] {
match self {
NamePattern::Single(ident) => std::slice::from_ref(ident),
NamePattern::Tuple(idents) => idents.as_slice(),
NamePattern::List(idents) => idents.as_slice(),
}
}
pub(crate) fn as_mut_slice(&mut self) -> &mut [AstNode<()>] {
match self {
NamePattern::Single(ident) => std::slice::from_mut(ident),
NamePattern::Tuple(idents) => idents.as_mut_slice(),
NamePattern::List(idents) => idents.as_mut_slice(),
}
}
}
#[derive(Debug, Clone)]
@@ -174,13 +183,13 @@ pub struct Function {
#[derive(Debug, Clone)]
pub struct Parameter {
pub name: Range<usize>,
pub name: AstNode<()>,
pub value: AstNode<Expr>,
}
#[derive(Debug, Clone)]
pub struct NameValuePair {
pub name: Range<usize>,
pub name: AstNode<()>,
pub value: AstNode<Expr>,
}
+11 -3
View File
@@ -1,9 +1,10 @@
pub use arcstr::{ArcStr, Substr};
use derive_more::Display;
pub use parser::{compilation_unit as parse, *};
pub use parser::*;
use rangemap::RangeMap;
use std::{
fmt::Debug,
ops::Range,
path::{Path, PathBuf},
sync::OnceLock,
};
@@ -11,10 +12,11 @@ use std::{
#[cfg(feature = "rope")]
pub use ropey::Rope;
use crate::ast::AstRoot;
use crate::{ast::AstRoot, path::ComputePaths};
pub mod ast;
mod parser;
mod path;
#[derive(Display)]
pub enum Text {
@@ -22,7 +24,7 @@ pub enum Text {
#[display("{_0}")]
Rope(Rope),
#[display("{_0}")]
ArcStr(ArcStr, OnceLock<RangeMap<usize, (usize, Substr)>>),
ArcStr(ArcStr, OnceLock<RangeMap<usize, (usize, Range<usize>)>>),
}
pub struct SourceCode {
@@ -68,3 +70,9 @@ impl Debug for SourceCode {
.finish_non_exhaustive()
}
}
pub fn parse(src: &SourceCode) -> Result<AstRoot, ParseError<LineCol>> {
let mut ast = compilation_unit(src)?;
ast.compute_paths(&mut vec![]);
Ok(ast)
}
+73 -65
View File
@@ -6,6 +6,9 @@ use peg::{ParseElem, ParseLiteral};
pub use peg::{error::*, str::LineCol};
use rangemap::RangeMap;
use std::ops::Range;
use std::sync::Arc;
use std::sync::OnceLock;
use std::time::Instant;
impl Parse for SourceCode {
type PositionRepr = LineCol;
@@ -42,14 +45,14 @@ impl Parse for SourceCode {
let lines = lines.get_or_init(|| {
let mut lines = RangeMap::new();
for (i, text) in s.split_inclusive('\n').enumerate() {
let text = s.substr_from(text);
let range = text.range();
lines.insert(range, (i, text));
let start = text.as_ptr() as usize - s.as_ptr() as usize;
let range = start..start + text.len();
lines.insert(range.clone(), (i, range));
}
lines
});
let (line, text) = lines.get(&p).unwrap();
let column = p - text.range().start;
let (line, range) = lines.get(&p).unwrap();
let column = p - range.start;
Self::PositionRepr {
line: *line,
column,
@@ -101,24 +104,29 @@ impl<'input> ParseSlice<'input> for SourceCode {
}
}
pub fn no_path() -> Arc<[u32]> {
static ARC: OnceLock<Arc<[u32]>> = OnceLock::new();
ARC.get_or_init(Arc::default).clone()
}
peg::parser! {
grammar leaf_parser() for SourceCode {
// #### ATOMS ####
rule number() -> AstNode<Number>
= s:position!() number:$(['0'..='9']+) ty:ident()? e:position!()
{ AstNode { node: Number { number, ty }, range: s..e } }
{ AstNode { node: Number { number, ty }, range: s..e, path: no_path() } }
/ s:position!() "0x" number:$(['0'..='9'|'a'..='f'|'A'..'F']+) ty:ident()? e:position!()
{ AstNode { node: Number { number, ty }, range: s..e } }
{ AstNode { node: Number { number, ty }, range: s..e, path: no_path() } }
/ s:position!() "0b" number:$(['0'|'1']+) ty:ident()? e:position!()
{ AstNode { node: Number { number, ty }, range: s..e } }
{ AstNode { node: Number { number, ty }, range: s..e, path: no_path() } }
rule ident() -> Range<usize>
rule ident() -> AstNode<()>
= text:$(['_'|'a'..='z'|'A'..='Z']['_'|'a'..='z'|'A'..='Z'|'0'..='9']*)
{ text }
{ AstNode { range: text, node: (), path: no_path() } }
rule ident2() -> Range<usize>
rule ident2() -> AstNode<()>
= text:$(['#']? ['_'|'a'..='z'|'A'..='Z']['_'|'a'..='z'|'A'..='Z'|'0'..='9']*)
{ text }
{ AstNode { range: text, node: (), path: no_path() } }
rule string() -> Range<usize>
= text:$("\"" [^'\\'|'"']* "\"")
@@ -127,106 +135,106 @@ peg::parser! {
// ### EXPRESSIONS ####
rule bop0() -> AstNode<BinaryOperator>
= op:$("as") { AstNode { range: op, node: BinaryOperator::Cast } }
/ op:$("=") { AstNode { range: op, node: BinaryOperator::Assign } }
= op:$("as") { AstNode { range: op, node: BinaryOperator::Cast, path: no_path() } }
/ op:$("=") { AstNode { range: op, node: BinaryOperator::Assign, path: no_path() } }
rule bop1() -> AstNode<BinaryOperator>
= op:$("+") { AstNode { range: op, node: BinaryOperator::Add } }
/ op:$("-") { AstNode { range: op, node: BinaryOperator::Sub } }
= op:$("+") { AstNode { range: op, node: BinaryOperator::Add, path: no_path() } }
/ op:$("-") { AstNode { range: op, node: BinaryOperator::Sub, path: no_path() } }
rule bop2() -> AstNode<BinaryOperator>
= op:$("*") { AstNode { range: op, node: BinaryOperator::Mul } }
/ op:$("/") { AstNode { range: op, node: BinaryOperator::Div } }
/ op:$("%") { AstNode { range: op, node: BinaryOperator::Mod } }
= op:$("*") { AstNode { range: op, node: BinaryOperator::Mul, path: no_path() } }
/ op:$("/") { AstNode { range: op, node: BinaryOperator::Div, path: no_path() } }
/ op:$("%") { AstNode { range: op, node: BinaryOperator::Mod, path: no_path() } }
rule bop3() -> AstNode<BinaryOperator>
= op:$("==") { AstNode { range: op, node: BinaryOperator::Eq } }
/ op:$("!=") { AstNode { range: op, node: BinaryOperator::Ne } }
/ op:$("<") { AstNode { range: op, node: BinaryOperator::Lt } }
/ op:$(">") { AstNode { range: op, node: BinaryOperator::Gt } }
/ op:$("<=") { AstNode { range: op, node: BinaryOperator::Le } }
/ op:$(">=") { AstNode { range: op, node: BinaryOperator::Ge } }
= op:$("==") { AstNode { range: op, node: BinaryOperator::Eq, path: no_path() } }
/ op:$("!=") { AstNode { range: op, node: BinaryOperator::Ne, path: no_path() } }
/ op:$("<") { AstNode { range: op, node: BinaryOperator::Lt, path: no_path() } }
/ op:$(">") { AstNode { range: op, node: BinaryOperator::Gt, path: no_path() } }
/ op:$("<=") { AstNode { range: op, node: BinaryOperator::Le, path: no_path() } }
/ op:$(">=") { AstNode { range: op, node: BinaryOperator::Ge, path: no_path() } }
rule bop4() -> AstNode<BinaryOperator>
= op:$("..") { AstNode { range: op, node: BinaryOperator::Range } }
= op:$("..") { AstNode { range: op, node: BinaryOperator::Range, path: no_path() } }
rule expr() -> AstNode<Expr> = precedence! {
lhs:@ __ op:bop0() __ rhs:expr()
{ AstNode { range: lhs.range.start..rhs.range.end, node: Expr::Binary { lhs: lhs.into(), rhs: rhs.into(), operator: op } } }
{ AstNode { range: lhs.range.start..rhs.range.end, node: Expr::Binary { lhs: lhs.into(), rhs: rhs.into(), operator: op }, path: no_path() } }
// --
value:@ __ op:$(".") __ field:ident2()
{ AstNode { range: value.range.start..field.end, node: Expr::Access { value: value.into(), field, operator: op } } }
{ AstNode { range: value.range.start..field.range.end, node: Expr::Access { value: value.into(), field, operator: op }, path: no_path() } }
value:@ __ op:$(".^")
{ AstNode { range: value.range.start..op.end, node: Expr::Deref { value: value.into(), operator: op } } }
{ AstNode { range: value.range.start..op.end, node: Expr::Deref { value: value.into(), operator: op }, path: no_path() } }
lhs:@ "(" __ args:(expr() ** list_separator()) __ e:$")"
{ AstNode { range: lhs.range.start..e.end, node: Expr::Call { func: lhs.into(), args } } }
{ AstNode { range: lhs.range.start..e.end, node: Expr::Call { func: lhs.into(), args }, path: no_path() } }
value:@ "[" __ index:(expr() **<1,> ("," __)) __ e:$"]"
{ AstNode { range: value.range.start..e.end, node: Expr::Index { value: value.into(), index } } }
{ AstNode { range: value.range.start..e.end, node: Expr::Index { value: value.into(), index }, path: no_path() } }
ty:@ __ "#{" __ values:name_value_pairs() __ "}" e:position!()
{ AstNode { range: ty.range.start..e, node: Expr::StructCtor { ty: Some(ty.into()), values } } }
{ AstNode { range: ty.range.start..e, node: Expr::StructCtor { ty: Some(ty.into()), values }, path: no_path() } }
s:$"#{" __ values:name_value_pairs() __ "}" e:position!()
{ AstNode { range: s.start..e, node: Expr::StructCtor { ty: None, values } } }
{ AstNode { range: s.start..e, node: Expr::StructCtor { ty: None, values }, path: no_path() } }
--
lhs:@ __ op:bop1() __ rhs:expr()
{ AstNode { range: lhs.range.start..rhs.range.end, node: Expr::Binary { lhs: lhs.into(), rhs: rhs.into(), operator: op } } }
{ AstNode { range: lhs.range.start..rhs.range.end, node: Expr::Binary { lhs: lhs.into(), rhs: rhs.into(), operator: op }, path: no_path() } }
--
lhs:@ __ op:bop2() __ rhs:expr()
{ AstNode { range: lhs.range.start..rhs.range.end, node: Expr::Binary { lhs: lhs.into(), rhs: rhs.into(), operator: op } } }
{ AstNode { range: lhs.range.start..rhs.range.end, node: Expr::Binary { lhs: lhs.into(), rhs: rhs.into(), operator: op }, path: no_path() } }
--
lhs:@ __ op:bop3() __ rhs:expr()
{ AstNode { range: lhs.range.start..rhs.range.end, node: Expr::Binary { lhs: lhs.into(), rhs: rhs.into(), operator: op } } }
{ AstNode { range: lhs.range.start..rhs.range.end, node: Expr::Binary { lhs: lhs.into(), rhs: rhs.into(), operator: op }, path: no_path() } }
--
lhs:@ __ op:bop4() __ rhs:expr()
{ AstNode { range: lhs.range.start..rhs.range.end, node: Expr::Binary { lhs: lhs.into(), rhs: rhs.into(), operator: op } } }
{ AstNode { range: lhs.range.start..rhs.range.end, node: Expr::Binary { lhs: lhs.into(), rhs: rhs.into(), operator: op }, path: no_path() } }
--
block:block() { AstNode { range: block.range.clone(), node: Expr::Block(block.into()) } }
block:block() { AstNode { range: block.range.clone(), node: Expr::Block(block.into()), path: no_path() } }
i:if_statement() { AstNode { range: i.range, node: Expr::If(i.node.into()) }}
l:while_loop() { AstNode { range: l.range, node: Expr::While(l.node.into()) }}
i:if_statement() { AstNode { range: i.range.clone(), node: Expr::If(i.into()), path: no_path() }}
l:while_loop() { AstNode { range: l.range.clone(), node: Expr::While(l.into()), path: no_path() }}
func:func() { AstNode { range: func.range.clone(), node: Expr::Func(func.into()) } }
func:func() { AstNode { range: func.range.clone(), node: Expr::Func(func.into()), path: no_path() } }
var_decl:var_decl()
{ AstNode { range: var_decl.range, node: Expr::VarDecl(var_decl.node.into()) } }
{ AstNode { range: var_decl.range.clone(), node: Expr::VarDecl(var_decl.into()), path: no_path() } }
const_decl:const_decl()
{ AstNode { range: const_decl.range, node: Expr::ConstDecl(const_decl.node.into()) } }
{ AstNode { range: const_decl.range.clone(), node: Expr::ConstDecl(const_decl.into()), path: no_path() } }
s:$"(" __ elements:(expr() **<2,> ("," __)) __ e:$")"
{ AstNode { range: s.start..e.end, node: Expr::Tuple(elements) } }
{ AstNode { range: s.start..e.end, node: Expr::Tuple(elements), path: no_path() } }
s:$"[" __ elements:(expr() **<2,> ("," __)) __ e:$"]"
{ AstNode { range: s.start..e.end, node: Expr::List(elements) } }
{ AstNode { range: s.start..e.end, node: Expr::List(elements), path: no_path() } }
s:$"(" __ v:expr() __ e:$")"
{ AstNode { range: s.start..e.end, node: v.node } }
{ AstNode { range: s.start..e.end, node: v.node, path: no_path() } }
t:$"*" __ m:$"mut"? __ v:expr()
{ AstNode { range: t.start..v.range.end, node: Expr::Ptr { ptr_tok: t, mutable: m, base: v.into() } } }
{ AstNode { range: t.start..v.range.end, node: Expr::Ptr { ptr_tok: t, mutable: m, base: v.into() }, path: no_path() } }
v:struct_t() { v }
v:string() { AstNode { range: v.clone(), node: Expr::String(v) } }
v:number() { AstNode { range: v.range, node: Expr::Number(v.node) } }
v:ident() { AstNode { range: v.clone(), node: Expr::Ident(v) } }
v:string() { AstNode { range: v.clone(), node: Expr::String(v), path: no_path() } }
v:number() { AstNode { range: v.range, node: Expr::Number(v.node), path: no_path() } }
v:ident() { AstNode { range: v.range.clone(), node: Expr::Ident, path: no_path() } }
}
rule block() -> AstNode<Block>
= s:$"{" __ exprs:(i:expr() statement_separator() {i})* __ e:$"}"
{ AstNode { range: s.start..e.end, node: Block(exprs) } }
{ AstNode { range: s.start..e.end, node: Block(exprs), path: no_path() } }
rule func() -> AstNode<Function>
= s:position!() t:$"fn" __ "(" __ args:parameters() __ ")" __ ret:("->" __ e:expr() {e})? __ block:block()? e:position!()
{ AstNode { range: s..e, node: Function { args, ret, block: block.map(Into::into), fn_tok: t, } } }
{ AstNode { range: s..e, node: Function { args, ret, block: block.map(Into::into), fn_tok: t, }, path: no_path() } }
rule parameter() -> AstNode<Parameter>
= name:ident() __ ":" __ value:expr()
{ AstNode { range: name.start..value.range.end, node: Parameter { name, value } } }
{ AstNode { range: name.range.start..value.range.end, node: Parameter { name, value }, path: no_path() } }
rule parameters() -> Vec<AstNode<Parameter>>
= v:(parameter() **<1,> list_separator()) list_separator()? { v }
@@ -234,7 +242,7 @@ peg::parser! {
rule name_value_pair() -> AstNode<NameValuePair>
= name:ident() __ "=" __ value:expr()
{ AstNode { range: name.start..value.range.end, node: NameValuePair { name, value } } }
{ AstNode { range: name.range.start..value.range.end, node: NameValuePair { name, value }, path: no_path() } }
rule name_value_pairs() -> Vec<AstNode<NameValuePair>>
= v:(name_value_pair() **<1,> list_separator()) list_separator()? { v }
@@ -242,11 +250,11 @@ peg::parser! {
rule struct_t() -> AstNode<Expr>
= t:$"struct" __ "{" __ fields:fields() __ e:$"}"
{ AstNode { range: t.start..e.end, node: Expr::Struct { fields, struct_tok: t } } }
{ AstNode { range: t.start..e.end, node: Expr::Struct { fields, struct_tok: t }, path: no_path() } }
rule field() -> AstNode<Field>
= s:position!() public:$"pub"? __ mutable:$"mut"? __ name:ident() __ ":" __ ty:expr() e:position!()
{ AstNode { node: Field { name, ty, public, mutable }, range: s..e } }
{ AstNode { node: Field { name, ty, public, mutable }, range: s..e, path: no_path() } }
rule fields() -> Vec<AstNode<Field>>
= v:(field() **<1,> list_separator()) list_separator()? { v }
@@ -254,31 +262,31 @@ peg::parser! {
rule import() -> AstNode<Import>
= t:$"import" _ expr:expr()
{ AstNode { range: t.start..expr.range.end, node: Import { import_tok: t, expr } } }
{ AstNode { range: t.start..expr.range.end, node: Import { import_tok: t, expr }, path: no_path() } }
rule name_pattern() -> AstNode<NamePattern>
= s:$"(" __ tuple:(ident() ** ("," __)) __ e:$")"
{ AstNode { range: s.start..e.end, node: NamePattern::Tuple(tuple) } }
{ AstNode { range: s.start..e.end, node: NamePattern::Tuple(tuple), path: no_path() } }
/ s:$"[" __ slice:(ident() ** ("," __)) __ e:$"]"
{ AstNode { range: s.start..e.end, node: NamePattern::List(slice) } }
/ ident:ident()
{ AstNode { range: ident.clone(), node: NamePattern::Single(ident) } }
{ AstNode { range: s.start..e.end, node: NamePattern::List(slice), path: no_path() } }
/ i:ident()
{ AstNode { range: i.range.clone(), node: NamePattern::Single(i), path: no_path() } }
rule const_decl() -> AstNode<ConstDecl> =
names:name_pattern() _? ":" r#type:(_ t:expr() _ {t})? ":" _ value:expr()
{ AstNode { range: names.range.start..value.range.end, node: ConstDecl { names, r#type, value } } }
{ AstNode { range: names.range.start..value.range.end, node: ConstDecl { names, r#type, value }, path: no_path() } }
rule var_decl() -> AstNode<VarDecl> =
names:name_pattern() _? ":" r#type:(_ t:expr() _ {t})? "=" _ value:expr()
{ AstNode { range: names.range.start..value.range.end, node: VarDecl { names, r#type, value } } }
{ AstNode { range: names.range.start..value.range.end, node: VarDecl { names, r#type, value }, path: no_path() } }
rule while_loop() -> AstNode<While>
= t:$"while" _ cond:expr() _ block:block()
{ AstNode { range: t.start..block.range.end, node: While { cond, block, while_tok: t } } }
{ AstNode { range: t.start..block.range.end, node: While { cond, block, while_tok: t }, path: no_path() } }
rule if_statement() -> AstNode<If>
= t:$"if" _ cond:expr() __ block:block() el:(__ e:else_statement() {e})? e:position!()
{ AstNode { range: t.start..e, node: If { cond, block, else_: el.map(Box::new), if_tok: t } } }
{ AstNode { range: t.start..e, node: If { cond, block, else_: el.map(Box::new), if_tok: t }, path: no_path() } }
rule else_statement() -> Else
= t:$"else" _ i:if_statement() { Else::If { else_tok: t, expr: i } }
+308
View File
@@ -0,0 +1,308 @@
use crate::ast::*;
use std::sync::Arc;
pub(crate) trait ComputePaths {
fn compute_paths(&mut self, path: &mut Vec<u32>);
}
impl ComputePaths for AstRoot {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
for decl in &mut self.decls {
path.push(id.next().unwrap());
decl.compute_paths(path);
path.pop();
}
}
}
impl ComputePaths for AstNode<()> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
self.path = Arc::from_iter(path.iter().cloned());
}
}
impl ComputePaths for AstNode<BinaryOperator> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
self.path = Arc::from_iter(path.iter().cloned());
}
}
impl ComputePaths for AstNode<ConstDecl> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
self.path = Arc::from_iter(path.iter().cloned());
path.push(id.next().unwrap());
self.node.names.compute_paths(path);
path.pop();
if let Some(ty) = &mut self.node.r#type {
path.push(id.next().unwrap());
ty.compute_paths(path);
path.pop();
}
path.push(id.next().unwrap());
self.node.value.compute_paths(path);
path.pop();
}
}
impl ComputePaths for AstNode<VarDecl> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
self.path = Arc::from_iter(path.iter().cloned());
path.push(id.next().unwrap());
self.node.names.compute_paths(path);
path.pop();
if let Some(ty) = &mut self.node.r#type {
path.push(id.next().unwrap());
ty.compute_paths(path);
path.pop();
}
path.push(id.next().unwrap());
self.node.value.compute_paths(path);
path.pop();
}
}
impl ComputePaths for AstNode<NamePattern> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
self.path = Arc::from_iter(path.iter().cloned());
for name in self.node.as_mut_slice() {
path.push(id.next().unwrap());
name.compute_paths(path);
path.pop();
}
}
}
impl ComputePaths for Number {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
if let Some(ty) = &mut self.ty {
path.push(0);
ty.compute_paths(path);
path.pop();
}
}
}
impl ComputePaths for AstNode<Expr> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
self.path = Arc::from_iter(path.iter().cloned());
match &mut self.node {
Expr::Ident => {}
Expr::Number(n) => {
n.compute_paths(path);
}
Expr::VarDecl(decl) => {
decl.compute_paths(path);
}
Expr::ConstDecl(decl) => {
decl.compute_paths(path);
}
Expr::Func(func) => {
let func = Arc::get_mut(func).unwrap();
func.compute_paths(path);
}
Expr::Ptr { base, .. } => {
path.push(id.next().unwrap());
base.compute_paths(path);
path.pop();
}
Expr::Struct { fields, .. } => {
for field in fields {
path.push(id.next().unwrap());
field.compute_paths(path);
path.pop();
}
}
Expr::StructCtor { ty, values } => {
if let Some(ty) = ty {
path.push(id.next().unwrap());
ty.compute_paths(path);
path.pop();
}
for value in values {
path.push(id.next().unwrap());
value.compute_paths(path);
path.pop();
}
}
Expr::Binary { lhs, operator, rhs } => {
path.push(id.next().unwrap());
lhs.compute_paths(path);
path.pop();
path.push(id.next().unwrap());
operator.compute_paths(path);
path.pop();
path.push(id.next().unwrap());
rhs.compute_paths(path);
path.pop();
}
Expr::Access { value, field, .. } => {
path.push(id.next().unwrap());
value.compute_paths(path);
path.pop();
path.push(id.next().unwrap());
field.compute_paths(path);
path.pop();
}
Expr::Deref { value, .. } => {
path.push(id.next().unwrap());
value.compute_paths(path);
path.pop();
}
Expr::Call { func, args } => {
path.push(id.next().unwrap());
func.compute_paths(path);
path.pop();
for arg in args {
path.push(id.next().unwrap());
arg.compute_paths(path);
path.pop();
}
}
Expr::If(expr) => {
expr.compute_paths(path);
}
Expr::While(expr) => {
expr.compute_paths(path);
}
_ => todo!("{self:#?}"),
}
}
}
impl ComputePaths for AstNode<While> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
path.push(id.next().unwrap());
self.node.cond.compute_paths(path);
path.pop();
path.push(id.next().unwrap());
self.node.block.compute_paths(path);
path.pop();
}
}
impl ComputePaths for AstNode<If> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
path.push(id.next().unwrap());
self.node.cond.compute_paths(path);
path.pop();
path.push(id.next().unwrap());
self.node.block.compute_paths(path);
path.pop();
if let Some(else_) = &mut self.node.else_ {
path.push(id.next().unwrap());
else_.compute_paths(path);
path.pop();
}
}
}
impl ComputePaths for Else {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
path.push(0);
match self {
Else::If { expr, .. } => expr.compute_paths(path),
Else::Block { expr, .. } => expr.compute_paths(path),
}
path.pop();
}
}
impl ComputePaths for AstNode<NameValuePair> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
self.path = Arc::from_iter(path.iter().cloned());
path.push(id.next().unwrap());
self.node.name.compute_paths(path);
path.pop();
path.push(id.next().unwrap());
self.node.value.compute_paths(path);
path.pop();
}
}
impl ComputePaths for AstNode<Function> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
self.path = Arc::from_iter(path.iter().cloned());
for arg in &mut self.node.args {
path.push(id.next().unwrap());
arg.compute_paths(path);
path.pop();
}
if let Some(ret) = &mut self.node.ret {
path.push(id.next().unwrap());
ret.compute_paths(path);
path.pop();
}
if let Some(block) = &mut self.node.block {
let block = Arc::get_mut(block).unwrap();
path.push(id.next().unwrap());
block.compute_paths(path);
path.pop();
}
}
}
impl ComputePaths for AstNode<Block> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
self.path = Arc::from_iter(path.iter().cloned());
for expr in self.node.0.iter_mut() {
path.push(id.next().unwrap());
expr.compute_paths(path);
path.pop();
}
}
}
impl ComputePaths for AstNode<Parameter> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
self.path = Arc::from_iter(path.iter().cloned());
path.push(id.next().unwrap());
self.node.name.compute_paths(path);
path.pop();
path.push(id.next().unwrap());
self.node.value.compute_paths(path);
path.pop();
}
}
impl ComputePaths for AstNode<Field> {
fn compute_paths(&mut self, path: &mut Vec<u32>) {
let mut id = 0..;
self.path = Arc::from_iter(path.iter().cloned());
path.push(id.next().unwrap());
self.node.name.compute_paths(path);
path.pop();
path.push(id.next().unwrap());
self.node.ty.compute_paths(path);
path.pop();
}
}