mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Merge branch 'main' of https://github.com/erg-lang/erg
This commit is contained in:
commit
e1be2d2b51
8 changed files with 33 additions and 41 deletions
|
@ -7,7 +7,6 @@ use std::io::{stdin, BufRead, BufReader, Read};
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
use crate::stdin::GLOBAL_STDIN;
|
use crate::stdin::GLOBAL_STDIN;
|
||||||
use crate::Str;
|
|
||||||
use crate::{power_assert, read_file};
|
use crate::{power_assert, read_file};
|
||||||
|
|
||||||
pub const SEMVER: &str = env!("CARGO_PKG_VERSION");
|
pub const SEMVER: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
@ -19,12 +18,12 @@ pub const BUILD_DATE: &str = env!("BUILD_DATE");
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum Input {
|
pub enum Input {
|
||||||
/// filename
|
/// filename
|
||||||
File(Str),
|
File(String),
|
||||||
REPL,
|
REPL,
|
||||||
/// same content as cfg.command
|
/// same content as cfg.command
|
||||||
Pipe(Str),
|
Pipe(String),
|
||||||
/// from command option | eval
|
/// from command option | eval
|
||||||
Str(Str),
|
Str(String),
|
||||||
Dummy,
|
Dummy,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +51,7 @@ impl Input {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(&self) -> Str {
|
pub fn read(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Self::File(filename) => {
|
Self::File(filename) => {
|
||||||
let file = match File::open(&filename[..]) {
|
let file = match File::open(&filename[..]) {
|
||||||
|
@ -63,15 +62,14 @@ impl Input {
|
||||||
process::exit(code);
|
process::exit(code);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let src = match read_file(file) {
|
match read_file(file) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let code = e.raw_os_error().unwrap_or(1);
|
let code = e.raw_os_error().unwrap_or(1);
|
||||||
println!("cannot read '{filename}': [Errno {code}] {e}");
|
println!("cannot read '{filename}': [Errno {code}] {e}");
|
||||||
process::exit(code);
|
process::exit(code);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
Str::from(src)
|
|
||||||
}
|
}
|
||||||
Self::Pipe(s) | Self::Str(s) => s.clone(),
|
Self::Pipe(s) | Self::Str(s) => s.clone(),
|
||||||
Self::REPL => GLOBAL_STDIN.read(),
|
Self::REPL => GLOBAL_STDIN.read(),
|
||||||
|
@ -79,7 +77,7 @@ impl Input {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reread_lines(&self, ln_begin: usize, ln_end: usize) -> Vec<Str> {
|
pub fn reread_lines(&self, ln_begin: usize, ln_end: usize) -> Vec<String> {
|
||||||
power_assert!(ln_begin, >=, 1);
|
power_assert!(ln_begin, >=, 1);
|
||||||
match self {
|
match self {
|
||||||
Self::File(filename) => match File::open(&filename[..]) {
|
Self::File(filename) => match File::open(&filename[..]) {
|
||||||
|
@ -87,7 +85,7 @@ impl Input {
|
||||||
let mut codes = vec![];
|
let mut codes = vec![];
|
||||||
let mut lines = BufReader::new(file).lines().skip(ln_begin - 1);
|
let mut lines = BufReader::new(file).lines().skip(ln_begin - 1);
|
||||||
for _ in ln_begin..=ln_end {
|
for _ in ln_begin..=ln_end {
|
||||||
codes.push(Str::from(lines.next().unwrap().unwrap()));
|
codes.push(lines.next().unwrap().unwrap());
|
||||||
}
|
}
|
||||||
codes
|
codes
|
||||||
}
|
}
|
||||||
|
@ -96,18 +94,18 @@ impl Input {
|
||||||
Self::Pipe(s) | Self::Str(s) => s.split('\n').collect::<Vec<_>>()
|
Self::Pipe(s) | Self::Str(s) => s.split('\n').collect::<Vec<_>>()
|
||||||
[ln_begin - 1..=ln_end - 1]
|
[ln_begin - 1..=ln_end - 1]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| Str::rc(*s))
|
.map(|s| s.to_string())
|
||||||
.collect(),
|
.collect(),
|
||||||
Self::REPL => GLOBAL_STDIN.reread_lines(ln_begin, ln_end),
|
Self::REPL => GLOBAL_STDIN.reread_lines(ln_begin, ln_end),
|
||||||
Self::Dummy => panic!("cannot read lines from a dummy file"),
|
Self::Dummy => panic!("cannot read lines from a dummy file"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reread(&self) -> Str {
|
pub fn reread(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Self::File(_filename) => todo!(),
|
Self::File(_filename) => todo!(),
|
||||||
Self::Pipe(s) | Self::Str(s) => s.clone(),
|
Self::Pipe(s) | Self::Str(s) => s.clone(),
|
||||||
Self::REPL => Str::from(GLOBAL_STDIN.reread().trim_end().to_owned()),
|
Self::REPL => GLOBAL_STDIN.reread().trim_end().to_owned(),
|
||||||
Self::Dummy => panic!("cannot read from a dummy file"),
|
Self::Dummy => panic!("cannot read from a dummy file"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,7 +140,7 @@ impl Default for ErgConfig {
|
||||||
let input = if is_stdin_piped {
|
let input = if is_stdin_piped {
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
stdin().read_to_string(&mut buffer).unwrap();
|
stdin().read_to_string(&mut buffer).unwrap();
|
||||||
Input::Pipe(Str::from(buffer))
|
Input::Pipe(buffer)
|
||||||
} else {
|
} else {
|
||||||
Input::REPL
|
Input::REPL
|
||||||
};
|
};
|
||||||
|
@ -174,7 +172,7 @@ impl ErgConfig {
|
||||||
while let Some(arg) = args.next() {
|
while let Some(arg) = args.next() {
|
||||||
match &arg[..] {
|
match &arg[..] {
|
||||||
"-c" => {
|
"-c" => {
|
||||||
cfg.input = Input::Str(Str::from(args.next().unwrap()));
|
cfg.input = Input::Str(args.next().unwrap());
|
||||||
}
|
}
|
||||||
"--dump-as-pyc" => {
|
"--dump-as-pyc" => {
|
||||||
cfg.dump_as_pyc = true;
|
cfg.dump_as_pyc = true;
|
||||||
|
@ -223,7 +221,7 @@ impl ErgConfig {
|
||||||
panic!("invalid option: {other}");
|
panic!("invalid option: {other}");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
cfg.input = Input::File(Str::from(arg));
|
cfg.input = Input::File(arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,29 +2,27 @@ use std::cell::RefCell;
|
||||||
use std::io::{stdin, BufRead, BufReader};
|
use std::io::{stdin, BufRead, BufReader};
|
||||||
use std::thread::LocalKey;
|
use std::thread::LocalKey;
|
||||||
|
|
||||||
use crate::Str;
|
|
||||||
|
|
||||||
pub struct StdinReader {
|
pub struct StdinReader {
|
||||||
pub lineno: usize,
|
pub lineno: usize,
|
||||||
buf: Vec<Str>,
|
buf: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StdinReader {
|
impl StdinReader {
|
||||||
pub fn read(&mut self) -> Str {
|
pub fn read(&mut self) -> String {
|
||||||
let mut buf = "".to_string();
|
let mut buf = "".to_string();
|
||||||
let stdin = stdin();
|
let stdin = stdin();
|
||||||
let mut reader = BufReader::new(stdin.lock());
|
let mut reader = BufReader::new(stdin.lock());
|
||||||
reader.read_line(&mut buf).unwrap();
|
reader.read_line(&mut buf).unwrap();
|
||||||
self.lineno += 1;
|
self.lineno += 1;
|
||||||
self.buf.push(buf.into());
|
self.buf.push(buf);
|
||||||
self.buf.last().unwrap().clone()
|
self.buf.last().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reread(&self) -> Str {
|
pub fn reread(&self) -> String {
|
||||||
self.buf.last().unwrap().clone()
|
self.buf.last().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reread_lines(&self, ln_begin: usize, ln_end: usize) -> Vec<Str> {
|
pub fn reread_lines(&self, ln_begin: usize, ln_end: usize) -> Vec<String> {
|
||||||
self.buf[ln_begin - 1..=ln_end - 1].to_vec()
|
self.buf[ln_begin - 1..=ln_end - 1].to_vec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,15 +37,15 @@ pub struct GlobalStdin(LocalKey<RefCell<StdinReader>>);
|
||||||
pub static GLOBAL_STDIN: GlobalStdin = GlobalStdin(READER);
|
pub static GLOBAL_STDIN: GlobalStdin = GlobalStdin(READER);
|
||||||
|
|
||||||
impl GlobalStdin {
|
impl GlobalStdin {
|
||||||
pub fn read(&'static self) -> Str {
|
pub fn read(&'static self) -> String {
|
||||||
self.0.with(|s| s.borrow_mut().read())
|
self.0.with(|s| s.borrow_mut().read())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reread(&'static self) -> Str {
|
pub fn reread(&'static self) -> String {
|
||||||
self.0.with(|s| s.borrow().reread())
|
self.0.with(|s| s.borrow().reread())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reread_lines(&'static self, ln_begin: usize, ln_end: usize) -> Vec<Str> {
|
pub fn reread_lines(&'static self, ln_begin: usize, ln_end: usize) -> Vec<String> {
|
||||||
self.0
|
self.0
|
||||||
.with(|s| s.borrow_mut().reread_lines(ln_begin, ln_end))
|
.with(|s| s.borrow_mut().reread_lines(ln_begin, ln_end))
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ use std::vec::IntoIter;
|
||||||
|
|
||||||
use crate::config::{ErgConfig, Input, BUILD_DATE, GIT_HASH_SHORT, SEMVER};
|
use crate::config::{ErgConfig, Input, BUILD_DATE, GIT_HASH_SHORT, SEMVER};
|
||||||
use crate::error::{ErrorDisplay, ErrorKind, Location, MultiErrorDisplay};
|
use crate::error::{ErrorDisplay, ErrorKind, Location, MultiErrorDisplay};
|
||||||
use crate::Str;
|
|
||||||
use crate::{addr_eq, chomp, log, switch_unreachable};
|
use crate::{addr_eq, chomp, log, switch_unreachable};
|
||||||
|
|
||||||
pub trait Stream<T>: Sized {
|
pub trait Stream<T>: Sized {
|
||||||
|
@ -334,7 +333,7 @@ pub trait Runnable: Sized {
|
||||||
}
|
}
|
||||||
fn finish(&mut self); // called when the :exit command is received.
|
fn finish(&mut self); // called when the :exit command is received.
|
||||||
fn clear(&mut self);
|
fn clear(&mut self);
|
||||||
fn eval(&mut self, src: Str) -> Result<String, Self::Errs>;
|
fn eval(&mut self, src: String) -> Result<String, Self::Errs>;
|
||||||
fn exec(&mut self) -> Result<(), Self::Errs>;
|
fn exec(&mut self) -> Result<(), Self::Errs>;
|
||||||
|
|
||||||
fn ps1(&self) -> String {
|
fn ps1(&self) -> String {
|
||||||
|
@ -395,7 +394,7 @@ pub trait Runnable: Sized {
|
||||||
output.flush().unwrap();
|
output.flush().unwrap();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
match instance.eval(mem::take(&mut lines).into()) {
|
match instance.eval(mem::take(&mut lines)) {
|
||||||
Ok(out) => {
|
Ok(out) => {
|
||||||
output.write_all((out + "\n").as_bytes()).unwrap();
|
output.write_all((out + "\n").as_bytes()).unwrap();
|
||||||
output.flush().unwrap();
|
output.flush().unwrap();
|
||||||
|
|
|
@ -7,7 +7,6 @@ use erg_common::config::{ErgConfig, Input};
|
||||||
use erg_common::error::MultiErrorDisplay;
|
use erg_common::error::MultiErrorDisplay;
|
||||||
use erg_common::log;
|
use erg_common::log;
|
||||||
use erg_common::traits::{Runnable, Stream};
|
use erg_common::traits::{Runnable, Stream};
|
||||||
use erg_common::Str;
|
|
||||||
use erg_type::codeobj::CodeObj;
|
use erg_type::codeobj::CodeObj;
|
||||||
|
|
||||||
use erg_parser::ParserRunner;
|
use erg_parser::ParserRunner;
|
||||||
|
@ -134,7 +133,7 @@ impl Runnable for Compiler {
|
||||||
self.compile_and_dump_as_pyc(src, path, "exec")
|
self.compile_and_dump_as_pyc(src, path, "exec")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval(&mut self, src: Str) -> Result<String, CompileErrors> {
|
fn eval(&mut self, src: String) -> Result<String, CompileErrors> {
|
||||||
let codeobj = self.compile(src, "eval")?;
|
let codeobj = self.compile(src, "eval")?;
|
||||||
Ok(codeobj.code_info())
|
Ok(codeobj.code_info())
|
||||||
}
|
}
|
||||||
|
@ -150,7 +149,7 @@ impl Compiler {
|
||||||
|
|
||||||
pub fn compile_and_dump_as_pyc<P: AsRef<Path>>(
|
pub fn compile_and_dump_as_pyc<P: AsRef<Path>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
src: Str,
|
src: String,
|
||||||
path: P,
|
path: P,
|
||||||
mode: &str,
|
mode: &str,
|
||||||
) -> Result<(), CompileErrors> {
|
) -> Result<(), CompileErrors> {
|
||||||
|
@ -160,7 +159,7 @@ impl Compiler {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compile(&mut self, src: Str, mode: &str) -> Result<CodeObj, CompileErrors> {
|
pub fn compile(&mut self, src: String, mode: &str) -> Result<CodeObj, CompileErrors> {
|
||||||
log!(info "the compiling process has started.");
|
log!(info "the compiling process has started.");
|
||||||
let mut cfg = self.cfg.copy();
|
let mut cfg = self.cfg.copy();
|
||||||
cfg.input = Input::Str(src);
|
cfg.input = Input::Str(src);
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl Runnable for ASTLowererRunner {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval(&mut self, src: Str) -> Result<String, CompileErrors> {
|
fn eval(&mut self, src: String) -> Result<String, CompileErrors> {
|
||||||
let ts = Lexer::new(Input::Str(src))
|
let ts = Lexer::new(Input::Str(src))
|
||||||
.lex()
|
.lex()
|
||||||
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
|
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
|
||||||
|
|
|
@ -5,7 +5,6 @@ use erg_common::cache::CacheSet;
|
||||||
use erg_common::config::ErgConfig;
|
use erg_common::config::ErgConfig;
|
||||||
use erg_common::config::Input;
|
use erg_common::config::Input;
|
||||||
use erg_common::traits::{Locational, Runnable, Stream};
|
use erg_common::traits::{Locational, Runnable, Stream};
|
||||||
use erg_common::Str;
|
|
||||||
use erg_common::{debug_power_assert, fn_name_full, normalize_newline, switch_lang};
|
use erg_common::{debug_power_assert, fn_name_full, normalize_newline, switch_lang};
|
||||||
|
|
||||||
use crate::error::{LexError, LexErrors, LexResult, LexerRunnerError, LexerRunnerErrors};
|
use crate::error::{LexError, LexErrors, LexResult, LexerRunnerError, LexerRunnerErrors};
|
||||||
|
@ -47,7 +46,7 @@ impl Runnable for LexerRunner {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval(&mut self, src: Str) -> Result<String, LexerRunnerErrors> {
|
fn eval(&mut self, src: String) -> Result<String, LexerRunnerErrors> {
|
||||||
let lexer = Lexer::from_str(src);
|
let lexer = Lexer::from_str(src);
|
||||||
if cfg!(feature = "debug") {
|
if cfg!(feature = "debug") {
|
||||||
let ts = lexer
|
let ts = lexer
|
||||||
|
@ -97,7 +96,7 @@ impl Lexer /*<'a>*/ {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::should_implement_trait)]
|
#[allow(clippy::should_implement_trait)]
|
||||||
pub fn from_str(src: Str) -> Self {
|
pub fn from_str(src: String) -> Self {
|
||||||
let escaped = normalize_newline(&src);
|
let escaped = normalize_newline(&src);
|
||||||
Lexer {
|
Lexer {
|
||||||
str_cache: CacheSet::new(),
|
str_cache: CacheSet::new(),
|
||||||
|
|
|
@ -194,7 +194,7 @@ impl Runnable for ParserRunner {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval(&mut self, src: Str) -> Result<String, ParserRunnerErrors> {
|
fn eval(&mut self, src: String) -> Result<String, ParserRunnerErrors> {
|
||||||
let ast = self.parse_with_input(src)?;
|
let ast = self.parse_with_input(src)?;
|
||||||
Ok(format!("{ast}"))
|
Ok(format!("{ast}"))
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ impl ParserRunner {
|
||||||
self_.parse()
|
self_.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_with_input(&mut self, src: Str) -> Result<AST, ParserRunnerErrors> {
|
fn parse_with_input(&mut self, src: String) -> Result<AST, ParserRunnerErrors> {
|
||||||
let ts = Lexer::new(Input::Str(src))
|
let ts = Lexer::new(Input::Str(src))
|
||||||
.lex()
|
.lex()
|
||||||
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
|
.map_err(|errs| ParserRunnerErrors::convert(self.input(), errs))?;
|
||||||
|
|
|
@ -6,7 +6,6 @@ use std::time::Duration;
|
||||||
|
|
||||||
use erg_common::config::{ErgConfig, Input};
|
use erg_common::config::{ErgConfig, Input};
|
||||||
use erg_common::python_util::{exec_py, exec_pyc};
|
use erg_common::python_util::{exec_py, exec_pyc};
|
||||||
use erg_common::str::Str;
|
|
||||||
use erg_common::traits::Runnable;
|
use erg_common::traits::Runnable;
|
||||||
|
|
||||||
use erg_compiler::error::{CompileError, CompileErrors};
|
use erg_compiler::error::{CompileError, CompileErrors};
|
||||||
|
@ -100,7 +99,7 @@ impl Runnable for DummyVM {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval(&mut self, src: Str) -> Result<String, EvalErrors> {
|
fn eval(&mut self, src: String) -> Result<String, EvalErrors> {
|
||||||
self.compiler
|
self.compiler
|
||||||
.compile_and_dump_as_pyc(src, "o.pyc", "eval")?;
|
.compile_and_dump_as_pyc(src, "o.pyc", "eval")?;
|
||||||
let mut res = match self.stream.as_mut().unwrap().write("load".as_bytes()) {
|
let mut res = match self.stream.as_mut().unwrap().write("load".as_bytes()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue