diff --git a/ast/asdl_rs.py b/ast/asdl_rs.py index a4c894a..71c9032 100755 --- a/ast/asdl_rs.py +++ b/ast/asdl_rs.py @@ -645,7 +645,7 @@ def write_ast_def(mod, typeinfo, f): #![allow(clippy::derive_partial_eq_without_eq)] pub use crate::constant::*; - pub use crate::location::Location; + pub use crate::Location; type Ident = String; \n diff --git a/ast/src/ast_gen.rs b/ast/src/ast_gen.rs index fda39b8..17900fe 100644 --- a/ast/src/ast_gen.rs +++ b/ast/src/ast_gen.rs @@ -3,7 +3,7 @@ #![allow(clippy::derive_partial_eq_without_eq)] pub use crate::constant::*; -pub use crate::location::Location; +pub use crate::Location; type Ident = String; diff --git a/ast/src/lib.rs b/ast/src/lib.rs index b696998..d668bed 100644 --- a/ast/src/lib.rs +++ b/ast/src/lib.rs @@ -3,11 +3,10 @@ mod constant; #[cfg(feature = "fold")] mod fold_helpers; mod impls; -mod location; #[cfg(feature = "unparse")] mod unparse; pub use ast_gen::*; -pub use location::Location; +pub use rustpython_compiler_core::Location; pub type Suite = Vec>; diff --git a/ast/src/location.rs b/ast/src/location.rs deleted file mode 100644 index 9584320..0000000 --- a/ast/src/location.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! Datatypes to support source location information. - -use std::fmt; - -/// A location somewhere in the sourcecode. -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub struct Location(rustpython_compiler_core::Location); - -impl std::ops::Deref for Location { - type Target = rustpython_compiler_core::Location; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl std::ops::DerefMut for Location { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -impl fmt::Display for Location { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "line {} column {}", self.row(), self.column()) - } -} - -impl Location { - pub fn visualize<'a>( - &self, - line: &'a str, - desc: impl fmt::Display + 'a, - ) -> impl fmt::Display + 'a { - struct Visualize<'a, D: fmt::Display> { - loc: Location, - line: &'a str, - desc: D, - } - impl fmt::Display for Visualize<'_, D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "{}\n{}{arrow:>pad$}", - self.desc, - self.line, - pad = self.loc.column(), - arrow = "^", - ) - } - } - Visualize { - loc: *self, - line, - desc, - } - } -} - -impl Location { - pub fn new(row: usize, column: usize) -> Self { - Location(rustpython_compiler_core::Location::new(row, column)) - } -} diff --git a/codegen/src/compile.rs b/codegen/src/compile.rs index 0b59358..6cf33ac 100644 --- a/codegen/src/compile.rs +++ b/codegen/src/compile.rs @@ -15,7 +15,7 @@ use itertools::Itertools; use num_complex::Complex64; use num_traits::ToPrimitive; use rustpython_ast as ast; -use rustpython_compiler_core::{self as bytecode, CodeObject, ConstantData, Instruction}; +use rustpython_compiler_core::{self as bytecode, CodeObject, ConstantData, Instruction, Location}; use std::borrow::Cow; pub use rustpython_compiler_core::Mode; @@ -64,7 +64,7 @@ struct Compiler { code_stack: Vec, symbol_table_stack: Vec, source_path: String, - current_source_location: ast::Location, + current_source_location: Location, qualified_path: Vec, done_with_future_stmts: bool, future_annotations: bool, @@ -220,7 +220,7 @@ impl Compiler { code_stack: vec![module_code], symbol_table_stack: Vec::new(), source_path, - current_source_location: ast::Location::default(), + current_source_location: Location::default(), qualified_path: Vec::new(), done_with_future_stmts: false, future_annotations: false, @@ -237,7 +237,7 @@ impl Compiler { fn error(&self, error: CodegenErrorType) -> CodegenError { self.error_loc(error, self.current_source_location) } - fn error_loc(&self, error: CodegenErrorType, location: ast::Location) -> CodegenError { + fn error_loc(&self, error: CodegenErrorType, location: Location) -> CodegenError { CodegenError { error, location, @@ -2617,7 +2617,7 @@ impl Compiler { code.current_block = block; } - fn set_source_location(&mut self, location: ast::Location) { + fn set_source_location(&mut self, location: Location) { self.current_source_location = location; } @@ -2672,7 +2672,7 @@ fn try_get_constant_string(values: &[ast::Expr]) -> Option { } } -fn compile_location(location: &ast::Location) -> bytecode::Location { +fn compile_location(location: &Location) -> bytecode::Location { bytecode::Location::new(location.row(), location.column()) } diff --git a/codegen/src/error.rs b/codegen/src/error.rs index 60444a2..8c3ea3f 100644 --- a/codegen/src/error.rs +++ b/codegen/src/error.rs @@ -1,5 +1,4 @@ -use rustpython_ast::Location; - +use rustpython_compiler_core::Location; use std::{error::Error, fmt}; #[derive(Debug)] @@ -91,7 +90,7 @@ impl Error for CodegenErrorType {} impl fmt::Display for CodegenError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} at {}", self.error, self.location) + self.location.fmt_with(f, &self.error) } } diff --git a/codegen/src/symboltable.rs b/codegen/src/symboltable.rs index 6c2bcf5..1044f98 100644 --- a/codegen/src/symboltable.rs +++ b/codegen/src/symboltable.rs @@ -11,7 +11,8 @@ use crate::{ error::{CodegenError, CodegenErrorType}, IndexMap, }; -use rustpython_ast::{self as ast, Location}; +use rustpython_ast as ast; +use rustpython_compiler_core::Location; use std::{borrow::Cow, fmt}; /// Captures all symbols in the current scope, and has a list of subscopes in this scope. diff --git a/core/src/location.rs b/core/src/location.rs index 1763763..fedcdcf 100644 --- a/core/src/location.rs +++ b/core/src/location.rs @@ -7,6 +7,16 @@ pub struct Location { pub(super) column: u32, } +impl Location { + pub fn fmt_with( + &self, + f: &mut std::fmt::Formatter, + e: &impl std::fmt::Display, + ) -> std::fmt::Result { + write!(f, "{} at line {} column {}", e, self.row(), self.column()) + } +} + impl Location { /// Creates a new Location object at the given row and column. /// diff --git a/parser/src/error.rs b/parser/src/error.rs index d256e2a..76f02dc 100644 --- a/parser/src/error.rs +++ b/parser/src/error.rs @@ -1,12 +1,9 @@ //! Define internal parse error types //! The goal is to provide a matching and a safe error API, maksing errors from LALR + +use crate::{ast::Location, token::Tok}; use lalrpop_util::ParseError as LalrpopError; - -use crate::ast::Location; -use crate::token::Tok; - -use std::error::Error; -use std::fmt; +use std::{error::Error, fmt}; /// Represents an error during lexical scanning. #[derive(Debug, PartialEq)] @@ -186,7 +183,7 @@ impl ParseError { impl fmt::Display for ParseError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} at {}", self.error, self.location) + self.location.fmt_with(f, &self.error) } } diff --git a/parser/src/function.rs b/parser/src/function.rs index 68d890f..2a384dd 100644 --- a/parser/src/function.rs +++ b/parser/src/function.rs @@ -1,8 +1,7 @@ -use ahash::RandomState; -use std::collections::HashSet; - use crate::ast; use crate::error::{LexicalError, LexicalErrorType}; +use ahash::RandomState; +use std::collections::HashSet; pub struct ArgumentList { pub args: Vec, diff --git a/parser/src/parser.rs b/parser/src/parser.rs index 3199701..ff86ef4 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -5,13 +5,9 @@ //! parse a whole program, a single statement, or a single //! expression. -use std::iter; - -use crate::ast; -use crate::error::ParseError; -use crate::lexer; pub use crate::mode::Mode; -use crate::python; +use crate::{ast, error::ParseError, lexer, python}; +use std::iter; /* * Parse python code. diff --git a/src/lib.rs b/src/lib.rs index 5f3e72c..a96eefa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,13 +30,10 @@ impl fmt::Display for CompileError { let loc = self.location; if let Some(ref stmt) = self.statement { // visualize the error when location and statement are provided - write!( - f, - "{}", - loc.visualize(stmt, &format_args!("{} at {}", self.error, loc)) - ) + loc.fmt_with(f, &self.error)?; + write!(f, "\n{stmt}{arrow:>pad$}", pad = loc.column(), arrow = "^") } else { - write!(f, "{} at {}", self.error, loc) + loc.fmt_with(f, &self.error) } } }