This commit is contained in:
Shunsuke Shibayama 2022-09-14 12:47:46 +09:00
commit e1be2d2b51
8 changed files with 33 additions and 41 deletions

View file

@ -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;
} }
} }

View file

@ -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))
} }

View file

@ -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();

View file

@ -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);

View file

@ -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))?;

View file

@ -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(),

View file

@ -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))?;

View file

@ -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()) {