This commit is contained in:
Shunsuke Shibayama 2023-07-26 01:19:48 +09:00
parent ada421cd5c
commit 3fc42f65e8
4 changed files with 59 additions and 19 deletions

View file

@ -3,9 +3,10 @@
//! CPythonを呼び出すためのユーティリティー
use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::process::{Command, ExitStatus, Stdio};
use crate::fn_name_full;
use crate::io::Output;
use crate::pathutil::remove_verbatim;
use crate::serialize::get_magic_num_from_bytes;
@ -849,3 +850,23 @@ pub fn spawn_py(py_command: Option<&str>, code: &str) {
.expect("cannot execute python");
}
}
pub fn exec_py_code(code: &str, output: Output) -> std::io::Result<ExitStatus> {
let mut out = if cfg!(windows) {
Command::new(which_python())
.arg("-c")
.arg(code)
.stdout(output)
.spawn()
.expect("cannot execute python")
} else {
let exec_command = format!("{} -c \"{code}\"", which_python());
Command::new("sh")
.arg("-c")
.arg(exec_command)
.stdout(output)
.spawn()
.expect("cannot execute python")
};
out.wait()
}

View file

@ -226,6 +226,20 @@ impl Compiler {
Ok(CompleteArtifact::new(last, arti.warns))
}
pub fn exec_compile(
&mut self,
src: String,
mode: &str,
) -> Result<CompleteArtifact<ExitStatus>, ErrorArtifact> {
let arti = self.compile(src, mode)?;
let stat = arti
.object
.exec(self.cfg.py_magic_num, self.cfg.output.clone())
.expect("failed to dump a .pyc file (maybe permission denied)");
let stat = ExitStatus::new(stat.code().unwrap_or(0), arti.warns.len(), 0);
Ok(CompleteArtifact::new(stat, arti.warns))
}
pub fn compile(
&mut self,
src: String,

View file

@ -3,8 +3,10 @@ use std::fmt::Write as _;
use std::fs::File;
use std::io::{BufReader, Read, Write as _};
use std::path::Path;
use std::process::ExitStatus;
use erg_common::impl_display_from_debug;
use erg_common::io::Output;
#[allow(unused_imports)]
use erg_common::log;
use erg_common::opcode::CommonOpcode;
@ -12,7 +14,7 @@ use erg_common::opcode308::Opcode308;
use erg_common::opcode309::Opcode309;
use erg_common::opcode310::Opcode310;
use erg_common::opcode311::{BinOpCode, Opcode311};
use erg_common::python_util::{env_magic_number, PythonVersion};
use erg_common::python_util::{env_magic_number, exec_py_code, PythonVersion};
use erg_common::serialize::*;
use erg_common::Str;
@ -439,6 +441,19 @@ impl CodeObj {
Ok(())
}
pub fn exec(self, py_magic_num: Option<u32>, output: Output) -> std::io::Result<ExitStatus> {
let mut bytes = Vec::with_capacity(16);
let py_magic_num = py_magic_num.unwrap_or_else(env_magic_number);
let python_ver = get_ver_from_magic_num(py_magic_num);
bytes.append(&mut self.into_bytes(python_ver));
let mut bytecode = "".to_string();
for b in bytes {
write!(bytecode, "\\x{b:0>2x}").unwrap();
}
let code = format!("import marshal; exec(marshal.loads(b'{bytecode}'))");
exec_py_code(&code, output)
}
fn tables_info(&self) -> String {
let mut tables = "".to_string();
if !self.consts.is_empty() {

View file

@ -281,24 +281,14 @@ impl Runnable for DummyVM {
fn exec(&mut self) -> Result<ExitStatus, Self::Errs> {
// Parallel execution is not possible without dumping with a unique file name.
let filename = self.cfg().dump_pyc_filename();
// let filename = self.cfg().dump_pyc_filename();
let src = self.cfg_mut().input.read();
let warns = self
.compiler
.compile_and_dump_as_pyc(&filename, src, "exec")
.map_err(|eart| {
eart.warns.write_all_to(&mut self.cfg_mut().output);
eart.errors
})?;
warns.write_all_to(&mut self.cfg_mut().output);
let code = exec_pyc(
&filename,
self.cfg().py_command,
&self.cfg().runtime_args,
self.cfg().output.clone(),
);
remove_file(&filename).unwrap();
Ok(ExitStatus::new(code.unwrap_or(1), warns.len(), 0))
let art = self.compiler.exec_compile(src, "exec").map_err(|eart| {
eart.warns.write_all_to(&mut self.cfg_mut().output);
eart.errors
})?;
art.warns.write_all_to(&mut self.cfg_mut().output);
Ok(art.object)
}
fn eval(&mut self, src: String) -> Result<String, EvalErrors> {