mirror of
https://github.com/RustPython/Parser.git
synced 2025-09-01 08:07:50 +00:00
Move out CompileError to core as generic form
This commit is contained in:
parent
5b50c547d6
commit
4724cc63f7
4 changed files with 52 additions and 55 deletions
|
@ -17,3 +17,4 @@ num-bigint = { version = "0.4.3", features = ["serde"] }
|
||||||
num-complex = { version = "0.4.0", features = ["serde"] }
|
num-complex = { version = "0.4.0", features = ["serde"] }
|
||||||
serde = { version = "1.0.136", features = ["derive"] }
|
serde = { version = "1.0.136", features = ["derive"] }
|
||||||
static_assertions = "1.1.0"
|
static_assertions = "1.1.0"
|
||||||
|
thiserror = "1.0"
|
||||||
|
|
|
@ -58,3 +58,32 @@ impl<T> BaseError<T> {
|
||||||
BaseError::from(self)
|
BaseError::from(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub struct CompileError<T> {
|
||||||
|
pub body: BaseError<T>,
|
||||||
|
pub statement: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::ops::Deref for CompileError<T> {
|
||||||
|
type Target = BaseError<T>;
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> std::fmt::Display for CompileError<T>
|
||||||
|
where
|
||||||
|
T: std::fmt::Display,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
let loc = self.location;
|
||||||
|
if let Some(ref stmt) = self.statement {
|
||||||
|
// visualize the error when location and statement are provided
|
||||||
|
loc.fmt_with(f, &self.error)?;
|
||||||
|
write!(f, "\n{stmt}{arrow:>pad$}", pad = loc.column(), arrow = "^")
|
||||||
|
} else {
|
||||||
|
loc.fmt_with(f, &self.error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,6 @@ mod location;
|
||||||
mod mode;
|
mod mode;
|
||||||
|
|
||||||
pub use bytecode::*;
|
pub use bytecode::*;
|
||||||
pub use error::BaseError;
|
pub use error::{BaseError, CompileError};
|
||||||
pub use location::Location;
|
pub use location::Location;
|
||||||
pub use mode::Mode;
|
pub use mode::Mode;
|
||||||
|
|
75
src/lib.rs
75
src/lib.rs
|
@ -1,14 +1,13 @@
|
||||||
use rustpython_codegen::{compile, symboltable};
|
use rustpython_codegen::{compile, symboltable};
|
||||||
use rustpython_compiler_core::{BaseError, CodeObject};
|
use rustpython_compiler_core::CodeObject;
|
||||||
use rustpython_parser::{
|
use rustpython_parser::{
|
||||||
ast::{fold::Fold, ConstantOptimizer, Location},
|
ast::{fold::Fold, ConstantOptimizer, Location},
|
||||||
error::ParseErrorType,
|
error::ParseErrorType,
|
||||||
parser,
|
parser,
|
||||||
};
|
};
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
pub use rustpython_codegen::compile::CompileOpts;
|
pub use rustpython_codegen::compile::CompileOpts;
|
||||||
pub use rustpython_compiler_core::Mode;
|
pub use rustpython_compiler_core::{BaseError as CompileErrorBody, Mode};
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum CompileErrorType {
|
pub enum CompileErrorType {
|
||||||
|
@ -18,56 +17,25 @@ pub enum CompileErrorType {
|
||||||
Parse(#[from] rustpython_parser::error::ParseErrorType),
|
Parse(#[from] rustpython_parser::error::ParseErrorType),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type CompileErrorBody = BaseError<CompileErrorType>;
|
pub type CompileError = rustpython_compiler_core::CompileError<CompileErrorType>;
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
fn error_from_codegen(
|
||||||
pub struct CompileError {
|
error: rustpython_codegen::error::CodegenError,
|
||||||
pub body: CompileErrorBody,
|
source: &str,
|
||||||
pub statement: Option<String>,
|
) -> CompileError {
|
||||||
}
|
let statement = get_statement(source, error.location);
|
||||||
|
CompileError {
|
||||||
impl std::ops::Deref for CompileError {
|
body: error.into(),
|
||||||
type Target = CompileErrorBody;
|
statement,
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.body
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for CompileError {
|
fn error_from_parse(error: rustpython_parser::error::ParseError, source: &str) -> CompileError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
let error: CompileErrorBody<ParseErrorType> = error.into();
|
||||||
let loc = self.location;
|
let statement = get_statement(source, error.location);
|
||||||
if let Some(ref stmt) = self.statement {
|
CompileError {
|
||||||
// visualize the error when location and statement are provided
|
body: error.into(),
|
||||||
loc.fmt_with(f, &self.error)?;
|
statement,
|
||||||
write!(f, "\n{stmt}{arrow:>pad$}", pad = loc.column(), arrow = "^")
|
|
||||||
} else {
|
|
||||||
loc.fmt_with(f, &self.error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CompileError {
|
|
||||||
fn from_codegen(error: rustpython_codegen::error::CodegenError, source: &str) -> Self {
|
|
||||||
let statement = get_statement(source, error.location);
|
|
||||||
Self {
|
|
||||||
body: error.into(),
|
|
||||||
statement,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn from_parse(error: rustpython_parser::error::ParseError, source: &str) -> Self {
|
|
||||||
let error: rustpython_compiler_core::BaseError<ParseErrorType> = error.into();
|
|
||||||
let statement = get_statement(source, error.location);
|
|
||||||
Self {
|
|
||||||
body: error.into(),
|
|
||||||
statement,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn from_symtable(
|
|
||||||
error: symboltable::SymbolTableError,
|
|
||||||
source: &str,
|
|
||||||
source_path: String,
|
|
||||||
) -> Self {
|
|
||||||
Self::from_codegen(error.into_codegen_error(source_path), source)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,15 +53,14 @@ pub fn compile(
|
||||||
};
|
};
|
||||||
let mut ast = match parser::parse(source, parser_mode, &source_path) {
|
let mut ast = match parser::parse(source, parser_mode, &source_path) {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(e) => return Err(CompileError::from_parse(e, source)),
|
Err(e) => return Err(error_from_parse(e, source)),
|
||||||
};
|
};
|
||||||
if opts.optimize > 0 {
|
if opts.optimize > 0 {
|
||||||
ast = ConstantOptimizer::new()
|
ast = ConstantOptimizer::new()
|
||||||
.fold_mod(ast)
|
.fold_mod(ast)
|
||||||
.unwrap_or_else(|e| match e {});
|
.unwrap_or_else(|e| match e {});
|
||||||
}
|
}
|
||||||
compile::compile_top(&ast, source_path, mode, opts)
|
compile::compile_top(&ast, source_path, mode, opts).map_err(|e| error_from_codegen(e, source))
|
||||||
.map_err(|e| CompileError::from_codegen(e, source))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile_symtable(
|
pub fn compile_symtable(
|
||||||
|
@ -101,7 +68,7 @@ pub fn compile_symtable(
|
||||||
mode: compile::Mode,
|
mode: compile::Mode,
|
||||||
source_path: &str,
|
source_path: &str,
|
||||||
) -> Result<symboltable::SymbolTable, CompileError> {
|
) -> Result<symboltable::SymbolTable, CompileError> {
|
||||||
let parse_err = |e| CompileError::from_parse(e, source);
|
let parse_err = |e| error_from_parse(e, source);
|
||||||
let res = match mode {
|
let res = match mode {
|
||||||
compile::Mode::Exec | compile::Mode::Single | compile::Mode::BlockExpr => {
|
compile::Mode::Exec | compile::Mode::Single | compile::Mode::BlockExpr => {
|
||||||
let ast = parser::parse_program(source, source_path).map_err(parse_err)?;
|
let ast = parser::parse_program(source, source_path).map_err(parse_err)?;
|
||||||
|
@ -112,7 +79,7 @@ pub fn compile_symtable(
|
||||||
symboltable::SymbolTable::scan_expr(&expr)
|
symboltable::SymbolTable::scan_expr(&expr)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
res.map_err(|e| CompileError::from_symtable(e, source, source_path.to_owned()))
|
res.map_err(|e| error_from_codegen(e.into_codegen_error(source_path.to_owned()), source))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_statement(source: &str, loc: Location) -> Option<String> {
|
fn get_statement(source: &str, loc: Location) -> Option<String> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue