Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace DUMMY_SPAN with Span::Panic and Span::Rust #498

Merged
merged 4 commits into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 20 additions & 14 deletions src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,24 +130,30 @@ impl ResolvedExpr {
}
}

impl Expr {
pub fn call_no_span(op: impl Into<Symbol>, children: impl IntoIterator<Item = Self>) -> Self {
Self::Call(
DUMMY_SPAN.clone(),
op.into(),
children.into_iter().collect(),
)
}
#[macro_export]
macro_rules! call {
($func:expr, $args:expr) => {
$crate::ast::GenericExpr::Call($crate::span!(), $func.into(), $args.into_iter().collect())
};
}

pub fn lit_no_span(lit: impl Into<Literal>) -> Self {
Self::Lit(DUMMY_SPAN.clone(), lit.into())
}
#[macro_export]
macro_rules! lit {
($lit:expr) => {
$crate::ast::GenericExpr::Lit($crate::span!(), $lit.into())
};
}

pub fn var_no_span(v: impl Into<Symbol>) -> Self {
Self::Var(DUMMY_SPAN.clone(), v.into())
}
#[macro_export]
macro_rules! var {
($var:expr) => {
$crate::ast::GenericExpr::Var($crate::span!(), $var.into())
};
}

// Rust macro annoyance; see stackoverflow.com/questions/26731243/how-do-i-use-a-macro-across-module-files
pub use {call, lit, var};

impl<Head: Clone + Display, Leaf: Hash + Clone + Display + Eq> GenericExpr<Head, Leaf> {
pub fn span(&self) -> Span {
match self {
Expand Down
133 changes: 93 additions & 40 deletions src/ast/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,54 @@ pub fn parse_expr(

/// A [`Span`] contains the file name and a pair of offsets representing the start and the end.
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Span(Arc<SrcFile>, usize, usize);
pub enum Span {
/// Panics if a span is needed. Prefer `Span::Rust` (see `span!`)
/// unless this behaviour is explicitly desired.
Panic,
/// A span from a `.egg` file.
/// Constructed by `parse_program` and `parse_expr`.
Egglog(Arc<EgglogSpan>),
/// A span from a `.rs` file. Constructed by the `span!` macro.
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,
}

lazy_static::lazy_static! {
pub static ref DUMMY_SPAN: Span = Span(Arc::new(SrcFile {name: None, contents: String::new()}), 0, 0);
#[macro_export]
macro_rules! span {
() => {
$crate::ast::Span::Rust(std::sync::Arc::new($crate::ast::RustSpan {
file: file!(),
line: line!(),
column: column!(),
}))
};
}

impl Span {
pub fn string(&self) -> &str {
&self.0.contents[self.1..self.2]
match self {
Span::Panic => panic!("Span::Panic in Span::String"),
Span::Rust(_) => todo!(),
Alex-Fischman marked this conversation as resolved.
Show resolved Hide resolved
Span::Egglog(span) => &span.file.contents[span.i..span.j],
}
}
}

#[derive(Debug, PartialEq, Eq, Hash)]
struct SrcFile {
pub struct SrcFile {
name: Option<String>,
contents: String,
}
Expand All @@ -70,7 +104,7 @@ struct Location {
}

impl SrcFile {
pub fn get_location(&self, offset: usize) -> Location {
fn get_location(&self, offset: usize) -> Location {
let mut line = 1;
let mut col = 1;
for (i, c) in self.contents.char_indices() {
Expand Down Expand Up @@ -98,26 +132,36 @@ impl Debug for Span {

impl Display for Span {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let start = self.0.get_location(self.1);
let end = self.0.get_location((self.2.saturating_sub(1)).max(self.1));
let quote = self.string();
match (&self.0.name, start.line == end.line) {
(Some(filename), true) => write!(
f,
"In {}:{}-{} of {filename}: {quote}",
start.line, start.col, end.col
),
(Some(filename), false) => write!(
f,
"In {}:{}-{}:{} of {filename}: {quote}",
start.line, start.col, end.line, end.col
),
(None, false) => write!(
f,
"In {}:{}-{}:{}: {quote}",
start.line, start.col, end.line, end.col
),
(None, true) => write!(f, "In {}:{}-{}: {quote}", start.line, start.col, end.col),
match self {
Span::Panic => panic!("Span::Panic in impl Display"),
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 (&span.file.name, start.line == end.line) {
(Some(filename), true) => write!(
f,
"In {}:{}-{} of {filename}: {quote}",
start.line, start.col, end.col
),
(Some(filename), false) => write!(
f,
"In {}:{}-{}:{} of {filename}: {quote}",
start.line, start.col, end.line, end.col
),
(None, false) => write!(
f,
"In {}:{}-{}:{}: {quote}",
start.line, start.col, end.line, end.col
),
(None, true) => {
write!(f, "In {}:{}-{}: {quote}", start.line, start.col, end.col)
}
}
}
}
}
}
Expand Down Expand Up @@ -837,12 +881,16 @@ impl Context {
self.index == self.source.contents.len()
}

fn next(&mut self) -> Result<(Token, Span), ParseError> {
fn next(&mut self) -> Result<(Token, EgglogSpan), ParseError> {
self.advance_past_whitespace();
let mut span = 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!(span, "unexpected end of file");
return error!(s(span), "unexpected end of file");
};
self.advance_char();

Expand All @@ -854,9 +902,9 @@ impl Context {
let mut string = String::new();

loop {
span.2 = self.index;
span.j = self.index;
match self.current_char() {
None => return error!(span, "string is missing end quote"),
None => return error!(s(span), "string is missing end quote"),
Some('"') if !in_escape => break,
Some('\\') if !in_escape => in_escape = true,
Some(c) => {
Expand All @@ -866,7 +914,7 @@ impl Context {
(true, 't') => '\t',
(true, '\\') => '\\',
(true, c) => {
return error!(span, "unrecognized escape character {c}")
return error!(s(span), "unrecognized escape character {c}")
}
});
in_escape = false;
Expand All @@ -891,13 +939,17 @@ impl Context {
}
};

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

Ok((token, span))
}
}

fn s(span: EgglogSpan) -> Span {
Span::Egglog(Arc::new(span))
}

enum Token {
Open,
Close,
Expand All @@ -906,7 +958,7 @@ enum Token {
}

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

loop {
let (token, span) = ctx.next()?;
Expand All @@ -918,14 +970,15 @@ fn sexp(ctx: &mut Context) -> Result<Sexp, ParseError> {
}
Token::Close => {
if stack.is_empty() {
return error!(span, "unexpected `)`");
return error!(s(span), "unexpected `)`");
}
let (mut list_span, list) = stack.pop().unwrap();
list_span.2 = span.2;
Sexp::List(list, list_span)
list_span.j = span.j;
Sexp::List(list, s(list_span))
}
Token::String(s) => Sexp::Literal(Literal::String(s), span),
Token::String(sym) => Sexp::Literal(Literal::String(sym), s(span)),
Token::Other => {
let span = s(span);
let s = span.string();

if s == "true" {
Expand Down Expand Up @@ -980,8 +1033,8 @@ mod tests {
}

#[test]
fn dummy_span_display() {
assert_eq!(format!("{}", *super::DUMMY_SPAN), "In 1:1-1: ");
fn rust_span_display() {
assert_eq!(format!("{}", span!()), "At 1037:34 of src/ast/parse.rs");
}

#[test]
Expand Down
18 changes: 4 additions & 14 deletions src/constraint.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
use crate::{
ast::{
GenericAction, GenericActions, GenericExpr, GenericFact, MappedAction, ResolvedAction,
ResolvedActions, ResolvedExpr, ResolvedFact, ResolvedVar,
},
core::{
Atom, AtomTerm, CoreAction, CoreRule, GenericCoreActions, Query, ResolvedCall, SymbolOrEq,
},
sort::I64Sort,
typechecking::TypeError,
util::{FreshGen, HashSet, SymbolGen},
ArcSort, CorrespondingVar, Span, Symbol, TypeInfo, DUMMY_SPAN,
core::{Atom, CoreAction, CoreRule, GenericCoreActions, Query, SymbolOrEq},
*,
};
use core::{hash::Hash, panic};
// Use immutable hashmap for performance
// cloning assignments is common and O(1) with immutable hashmap
use im_rc::HashMap;
Expand Down Expand Up @@ -243,7 +233,7 @@ impl Assignment<AtomTerm, ArcSort> {
let ty = global_ty
.clone()
// Span is ignored when looking up atom_terms
.or_else(|| self.get(&AtomTerm::Var(DUMMY_SPAN.clone(), *var)).cloned())
.or_else(|| self.get(&AtomTerm::Var(Span::Panic, *var)).cloned())
.expect("All variables should be assigned before annotation");
ResolvedExpr::Var(
span.clone(),
Expand Down Expand Up @@ -271,7 +261,7 @@ impl Assignment<AtomTerm, ArcSort> {
.iter()
.map(|arg| arg.output_type())
.chain(once(
self.get(&AtomTerm::Var(DUMMY_SPAN.clone(), *corresponding_var))
self.get(&AtomTerm::Var(span.clone(), *corresponding_var))
.unwrap()
.clone(),
))
Expand Down
4 changes: 1 addition & 3 deletions src/extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ impl EGraph {
/// )
/// .unwrap();
/// let mut termdag = TermDag::default();
/// let (sort, value) = egraph
/// .eval_expr(&egglog::ast::Expr::var_no_span("expr"))
/// .unwrap();
/// let (sort, value) = egraph.eval_expr(&egglog::var!("expr")).unwrap();
/// let (_, extracted) = egraph.extract(value, &mut termdag, &sort);
/// assert_eq!(termdag.to_string(&extracted), "(Add 1 1)");
/// ```
Expand Down
18 changes: 9 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,12 +296,12 @@ impl Primitive {
fn accept(&self, tys: &[Arc<dyn Sort>], typeinfo: &TypeInfo) -> bool {
let mut constraints = vec![];
let lits: Vec<_> = (0..tys.len())
.map(|i| AtomTerm::Literal(DUMMY_SPAN.clone(), Literal::Int(i as i64)))
.map(|i| AtomTerm::Literal(Span::Panic, Literal::Int(i as i64)))
.collect();
for (lit, ty) in lits.iter().zip(tys.iter()) {
constraints.push(Constraint::Assign(lit.clone(), ty.clone()))
}
constraints.extend(self.get_type_constraints(&DUMMY_SPAN).get(&lits, typeinfo));
constraints.extend(self.get_type_constraints(&Span::Panic).get(&lits, typeinfo));
let problem = Problem {
constraints,
range: HashSet::default(),
Expand Down Expand Up @@ -535,7 +535,7 @@ impl EGraph {
self.msgs = messages;
Ok(())
}
None => Err(Error::Pop(DUMMY_SPAN.clone())),
None => Err(Error::Pop(span!())),
}
}

Expand Down Expand Up @@ -710,7 +710,7 @@ impl EGraph {
let f = self
.functions
.get(&sym)
.ok_or(TypeError::UnboundFunction(sym, DUMMY_SPAN.clone()))?;
.ok_or(TypeError::UnboundFunction(sym, span!()))?;
let schema = f.schema.clone();
let nodes = f
.nodes
Expand Down Expand Up @@ -796,7 +796,7 @@ impl EGraph {
let f = self
.functions
.get(&sym)
.ok_or(TypeError::UnboundFunction(sym, DUMMY_SPAN.clone()))?;
.ok_or(TypeError::UnboundFunction(sym, span!()))?;
log::info!("Function {} has size {}", sym, f.nodes.len());
self.print_msg(f.nodes.len().to_string());
Ok(())
Expand Down Expand Up @@ -1122,7 +1122,7 @@ impl EGraph {

pub fn eval_expr(&mut self, expr: &Expr) -> Result<(ArcSort, Value), Error> {
let fresh_name = self.parser.symbol_gen.fresh(&"egraph_evalexpr".into());
let command = Command::Action(Action::Let(DUMMY_SPAN.clone(), fresh_name, expr.clone()));
let command = Command::Action(Action::Let(expr.span(), fresh_name, expr.clone()));
self.run_program(vec![command])?;
// find the table with the same name as the fresh name
let func = self.functions.get(&fresh_name).unwrap();
Expand Down Expand Up @@ -1373,7 +1373,7 @@ impl EGraph {
let mut contents = String::new();
f.read_to_string(&mut contents).unwrap();

let span: Span = DUMMY_SPAN.clone();
let span: Span = span!();
let mut actions: Vec<Action> = vec![];
let mut str_buf: Vec<&str> = vec![];
for line in contents.lines() {
Expand Down Expand Up @@ -1508,8 +1508,8 @@ impl EGraph {
}

/// Add a user-defined sort
pub fn add_arcsort(&mut self, arcsort: ArcSort) -> Result<(), TypeError> {
self.type_info.add_arcsort(arcsort, DUMMY_SPAN.clone())
pub fn add_arcsort(&mut self, arcsort: ArcSort, span: Span) -> Result<(), TypeError> {
self.type_info.add_arcsort(arcsort, span)
}

/// Add a user-defined primitive
Expand Down
Loading
Loading