mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 10:49:54 +00:00
feat: add erg_compiler::Compiler
(python module)
This commit is contained in:
parent
163f4c07f3
commit
4466a5a463
6 changed files with 225 additions and 52 deletions
|
@ -226,6 +226,11 @@ impl<ASTBuilder: ASTBuildable, HIRBuilder: BuildRunnable> Runnable
|
|||
// don't initialize the ownership checker
|
||||
}
|
||||
|
||||
fn set_input(&mut self, input: Input) {
|
||||
self.cfg.input = input;
|
||||
self.main_builder.set_input(self.cfg.input.clone());
|
||||
}
|
||||
|
||||
fn exec(&mut self) -> Result<ExitStatus, Self::Errs> {
|
||||
let src = self.cfg_mut().input.read();
|
||||
let artifact = self
|
||||
|
|
|
@ -210,7 +210,7 @@ impl_stream!(PyCodeGenStack, PyCodeGenUnit);
|
|||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct PyCodeGenerator {
|
||||
cfg: ErgConfig,
|
||||
pub(crate) cfg: ErgConfig,
|
||||
pub(crate) py_version: PythonVersion,
|
||||
str_cache: CacheSet<str>,
|
||||
prelude_loaded: bool,
|
||||
|
@ -286,6 +286,10 @@ impl PyCodeGenerator {
|
|||
self.units.clear();
|
||||
}
|
||||
|
||||
pub fn set_input(&mut self, input: Input) {
|
||||
self.cfg.input = input;
|
||||
}
|
||||
|
||||
pub fn initialize(&mut self) {
|
||||
self.prelude_loaded = false;
|
||||
self.mutate_op_loaded = false;
|
||||
|
|
|
@ -163,6 +163,12 @@ impl Runnable for Compiler {
|
|||
self.code_generator.clear();
|
||||
}
|
||||
|
||||
fn set_input(&mut self, input: erg_common::io::Input) {
|
||||
self.cfg.input = input;
|
||||
self.builder.set_input(self.cfg.input.clone());
|
||||
self.code_generator.set_input(self.cfg.input.clone());
|
||||
}
|
||||
|
||||
fn exec(&mut self) -> Result<ExitStatus, Self::Errs> {
|
||||
let path = self.cfg.dump_pyc_path();
|
||||
let src = self.cfg.input.read();
|
||||
|
|
|
@ -28,7 +28,11 @@ pub mod ty;
|
|||
pub mod varinfo;
|
||||
|
||||
#[allow(unused)]
|
||||
use erg_common::config::Package;
|
||||
use erg_common::config::{ErgConfig, Package};
|
||||
#[allow(unused)]
|
||||
use erg_common::io::Input;
|
||||
#[allow(unused)]
|
||||
use erg_common::traits::Runnable;
|
||||
|
||||
pub use build_hir::{GenericHIRBuilder, HIRBuilder};
|
||||
pub use erg_parser::build_ast::ASTBuilder;
|
||||
|
@ -39,10 +43,103 @@ use pyo3::prelude::*;
|
|||
#[cfg(feature = "pylib")]
|
||||
use pyo3::types::{IntoPyDict, PyBytes};
|
||||
|
||||
#[cfg(feature = "pylib")]
|
||||
#[pyclass(unsendable)]
|
||||
#[pyo3(name = "Compiler")]
|
||||
#[derive(Debug)]
|
||||
struct _Compiler {
|
||||
compiler: compile::Compiler,
|
||||
}
|
||||
|
||||
#[cfg(feature = "pylib")]
|
||||
#[pymethods]
|
||||
impl _Compiler {
|
||||
#[new]
|
||||
fn new(deps: Vec<Package>) -> Self {
|
||||
let cfg = ErgConfig {
|
||||
packages: deps,
|
||||
..ErgConfig::default()
|
||||
};
|
||||
Self {
|
||||
compiler: compile::Compiler::new(cfg),
|
||||
}
|
||||
}
|
||||
|
||||
#[pyo3(name = "clear")]
|
||||
fn _clear(&mut self) {
|
||||
self.compiler.clear();
|
||||
}
|
||||
|
||||
/// compile(code: str, mode: str) -> code
|
||||
/// --
|
||||
///
|
||||
/// compile an Erg code as a module at runtime
|
||||
#[pyo3(name = "compile")]
|
||||
fn _compile(
|
||||
&mut self,
|
||||
py: Python<'_>,
|
||||
code: String,
|
||||
mode: &str,
|
||||
) -> Result<PyObject, error::CompileErrors> {
|
||||
self.compiler.set_input(Input::str(code));
|
||||
let src = self.compiler.cfg_mut().input.read();
|
||||
let code = self
|
||||
.compiler
|
||||
.compile(src, mode)
|
||||
.map(|art| art.object)
|
||||
.map_err(|iart| iart.errors)?;
|
||||
let bytes = code.into_bytes(py.version().parse().unwrap());
|
||||
let dict = [("bytes", PyBytes::new(py, &bytes))].into_py_dict(py);
|
||||
py.run("import marshal", None, None).unwrap();
|
||||
let code = py.eval("marshal.loads(bytes)", None, Some(dict)).unwrap();
|
||||
Ok(code.into())
|
||||
}
|
||||
|
||||
/// compile_file(path: str) -> code
|
||||
/// --
|
||||
///
|
||||
/// compile an Erg file as a module at runtime
|
||||
#[pyo3(name = "compile_file")]
|
||||
fn _compile_file(
|
||||
&mut self,
|
||||
py: Python<'_>,
|
||||
path: String,
|
||||
) -> Result<PyObject, error::CompileErrors> {
|
||||
let code =
|
||||
std::fs::read_to_string(&path).unwrap_or_else(|err| panic!("{err}, path: {path}"));
|
||||
self._compile(py, code, "exec")
|
||||
}
|
||||
|
||||
/// compile_ast(ast: erg_parser.AST, mode: str) -> code
|
||||
/// --
|
||||
///
|
||||
/// compile an Erg AST as a module at runtime with dependencies
|
||||
#[pyo3(name = "compile_ast")]
|
||||
fn _compile_ast(
|
||||
&mut self,
|
||||
py: Python<'_>,
|
||||
ast: erg_parser::ast::AST,
|
||||
mode: &str,
|
||||
) -> Result<PyObject, error::CompileErrors> {
|
||||
let code = self
|
||||
.compiler
|
||||
.compile_ast(ast, mode)
|
||||
.map(|art| art.object)
|
||||
.map_err(|iart| iart.errors)?;
|
||||
let bytes = code.into_bytes(py.version().parse().unwrap());
|
||||
let dict = [("bytes", PyBytes::new(py, &bytes))].into_py_dict(py);
|
||||
py.run("import marshal", None, None).unwrap();
|
||||
Ok(py
|
||||
.eval("marshal.loads(bytes)", None, Some(dict))
|
||||
.unwrap()
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// compile_with_dependencies(code: str, mode: str, pkgs: list[Package]) -> code
|
||||
/// --
|
||||
///
|
||||
/// compile an Erg code as a module at runtime
|
||||
/// compile an Erg code as a module at runtime with dependencies
|
||||
#[cfg(feature = "pylib")]
|
||||
#[pyfunction]
|
||||
#[pyo3(name = "compile_with_dependencies")]
|
||||
|
@ -52,20 +149,8 @@ fn _compile_with_dependencies(
|
|||
mode: &str,
|
||||
pkgs: Vec<Package>,
|
||||
) -> Result<PyObject, error::CompileErrors> {
|
||||
use erg_common::{config::ErgConfig, traits::Runnable};
|
||||
let mut cfg = ErgConfig::string(code);
|
||||
cfg.packages = pkgs;
|
||||
let mut compiler = Compiler::new(cfg);
|
||||
let src = compiler.cfg_mut().input.read();
|
||||
let code = compiler
|
||||
.compile(src, mode)
|
||||
.map(|art| art.object)
|
||||
.map_err(|iart| iart.errors)?;
|
||||
let bytes = code.into_bytes(py.version().parse().unwrap());
|
||||
let dict = [("bytes", PyBytes::new(py, &bytes))].into_py_dict(py);
|
||||
py.run("import marshal", None, None).unwrap();
|
||||
let code = py.eval("marshal.loads(bytes)", None, Some(dict)).unwrap();
|
||||
Ok(code.into())
|
||||
let mut compiler = _Compiler::new(pkgs);
|
||||
compiler._compile(py, code, mode)
|
||||
}
|
||||
|
||||
/// compile(code: str, mode: str) -> code
|
||||
|
@ -79,6 +164,23 @@ fn _compile(py: Python<'_>, code: String, mode: &str) -> Result<PyObject, error:
|
|||
_compile_with_dependencies(py, code, mode, vec![])
|
||||
}
|
||||
|
||||
/// compile_ast_with_dependencies(ast: erg_parser.AST, mode: str, pkgs: list[Package]) -> code
|
||||
/// --
|
||||
///
|
||||
/// compile an Erg AST as a module at runtime with dependencies
|
||||
#[cfg(feature = "pylib")]
|
||||
#[pyfunction]
|
||||
#[pyo3(name = "compile_ast_with_dependencies")]
|
||||
fn _compile_ast_with_dependencies(
|
||||
py: Python<'_>,
|
||||
ast: erg_parser::ast::AST,
|
||||
mode: &str,
|
||||
pkgs: Vec<Package>,
|
||||
) -> Result<PyObject, error::CompileErrors> {
|
||||
let mut compiler = _Compiler::new(pkgs);
|
||||
compiler._compile_ast(py, ast, mode)
|
||||
}
|
||||
|
||||
/// compile_ast(ast: erg_parser.AST, mode: str) -> code
|
||||
/// --
|
||||
///
|
||||
|
@ -91,38 +193,13 @@ fn _compile_ast(
|
|||
ast: erg_parser::ast::AST,
|
||||
mode: &str,
|
||||
) -> Result<PyObject, error::CompileErrors> {
|
||||
use erg_common::config::ErgConfig;
|
||||
let cfg = ErgConfig::default();
|
||||
let mut compiler = Compiler::new(cfg);
|
||||
let code = compiler
|
||||
.compile_ast(ast, mode)
|
||||
.map(|art| art.object)
|
||||
.map_err(|iart| iart.errors)?;
|
||||
let bytes = code.into_bytes(py.version().parse().unwrap());
|
||||
let dict = [("bytes", PyBytes::new(py, &bytes))].into_py_dict(py);
|
||||
py.run("import marshal", None, None).unwrap();
|
||||
Ok(py
|
||||
.eval("marshal.loads(bytes)", None, Some(dict))
|
||||
.unwrap()
|
||||
.into())
|
||||
}
|
||||
|
||||
/// compile_file(path: str) -> code
|
||||
/// --
|
||||
///
|
||||
/// compile an Erg file as a module at runtime
|
||||
#[cfg(feature = "pylib")]
|
||||
#[pyfunction]
|
||||
#[pyo3(name = "compile_file")]
|
||||
fn _compile_file(py: Python<'_>, path: String) -> Result<PyObject, error::CompileErrors> {
|
||||
let code = std::fs::read_to_string(&path).unwrap_or_else(|err| panic!("{err}, path: {path}"));
|
||||
_compile(py, code, "exec")
|
||||
_compile_ast_with_dependencies(py, ast, mode, vec![])
|
||||
}
|
||||
|
||||
/// compile_file_with_dependencies(path: str, pkgs: list[Package]) -> code
|
||||
/// --
|
||||
///
|
||||
/// compile an Erg file as a module at runtime
|
||||
/// compile an Erg file as a module at runtime with dependencies
|
||||
#[cfg(feature = "pylib")]
|
||||
#[pyfunction]
|
||||
#[pyo3(name = "compile_file_with_dependencies")]
|
||||
|
@ -135,6 +212,37 @@ fn _compile_file_with_dependencies(
|
|||
_compile_with_dependencies(py, code, "exec", pkgs)
|
||||
}
|
||||
|
||||
/// compile_file(path: str) -> code
|
||||
/// --
|
||||
///
|
||||
/// compile an Erg file as a module at runtime
|
||||
#[cfg(feature = "pylib")]
|
||||
#[pyfunction]
|
||||
#[pyo3(name = "compile_file")]
|
||||
fn _compile_file(py: Python<'_>, path: String) -> Result<PyObject, error::CompileErrors> {
|
||||
_compile_file_with_dependencies(py, path, vec![])
|
||||
}
|
||||
|
||||
/// exec_with_dependencies(code: str, pkgs: list[Package]) -> module
|
||||
/// --
|
||||
///
|
||||
/// compile and execute an Erg code as a module at runtime with dependencies
|
||||
///
|
||||
#[cfg(feature = "pylib")]
|
||||
#[pyfunction]
|
||||
#[pyo3(name = "exec_with_dependencies")]
|
||||
fn _exec_with_dependencies(
|
||||
py: Python<'_>,
|
||||
code: String,
|
||||
pkgs: Vec<Package>,
|
||||
) -> Result<PyObject, error::CompileErrors> {
|
||||
let code = _compile_with_dependencies(py, code, "exec", pkgs)?;
|
||||
let module = pyo3::types::PyModule::new(py, "<erg>").unwrap();
|
||||
let dic = [("code", code), ("dict", PyObject::from(module.dict()))].into_py_dict(py);
|
||||
py.run("exec(code, dict)", None, Some(dic)).unwrap();
|
||||
Ok(module.into())
|
||||
}
|
||||
|
||||
/// exec(code: str) -> module
|
||||
/// --
|
||||
///
|
||||
|
@ -143,7 +251,49 @@ fn _compile_file_with_dependencies(
|
|||
#[pyfunction]
|
||||
#[pyo3(name = "exec")]
|
||||
fn _exec(py: Python<'_>, code: String) -> Result<PyObject, error::CompileErrors> {
|
||||
let code = _compile(py, code, "exec")?;
|
||||
_exec_with_dependencies(py, code, vec![])
|
||||
}
|
||||
|
||||
/// exec_with_dependencies(code: str, pkgs: list[Package]) -> module
|
||||
/// --
|
||||
///
|
||||
/// compile and execute an Erg code as a module at runtime
|
||||
#[cfg(feature = "pylib")]
|
||||
#[pyfunction]
|
||||
#[pyo3(name = "exec_file_with_dependencies")]
|
||||
fn _exec_file_with_dependencies(
|
||||
py: Python<'_>,
|
||||
path: String,
|
||||
pkgs: Vec<Package>,
|
||||
) -> Result<PyObject, error::CompileErrors> {
|
||||
let code = std::fs::read_to_string(&path).unwrap_or_else(|err| panic!("{err}, path: {path}"));
|
||||
_exec_with_dependencies(py, code, pkgs)
|
||||
}
|
||||
|
||||
/// exec_file(path: str) -> module
|
||||
/// --
|
||||
///
|
||||
/// compile and execute an Erg file as a module at runtime
|
||||
#[cfg(feature = "pylib")]
|
||||
#[pyfunction]
|
||||
#[pyo3(name = "exec_file")]
|
||||
fn _exec_file(py: Python<'_>, path: String) -> Result<PyObject, error::CompileErrors> {
|
||||
_exec_file_with_dependencies(py, path, vec![])
|
||||
}
|
||||
|
||||
/// exec_ast_with_dependencies(ast: erg_parser.AST, pkgs: list[Package]) -> module
|
||||
/// --
|
||||
///
|
||||
/// compile and execute an Erg AST as a module at runtime with dependencies
|
||||
#[cfg(feature = "pylib")]
|
||||
#[pyfunction]
|
||||
#[pyo3(name = "exec_ast_with_dependencies")]
|
||||
fn _exec_ast_with_dependencies(
|
||||
py: Python<'_>,
|
||||
ast: erg_parser::ast::AST,
|
||||
pkgs: Vec<Package>,
|
||||
) -> Result<PyObject, error::CompileErrors> {
|
||||
let code = _compile_ast_with_dependencies(py, ast, "exec", pkgs)?;
|
||||
let module = pyo3::types::PyModule::new(py, "<erg>").unwrap();
|
||||
let dic = [("code", code), ("dict", PyObject::from(module.dict()))].into_py_dict(py);
|
||||
py.run("exec(code, dict)", None, Some(dic)).unwrap();
|
||||
|
@ -158,11 +308,7 @@ fn _exec(py: Python<'_>, code: String) -> Result<PyObject, error::CompileErrors>
|
|||
#[pyfunction]
|
||||
#[pyo3(name = "exec_ast")]
|
||||
fn _exec_ast(py: Python<'_>, ast: erg_parser::ast::AST) -> Result<PyObject, error::CompileErrors> {
|
||||
let code = _compile_ast(py, ast, "exec")?;
|
||||
let module = pyo3::types::PyModule::new(py, "<erg>").unwrap();
|
||||
let dic = [("code", code), ("dict", PyObject::from(module.dict()))].into_py_dict(py);
|
||||
py.run("exec(code, dict)", None, Some(dic)).unwrap();
|
||||
Ok(module.into())
|
||||
_exec_ast_with_dependencies(py, ast, vec![])
|
||||
}
|
||||
|
||||
/// __import__(name: str) -> module
|
||||
|
@ -182,13 +328,19 @@ fn _import(py: Python<'_>, name: String) -> Result<PyObject, error::CompileError
|
|||
#[pymodule]
|
||||
fn erg_compiler(py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||
m.add_class::<Package>()?;
|
||||
m.add_class::<_Compiler>()?;
|
||||
m.add_function(wrap_pyfunction!(_compile, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_compile_with_dependencies, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_compile_ast, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_compile_ast_with_dependencies, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_compile_file, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_compile_file_with_dependencies, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_exec, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_exec_with_dependencies, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_exec_ast, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_exec_ast_with_dependencies, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_exec_file, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_exec_file_with_dependencies, m)?)?;
|
||||
m.add_function(wrap_pyfunction!(_import, m)?)?;
|
||||
|
||||
use crate::erg_parser::erg_parser;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue