mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
91 lines
3.1 KiB
Rust
91 lines
3.1 KiB
Rust
use rustpython_codegen::{compile, symboltable};
|
|
use rustpython_parser::ast::{self as ast, fold::Fold, ConstantOptimizer};
|
|
|
|
pub use rustpython_codegen::compile::CompileOpts;
|
|
pub use rustpython_compiler_core::{bytecode::CodeObject, Mode};
|
|
pub use rustpython_parser::{source_code::LinearLocator, Parse};
|
|
|
|
// these modules are out of repository. re-exporting them here for convenience.
|
|
pub use rustpython_codegen as codegen;
|
|
pub use rustpython_compiler_core as core;
|
|
pub use rustpython_parser as parser;
|
|
|
|
#[derive(Debug)]
|
|
pub enum CompileErrorType {
|
|
Codegen(rustpython_codegen::error::CodegenErrorType),
|
|
Parse(parser::ParseErrorType),
|
|
}
|
|
|
|
impl std::error::Error for CompileErrorType {
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
match self {
|
|
CompileErrorType::Codegen(e) => e.source(),
|
|
CompileErrorType::Parse(e) => e.source(),
|
|
}
|
|
}
|
|
}
|
|
impl std::fmt::Display for CompileErrorType {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
match self {
|
|
CompileErrorType::Codegen(e) => e.fmt(f),
|
|
CompileErrorType::Parse(e) => e.fmt(f),
|
|
}
|
|
}
|
|
}
|
|
impl From<rustpython_codegen::error::CodegenErrorType> for CompileErrorType {
|
|
fn from(source: rustpython_codegen::error::CodegenErrorType) -> Self {
|
|
CompileErrorType::Codegen(source)
|
|
}
|
|
}
|
|
impl From<parser::ParseErrorType> for CompileErrorType {
|
|
fn from(source: parser::ParseErrorType) -> Self {
|
|
CompileErrorType::Parse(source)
|
|
}
|
|
}
|
|
|
|
pub type CompileError = rustpython_parser::source_code::LocatedError<CompileErrorType>;
|
|
|
|
/// Compile a given source code into a bytecode object.
|
|
pub fn compile(
|
|
source: &str,
|
|
mode: Mode,
|
|
source_path: String,
|
|
opts: CompileOpts,
|
|
) -> Result<CodeObject, CompileError> {
|
|
let mut locator = LinearLocator::new(source);
|
|
let mut ast = match parser::parse(source, mode.into(), &source_path) {
|
|
Ok(x) => x,
|
|
Err(e) => return Err(locator.locate_error(e)),
|
|
};
|
|
if opts.optimize > 0 {
|
|
ast = ConstantOptimizer::new()
|
|
.fold_mod(ast)
|
|
.unwrap_or_else(|e| match e {});
|
|
}
|
|
let ast = locator.fold_mod(ast).unwrap_or_else(|e| match e {});
|
|
compile::compile_top(&ast, source_path, mode, opts).map_err(|e| e.into())
|
|
}
|
|
|
|
pub fn compile_symtable(
|
|
source: &str,
|
|
mode: Mode,
|
|
source_path: &str,
|
|
) -> Result<symboltable::SymbolTable, CompileError> {
|
|
let mut locator = LinearLocator::new(source);
|
|
let res = match mode {
|
|
Mode::Exec | Mode::Single | Mode::BlockExpr => {
|
|
let ast =
|
|
ast::Suite::parse(source, source_path).map_err(|e| locator.locate_error(e))?;
|
|
let ast = locator.fold(ast).unwrap();
|
|
symboltable::SymbolTable::scan_program(&ast)
|
|
}
|
|
Mode::Eval => {
|
|
let expr =
|
|
ast::Expr::parse(source, source_path).map_err(|e| locator.locate_error(e))?;
|
|
let expr = locator.fold(expr).unwrap();
|
|
symboltable::SymbolTable::scan_expr(&expr)
|
|
}
|
|
};
|
|
res.map_err(|e| e.into_codegen_error(source_path.to_owned()).into())
|
|
}
|