codegen::{CompileError -> CodegenError}

This commit is contained in:
Jeong YunWon 2022-08-22 06:30:06 +09:00
parent 3690272256
commit cf10e800a6
4 changed files with 72 additions and 71 deletions

View file

@ -6,7 +6,7 @@
//! <https://github.com/micropython/micropython/blob/master/py/compile.c> //! <https://github.com/micropython/micropython/blob/master/py/compile.c>
use crate::{ use crate::{
error::{CompileError, CompileErrorType}, error::{CodegenError, CodegenErrorType},
ir, ir,
symboltable::{self, SymbolScope, SymbolTable}, symboltable::{self, SymbolScope, SymbolTable},
IndexSet, IndexSet,
@ -20,7 +20,7 @@ use std::borrow::Cow;
pub use rustpython_bytecode::Mode; pub use rustpython_bytecode::Mode;
type CompileResult<T> = Result<T, CompileError>; type CompileResult<T> = Result<T, CodegenError>;
#[derive(PartialEq, Eq, Clone, Copy)] #[derive(PartialEq, Eq, Clone, Copy)]
enum NameUsage { enum NameUsage {
@ -129,7 +129,7 @@ fn compile_impl<Ast: ?Sized>(
) -> CompileResult<CodeObject> { ) -> CompileResult<CodeObject> {
let symbol_table = match make_symbol_table(ast) { let symbol_table = match make_symbol_table(ast) {
Ok(x) => x, Ok(x) => x,
Err(e) => return Err(e.into_compile_error(source_path)), Err(e) => return Err(e.into_codegen_error(source_path)),
}; };
let mut compiler = Compiler::new(opts, source_path, "<module>".to_owned()); let mut compiler = Compiler::new(opts, source_path, "<module>".to_owned());
@ -234,11 +234,11 @@ impl Compiler {
} }
} }
fn error(&self, error: CompileErrorType) -> CompileError { fn error(&self, error: CodegenErrorType) -> CodegenError {
self.error_loc(error, self.current_source_location) self.error_loc(error, self.current_source_location)
} }
fn error_loc(&self, error: CompileErrorType, location: ast::Location) -> CompileError { fn error_loc(&self, error: CodegenErrorType, location: ast::Location) -> CodegenError {
CompileError { CodegenError {
error, error,
location, location,
source_path: self.source_path.clone(), source_path: self.source_path.clone(),
@ -455,7 +455,7 @@ impl Compiler {
NameUsage::Delete if is_forbidden_name(name) => "cannot delete", NameUsage::Delete if is_forbidden_name(name) => "cannot delete",
_ => return Ok(()), _ => return Ok(()),
}; };
Err(self.error(CompileErrorType::SyntaxError(format!("{} {}", msg, name)))) Err(self.error(CodegenErrorType::SyntaxError(format!("{} {}", msg, name))))
} }
fn compile_name(&mut self, name: &str, usage: NameUsage) -> CompileResult<()> { fn compile_name(&mut self, name: &str, usage: NameUsage) -> CompileResult<()> {
@ -580,7 +580,7 @@ impl Compiler {
let from_list = if import_star { let from_list = if import_star {
if self.ctx.in_func() { if self.ctx.in_func() {
return Err(self return Err(self
.error_loc(CompileErrorType::FunctionImportStar, statement.location)); .error_loc(CodegenErrorType::FunctionImportStar, statement.location));
} }
vec![ConstantData::Str { vec![ConstantData::Str {
value: "*".to_owned(), value: "*".to_owned(),
@ -769,7 +769,7 @@ impl Compiler {
self.emit(Instruction::Break { target: end }); self.emit(Instruction::Break { target: end });
} }
None => { None => {
return Err(self.error_loc(CompileErrorType::InvalidBreak, statement.location)); return Err(self.error_loc(CodegenErrorType::InvalidBreak, statement.location));
} }
}, },
Continue => match self.ctx.loop_data { Continue => match self.ctx.loop_data {
@ -778,13 +778,13 @@ impl Compiler {
} }
None => { None => {
return Err( return Err(
self.error_loc(CompileErrorType::InvalidContinue, statement.location) self.error_loc(CodegenErrorType::InvalidContinue, statement.location)
); );
} }
}, },
Return { value } => { Return { value } => {
if !self.ctx.in_func() { if !self.ctx.in_func() {
return Err(self.error_loc(CompileErrorType::InvalidReturn, statement.location)); return Err(self.error_loc(CodegenErrorType::InvalidReturn, statement.location));
} }
match value { match value {
Some(v) => { Some(v) => {
@ -795,7 +795,7 @@ impl Compiler {
.contains(bytecode::CodeFlags::IS_GENERATOR) .contains(bytecode::CodeFlags::IS_GENERATOR)
{ {
return Err(self.error_loc( return Err(self.error_loc(
CompileErrorType::AsyncReturnValue, CodegenErrorType::AsyncReturnValue,
statement.location, statement.location,
)); ));
} }
@ -857,9 +857,9 @@ impl Compiler {
} }
} }
ast::ExprKind::BinOp { .. } | ast::ExprKind::UnaryOp { .. } => { ast::ExprKind::BinOp { .. } | ast::ExprKind::UnaryOp { .. } => {
return Err(self.error(CompileErrorType::Delete("expression"))) return Err(self.error(CodegenErrorType::Delete("expression")))
} }
_ => return Err(self.error(CompileErrorType::Delete(expression.node.name()))), _ => return Err(self.error(CodegenErrorType::Delete(expression.node.name()))),
} }
Ok(()) Ok(())
} }
@ -922,7 +922,7 @@ impl Compiler {
.chain(&args.kwonlyargs); .chain(&args.kwonlyargs);
for name in args_iter { for name in args_iter {
if Compiler::is_forbidden_arg_name(&name.node.arg) { if Compiler::is_forbidden_arg_name(&name.node.arg) {
return Err(self.error(CompileErrorType::SyntaxError(format!( return Err(self.error(CodegenErrorType::SyntaxError(format!(
"cannot assign to {}", "cannot assign to {}",
&name.node.arg &name.node.arg
)))); ))));
@ -1401,7 +1401,7 @@ impl Compiler {
let (item, items) = if let Some(parts) = items.split_first() { let (item, items) = if let Some(parts) = items.split_first() {
parts parts
} else { } else {
return Err(self.error(CompileErrorType::EmptyWithItems)); return Err(self.error(CodegenErrorType::EmptyWithItems));
}; };
let final_block = { let final_block = {
@ -1433,7 +1433,7 @@ impl Compiler {
if items.is_empty() { if items.is_empty() {
if body.is_empty() { if body.is_empty() {
return Err(self.error(CompileErrorType::EmptyWithBody)); return Err(self.error(CodegenErrorType::EmptyWithBody));
} }
self.compile_statements(body)?; self.compile_statements(body)?;
} else { } else {
@ -1529,7 +1529,7 @@ impl Compiler {
) -> CompileResult<()> { ) -> CompileResult<()> {
eprintln!("match subject: {subject:?}"); eprintln!("match subject: {subject:?}");
eprintln!("match cases: {cases:?}"); eprintln!("match cases: {cases:?}");
Err(self.error(CompileErrorType::NotImplementedYet)) Err(self.error(CodegenErrorType::NotImplementedYet))
} }
fn compile_chained_comparison( fn compile_chained_comparison(
@ -1699,7 +1699,7 @@ impl Compiler {
for (i, element) in elts.iter().enumerate() { for (i, element) in elts.iter().enumerate() {
if let ast::ExprKind::Starred { .. } = &element.node { if let ast::ExprKind::Starred { .. } = &element.node {
if seen_star { if seen_star {
return Err(self.error(CompileErrorType::MultipleStarArgs)); return Err(self.error(CodegenErrorType::MultipleStarArgs));
} else { } else {
seen_star = true; seen_star = true;
let before = i; let before = i;
@ -1707,7 +1707,7 @@ impl Compiler {
let (before, after) = (|| Some((before.to_u8()?, after.to_u8()?)))() let (before, after) = (|| Some((before.to_u8()?, after.to_u8()?)))()
.ok_or_else(|| { .ok_or_else(|| {
self.error_loc( self.error_loc(
CompileErrorType::TooManyStarUnpack, CodegenErrorType::TooManyStarUnpack,
target.location, target.location,
) )
})?; })?;
@ -1732,10 +1732,10 @@ impl Compiler {
} }
_ => { _ => {
return Err(self.error(match target.node { return Err(self.error(match target.node {
ast::ExprKind::Starred { .. } => CompileErrorType::SyntaxError( ast::ExprKind::Starred { .. } => CodegenErrorType::SyntaxError(
"starred assignment target must be in a list or tuple".to_owned(), "starred assignment target must be in a list or tuple".to_owned(),
), ),
_ => CompileErrorType::Assign(target.node.name()), _ => CodegenErrorType::Assign(target.node.name()),
})); }));
} }
} }
@ -1776,7 +1776,7 @@ impl Compiler {
AugAssignKind::Attr { idx } AugAssignKind::Attr { idx }
} }
_ => { _ => {
return Err(self.error(CompileErrorType::Assign(target.node.name()))); return Err(self.error(CodegenErrorType::Assign(target.node.name())));
} }
}; };
@ -2049,7 +2049,7 @@ impl Compiler {
} }
Yield { value } => { Yield { value } => {
if !self.ctx.in_func() { if !self.ctx.in_func() {
return Err(self.error(CompileErrorType::InvalidYield)); return Err(self.error(CodegenErrorType::InvalidYield));
} }
self.mark_generator(); self.mark_generator();
match value { match value {
@ -2060,7 +2060,7 @@ impl Compiler {
} }
Await { value } => { Await { value } => {
if self.ctx.func != FunctionContext::AsyncFunction { if self.ctx.func != FunctionContext::AsyncFunction {
return Err(self.error(CompileErrorType::InvalidAwait)); return Err(self.error(CodegenErrorType::InvalidAwait));
} }
self.compile_expression(value)?; self.compile_expression(value)?;
self.emit(Instruction::GetAwaitable); self.emit(Instruction::GetAwaitable);
@ -2070,10 +2070,10 @@ impl Compiler {
YieldFrom { value } => { YieldFrom { value } => {
match self.ctx.func { match self.ctx.func {
FunctionContext::NoFunction => { FunctionContext::NoFunction => {
return Err(self.error(CompileErrorType::InvalidYieldFrom)); return Err(self.error(CodegenErrorType::InvalidYieldFrom));
} }
FunctionContext::AsyncFunction => { FunctionContext::AsyncFunction => {
return Err(self.error(CompileErrorType::AsyncYieldFrom)); return Err(self.error(CodegenErrorType::AsyncYieldFrom));
} }
FunctionContext::Function => {} FunctionContext::Function => {}
} }
@ -2208,7 +2208,7 @@ impl Compiler {
})?; })?;
} }
Starred { .. } => { Starred { .. } => {
return Err(self.error(CompileErrorType::InvalidStarExpr)); return Err(self.error(CodegenErrorType::InvalidStarExpr));
} }
IfExp { test, body, orelse } => { IfExp { test, body, orelse } => {
let else_block = self.new_block(); let else_block = self.new_block();
@ -2417,8 +2417,8 @@ impl Compiler {
fn compile_comprehension_element(&mut self, element: &ast::Expr) -> CompileResult<()> { fn compile_comprehension_element(&mut self, element: &ast::Expr) -> CompileResult<()> {
self.compile_expression(element).map_err(|e| { self.compile_expression(element).map_err(|e| {
if let CompileErrorType::InvalidStarExpr = e.error { if let CodegenErrorType::InvalidStarExpr = e.error {
self.error(CompileErrorType::SyntaxError( self.error(CodegenErrorType::SyntaxError(
"iterable unpacking cannot be used in comprehension".to_owned(), "iterable unpacking cannot be used in comprehension".to_owned(),
)) ))
} else { } else {
@ -2547,9 +2547,9 @@ impl Compiler {
Ok(()) Ok(())
} }
fn compile_future_features(&mut self, features: &[ast::Alias]) -> Result<(), CompileError> { fn compile_future_features(&mut self, features: &[ast::Alias]) -> Result<(), CodegenError> {
if self.done_with_future_stmts { if self.done_with_future_stmts {
return Err(self.error(CompileErrorType::InvalidFuturePlacement)); return Err(self.error(CodegenErrorType::InvalidFuturePlacement));
} }
for feature in features { for feature in features {
match &*feature.node.name { match &*feature.node.name {
@ -2559,7 +2559,7 @@ impl Compiler {
// "generator_stop" => {} // "generator_stop" => {}
"annotations" => self.future_annotations = true, "annotations" => self.future_annotations = true,
other => { other => {
return Err(self.error(CompileErrorType::InvalidFutureFeature(other.to_owned()))) return Err(self.error(CodegenErrorType::InvalidFutureFeature(other.to_owned())))
} }
} }
} }

View file

@ -3,15 +3,15 @@ use rustpython_ast::Location;
use std::{error::Error, fmt}; use std::{error::Error, fmt};
#[derive(Debug)] #[derive(Debug)]
pub struct CompileError { pub struct CodegenError {
pub error: CompileErrorType, pub error: CodegenErrorType,
pub location: Location, pub location: Location,
pub source_path: String, pub source_path: String,
} }
#[derive(Debug)] #[derive(Debug)]
#[non_exhaustive] #[non_exhaustive]
pub enum CompileErrorType { pub enum CodegenErrorType {
/// Invalid assignment, cannot store value in target. /// Invalid assignment, cannot store value in target.
Assign(&'static str), Assign(&'static str),
/// Invalid delete /// Invalid delete
@ -40,61 +40,62 @@ pub enum CompileErrorType {
NotImplementedYet, // RustPython marker for unimplemented features NotImplementedYet, // RustPython marker for unimplemented features
} }
impl fmt::Display for CompileErrorType { impl fmt::Display for CodegenErrorType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use CodegenErrorType::*;
match self { match self {
CompileErrorType::Assign(target) => write!(f, "cannot assign to {}", target), Assign(target) => write!(f, "cannot assign to {}", target),
CompileErrorType::Delete(target) => write!(f, "cannot delete {}", target), Delete(target) => write!(f, "cannot delete {}", target),
CompileErrorType::SyntaxError(err) => write!(f, "{}", err.as_str()), SyntaxError(err) => write!(f, "{}", err.as_str()),
CompileErrorType::MultipleStarArgs => { MultipleStarArgs => {
write!(f, "two starred expressions in assignment") write!(f, "two starred expressions in assignment")
} }
CompileErrorType::InvalidStarExpr => write!(f, "cannot use starred expression here"), InvalidStarExpr => write!(f, "cannot use starred expression here"),
CompileErrorType::InvalidBreak => write!(f, "'break' outside loop"), InvalidBreak => write!(f, "'break' outside loop"),
CompileErrorType::InvalidContinue => write!(f, "'continue' outside loop"), InvalidContinue => write!(f, "'continue' outside loop"),
CompileErrorType::InvalidReturn => write!(f, "'return' outside function"), InvalidReturn => write!(f, "'return' outside function"),
CompileErrorType::InvalidYield => write!(f, "'yield' outside function"), InvalidYield => write!(f, "'yield' outside function"),
CompileErrorType::InvalidYieldFrom => write!(f, "'yield from' outside function"), InvalidYieldFrom => write!(f, "'yield from' outside function"),
CompileErrorType::InvalidAwait => write!(f, "'await' outside async function"), InvalidAwait => write!(f, "'await' outside async function"),
CompileErrorType::AsyncYieldFrom => write!(f, "'yield from' inside async function"), AsyncYieldFrom => write!(f, "'yield from' inside async function"),
CompileErrorType::AsyncReturnValue => { AsyncReturnValue => {
write!(f, "'return' with value inside async generator") write!(f, "'return' with value inside async generator")
} }
CompileErrorType::InvalidFuturePlacement => write!( InvalidFuturePlacement => write!(
f, f,
"from __future__ imports must occur at the beginning of the file" "from __future__ imports must occur at the beginning of the file"
), ),
CompileErrorType::InvalidFutureFeature(feat) => { InvalidFutureFeature(feat) => {
write!(f, "future feature {} is not defined", feat) write!(f, "future feature {} is not defined", feat)
} }
CompileErrorType::FunctionImportStar => { FunctionImportStar => {
write!(f, "import * only allowed at module level") write!(f, "import * only allowed at module level")
} }
CompileErrorType::TooManyStarUnpack => { TooManyStarUnpack => {
write!(f, "too many expressions in star-unpacking assignment") write!(f, "too many expressions in star-unpacking assignment")
} }
CompileErrorType::EmptyWithItems => { EmptyWithItems => {
write!(f, "empty items on With") write!(f, "empty items on With")
} }
CompileErrorType::EmptyWithBody => { EmptyWithBody => {
write!(f, "empty body on With") write!(f, "empty body on With")
} }
CompileErrorType::NotImplementedYet => { NotImplementedYet => {
write!(f, "RustPython does not implement this feature yet") write!(f, "RustPython does not implement this feature yet")
} }
} }
} }
} }
impl Error for CompileErrorType {} impl Error for CodegenErrorType {}
impl fmt::Display for CompileError { impl fmt::Display for CodegenError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} at {}", self.error, self.location) write!(f, "{} at {}", self.error, self.location)
} }
} }
impl Error for CompileError { impl Error for CodegenError {
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
None None
} }

View file

@ -8,7 +8,7 @@ Inspirational file: https://github.com/python/cpython/blob/main/Python/symtable.
*/ */
use crate::{ use crate::{
error::{CompileError, CompileErrorType}, error::{CodegenError, CodegenErrorType},
IndexMap, IndexMap,
}; };
use rustpython_ast::{self as ast, Location}; use rustpython_ast::{self as ast, Location};
@ -168,9 +168,9 @@ pub struct SymbolTableError {
} }
impl SymbolTableError { impl SymbolTableError {
pub fn into_compile_error(self, source_path: String) -> CompileError { pub fn into_codegen_error(self, source_path: String) -> CodegenError {
CompileError { CodegenError {
error: CompileErrorType::SyntaxError(self.error), error: CodegenErrorType::SyntaxError(self.error),
location: self.location, location: self.location,
source_path, source_path,
} }

View file

@ -10,19 +10,19 @@ pub use rustpython_bytecode::Mode;
pub use rustpython_codegen::compile::CompileOpts; pub use rustpython_codegen::compile::CompileOpts;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum CompileErrorType { pub enum CodegenErrorType {
#[error(transparent)] #[error(transparent)]
Compile(#[from] rustpython_codegen::error::CompileErrorType), Compile(#[from] rustpython_codegen::error::CodegenErrorType),
#[error(transparent)] #[error(transparent)]
Parse(#[from] rustpython_parser::error::ParseErrorType), Parse(#[from] rustpython_parser::error::ParseErrorType),
} }
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub struct CompileError { pub struct CompileError {
pub error: CompileErrorType, pub error: CodegenErrorType,
pub statement: Option<String>,
pub source_path: String, pub source_path: String,
pub location: Location, pub location: Location,
pub statement: Option<String>,
} }
impl fmt::Display for CompileError { impl fmt::Display for CompileError {
@ -42,7 +42,7 @@ impl fmt::Display for CompileError {
} }
impl CompileError { impl CompileError {
fn from_compile(error: rustpython_codegen::error::CompileError, source: &str) -> Self { fn from_codegen(error: rustpython_codegen::error::CodegenError, source: &str) -> Self {
CompileError { CompileError {
error: error.error.into(), error: error.error.into(),
location: error.location, location: error.location,
@ -67,7 +67,7 @@ impl CompileError {
source: &str, source: &str,
source_path: String, source_path: String,
) -> Self { ) -> Self {
Self::from_compile(error.into_compile_error(source_path), source) Self::from_codegen(error.into_codegen_error(source_path), source)
} }
} }
@ -93,7 +93,7 @@ pub fn compile(
.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| CompileError::from_compile(e, source)) .map_err(|e| CompileError::from_codegen(e, source))
} }
pub fn compile_symtable( pub fn compile_symtable(