Skip to content

Commit

Permalink
Try wrapping span data in arcs
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex-Fischman committed Dec 18, 2024
1 parent 984c74e commit eaec7e1
Showing 1 changed file with 40 additions and 28 deletions.
68 changes: 40 additions & 28 deletions src/ast/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,36 +22,42 @@ pub enum Span {
Panic,
/// A span from a `.egg` file.
/// Constructed by `parse_program` and `parse_expr`.
Egglog {
file: Arc<SrcFile>,
i: usize,
j: usize,
},
Egglog(Arc<EgglogSpan>),
/// A span from a `.rs` file. Constructed by the `span!` macro.
Rust {
file: &'static str,
line: u32,
column: u32,
},
Rust(Arc<RustSpan>),
}

#[derive(Clone, PartialEq, Eq, Hash)]
pub struct EgglogSpan {
file: Arc<SrcFile>,
i: usize,
j: usize,
}

#[derive(Clone, PartialEq, Eq, Hash)]
pub struct RustSpan {
pub file: &'static str,
pub line: u32,
pub column: u32,
}

#[macro_export]
macro_rules! span {
() => {
$crate::ast::Span::Rust {
$crate::ast::Span::Rust(std::sync::Arc::new($crate::ast::RustSpan {
file: file!(),
line: line!(),
column: column!(),
}
}))
};
}

impl Span {
pub fn string(&self) -> &str {
match self {
Span::Panic => panic!("Span::Panic in Span::String"),
Span::Rust { .. } => todo!(),
Span::Egglog { file, i, j } => &file.contents[*i..*j],
Span::Rust(_) => todo!(),
Span::Egglog(span) => &span.file.contents[span.i..span.j],
}
}
}
Expand Down Expand Up @@ -98,12 +104,14 @@ impl Display for Span {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Span::Panic => panic!("Span::Panic in impl Display"),
Span::Rust { file, line, column } => write!(f, "At {line}:{column} of {file}"),
Span::Egglog { file, i, j } => {
let start = file.get_location(*i);
let end = file.get_location((j.saturating_sub(1)).max(*i));
Span::Rust(span) => write!(f, "At {}:{} of {}", span.line, span.column, span.file),
Span::Egglog(span) => {
let start = span.file.get_location(span.i);
let end = span
.file
.get_location((span.j.saturating_sub(1)).max(span.i));
let quote = self.string();
match (&file.name, start.line == end.line) {
match (&span.file.name, start.line == end.line) {
(Some(filename), true) => write!(
f,
"In {}:{}-{} of {filename}: {quote}",
Expand Down Expand Up @@ -790,9 +798,13 @@ impl Context {
self.index == self.source.contents.len()
}

fn next(&mut self) -> Result<(Token, (Arc<SrcFile>, usize, usize)), ParseError> {
fn next(&mut self) -> Result<(Token, EgglogSpan), ParseError> {
self.advance_past_whitespace();
let mut span = (self.source.clone(), self.index, self.index);
let mut span = EgglogSpan {
file: self.source.clone(),
i: self.index,
j: self.index,
};

let Some(c) = self.current_char() else {
return error!(s(span), "unexpected end of file");
Expand All @@ -807,7 +819,7 @@ impl Context {
let mut string = String::new();

loop {
span.2 = self.index;
span.j = self.index;
match self.current_char() {
None => return error!(s(span), "string is missing end quote"),
Some('"') if !in_escape => break,
Expand Down Expand Up @@ -844,15 +856,15 @@ impl Context {
}
};

span.2 = self.index;
span.j = self.index;
self.advance_past_whitespace();

Ok((token, span))
}
}

fn s((file, i, j): (Arc<SrcFile>, usize, usize)) -> Span {
Span::Egglog { file, i, j }
fn s(span: EgglogSpan) -> Span {
Span::Egglog(Arc::new(span))
}

enum Token {
Expand All @@ -863,7 +875,7 @@ enum Token {
}

fn sexp(ctx: &mut Context) -> Result<Sexp, ParseError> {
let mut stack: Vec<((Arc<SrcFile>, usize, usize), Vec<Sexp>)> = vec![];
let mut stack: Vec<(EgglogSpan, Vec<Sexp>)> = vec![];

loop {
let (token, span) = ctx.next()?;
Expand All @@ -878,7 +890,7 @@ fn sexp(ctx: &mut Context) -> Result<Sexp, ParseError> {
return error!(s(span), "unexpected `)`");
}
let (mut list_span, list) = stack.pop().unwrap();
list_span.2 = span.2;
list_span.j = span.j;
Sexp::List(list, s(list_span))
}
Token::String(sym) => Sexp::Literal(Literal::String(sym), s(span)),
Expand Down Expand Up @@ -937,6 +949,6 @@ mod tests {

#[test]
fn rust_span_display() {
assert_eq!(format!("{}", span!()), "At 940:34 of src/ast/parse.rs");
assert_eq!(format!("{}", span!()), "At 952:34 of src/ast/parse.rs");
}
}

0 comments on commit eaec7e1

Please sign in to comment.