1#![allow(clippy::large_enum_variant)]
3#![allow(clippy::result_large_err)]
4extern crate erg_common;
5pub extern crate erg_parser;
6
7pub mod artifact;
8pub mod build_hir;
9mod compile;
10pub use compile::*;
11pub mod build_package;
12mod codegen;
13pub mod context;
14pub mod declare;
15pub mod desugar_hir;
16pub mod effectcheck;
17pub mod error;
18pub mod hir;
19pub mod link_ast;
20pub mod link_hir;
21pub mod lint;
22pub mod lower;
23pub mod module;
24pub mod optimize;
25pub mod ownercheck;
26pub mod transpile;
27pub mod ty;
28pub mod varinfo;
29
30#[allow(unused)]
31use erg_common::config::{ErgConfig, Package};
32#[allow(unused)]
33use erg_common::io::Input;
34#[allow(unused)]
35use erg_common::traits::Runnable;
36
37pub use build_hir::{GenericHIRBuilder, HIRBuilder};
38pub use erg_parser::build_ast::ASTBuilder;
39pub use transpile::Transpiler;
40
41#[cfg(feature = "pylib")]
42use pyo3::prelude::*;
43#[cfg(feature = "pylib")]
44use pyo3::types::{IntoPyDict, PyBytes};
45
46#[cfg(feature = "pylib")]
47#[pyclass(unsendable)]
48#[pyo3(name = "Compiler")]
49#[derive(Debug)]
50struct _Compiler {
51 compiler: compile::Compiler,
52}
53
54#[cfg(feature = "pylib")]
55#[pymethods]
56impl _Compiler {
57 #[new]
58 fn new(deps: Vec<Package>, path: Option<String>) -> Self {
59 let input = path.map_or(Input::repl(), |path| Input::file(path.into()));
60 let cfg = ErgConfig {
61 packages: erg_common::ArcArray::from(deps),
62 input,
63 ..ErgConfig::default()
64 };
65 Self {
66 compiler: compile::Compiler::new(cfg),
67 }
68 }
69
70 #[pyo3(name = "clear")]
71 fn _clear(&mut self) {
72 self.compiler.clear();
73 }
74
75 #[pyo3(name = "compile")]
80 fn _compile(
81 &mut self,
82 py: Python<'_>,
83 code: String,
84 mode: &str,
85 ) -> Result<PyObject, error::CompileErrors> {
86 self.compiler.set_input(Input::str(code));
87 let src = self.compiler.cfg_mut().input.read();
88 let code = self
89 .compiler
90 .compile(src, mode)
91 .map(|art| art.object)
92 .map_err(|iart| iart.errors)?;
93 let bytes = code.into_bytes(py.version().parse().unwrap());
94 let dict = [("bytes", PyBytes::new_bound(py, &bytes))].into_py_dict_bound(py);
95 py.run_bound("import marshal", None, None).unwrap();
96 let code = py
97 .eval_bound("marshal.loads(bytes)", None, Some(&dict))
98 .unwrap();
99 Ok(code.into())
100 }
101
102 #[pyo3(name = "compile_file")]
107 fn _compile_file(
108 &mut self,
109 py: Python<'_>,
110 path: String,
111 ) -> Result<PyObject, error::CompileErrors> {
112 let code =
113 std::fs::read_to_string(&path).unwrap_or_else(|err| panic!("{err}, path: {path}"));
114 self._compile(py, code, "exec")
115 }
116
117 #[pyo3(name = "compile_ast")]
122 fn _compile_ast(
123 &mut self,
124 py: Python<'_>,
125 ast: erg_parser::ast::AST,
126 mode: &str,
127 ) -> Result<PyObject, error::CompileErrors> {
128 let code = self
129 .compiler
130 .compile_ast(ast, mode)
131 .map(|art| art.object)
132 .map_err(|iart| iart.errors)?;
133 let bytes = code.into_bytes(py.version().parse().unwrap());
134 let dict = [("bytes", PyBytes::new_bound(py, &bytes))].into_py_dict_bound(py);
135 py.run_bound("import marshal", None, None).unwrap();
136 Ok(py
137 .eval_bound("marshal.loads(bytes)", None, Some(&dict))
138 .unwrap()
139 .into())
140 }
141}
142
143#[cfg(feature = "pylib")]
148#[pyfunction]
149#[pyo3(name = "compile_with_dependencies")]
150fn _compile_with_dependencies(
151 py: Python<'_>,
152 code: String,
153 mode: &str,
154 pkgs: Vec<Package>,
155 path: Option<String>,
156) -> Result<PyObject, error::CompileErrors> {
157 let mut compiler = _Compiler::new(pkgs, path);
158 compiler._compile(py, code, mode)
159}
160
161#[cfg(feature = "pylib")]
166#[pyfunction]
167#[pyo3(name = "compile")]
168fn _compile(
169 py: Python<'_>,
170 code: String,
171 mode: &str,
172 path: Option<String>,
173) -> Result<PyObject, error::CompileErrors> {
174 _compile_with_dependencies(py, code, mode, vec![], path)
175}
176
177#[cfg(feature = "pylib")]
182#[pyfunction]
183#[pyo3(name = "compile_ast_with_dependencies")]
184fn _compile_ast_with_dependencies(
185 py: Python<'_>,
186 ast: erg_parser::ast::AST,
187 mode: &str,
188 pkgs: Vec<Package>,
189 path: Option<String>,
190) -> Result<PyObject, error::CompileErrors> {
191 let mut compiler = _Compiler::new(pkgs, path);
192 compiler._compile_ast(py, ast, mode)
193}
194
195#[cfg(feature = "pylib")]
200#[pyfunction]
201#[pyo3(name = "compile_ast")]
202fn _compile_ast(
203 py: Python<'_>,
204 ast: erg_parser::ast::AST,
205 mode: &str,
206 path: Option<String>,
207) -> Result<PyObject, error::CompileErrors> {
208 _compile_ast_with_dependencies(py, ast, mode, vec![], path)
209}
210
211#[cfg(feature = "pylib")]
216#[pyfunction]
217#[pyo3(name = "compile_file_with_dependencies")]
218fn _compile_file_with_dependencies(
219 py: Python<'_>,
220 path: String,
221 pkgs: Vec<Package>,
222) -> Result<PyObject, error::CompileErrors> {
223 let code = std::fs::read_to_string(&path).unwrap_or_else(|err| panic!("{err}, path: {path}"));
224 _compile_with_dependencies(py, code, "exec", pkgs, Some(path))
225}
226
227#[cfg(feature = "pylib")]
232#[pyfunction]
233#[pyo3(name = "compile_file")]
234fn _compile_file(py: Python<'_>, path: String) -> Result<PyObject, error::CompileErrors> {
235 _compile_file_with_dependencies(py, path, vec![])
236}
237
238#[cfg(feature = "pylib")]
244#[pyfunction]
245#[pyo3(name = "exec_with_dependencies")]
246fn _exec_with_dependencies(
247 py: Python<'_>,
248 code: String,
249 pkgs: Vec<Package>,
250 path: Option<String>,
251) -> Result<PyObject, error::CompileErrors> {
252 let code = _compile_with_dependencies(py, code, "exec", pkgs, path)?;
253 let module = pyo3::types::PyModule::new_bound(py, "<erg>").unwrap();
254 let dic = [("code", code), ("dict", PyObject::from(module.dict()))].into_py_dict_bound(py);
255 py.run_bound("exec(code, dict)", None, Some(&dic)).unwrap();
256 Ok(module.into())
257}
258
259#[cfg(feature = "pylib")]
264#[pyfunction]
265#[pyo3(name = "exec")]
266fn _exec(
267 py: Python<'_>,
268 code: String,
269 path: Option<String>,
270) -> Result<PyObject, error::CompileErrors> {
271 _exec_with_dependencies(py, code, vec![], path)
272}
273
274#[cfg(feature = "pylib")]
279#[pyfunction]
280#[pyo3(name = "exec_file_with_dependencies")]
281fn _exec_file_with_dependencies(
282 py: Python<'_>,
283 path: String,
284 pkgs: Vec<Package>,
285) -> Result<PyObject, error::CompileErrors> {
286 let code = std::fs::read_to_string(&path).unwrap_or_else(|err| panic!("{err}, path: {path}"));
287 _exec_with_dependencies(py, code, pkgs, Some(path))
288}
289
290#[cfg(feature = "pylib")]
295#[pyfunction]
296#[pyo3(name = "exec_file")]
297fn _exec_file(py: Python<'_>, path: String) -> Result<PyObject, error::CompileErrors> {
298 _exec_file_with_dependencies(py, path, vec![])
299}
300
301#[cfg(feature = "pylib")]
306#[pyfunction]
307#[pyo3(name = "exec_ast_with_dependencies")]
308fn _exec_ast_with_dependencies(
309 py: Python<'_>,
310 ast: erg_parser::ast::AST,
311 pkgs: Vec<Package>,
312 path: Option<String>,
313) -> Result<PyObject, error::CompileErrors> {
314 let code = _compile_ast_with_dependencies(py, ast, "exec", pkgs, path)?;
315 let module = pyo3::types::PyModule::new_bound(py, "<erg>").unwrap();
316 let dic = [("code", code), ("dict", PyObject::from(module.dict()))].into_py_dict_bound(py);
317 py.run_bound("exec(code, dict)", None, Some(&dic)).unwrap();
318 Ok(module.into())
319}
320
321#[cfg(feature = "pylib")]
326#[pyfunction]
327#[pyo3(name = "exec_ast")]
328fn _exec_ast(
329 py: Python<'_>,
330 ast: erg_parser::ast::AST,
331 path: Option<String>,
332) -> Result<PyObject, error::CompileErrors> {
333 _exec_ast_with_dependencies(py, ast, vec![], path)
334}
335
336#[cfg(feature = "pylib")]
341#[pyfunction]
342#[pyo3(name = "__import__")]
343fn _import(py: Python<'_>, name: String) -> Result<PyObject, error::CompileErrors> {
344 let path = format!("{name}.er");
345 let code = std::fs::read_to_string(&path).unwrap_or_else(|err| panic!("{err}, path: {path}"));
346 _exec(py, code, Some(path))
347}
348
349#[cfg(feature = "pylib")]
350#[pymodule]
351fn erg_compiler(py: Python<'_>, m: &Bound<PyModule>) -> PyResult<()> {
352 m.add_class::<Package>()?;
353 m.add_class::<_Compiler>()?;
354 m.add_function(wrap_pyfunction!(_compile, m)?)?;
355 m.add_function(wrap_pyfunction!(_compile_with_dependencies, m)?)?;
356 m.add_function(wrap_pyfunction!(_compile_ast, m)?)?;
357 m.add_function(wrap_pyfunction!(_compile_ast_with_dependencies, m)?)?;
358 m.add_function(wrap_pyfunction!(_compile_file, m)?)?;
359 m.add_function(wrap_pyfunction!(_compile_file_with_dependencies, m)?)?;
360 m.add_function(wrap_pyfunction!(_exec, m)?)?;
361 m.add_function(wrap_pyfunction!(_exec_with_dependencies, m)?)?;
362 m.add_function(wrap_pyfunction!(_exec_ast, m)?)?;
363 m.add_function(wrap_pyfunction!(_exec_ast_with_dependencies, m)?)?;
364 m.add_function(wrap_pyfunction!(_exec_file, m)?)?;
365 m.add_function(wrap_pyfunction!(_exec_file_with_dependencies, m)?)?;
366 m.add_function(wrap_pyfunction!(_import, m)?)?;
367
368 use crate::erg_parser::erg_parser;
369 let parser = PyModule::new_bound(py, "erg_parser")?;
370 erg_parser(py, &parser)?;
371 m.add_submodule(&parser)?;
372
373 py.run_bound(
374 "\
375import sys
376sys.modules['erg_compiler.erg_parser'] = erg_parser
377sys.modules['erg_compiler.erg_parser.ast'] = erg_parser.ast
378sys.modules['erg_compiler.erg_parser.expr'] = erg_parser.expr
379",
380 None,
381 Some(&m.dict()),
382 )?;
383
384 Ok(())
385}