Skip to content

Commit

Permalink
improve list locations (#215)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrvidal authored Jun 11, 2024
1 parent 842dd02 commit 6a03f79
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 103 deletions.
31 changes: 17 additions & 14 deletions crates/steel-core/src/compiler/modules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2376,7 +2376,7 @@ impl<'a> ModuleBuilder<'a> {
match *for_syntax {
x if x == *FOR_SYNTAX => {
if l.args.len() != 2 {
stop!(ArityMismatch => "provide expects a single identifier in the (for-syntax <ident>)")
stop!(ArityMismatch => "provide expects a single identifier in the (for-syntax <ident>)"; opt l.location)
}

// Collect the for syntax expressions
Expand All @@ -2395,11 +2395,11 @@ impl<'a> ModuleBuilder<'a> {
}
}
} else {
stop!(TypeMismatch => "provide expects either an identifier or a (for-syntax <ident>)")
stop!(TypeMismatch => "provide expects either an identifier or a (for-syntax <ident>)"; opt l.location)
}
}
_ => {
stop!(TypeMismatch => "provide expects either a (for-syntax <ident>) or an ident")
stop!(TypeMismatch => "provide expects either a (for-syntax <ident>) or an ident"; opt expr.span())
}
}
}
Expand Down Expand Up @@ -2427,7 +2427,7 @@ impl<'a> ModuleBuilder<'a> {
if let Some(provide) = l.first_ident() {
if *provide == *PROVIDE {
if l.len() == 1 {
stop!(Generic => "provide expects at least one identifier to provide");
stop!(Generic => "provide expects at least one identifier to provide"; opt l.location);
}

// Swap out the value inside the list
Expand Down Expand Up @@ -2583,7 +2583,7 @@ impl<'a> ModuleBuilder<'a> {
match l.first_ident() {
Some(x) if *x == *ONLY_IN => {
if l.args.len() < 2 {
stop!(BadSyntax => "only-in expects a require-spec and optionally a list of ids to bind (maybe renamed)");
stop!(BadSyntax => "only-in expects a require-spec and optionally a list of ids to bind (maybe renamed)"; opt l.location);
}

self.parse_require_object_inner(home, r, &l.args[1], require_object)?;
Expand Down Expand Up @@ -2623,10 +2623,12 @@ impl<'a> ModuleBuilder<'a> {

Some(x) if *x == *PREFIX_IN => {
if l.args.len() != 3 {
stop!(BadSyntax => "prefix-in expects a prefix to prefix a given file or module"; r.location.span; r.location.source.clone());
stop!(BadSyntax => "prefix-in expects a prefix to prefix a given file or module"; opt l.location);
}

if let Some(prefix) = l.args[1].atom_identifier() {
let prefix = &l.args[1];

if let Some(prefix) = prefix.atom_identifier() {
match &mut require_object.prefix {
Some(existing_prefix) => {
// Append the new symbol to the existing prefix
Expand All @@ -2639,17 +2641,18 @@ impl<'a> ModuleBuilder<'a> {

self.parse_require_object_inner(home, r, &l.args[2], require_object)?;
} else {
stop!(TypeMismatch => "prefix-in expects an identifier to use for the prefix");
stop!(TypeMismatch => "prefix-in expects an identifier to use for the prefix"; opt prefix.span());
}
}

Some(x) if *x == *FOR_SYNTAX => {
// We're expecting something like (for-syntax "foo")
if l.args.len() != 2 {
stop!(BadSyntax => "for-syntax expects one string literal referring to a file or module"; r.location.span; r.location.source.clone());
stop!(BadSyntax => "for-syntax expects one string literal referring to a file or module"; opt l.location);
}

if let Some(path) = l.args[1].string_literal() {
let mod_name = &l.args[1];
if let Some(path) = mod_name.string_literal() {
if let Some(lib) = BUILT_INS.iter().find(|x| x.0 == path) {
// self.built_ins.push(PathBuf::from(lib.0));

Expand Down Expand Up @@ -2700,25 +2703,25 @@ impl<'a> ModuleBuilder<'a> {
}
}

stop!(Generic => format!("Module not found: {:?}", current); r.location.span)
stop!(Generic => format!("Module not found: {:?}", current); mod_name.span().unwrap())
}
}

require_object.for_syntax = true;
require_object.path = Some(PathOrBuiltIn::Path(current));
}
} else {
stop!(BadSyntax => "for-syntax expects a string literal referring to a file or module"; r.location.span; r.location.source.clone());
stop!(BadSyntax => "for-syntax expects a string literal referring to a file or module"; opt mod_name.span());
}
}
_ => {
stop!(BadSyntax => "require accepts either a string literal or a for-syntax expression"; r.location.span; r.location.source.clone())
stop!(BadSyntax => "require accepts either a string literal, a for-syntax expression or an only-in expression"; opt l.location)
}
}
}

_ => {
stop!(Generic => "require expected a string literal referring to a file/module"; r.location.span; r.location.source.clone())
stop!(Generic => "require object expected a string literal referring to a file/module"; opt atom.span())
}
}

Expand Down
6 changes: 6 additions & 0 deletions crates/steel-core/src/rerrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,12 @@ macro_rules! stop {
($type:ident => $thing:expr; $span:expr) => {
return Err($crate::rerrs::SteelErr::new($crate::rerrs::ErrorKind::$type, ($thing).to_string()).with_span($span))
};
($type:ident => $thing:expr; opt $span:expr) => {
match $span {
Some(span) => stop!($type => $thing; span),
None => stop!($type => $thing)
}
};
($type:ident => $thing:expr; $span:expr; $source:expr) => {
return Err($crate::rerrs::SteelErr::new($crate::rerrs::ErrorKind::$type, ($thing).to_string()).with_span($span))

Expand Down
6 changes: 3 additions & 3 deletions crates/steel-core/src/steel_vm/const_evaluation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ impl<'a> ConsumingVisitor for ConstantEvaluator<'a> {
if let ExprKind::LambdaFunction(f) = &func {
if !f.rest {
if !f.args.is_empty() {
stop!(ArityMismatch => format!("function expected {} arguments, found 0", f.args.len()))
stop!(ArityMismatch => format!("function expected {} arguments, found 0", f.args.len()); f.location.span)
}

// If the body is constant we can safely remove the application
Expand Down Expand Up @@ -894,8 +894,8 @@ impl<'a> ConsumingVisitor for ConstantEvaluator<'a> {
Ok(ExprKind::Set(s))
}

fn visit_require(&mut self, _s: crate::parser::ast::Require) -> Self::Output {
stop!(Generic => "unexpected require - require is only allowed at the top level");
fn visit_require(&mut self, s: crate::parser::ast::Require) -> Self::Output {
stop!(Generic => "unexpected require - require is only allowed at the top level"; s.location.span);
}

// TODO come back to this
Expand Down
8 changes: 6 additions & 2 deletions crates/steel-core/src/steel_vm/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1606,10 +1606,14 @@ impl Engine {

/// Emit the unexpanded AST
pub fn emit_ast_to_string(expr: &str) -> Result<String> {
let parsed = Self::emit_ast(expr)?;
Ok(parsed.into_iter().map(|x| x.to_pretty(60)).join("\n\n"))
}

pub fn emit_ast(expr: &str) -> Result<Vec<ExprKind>> {
let parsed: std::result::Result<Vec<ExprKind>, ParseError> =
Parser::new(expr, None).collect();
let parsed = parsed?;
Ok(parsed.into_iter().map(|x| x.to_pretty(60)).join("\n\n"))
Ok(parsed?)
}

/// Emit the fully expanded AST as a pretty printed string
Expand Down
28 changes: 25 additions & 3 deletions crates/steel-parser/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,24 @@ macro_rules! expr_list {
}

impl ExprKind {
pub fn span(&self) -> Option<Span> {
match self {
ExprKind::Atom(expr) => Some(expr.syn.span),
ExprKind::If(expr) => Some(expr.location.span),
ExprKind::Let(expr) => Some(expr.location.span),
ExprKind::Define(expr) => Some(expr.location.span),
ExprKind::LambdaFunction(expr) => Some(expr.location.span),
ExprKind::Begin(expr) => Some(expr.location.span),
ExprKind::Return(expr) => Some(expr.location.span),
ExprKind::Quote(expr) => Some(expr.location.span),
ExprKind::Macro(expr) => Some(expr.location.span),
ExprKind::SyntaxRules(expr) => Some(expr.location.span),
ExprKind::List(expr) => expr.location,
ExprKind::Set(expr) => Some(expr.location.span),
ExprKind::Require(expr) => Some(expr.location.span),
}
}

pub fn to_string_literal(&self) -> Option<&String> {
if let ExprKind::Atom(a) = self {
if let TokenType::StringLiteral(s) = &a.syn.ty {
Expand Down Expand Up @@ -972,9 +990,13 @@ impl List {
}
}

pub fn with_span(mut self, location: Span) -> Self {
self.location = Some(location);
self
pub fn with_spans(args: Vec<ExprKind>, open: Span, close: Span) -> Self {
List {
args,
improper: false,
location: Some(Span::merge(open, close)),
syntax_object_id: SyntaxObjectId::fresh().0,
}
}

pub fn make_improper(mut self) -> Self {
Expand Down
Loading

0 comments on commit 6a03f79

Please sign in to comment.