mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
commit
6d7c20fa99
13 changed files with 143 additions and 36 deletions
5
.github/workflows/rust.yml
vendored
5
.github/workflows/rust.yml
vendored
|
@ -19,8 +19,9 @@ jobs:
|
|||
- uses: Swatinem/rust-cache@v2
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
||||
# Removed because it caused a segmentation fault and would not stop executing. Testing should be done locally.
|
||||
# - name: Run tests
|
||||
# run: cargo test --verbose -- --test-threads=2
|
||||
- uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clippy
|
||||
|
|
|
@ -7,6 +7,11 @@ repos:
|
|||
entry: cargo fmt --all
|
||||
language: system
|
||||
pass_filenames: false
|
||||
- id: cargo-test
|
||||
name: Cargo test
|
||||
entry: cargo test
|
||||
language: system
|
||||
# pass_filenames: false
|
||||
- id: rust-clippy
|
||||
name: Rust clippy
|
||||
description: Run cargo clippy on files included in the commit
|
||||
|
|
|
@ -180,7 +180,15 @@ impl Default for ErgConfig {
|
|||
}
|
||||
|
||||
impl ErgConfig {
|
||||
pub fn with_path(path: PathBuf) -> Self {
|
||||
pub fn with_main_path(path: PathBuf) -> Self {
|
||||
Self {
|
||||
module: "<module>",
|
||||
input: Input::File(path),
|
||||
..ErgConfig::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_module_path(path: PathBuf) -> Self {
|
||||
Self {
|
||||
module: Box::leak(path.to_str().unwrap().to_string().into_boxed_str()),
|
||||
input: Input::File(path),
|
||||
|
|
|
@ -54,7 +54,7 @@ pub fn detect_magic_number() -> u32 {
|
|||
}
|
||||
|
||||
/// executes over a shell, cause `python` may not exist as an executable file (like pyenv)
|
||||
pub fn exec_pyc<S: Into<String>>(file: S) {
|
||||
pub fn exec_pyc<S: Into<String>>(file: S) -> Option<i32> {
|
||||
let mut out = if cfg!(windows) {
|
||||
Command::new("cmd")
|
||||
.arg("/C")
|
||||
|
@ -70,7 +70,7 @@ pub fn exec_pyc<S: Into<String>>(file: S) {
|
|||
.spawn()
|
||||
.expect("cannot execute python")
|
||||
};
|
||||
out.wait().expect("python doesn't work");
|
||||
out.wait().expect("python doesn't work").code()
|
||||
}
|
||||
|
||||
/// evaluates over a shell, cause `python` may not exist as an executable file (like pyenv)
|
||||
|
@ -94,19 +94,20 @@ pub fn eval_pyc<S: Into<String>>(file: S) -> String {
|
|||
String::from_utf8_lossy(&out.stdout).to_string()
|
||||
}
|
||||
|
||||
pub fn exec_py(code: &str) {
|
||||
if cfg!(windows) {
|
||||
pub fn exec_py(code: &str) -> Option<i32> {
|
||||
let mut child = if cfg!(windows) {
|
||||
Command::new(which_python())
|
||||
.arg("-c")
|
||||
.arg(code)
|
||||
.spawn()
|
||||
.expect("cannot execute python");
|
||||
.expect("cannot execute python")
|
||||
} else {
|
||||
let python_command = format!("{} -c \"{}\"", which_python(), code);
|
||||
Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(python_command)
|
||||
.spawn()
|
||||
.expect("cannot execute python");
|
||||
}
|
||||
.expect("cannot execute python")
|
||||
};
|
||||
child.wait().expect("python doesn't work").code()
|
||||
}
|
||||
|
|
|
@ -359,7 +359,7 @@ pub trait Runnable: Sized {
|
|||
fn finish(&mut self); // called when the :exit command is received.
|
||||
fn clear(&mut self);
|
||||
fn eval(&mut self, src: String) -> Result<String, Self::Errs>;
|
||||
fn exec(&mut self) -> Result<(), Self::Errs>;
|
||||
fn exec(&mut self) -> Result<i32, Self::Errs>;
|
||||
|
||||
fn input(&self) -> &Input {
|
||||
&self.cfg().input
|
||||
|
|
|
@ -45,12 +45,12 @@ impl Runnable for HIRBuilder {
|
|||
|
||||
fn clear(&mut self) {}
|
||||
|
||||
fn exec(&mut self) -> Result<(), Self::Errs> {
|
||||
fn exec(&mut self) -> Result<i32, Self::Errs> {
|
||||
let mut builder = ASTBuilder::new(self.cfg().copy());
|
||||
let ast = builder.build(self.input().read())?;
|
||||
let hir = self.check(ast, "exec").map_err(|(_, errs)| errs)?;
|
||||
println!("{hir}");
|
||||
Ok(())
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn eval(&mut self, src: String) -> Result<String, Self::Errs> {
|
||||
|
|
|
@ -129,9 +129,10 @@ impl Runnable for Compiler {
|
|||
self.code_generator.clear();
|
||||
}
|
||||
|
||||
fn exec(&mut self) -> Result<(), Self::Errs> {
|
||||
fn exec(&mut self) -> Result<i32, Self::Errs> {
|
||||
let path = self.input().filename().replace(".er", ".pyc");
|
||||
self.compile_and_dump_as_pyc(path, self.input().read(), "exec")
|
||||
self.compile_and_dump_as_pyc(path, self.input().read(), "exec")?;
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn eval(&mut self, src: String) -> Result<String, CompileErrors> {
|
||||
|
|
|
@ -888,7 +888,7 @@ impl Context {
|
|||
if mod_cache.get(&path).is_some() {
|
||||
return Ok(path);
|
||||
}
|
||||
let cfg = ErgConfig::with_path(path.clone());
|
||||
let cfg = ErgConfig::with_module_path(path.clone());
|
||||
let src = cfg.input.read();
|
||||
let mut builder =
|
||||
HIRBuilder::new_with_cache(cfg, __name__, mod_cache.clone(), py_mod_cache.clone());
|
||||
|
@ -986,7 +986,7 @@ impl Context {
|
|||
if py_mod_cache.get(&path).is_some() {
|
||||
return Ok(path);
|
||||
}
|
||||
let cfg = ErgConfig::with_path(path.clone());
|
||||
let cfg = ErgConfig::with_module_path(path.clone());
|
||||
let src = cfg.input.read();
|
||||
let mut builder =
|
||||
HIRBuilder::new_with_cache(cfg, __name__, py_mod_cache.clone(), py_mod_cache.clone());
|
||||
|
|
|
@ -82,7 +82,7 @@ impl Runnable for ASTLowerer {
|
|||
self.warns.clear();
|
||||
}
|
||||
|
||||
fn exec(&mut self) -> Result<(), Self::Errs> {
|
||||
fn exec(&mut self) -> Result<i32, Self::Errs> {
|
||||
let mut ast_builder = ASTBuilder::new(self.cfg.copy());
|
||||
let ast = ast_builder.build(self.input().read())?;
|
||||
let (hir, warns) = self.lower(ast, "exec").map_err(|(_, errs)| errs)?;
|
||||
|
@ -90,7 +90,7 @@ impl Runnable for ASTLowerer {
|
|||
warns.fmt_all_stderr();
|
||||
}
|
||||
println!("{hir}");
|
||||
Ok(())
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn eval(&mut self, src: String) -> Result<String, Self::Errs> {
|
||||
|
|
|
@ -37,13 +37,13 @@ impl Runnable for LexerRunner {
|
|||
#[inline]
|
||||
fn clear(&mut self) {}
|
||||
|
||||
fn exec(&mut self) -> Result<(), Self::Errs> {
|
||||
fn exec(&mut self) -> Result<i32, Self::Errs> {
|
||||
let lexer = Lexer::from_str(self.input().read());
|
||||
let ts = lexer
|
||||
.lex()
|
||||
.map_err(|errs| LexerRunnerErrors::convert(self.input(), errs))?;
|
||||
println!("{ts}");
|
||||
Ok(())
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn eval(&mut self, src: String) -> Result<String, LexerRunnerErrors> {
|
||||
|
|
|
@ -186,10 +186,10 @@ impl Runnable for ParserRunner {
|
|||
#[inline]
|
||||
fn clear(&mut self) {}
|
||||
|
||||
fn exec(&mut self) -> Result<(), Self::Errs> {
|
||||
fn exec(&mut self) -> Result<i32, Self::Errs> {
|
||||
let ast = self.parse(self.input().read())?;
|
||||
println!("{ast}");
|
||||
Ok(())
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn eval(&mut self, src: String) -> Result<String, ParserRunnerErrors> {
|
||||
|
|
19
src/dummy.rs
19
src/dummy.rs
|
@ -94,12 +94,21 @@ impl Runnable for DummyVM {
|
|||
self.compiler.clear();
|
||||
}
|
||||
|
||||
fn exec(&mut self) -> Result<(), Self::Errs> {
|
||||
fn exec(&mut self) -> Result<i32, Self::Errs> {
|
||||
// Parallel execution is not possible without dumping with a unique file name.
|
||||
let filename = self
|
||||
.cfg()
|
||||
.input
|
||||
.filename()
|
||||
.split('/')
|
||||
.last()
|
||||
.unwrap()
|
||||
.replace(".er", ".pyc");
|
||||
self.compiler
|
||||
.compile_and_dump_as_pyc("o.pyc", self.input().read(), "exec")?;
|
||||
exec_pyc("o.pyc");
|
||||
remove_file("o.pyc").unwrap();
|
||||
Ok(())
|
||||
.compile_and_dump_as_pyc(&filename, self.input().read(), "exec")?;
|
||||
let code = exec_pyc(&filename);
|
||||
remove_file(&filename).unwrap();
|
||||
Ok(code.unwrap_or(1))
|
||||
}
|
||||
|
||||
fn eval(&mut self, src: String) -> Result<String, EvalErrors> {
|
||||
|
|
|
@ -1,11 +1,93 @@
|
|||
extern crate erg;
|
||||
use std::path::PathBuf;
|
||||
|
||||
mod tests {
|
||||
/*
|
||||
use erg_common::config::{ErgConfig, Input};
|
||||
use erg_common::error::MultiErrorFmt;
|
||||
use erg_common::config::ErgConfig;
|
||||
use erg_common::error::MultiErrorDisplay;
|
||||
use erg_common::traits::Runnable;
|
||||
|
||||
const FILE3: &str = "tests/test3_object_system.er";
|
||||
*/
|
||||
use erg::dummy::DummyVM;
|
||||
|
||||
#[test]
|
||||
fn exec_class() -> Result<(), ()> {
|
||||
expect_success("examples/class.er")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_fib() -> Result<(), ()> {
|
||||
expect_success("examples/fib.er")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_hello_world() -> Result<(), ()> {
|
||||
expect_success("examples/helloworld.er")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_import() -> Result<(), ()> {
|
||||
expect_success("examples/import.er")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_move_check() -> Result<(), ()> {
|
||||
expect_failure("examples/move_check.er")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_record() -> Result<(), ()> {
|
||||
expect_success("examples/record.er")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_side_effect() -> Result<(), ()> {
|
||||
expect_failure("examples/side_effect.er")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_trait() -> Result<(), ()> {
|
||||
expect_success("examples/trait.er")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_tuple() -> Result<(), ()> {
|
||||
expect_success("examples/tuple.er")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_unpack() -> Result<(), ()> {
|
||||
expect_success("examples/unpack.er")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_use_py() -> Result<(), ()> {
|
||||
expect_success("examples/use_py.er")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exec_with() -> Result<(), ()> {
|
||||
expect_success("examples/with.er")
|
||||
}
|
||||
|
||||
fn expect_success(file_path: &'static str) -> Result<(), ()> {
|
||||
let cfg = ErgConfig::with_main_path(PathBuf::from(file_path));
|
||||
let mut vm = DummyVM::new(cfg);
|
||||
match vm.exec() {
|
||||
Ok(0) => Ok(()),
|
||||
Ok(_) => Err(()),
|
||||
Err(errs) => {
|
||||
errs.fmt_all_stderr();
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn expect_failure(file_path: &'static str) -> Result<(), ()> {
|
||||
let cfg = ErgConfig::with_main_path(PathBuf::from(file_path));
|
||||
let mut vm = DummyVM::new(cfg);
|
||||
match vm.exec() {
|
||||
Ok(0) => Err(()),
|
||||
Ok(_) => Ok(()),
|
||||
Err(errs) => {
|
||||
errs.fmt_all_stderr();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue