Skip to content

Commit

Permalink
Replace DUMMY_SPAN with Span::Panic and Span::Rust
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex-Fischman committed Dec 23, 2024
1 parent cb44ce9 commit 9e26358
Show file tree
Hide file tree
Showing 10 changed files with 135 additions and 125 deletions.
18 changes: 0 additions & 18 deletions src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,24 +130,6 @@ 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(),
)
}

pub fn lit_no_span(lit: impl Into<Literal>) -> Self {
Self::Lit(DUMMY_SPAN.clone(), lit.into())
}

pub fn var_no_span(v: impl Into<Symbol>) -> Self {
Self::Var(DUMMY_SPAN.clone(), v.into())
}
}

impl<Head: Clone + Display, Leaf: Hash + Clone + Display + Eq> GenericExpr<Head, Leaf> {
pub fn span(&self) -> Span {
match self {
Expand Down
115 changes: 78 additions & 37 deletions src/ast/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,48 @@ 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 {
file: Arc<SrcFile>,
i: usize,
j: usize,
},
/// A span from a `.rs` file. Constructed by the `span!` macro.
Rust {
file: &'static str,
line: u32,
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 {
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!(),
Span::Egglog { file, i, j } => &file.contents[*i..*j],
}
}
}

#[derive(Debug, PartialEq, Eq, Hash)]
struct SrcFile {
pub struct SrcFile {
name: Option<String>,
contents: String,
}
Expand All @@ -70,7 +98,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 +126,34 @@ 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 { 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));
let quote = self.string();
match (&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 +873,12 @@ impl Context {
self.index == self.source.contents.len()
}

fn next(&mut self) -> Result<(Token, Span), ParseError> {
fn next(&mut self) -> Result<(Token, (Arc<SrcFile>, usize, usize)), ParseError> {
self.advance_past_whitespace();
let mut span = Span(self.source.clone(), self.index, self.index);
let mut span = (self.source.clone(), self.index, 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 @@ -856,7 +892,7 @@ impl Context {
loop {
span.2 = 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 +902,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 Down Expand Up @@ -898,6 +934,10 @@ impl Context {
}
}

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

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

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

loop {
let (token, span) = ctx.next()?;
Expand All @@ -918,14 +958,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)
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 +1021,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 940: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
2 changes: 1 addition & 1 deletion src/extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl EGraph {
/// .unwrap();
/// let mut termdag = TermDag::default();
/// let (sort, value) = egraph
/// .eval_expr(&egglog::ast::Expr::var_no_span("expr"))
/// .eval_expr(&egglog::ast::Expr::Var(egglog::span!(), "expr".into()))
/// .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
8 changes: 2 additions & 6 deletions src/serialize.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
use crate::{extract::Extractor, util::HashMap, *};
use ordered_float::NotNan;
use std::collections::VecDeque;

use crate::{
extract::Extractor, util::HashMap, ArcSort, EGraph, Function, Symbol, TermDag, TupleOutput,
Value,
};

pub struct SerializeConfig {
// Maximumum number of functions to include in the serialized graph, any after this will be discarded
pub max_functions: Option<usize>,
Expand Down Expand Up @@ -321,7 +317,7 @@ impl EGraph {
.extract_term(self, *value, &extractor, &mut termdag)
.expect("Extraction should be successful since extractor has been fully initialized");

termdag.term_to_expr(&term).to_string()
termdag.term_to_expr(&term, Span::Panic).to_string()
};
egraph.nodes.insert(
node_id.clone(),
Expand Down
4 changes: 2 additions & 2 deletions src/sort/fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,9 @@ fn call_fn(egraph: &mut EGraph, name: &Symbol, types: Vec<ArcSort>, args: Vec<Va
let binding = IndexSet::from_iter(arg_vars.clone());
let resolved_args = arg_vars
.into_iter()
.map(|v| GenericExpr::Var(DUMMY_SPAN.clone(), v))
.map(|v| GenericExpr::Var(span!(), v))
.collect();
let expr = GenericExpr::Call(DUMMY_SPAN.clone(), resolved_call, resolved_args);
let expr = GenericExpr::Call(span!(), resolved_call, resolved_args);
// Similar to how the merge function is created in `Function::new`
let (actions, mapped_expr) = expr
.to_core_actions(
Expand Down
Loading

0 comments on commit 9e26358

Please sign in to comment.