mirror of
https://github.com/RustPython/Parser.git
synced 2025-07-15 17:15:24 +00:00
reorganize compiler crates
This commit is contained in:
parent
3351b4408b
commit
060d153bb3
82 changed files with 12368 additions and 164 deletions
133
src/lib.rs
133
src/lib.rs
|
@ -1,15 +1,124 @@
|
|||
//! Compile a Python AST or source code into bytecode consumable by RustPython.
|
||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/main/logo.png")]
|
||||
#![doc(html_root_url = "https://docs.rs/rustpython-compiler/")]
|
||||
use rustpython_bytecode::CodeObject;
|
||||
use rustpython_codegen::{compile, symboltable};
|
||||
use rustpython_parser::{
|
||||
ast::{fold::Fold, ConstantOptimizer, Location},
|
||||
parser,
|
||||
};
|
||||
use std::fmt;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
pub use compile::{CompileOpts, Mode};
|
||||
pub use symboltable::{Symbol, SymbolScope, SymbolTable, SymbolTableType};
|
||||
|
||||
type IndexMap<K, V> = indexmap::IndexMap<K, V, ahash::RandomState>;
|
||||
type IndexSet<T> = indexmap::IndexSet<T, ahash::RandomState>;
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum CompileErrorType {
|
||||
#[error(transparent)]
|
||||
Compile(#[from] rustpython_codegen::error::CompileErrorType),
|
||||
#[error(transparent)]
|
||||
Parse(#[from] rustpython_parser::error::ParseErrorType),
|
||||
}
|
||||
|
||||
pub mod compile;
|
||||
pub mod error;
|
||||
pub mod ir;
|
||||
pub mod mode;
|
||||
pub mod symboltable;
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub struct CompileError {
|
||||
pub error: CompileErrorType,
|
||||
pub statement: Option<String>,
|
||||
pub source_path: String,
|
||||
pub location: Location,
|
||||
}
|
||||
|
||||
impl fmt::Display for CompileError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
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))
|
||||
)
|
||||
} else {
|
||||
write!(f, "{} at {}", self.error, loc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CompileError {
|
||||
fn from_compile(error: rustpython_codegen::error::CompileError, source: &str) -> Self {
|
||||
CompileError {
|
||||
error: error.error.into(),
|
||||
location: error.location,
|
||||
source_path: error.source_path,
|
||||
statement: get_statement(source, error.location),
|
||||
}
|
||||
}
|
||||
fn from_parse(
|
||||
error: rustpython_parser::error::ParseError,
|
||||
source: &str,
|
||||
source_path: String,
|
||||
) -> Self {
|
||||
CompileError {
|
||||
error: error.error.into(),
|
||||
location: error.location,
|
||||
source_path,
|
||||
statement: get_statement(source, error.location),
|
||||
}
|
||||
}
|
||||
fn from_symtable(
|
||||
error: symboltable::SymbolTableError,
|
||||
source: &str,
|
||||
source_path: String,
|
||||
) -> Self {
|
||||
Self::from_compile(error.into_compile_error(source_path), source)
|
||||
}
|
||||
}
|
||||
|
||||
/// Compile a given sourcecode into a bytecode object.
|
||||
pub fn compile(
|
||||
source: &str,
|
||||
mode: compile::Mode,
|
||||
source_path: String,
|
||||
opts: CompileOpts,
|
||||
) -> Result<CodeObject, CompileError> {
|
||||
let parser_mode = match mode {
|
||||
compile::Mode::Exec => parser::Mode::Module,
|
||||
compile::Mode::Eval => parser::Mode::Expression,
|
||||
compile::Mode::Single | compile::Mode::BlockExpr => parser::Mode::Interactive,
|
||||
};
|
||||
let mut ast = match parser::parse(source, parser_mode) {
|
||||
Ok(x) => x,
|
||||
Err(e) => return Err(CompileError::from_parse(e, source, source_path)),
|
||||
};
|
||||
if opts.optimize > 0 {
|
||||
ast = ConstantOptimizer::new()
|
||||
.fold_mod(ast)
|
||||
.unwrap_or_else(|e| match e {});
|
||||
}
|
||||
compile::compile_top(&ast, source_path, mode, opts)
|
||||
.map_err(|e| CompileError::from_compile(e, source))
|
||||
}
|
||||
|
||||
pub fn compile_symtable(
|
||||
source: &str,
|
||||
mode: compile::Mode,
|
||||
source_path: &str,
|
||||
) -> Result<symboltable::SymbolTable, CompileError> {
|
||||
let parse_err = |e| CompileError::from_parse(e, source, source_path.to_owned());
|
||||
let res = match mode {
|
||||
compile::Mode::Exec | compile::Mode::Single | compile::Mode::BlockExpr => {
|
||||
let ast = parser::parse_program(source).map_err(parse_err)?;
|
||||
symboltable::make_symbol_table(&ast)
|
||||
}
|
||||
compile::Mode::Eval => {
|
||||
let expr = parser::parse_expression(source).map_err(parse_err)?;
|
||||
symboltable::make_symbol_table_expr(&expr)
|
||||
}
|
||||
};
|
||||
res.map_err(|e| CompileError::from_symtable(e, source, source_path.to_owned()))
|
||||
}
|
||||
|
||||
fn get_statement(source: &str, loc: Location) -> Option<String> {
|
||||
if loc.column() == 0 || loc.row() == 0 {
|
||||
return None;
|
||||
}
|
||||
let line = source.split('\n').nth(loc.row() - 1)?.to_owned();
|
||||
Some(line + "\n")
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue