rustpython_compiler/
lib.rs

1use rustpython_codegen::{compile, symboltable};
2use rustpython_parser::ast::{self as ast, fold::Fold, ConstantOptimizer};
3
4pub use rustpython_codegen::compile::CompileOpts;
5pub use rustpython_compiler_core::{bytecode::CodeObject, Mode};
6pub use rustpython_parser::{source_code::LinearLocator, Parse};
7
8// these modules are out of repository. re-exporting them here for convenience.
9pub use rustpython_codegen as codegen;
10pub use rustpython_compiler_core as core;
11pub use rustpython_parser as parser;
12
13#[derive(Debug)]
14pub enum CompileErrorType {
15    Codegen(rustpython_codegen::error::CodegenErrorType),
16    Parse(parser::ParseErrorType),
17}
18
19impl std::error::Error for CompileErrorType {
20    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
21        match self {
22            CompileErrorType::Codegen(e) => e.source(),
23            CompileErrorType::Parse(e) => e.source(),
24        }
25    }
26}
27impl std::fmt::Display for CompileErrorType {
28    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
29        match self {
30            CompileErrorType::Codegen(e) => e.fmt(f),
31            CompileErrorType::Parse(e) => e.fmt(f),
32        }
33    }
34}
35impl From<rustpython_codegen::error::CodegenErrorType> for CompileErrorType {
36    fn from(source: rustpython_codegen::error::CodegenErrorType) -> Self {
37        CompileErrorType::Codegen(source)
38    }
39}
40impl From<parser::ParseErrorType> for CompileErrorType {
41    fn from(source: parser::ParseErrorType) -> Self {
42        CompileErrorType::Parse(source)
43    }
44}
45
46pub type CompileError = rustpython_parser::source_code::LocatedError<CompileErrorType>;
47
48/// Compile a given source code into a bytecode object.
49pub fn compile(
50    source: &str,
51    mode: Mode,
52    source_path: String,
53    opts: CompileOpts,
54) -> Result<CodeObject, CompileError> {
55    let mut locator = LinearLocator::new(source);
56    let mut ast = match parser::parse(source, mode.into(), &source_path) {
57        Ok(x) => x,
58        Err(e) => return Err(locator.locate_error(e)),
59    };
60    if opts.optimize > 0 {
61        ast = ConstantOptimizer::new()
62            .fold_mod(ast)
63            .unwrap_or_else(|e| match e {});
64    }
65    let ast = locator.fold_mod(ast).unwrap_or_else(|e| match e {});
66    compile::compile_top(&ast, source_path, mode, opts).map_err(|e| e.into())
67}
68
69pub fn compile_symtable(
70    source: &str,
71    mode: Mode,
72    source_path: &str,
73) -> Result<symboltable::SymbolTable, CompileError> {
74    let mut locator = LinearLocator::new(source);
75    let res = match mode {
76        Mode::Exec | Mode::Single | Mode::BlockExpr => {
77            let ast =
78                ast::Suite::parse(source, source_path).map_err(|e| locator.locate_error(e))?;
79            let ast = locator.fold(ast).unwrap();
80            symboltable::SymbolTable::scan_program(&ast)
81        }
82        Mode::Eval => {
83            let expr =
84                ast::Expr::parse(source, source_path).map_err(|e| locator.locate_error(e))?;
85            let expr = locator.fold(expr).unwrap();
86            symboltable::SymbolTable::scan_expr(&expr)
87        }
88    };
89    res.map_err(|e| e.into_codegen_error(source_path.to_owned()).into())
90}