fixed warnings, cargo clippy, and mers-nu

This commit is contained in:
mark 2023-06-06 15:22:45 +02:00
parent 50e11dc967
commit 46dbb13e0f
19 changed files with 280 additions and 259 deletions

1
args.mers Normal file
View File

@ -0,0 +1 @@
args.debug()

View File

@ -1,12 +1,9 @@
use std::{ use std::io::{Stdin, StdinLock, Write};
collections::HashMap,
io::{BufRead, Stdin, StdinLock, Stdout, StdoutLock, Write},
};
use crate::lang::{val_data::VData, val_type::VType}; use crate::lang::val_type::VType;
use super::{ use super::libs::{
comms::{self, ByteData, ByteDataA, Message, MessageResponse, RespondableMessage}, comms::{self, ByteData, ByteDataA, Message, RespondableMessage},
LibInitInfo, LibInitReq, LibInitInfo, LibInitReq,
}; };
@ -18,6 +15,7 @@ pub struct MyLib {
pub callbacks: Callbacks, pub callbacks: Callbacks,
enum_variants: Vec<(String, usize)>, enum_variants: Vec<(String, usize)>,
stdin: StdinLock<'static>, stdin: StdinLock<'static>,
#[allow(unused)]
stdin_no_lock: Stdin, stdin_no_lock: Stdin,
} }
impl MyLib { impl MyLib {
@ -32,12 +30,14 @@ impl MyLib {
let mut stdout = stdout_no_lock.lock(); let mut stdout = stdout_no_lock.lock();
let mut stdin = stdin_no_lock.lock(); let mut stdin = stdin_no_lock.lock();
// comms version // comms version
stdout.write(1u128.as_byte_data_vec().as_slice()).unwrap(); stdout
.write_all(1u128.as_byte_data_vec().as_slice())
.unwrap();
let init_req: LibInitReq = (version.0, version.1, name, description, functions); let init_req: LibInitReq = (version.0, version.1, name, description, functions);
stdout stdout
.write(init_req.as_byte_data_vec().as_slice()) .write_all(init_req.as_byte_data_vec().as_slice())
.unwrap(); .unwrap();
stdout.flush(); stdout.flush().unwrap();
let enum_variants = LibInitInfo::from_byte_data(&mut stdin).unwrap(); let enum_variants = LibInitInfo::from_byte_data(&mut stdin).unwrap();
Self { Self {
// name: name.clone(), // name: name.clone(),
@ -56,10 +56,13 @@ impl MyLib {
fn get_one_msg(&mut self) -> Result<Result<(), Message>, std::io::Error> { fn get_one_msg(&mut self) -> Result<Result<(), Message>, std::io::Error> {
let id = u128::from_byte_data(&mut self.stdin)?; let id = u128::from_byte_data(&mut self.stdin)?;
let message = Message::from_byte_data(&mut self.stdin)?; let message = Message::from_byte_data(&mut self.stdin)?;
match message { Ok(match message {
Message::RunFunction(msg) => self.callbacks.run_function.run(Respondable::new(id, msg)), Message::RunFunction(msg) => self
}; .callbacks
Ok(Ok(())) .run_function
.run(Respondable::new(id, msg))
.map_err(|e| Message::RunFunction(e.msg)),
})
} }
pub fn get_next_unhandled_message(&mut self) -> Result<(), Message> { pub fn get_next_unhandled_message(&mut self) -> Result<(), Message> {
loop { loop {
@ -68,7 +71,7 @@ impl MyLib {
// unhandled message. return it to be handeled or included in the error // unhandled message. return it to be handeled or included in the error
Ok(Err(msg)) => return Err(msg), Ok(Err(msg)) => return Err(msg),
// i/o error, probably because mers exited. return successfully. // i/o error, probably because mers exited. return successfully.
Err(e) => return Ok(()), Err(_e) => return Ok(()),
} }
} }
} }
@ -89,9 +92,9 @@ where
{ {
pub fn respond(self, with: M::With) { pub fn respond(self, with: M::With) {
let mut stdout = std::io::stdout().lock(); let mut stdout = std::io::stdout().lock();
stdout.write(&self.id.as_byte_data_vec()).unwrap(); stdout.write_all(&self.id.as_byte_data_vec()).unwrap();
stdout stdout
.write(&self.msg.respond(with).as_byte_data_vec()) .write_all(&self.msg.respond(with).as_byte_data_vec())
.unwrap(); .unwrap();
stdout.flush().unwrap(); stdout.flush().unwrap();
} }
@ -117,14 +120,14 @@ impl Callbacks {
} }
pub struct Callback<M> pub struct Callback<M>
where where
M: super::comms::RespondableMessage, M: RespondableMessage,
{ {
pub nonconsuming: Vec<Box<dyn FnMut(&M)>>, pub nonconsuming: Vec<Box<dyn FnMut(&M)>>,
pub consuming: Option<Box<dyn FnMut(Respondable<M>)>>, pub consuming: Option<Box<dyn FnMut(Respondable<M>)>>,
} }
impl<M> Callback<M> impl<M> Callback<M>
where where
M: super::comms::RespondableMessage, M: RespondableMessage,
{ {
pub fn empty() -> Self { pub fn empty() -> Self {
Self { Self {

View File

@ -1,11 +1,4 @@
use std::{ use std::{io::Write, path::PathBuf, sync::Arc, time::Duration};
io::Write,
path::PathBuf,
sync::{Arc, Mutex},
time::Duration,
};
use crate::libs;
use super::{ use super::{
code_runnable::RStatement, code_runnable::RStatement,
@ -42,6 +35,7 @@ pub enum BuiltinFunction {
Run, Run,
Thread, Thread,
Await, Await,
TryAwait,
Sleep, Sleep,
Exit, Exit,
// FS // FS
@ -109,6 +103,7 @@ impl BuiltinFunction {
"run" => Self::Run, "run" => Self::Run,
"thread" => Self::Thread, "thread" => Self::Thread,
"await" => Self::Await, "await" => Self::Await,
"try_await" => Self::TryAwait,
"sleep" => Self::Sleep, "sleep" => Self::Sleep,
"exit" => Self::Exit, "exit" => Self::Exit,
// "command" => Self::Command, // "command" => Self::Command,
@ -271,7 +266,7 @@ impl BuiltinFunction {
false false
} }
} }
Self::Await => { Self::Await | Self::TryAwait => {
input.len() == 1 input.len() == 1
&& input[0] && input[0]
.types .types
@ -594,7 +589,7 @@ impl BuiltinFunction {
unreachable!("run or thread called without args") unreachable!("run or thread called without args")
} }
} }
Self::Await => { Self::Await | Self::TryAwait => {
if let Some(v) = input.first() { if let Some(v) = input.first() {
let mut out = VType { types: vec![] }; let mut out = VType { types: vec![] };
for v in &v.types { for v in &v.types {
@ -604,7 +599,13 @@ impl BuiltinFunction {
unreachable!("await called with non-thread arg") unreachable!("await called with non-thread arg")
} }
} }
out if let Self::TryAwait = self {
let mut o = VSingleType::Tuple(vec![out]).to();
o.add_type(VSingleType::Tuple(vec![]), info);
o
} else {
out
}
} else { } else {
unreachable!("await called without args") unreachable!("await called without args")
} }
@ -795,7 +796,7 @@ impl BuiltinFunction {
pub fn run(&self, args: &Vec<RStatement>, info: &GSInfo) -> VData { pub fn run(&self, args: &Vec<RStatement>, info: &GSInfo) -> VData {
match self { match self {
Self::Assume1 => { Self::Assume1 => {
let mut a0 = args[0].run(info); let a0 = args[0].run(info);
match a0.operate_on_data_immut(|v| { match a0.operate_on_data_immut(|v| {
if let VDataEnum::Tuple(v) = v { if let VDataEnum::Tuple(v) = v {
if let Some(v) = v.get(0) { if let Some(v) = v.get(0) {
@ -877,12 +878,12 @@ impl BuiltinFunction {
#[cfg(not(feature = "nushell_plugin"))] #[cfg(not(feature = "nushell_plugin"))]
{ {
print!("{}", arg); print!("{}", arg);
std::io::stdout().flush(); _ = std::io::stdout().flush();
} }
#[cfg(feature = "nushell_plugin")] #[cfg(feature = "nushell_plugin")]
{ {
eprint!("{}", arg); eprint!("{}", arg);
std::io::stderr().flush(); _ = std::io::stderr().flush();
} }
VDataEnum::Tuple(vec![]).to() VDataEnum::Tuple(vec![]).to()
} else { } else {
@ -991,7 +992,7 @@ impl BuiltinFunction {
var.lock().unwrap().0 = val; var.lock().unwrap().0 = val;
} }
let out_type = f let out_type = f
.out( .out_by_map(
&run_input_types.iter().map(|v| v.clone().into()).collect(), &run_input_types.iter().map(|v| v.clone().into()).collect(),
&info, &info,
) )
@ -1014,6 +1015,18 @@ impl BuiltinFunction {
unreachable!() unreachable!()
} }
}), }),
BuiltinFunction::TryAwait => args[0].run(info).operate_on_data_immut(|v| {
if let VDataEnum::Thread(t, _) = v {
if let Some(v) = t.try_get() {
VDataEnum::Tuple(vec![v])
} else {
VDataEnum::Tuple(vec![])
}
.to()
} else {
unreachable!()
}
}),
BuiltinFunction::Sleep => args[0].run(info).operate_on_data_immut(|v| { BuiltinFunction::Sleep => args[0].run(info).operate_on_data_immut(|v| {
match v { match v {
VDataEnum::Int(v) => std::thread::sleep(Duration::from_secs(*v as _)), VDataEnum::Int(v) => std::thread::sleep(Duration::from_secs(*v as _)),

View File

@ -5,7 +5,9 @@ use crate::parsing::{
parse::{self, ParseError, ScriptError}, parse::{self, ParseError, ScriptError},
}; };
use super::{code_parsed::SStatement, code_runnable::RScript, val_data::VData, val_type::VType}; use crate::lang::val_data::VDataEnum;
use super::{code_runnable::RScript, val_data::VData};
// macro format is !(macro_type [...]) // macro format is !(macro_type [...])
@ -30,7 +32,11 @@ pub fn parse_macro(file: &mut File) -> Result<Macro, MacroError> {
} }
args.push(parse_string_val(file)); args.push(parse_string_val(file));
} }
let val = code.run(args); let val = code.run(
args.into_iter()
.map(|v| VDataEnum::String(v).to())
.collect(),
);
if val.safe_to_share() { if val.safe_to_share() {
val val
} else { } else {
@ -57,7 +63,7 @@ fn parse_mers_code(file: &mut File) -> Result<RScript, MacroError> {
let path = parse_string_val(file); let path = parse_string_val(file);
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
eprintln!("macro: mers: path: {path}"); eprintln!("macro: mers: path: {path}");
let path = crate::libs::path::path_from_string(path.as_str(), file.path()) let path = crate::pathutil::path_from_string(path.as_str(), file.path(), false)
.expect("can't include mers code because no file was found at that path"); .expect("can't include mers code because no file was found at that path");
let mut file = File::new( let mut file = File::new(
fs::read_to_string(&path) fs::read_to_string(&path)

View File

@ -1,6 +1,4 @@
use std::fmt::{self, Display, Formatter, Pointer}; use std::fmt::{self, Display, Formatter};
use crate::lang::global_info::ColorFormatMode;
use super::{ use super::{
code_macro::Macro, fmtgs::FormatGs, global_info::GlobalScriptInfo, val_data::VData, code_macro::Macro, fmtgs::FormatGs, global_info::GlobalScriptInfo, val_data::VData,
@ -61,11 +59,6 @@ impl SStatement {
self.output_to = Some((Box::new(statement), true)); self.output_to = Some((Box::new(statement), true));
self self
} }
// forces the statement's output to fit in a certain type.
pub fn force_output_type(mut self, force_output_type: Option<VType>) -> Self {
self.force_output_type = force_output_type;
self
}
} }
/// A block of code is a collection of statements. /// A block of code is a collection of statements.
@ -115,7 +108,7 @@ impl FormatGs for SStatementEnum {
} }
Self::List(v) => { Self::List(v) => {
write!(f, "{}", form.open_bracket(info, "[".to_owned()))?; write!(f, "{}", form.open_bracket(info, "[".to_owned()))?;
for (i, v) in v.iter().enumerate() { for (_i, v) in v.iter().enumerate() {
v.fmtgs(f, info, form, file)?; v.fmtgs(f, info, form, file)?;
write!(f, " ")?; write!(f, " ")?;
} }
@ -136,7 +129,7 @@ impl FormatGs for SStatementEnum {
)?; )?;
for (i, arg) in args.iter().enumerate() { for (i, arg) in args.iter().enumerate() {
if i != 0 { if i != 0 {
write!(f, " "); write!(f, " ")?;
} }
arg.fmtgs(f, info, form, file)?; arg.fmtgs(f, info, form, file)?;
} }

View File

@ -1,8 +1,4 @@
use std::{ use std::sync::{Arc, Mutex};
assert_eq, eprintln,
ops::Deref,
sync::{Arc, Mutex},
};
use super::{ use super::{
builtins::BuiltinFunction, builtins::BuiltinFunction,
@ -66,7 +62,7 @@ pub struct RFunction {
pub out_map: Vec<(Vec<VType>, VType)>, pub out_map: Vec<(Vec<VType>, VType)>,
} }
impl PartialEq for RFunction { impl PartialEq for RFunction {
fn eq(&self, other: &Self) -> bool { fn eq(&self, _other: &Self) -> bool {
false false
} }
} }
@ -77,7 +73,7 @@ impl RFunction {
pub fn run(&self, info: &GSInfo) -> VData { pub fn run(&self, info: &GSInfo) -> VData {
self.statement.run(info) self.statement.run(info)
} }
pub fn out(&self, input_types: &Vec<VType>, info: &GlobalScriptInfo) -> Option<VType> { pub fn out_by_map(&self, input_types: &Vec<VType>, info: &GlobalScriptInfo) -> Option<VType> {
// NOTE: This can ONLY use self.out_map, because it's used by the VSingleType.fits_in method. // NOTE: This can ONLY use self.out_map, because it's used by the VSingleType.fits_in method.
let mut empty = true; let mut empty = true;
let out = self let out = self
@ -101,15 +97,30 @@ impl RFunction {
Some(out) Some(out)
} }
} }
pub fn out_all(&self, info: &GlobalScriptInfo) -> VType { pub fn out_all_by_map(&self, info: &GlobalScriptInfo) -> VType {
// self.statement.out(info) // self.statement.out(info)
self.out_map.iter().fold(VType::empty(), |mut t, (_, v)| { self.out_map.iter().fold(VType::empty(), |mut t, (_, v)| {
t.add_typesr(v, info); t.add_typesr(v, info);
t t
}) })
} }
pub fn in_types(&self) -> &Vec<VType> { pub fn out_by_statement(&self, input_types: &Vec<VType>, info: &GlobalScriptInfo) -> VType {
&self.input_types let mut actual = Vec::with_capacity(self.inputs.len());
// simulate these variable types
for (fn_input, c_type) in self.inputs.iter().zip(input_types.iter()) {
actual.push(std::mem::replace(
&mut fn_input.lock().unwrap().1,
c_type.clone(),
));
}
// not get the return type if these were the actual types
let out = self.statement.out(info);
// reset
for (fn_input, actual) in self.inputs.iter().zip(actual) {
fn_input.lock().unwrap().1 = actual;
}
// return
out
} }
} }
@ -124,18 +135,16 @@ pub struct RStatement {
impl RStatement { impl RStatement {
pub fn run(&self, info: &GSInfo) -> VData { pub fn run(&self, info: &GSInfo) -> VData {
let out = self.statement.run(info); let out = self.statement.run(info);
let mut o = if let Some((v, is_init)) = &self.output_to { let mut o = if let Some((v, _is_init)) = &self.output_to {
'init: { // // assigns a new VData to the variable's Arc<Mutex<_>>, so that threads which have captured the variable at some point
// // assigns a new VData to the variable's Arc<Mutex<_>>, so that threads which have captured the variable at some point // // won't be updated with its new value (is_init is set to true for initializations, such as in a loop - this can happen multiple times, but each should be its own variable with the same name)
// // won't be updated with its new value (is_init is set to true for initializations, such as in a loop - this can happen multiple times, but each should be its own variable with the same name) // if *is_init && *derefs == 0 {
// if *is_init && *derefs == 0 { // Self::assign_to(out, v.run(info), info);
// Self::assign_to(out, v.run(info), info); // break 'init;
// break 'init; // }
// } let val = v.run(info);
let mut val = v.run(info); out.assign_to(val, info);
out.assign_to(val, info); // val.assign(out);
// val.assign(out);
}
VDataEnum::Tuple(vec![]).to() VDataEnum::Tuple(vec![]).to()
} else { } else {
out out
@ -226,7 +235,7 @@ impl RStatementEnum {
Self::For(v, c, b) => { Self::For(v, c, b) => {
// matching values also break with value from a for loop. // matching values also break with value from a for loop.
let vv = v.run(info); let vv = v.run(info);
let mut in_loop = |c: VData| { let in_loop = |c: VData| {
c.assign_to(vv.clone_mut(), info); c.assign_to(vv.clone_mut(), info);
b.run(info) b.run(info)
}; };
@ -270,7 +279,7 @@ impl RStatementEnum {
break; break;
} }
}, },
VDataEnum::Reference(r) => return None, VDataEnum::Reference(_r) => return None,
_ => unreachable!(), _ => unreachable!(),
} }
Some(oval) Some(oval)
@ -355,7 +364,7 @@ impl RStatementEnum {
} }
} }
Self::FunctionCall(f, args) => f Self::FunctionCall(f, args) => f
.out(&args.iter().map(|v| v.out(info)).collect(), info) .out_by_map(&args.iter().map(|v| v.out(info)).collect(), info)
.expect("invalid args for function -> can't determine output type"), .expect("invalid args for function -> can't determine output type"),
Self::LibFunctionCall(.., out) => out.clone(), Self::LibFunctionCall(.., out) => out.clone(),
Self::Block(b) => b.out(info), Self::Block(b) => b.out(info),
@ -379,13 +388,13 @@ impl RStatementEnum {
} }
Self::Switch(switch_on, cases, force) => { Self::Switch(switch_on, cases, force) => {
let switch_on = switch_on.out(info).types; let switch_on = switch_on.out(info).types;
let mut might_return_empty = switch_on.is_empty(); let _might_return_empty = switch_on.is_empty();
let mut out = if *force { let mut out = if *force {
VType::empty() VType::empty()
} else { } else {
VSingleType::Tuple(vec![]).to() VSingleType::Tuple(vec![]).to()
}; };
for switch_on in switch_on { for _switch_on in switch_on {
for (_on_type, _assign_to, case) in cases.iter() { for (_on_type, _assign_to, case) in cases.iter() {
out.add_types(case.out(info), info); out.add_types(case.out(info), info);
} }
@ -423,7 +432,7 @@ impl RStatementEnum {
pub struct RScript { pub struct RScript {
main: RFunction, main: RFunction,
info: GSInfo, pub info: GSInfo,
} }
impl RScript { impl RScript {
pub fn new(main: RFunction, info: GSInfo) -> Result<Self, ToRunnableError> { pub fn new(main: RFunction, info: GSInfo) -> Result<Self, ToRunnableError> {
@ -432,20 +441,8 @@ impl RScript {
} }
Ok(Self { main, info }) Ok(Self { main, info })
} }
pub fn run(&self, args: Vec<String>) -> VData { pub fn run(&self, args: Vec<VData>) -> VData {
let mut vars = vec![]; self.main.inputs[0].lock().unwrap().0 = VDataEnum::List(VSingleType::Any.into(), args).to();
vars.push(
VDataEnum::List(
VSingleType::String.into(),
args.into_iter()
.map(|v| VDataEnum::String(v).to())
.collect(),
)
.to(),
);
self.main.run(&self.info) self.main.run(&self.info)
} }
pub fn info(&self) -> &GSInfo {
&self.info
}
} }

View File

@ -5,7 +5,7 @@ use super::global_info::{ColorFormatMode, ColorFormatter, GlobalScriptInfo};
use colorize::AnsiColor; use colorize::AnsiColor;
pub enum Color { pub enum Color {
Keep, // Keep,
Grey, Grey,
Red, Red,
Yellow, Yellow,
@ -17,7 +17,7 @@ pub enum Color {
impl Color { impl Color {
pub fn colorize(&self, s: String) -> String { pub fn colorize(&self, s: String) -> String {
match self { match self {
Self::Keep => s, // Self::Keep => s,
Self::Grey => s.grey().to_string(), Self::Grey => s.grey().to_string(),
Self::Red => s.red().to_string(), Self::Red => s.red().to_string(),
Self::Yellow => s.yellow().to_string(), Self::Yellow => s.yellow().to_string(),
@ -72,7 +72,7 @@ impl FormatInfo {
pub fn go_shallower(&mut self) { pub fn go_shallower(&mut self) {
self.depth -= 1; self.depth -= 1;
} }
pub fn variable_ref_symbol(&self, info: Option<&GlobalScriptInfo>, s: String) -> String { pub fn variable_ref_symbol(&self, _info: Option<&GlobalScriptInfo>, s: String) -> String {
s s
} }
pub fn variable(&self, info: Option<&GlobalScriptInfo>, s: String) -> String { pub fn variable(&self, info: Option<&GlobalScriptInfo>, s: String) -> String {

View File

@ -1,23 +1,19 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
default,
fmt::Display, fmt::Display,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use crate::libs;
use super::{ use super::{
builtins, builtins,
fmtgs::Color, fmtgs::Color,
val_data::VDataEnum,
val_type::{VSingleType, VType}, val_type::{VSingleType, VType},
}; };
pub type GSInfo = Arc<GlobalScriptInfo>; pub type GSInfo = Arc<GlobalScriptInfo>;
pub struct GlobalScriptInfo { pub struct GlobalScriptInfo {
pub libs: Vec<libs::Lib>, pub libs: Vec<crate::libs::Lib>,
pub lib_fns: HashMap<String, (usize, usize)>, pub lib_fns: HashMap<String, (usize, usize)>,
pub enum_variants: HashMap<String, usize>, pub enum_variants: HashMap<String, usize>,
@ -121,7 +117,6 @@ pub struct Logger {
pub after_parse: LogKind, pub after_parse: LogKind,
pub vdata_clone: LogKind,
pub vtype_fits_in: LogKind, pub vtype_fits_in: LogKind,
pub vsingletype_fits_in: LogKind, pub vsingletype_fits_in: LogKind,
} }
@ -130,7 +125,6 @@ impl Logger {
Self { Self {
logs: Arc::new(Mutex::new(vec![])), logs: Arc::new(Mutex::new(vec![])),
after_parse: Default::default(), after_parse: Default::default(),
vdata_clone: Default::default(),
vtype_fits_in: Default::default(), vtype_fits_in: Default::default(),
vsingletype_fits_in: Default::default(), vsingletype_fits_in: Default::default(),
} }
@ -140,7 +134,6 @@ impl Logger {
#[derive(Debug)] #[derive(Debug)]
pub enum LogMsg { pub enum LogMsg {
AfterParse(String), AfterParse(String),
VDataClone(Option<String>, VDataEnum, usize, usize),
VTypeFitsIn(VType, VType, Vec<VSingleType>), VTypeFitsIn(VType, VType, Vec<VSingleType>),
VSingleTypeFitsIn(VSingleType, VSingleType, bool), VSingleTypeFitsIn(VSingleType, VSingleType, bool),
} }
@ -148,7 +141,6 @@ impl Logger {
pub fn log(&self, msg: LogMsg) { pub fn log(&self, msg: LogMsg) {
let kind = match msg { let kind = match msg {
LogMsg::AfterParse(..) => &self.after_parse, LogMsg::AfterParse(..) => &self.after_parse,
LogMsg::VDataClone(..) => &self.vdata_clone,
LogMsg::VTypeFitsIn(..) => &self.vtype_fits_in, LogMsg::VTypeFitsIn(..) => &self.vtype_fits_in,
LogMsg::VSingleTypeFitsIn(..) => &self.vsingletype_fits_in, LogMsg::VSingleTypeFitsIn(..) => &self.vsingletype_fits_in,
}; };
@ -168,17 +160,6 @@ impl Display for LogMsg {
Self::AfterParse(code) => { Self::AfterParse(code) => {
write!(f, "AfterParse :: {code}") write!(f, "AfterParse :: {code}")
} }
Self::VDataClone(varname, data, src_addr, new_addr) => {
write!(
f,
"VDataClone ::::\n{data} ({}{src_addr} -> {new_addr})",
if let Some(v) = varname {
format!("{v} | ")
} else {
String::new()
}
)
}
Self::VTypeFitsIn(a, b, no) => write!(f, "VTypeFitsIn :: {a} in {b} ? -> {no:?}"), Self::VTypeFitsIn(a, b, no) => write!(f, "VTypeFitsIn :: {a} in {b} ? -> {no:?}"),
Self::VSingleTypeFitsIn(a, b, fits) => { Self::VSingleTypeFitsIn(a, b, fits) => {
write!(f, "VSingleTypeFitsIn :: {a} in {b} ? -> {fits}") write!(f, "VSingleTypeFitsIn :: {a} in {b} ? -> {fits}")

View File

@ -1,20 +1,14 @@
use core::panic; use core::panic;
use std::{ use std::{
collections::HashMap, collections::HashMap,
eprintln,
fmt::{Debug, Display}, fmt::{Debug, Display},
sync::{Arc, Mutex}, sync::{Arc, Mutex},
time::Duration,
}; };
use crate::{ use crate::lang::{
lang::{ global_info::GlobalScriptInfo,
builtins, val_data::{VData, VDataEnum},
global_info::GlobalScriptInfo, val_type::{VSingleType, VType},
val_data::{VData, VDataEnum},
val_type::{VSingleType, VType},
},
libs,
}; };
use super::{ use super::{
@ -84,12 +78,12 @@ impl FormatGs for ToRunnableError {
write!(f, "Cannot dereference type ")?; write!(f, "Cannot dereference type ")?;
og_type.fmtgs(f, info, form, file)?; og_type.fmtgs(f, info, form, file)?;
write!(f, " {derefs_wanted} times (stopped at ")?; write!(f, " {derefs_wanted} times (stopped at ")?;
last_valid_type.fmtgs(f, info, form, file); last_valid_type.fmtgs(f, info, form, file)?;
write!(f, ")")?; write!(f, ")")?;
Ok(()) Ok(())
} }
Self::FunctionWrongArgs(fn_name, possible_fns, given_types) => { Self::FunctionWrongArgs(fn_name, possible_fns, given_types) => {
write!(f, "Wrong args for function \"{fn_name}\": Found ("); write!(f, "Wrong args for function \"{fn_name}\": Found (")?;
for (i, t) in given_types.iter().enumerate() { for (i, t) in given_types.iter().enumerate() {
if i > 0 { if i > 0 {
write!(f, ", ")?; write!(f, ", ")?;
@ -277,25 +271,7 @@ fn function(
} }
} }
} }
// let out = o.out(&current_types, ginfo).expect("invalid args????"); let out = o.out_by_statement(&current_types, &ginfo);
let out = {
let mut actual = Vec::with_capacity(o.inputs.len());
// simulate these variable types
for (fn_input, c_type) in o.inputs.iter().zip(current_types.iter()) {
actual.push(std::mem::replace(
&mut fn_input.lock().unwrap().1,
c_type.clone(),
));
}
// not get the return type if these were the actual types
let out = o.statement.out(ginfo);
// reset
for (fn_input, actual) in o.inputs.iter().zip(actual) {
std::mem::replace(&mut fn_input.lock().unwrap().1, actual);
}
// return
out
};
map.push((current_types, out)); map.push((current_types, out));
if was_last { if was_last {
break map; break map;
@ -627,11 +603,11 @@ fn statement_adv(
RStatementEnum::Switch(switch_on, ncases, *force).to() RStatementEnum::Switch(switch_on, ncases, *force).to()
} }
SStatementEnum::Match(cases) => { SStatementEnum::Match(cases) => {
let mut ncases: Vec<(RStatement, RStatement, RStatement)> = let _ncases: Vec<(RStatement, RStatement, RStatement)> =
Vec::with_capacity(cases.len()); Vec::with_capacity(cases.len());
let mut ncases = Vec::with_capacity(cases.len()); let mut ncases = Vec::with_capacity(cases.len());
let mut out_type = VType::empty(); let mut out_type = VType::empty();
let mut may_not_match = true; let may_not_match = true;
for (condition, assign_to, action) in cases.iter() { for (condition, assign_to, action) in cases.iter() {
let mut linfo = linfo.clone(); let mut linfo = linfo.clone();
let condition = statement(condition, ginfo, &mut linfo)?; let condition = statement(condition, ginfo, &mut linfo)?;

View File

@ -1,10 +1,8 @@
use std::{ use std::{
fmt::{self, Debug, Display, Formatter}, fmt::{self, Debug, Display, Formatter},
ops::Deref, sync::{Arc, Mutex},
sync::{Arc, Mutex, MutexGuard},
}; };
use super::global_info::LogMsg;
use super::{ use super::{
code_runnable::RFunction, code_runnable::RFunction,
fmtgs::FormatGs, fmtgs::FormatGs,
@ -68,14 +66,14 @@ impl VData {
pub fn clone_data(&self) -> Self { pub fn clone_data(&self) -> Self {
// TODO! implement CopyOnWrite. For now, just always copy. This also prevents mut references not existing since in ::Dat(cloned, _), cloned will always stay 0. // TODO! implement CopyOnWrite. For now, just always copy. This also prevents mut references not existing since in ::Dat(cloned, _), cloned will always stay 0.
return self.operate_on_data_immut(|v| v.clone()).to(); return self.operate_on_data_immut(|v| v.clone()).to();
match &mut *self.0.lock().unwrap() { // match &mut *self.0.lock().unwrap() {
VDataInner::Data(cloned, _data) => { // VDataInner::Data(cloned, _data) => {
*cloned += 1; // *cloned += 1;
VDataInner::ClonedFrom(self.clone_arc()).to() // VDataInner::ClonedFrom(self.clone_arc()).to()
} // }
VDataInner::Mut(inner) => inner.lock().unwrap().clone_data(), // VDataInner::Mut(inner) => inner.lock().unwrap().clone_data(),
VDataInner::ClonedFrom(inner) => inner.clone_data(), // VDataInner::ClonedFrom(inner) => inner.clone_data(),
} // }
} }
/// clones self, returning a new instance of self that will always yield the same data as self, so that changes done to either are shared between both. /// clones self, returning a new instance of self that will always yield the same data as self, so that changes done to either are shared between both.
pub fn clone_mut(&self) -> Self { pub fn clone_mut(&self) -> Self {
@ -87,7 +85,7 @@ impl VData {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
return Self(Arc::clone(&self.0), self.1.clone()); return Self(Arc::clone(&self.0), self.1.clone());
} }
pub fn operate_on_data_immut<F, O>(&self, mut func: F) -> O pub fn operate_on_data_immut<F, O>(&self, func: F) -> O
where where
F: FnOnce(&VDataEnum) -> O, F: FnOnce(&VDataEnum) -> O,
{ {
@ -100,7 +98,7 @@ impl VData {
/// runs func on the underlying data. /// runs func on the underlying data.
/// attempts to get a mutable reference to the data. if this fails, it will (partially) clone the data, then point the VData to the new data, /// attempts to get a mutable reference to the data. if this fails, it will (partially) clone the data, then point the VData to the new data,
/// so that other VDatas pointing to the same original data aren't changed. /// so that other VDatas pointing to the same original data aren't changed.
pub fn operate_on_data_mut<F, O>(&mut self, mut func: F) -> O pub fn operate_on_data_mut<F, O>(&mut self, func: F) -> O
where where
F: FnOnce(&mut VDataEnum) -> O, F: FnOnce(&mut VDataEnum) -> O,
{ {
@ -170,7 +168,7 @@ impl VData {
impl Drop for VDataInner { impl Drop for VDataInner {
fn drop(&mut self) { fn drop(&mut self) {
if let Self::ClonedFrom(origin) = self { if let Self::ClonedFrom(origin) = self {
if let Self::Data(ref_count, _data) = &mut *origin.0.lock().unwrap() { if let Self::Data(_ref_count, _data) = &mut *origin.0.lock().unwrap() {
// *ref_count = ref_count.saturating_sub(1); // *ref_count = ref_count.saturating_sub(1);
} }
} }
@ -340,7 +338,7 @@ impl VDataEnum {
pub fn noenum(&self) -> Option<VData> { pub fn noenum(&self) -> Option<VData> {
match self { match self {
Self::EnumVariant(_, v) => Some(v.clone_data()), Self::EnumVariant(_, v) => Some(v.clone_data()),
v => None, _v => None,
} }
} }
pub fn get(&self, i: usize) -> Option<VData> { pub fn get(&self, i: usize) -> Option<VData> {
@ -372,19 +370,12 @@ impl VDataEnum {
| Self::Function(..) | Self::Function(..)
| Self::Thread(..) => None, | Self::Thread(..) => None,
// TODO: String // TODO: String
Self::String(s) => None, Self::String(_s) => None,
Self::Tuple(v) | Self::List(_, v) => v.get(i).map(|v| v.clone_mut()), Self::Tuple(v) | Self::List(_, v) => v.get(i).map(|v| v.clone_mut()),
Self::Reference(r) => r.get_ref(i), Self::Reference(r) => r.get_ref(i),
Self::EnumVariant(_, v) => v.get_ref(i), Self::EnumVariant(_, v) => v.get_ref(i),
} }
} }
pub fn matches_ref_bool(&self) -> bool {
match self {
VDataEnum::Tuple(v) => !v.is_empty(),
VDataEnum::Bool(false) => false,
_ => true,
}
}
/// Some(None) => matches with self /// Some(None) => matches with self
pub fn matches(&self) -> Option<Option<VData>> { pub fn matches(&self) -> Option<Option<VData>> {
match self { match self {
@ -397,7 +388,7 @@ impl VDataEnum {
} }
} }
VDataEnum::EnumVariant(..) => None, VDataEnum::EnumVariant(..) => None,
other => Some(None), _other => Some(None),
} }
} }
} }
@ -487,7 +478,7 @@ pub mod thread {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &*self.lock() { match &*self.lock() {
VDataThreadEnum::Running(_) => write!(f, "(thread running)"), VDataThreadEnum::Running(_) => write!(f, "(thread running)"),
VDataThreadEnum::Finished(v) => write!(f, "(thread finished)"), VDataThreadEnum::Finished(_v) => write!(f, "(thread finished)"),
} }
} }
} }
@ -553,7 +544,7 @@ impl FormatGs for VDataEnum {
} }
Self::List(_t, v) => { Self::List(_t, v) => {
write!(f, "[")?; write!(f, "[")?;
for (i, v) in v.iter().enumerate() { for (_i, v) in v.iter().enumerate() {
v.fmtgs(f, info, form, file)?; v.fmtgs(f, info, form, file)?;
write!(f, " ")?; write!(f, " ")?;
} }

View File

@ -1,14 +1,12 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
fmt::{self, Debug, Display, Formatter}, fmt::{self, Debug, Display, Formatter},
ops::BitOr,
sync::Arc,
}; };
use super::{ use super::{
code_runnable::{RFunction, RStatementEnum}, code_runnable::{RFunction, RStatementEnum},
fmtgs::FormatGs, fmtgs::FormatGs,
global_info::{self, GSInfo, GlobalScriptInfo}, global_info::{GSInfo, GlobalScriptInfo},
val_data::VDataEnum, val_data::VDataEnum,
}; };
@ -173,7 +171,7 @@ impl VType {
Some(out) Some(out)
} }
pub fn reference(&self) -> Self { pub fn reference(&self) -> Self {
let mut out = Self::empty(); let _out = Self::empty();
Self { Self {
types: self types: self
.types .types
@ -474,7 +472,7 @@ impl VSingleType {
}; };
for (ins, out) in b { for (ins, out) in b {
// try everything that would be valid for b // try everything that would be valid for b
if let Some(v) = af.out(ins, info) { if let Some(v) = af.out_by_map(ins, info) {
if !v.fits_in(out, info).is_empty() { if !v.fits_in(out, info).is_empty() {
// found something that's valid for both, but a returns something that doesn't fit in what b would have returned -> a doesn't fit. // found something that's valid for both, but a returns something that doesn't fit in what b would have returned -> a doesn't fit.
break 'fnt false; break 'fnt false;
@ -572,7 +570,7 @@ impl FormatGs for VSingleType {
write!(f, "(")?; write!(f, "(")?;
for i in inputs { for i in inputs {
i.fmtgs(f, info, form, file)?; i.fmtgs(f, info, form, file)?;
write!(f, " "); write!(f, " ")?;
} }
output.fmtgs(f, info, form, file)?; output.fmtgs(f, info, form, file)?;
write!(f, ")")?; write!(f, ")")?;

View File

@ -1,12 +1,12 @@
mod inlib;
mod lang; mod lang;
mod libs; mod libs;
mod parsing; mod parsing;
mod pathutil;
pub use inlib::MyLib;
pub use lang::{global_info::GlobalScriptInfo, val_data::*, val_type::*}; pub use lang::{global_info::GlobalScriptInfo, val_data::*, val_type::*};
pub use libs::{ pub use libs::comms::{ByteData, ByteDataA, Message, RespondableMessage};
comms::{ByteData, ByteDataA, Message, RespondableMessage},
inlib::MyLib,
};
pub use parsing::*; pub use parsing::*;
pub mod prelude { pub mod prelude {

View File

@ -42,10 +42,10 @@ impl ByteData for Message {
where where
R: std::io::Read, R: std::io::Read,
{ {
let mut type_id = u32::from_byte_data(data)?; let type_id = u32::from_byte_data(data)?;
Ok(match type_id { Ok(match type_id {
0 => Self::RunFunction(ByteData::from_byte_data(data)?), 0 => Self::RunFunction(ByteData::from_byte_data(data)?),
other => unreachable!("read unknown type_id byte for message!"), _other => unreachable!("read unknown type_id byte for message!"),
}) })
} }
} }
@ -270,7 +270,7 @@ impl ByteData for String {
{ {
let len = ByteData::from_byte_data(data)?; let len = ByteData::from_byte_data(data)?;
let mut buf = vec![0; len]; let mut buf = vec![0; len];
data.read_exact(buf.as_mut_slice()); data.read_exact(buf.as_mut_slice())?;
let str = String::from_utf8(buf).unwrap(); let str = String::from_utf8(buf).unwrap();
Ok(str) Ok(str)
} }
@ -503,7 +503,7 @@ impl ByteDataA for VDataEnum {
// TODO? // TODO?
Self::Function(_) => vec.push(b'F'), Self::Function(_) => vec.push(b'F'),
Self::Thread(..) => vec.push(b'T'), Self::Thread(..) => vec.push(b'T'),
Self::Reference(r) => vec.push(b'R'), Self::Reference(_r) => vec.push(b'R'),
Self::EnumVariant(enum_id, inner) => { Self::EnumVariant(enum_id, inner) => {
vec.push(b'E'); vec.push(b'E');
enum_id.as_byte_data(vec); enum_id.as_byte_data(vec);

View File

@ -1,26 +1,17 @@
pub mod comms; pub mod comms;
pub mod inlib;
pub mod path;
use std::{ use std::{
collections::HashMap, collections::HashMap,
io::{self, BufRead, BufReader, Read, Write}, io::{self, BufReader, Write},
path::PathBuf,
process::{Child, ChildStdin, ChildStdout, Command, Stdio}, process::{Child, ChildStdin, ChildStdout, Command, Stdio},
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use crate::{ use crate::lang::{
lang::{ global_info::GlobalScriptInfo, to_runnable::ToRunnableError, val_data::VData, val_type::VType,
global_info::GlobalScriptInfo,
val_data::{VData, VDataEnum},
val_type::VType,
},
libs::comms::{ByteData, ByteDataA},
parsing::{file::File, parse},
}; };
use self::comms::{MessageResponse, RespondableMessage}; use self::comms::{ByteData, ByteDataA, RespondableMessage};
// Libraries are processes that communicate via stdout/stdin. // Libraries are processes that communicate via stdout/stdin.
@ -59,6 +50,8 @@ pub type LibInitReq<'a> = (
); );
/// Sent by mers to finish initializing a library. /// Sent by mers to finish initializing a library.
/// [enum variants] /// [enum variants]
// used by crate::inlib
#[allow(unused)]
pub type LibInitInfo = Vec<(String, usize)>; pub type LibInitInfo = Vec<(String, usize)>;
pub type LibInitInfoRef<'a> = Vec<(&'a String, &'a usize)>; pub type LibInitInfoRef<'a> = Vec<(&'a String, &'a usize)>;
@ -93,9 +86,13 @@ impl Lib {
for (_name, func) in registered_fns.iter_mut() { for (_name, func) in registered_fns.iter_mut() {
for (args, out) in func.iter_mut() { for (args, out) in func.iter_mut() {
for t in args.iter_mut() { for t in args.iter_mut() {
crate::lang::to_runnable::stypes(t, &mut ginfo); if let Err(e) = crate::lang::to_runnable::stypes(t, &mut ginfo) {
return Err(LaunchError::ErrorAddingEnumsOrTypes(e));
}
}
if let Err(e) = crate::lang::to_runnable::stypes(out, &mut ginfo) {
return Err(LaunchError::ErrorAddingEnumsOrTypes(e));
} }
crate::lang::to_runnable::stypes(out, &mut ginfo);
} }
} }
for (name, id) in ginfo.enum_variants { for (name, id) in ginfo.enum_variants {
@ -104,13 +101,17 @@ impl Lib {
} }
} }
let si: LibInitInfoRef = enum_variants.iter().collect(); let si: LibInitInfoRef = enum_variants.iter().collect();
stdin.write(si.as_byte_data_vec().as_slice()); if let Err(e) = stdin.write_all(si.as_byte_data_vec().as_slice()) {
stdin.flush(); return Err(LaunchError::StdioError(e));
};
if let Err(e) = stdin.flush() {
return Err(LaunchError::StdioError(e));
};
let (task_sender, recv) = std::sync::mpsc::channel::<( let (task_sender, recv) = std::sync::mpsc::channel::<(
u128, u128,
Box<dyn FnOnce(&mut BufReader<ChildStdout>) + Send>, Box<dyn FnOnce(&mut BufReader<ChildStdout>) + Send>,
)>(); )>();
let stdout_reader = std::thread::spawn(move || { let _stdout_reader = std::thread::spawn(move || {
let dur = std::time::Duration::from_millis(20); let dur = std::time::Duration::from_millis(20);
let mut pending = HashMap::new(); let mut pending = HashMap::new();
loop { loop {
@ -192,11 +193,11 @@ impl Lib {
)) ))
.unwrap(); .unwrap();
// id - type_id - message // id - type_id - message
stdin.write(id.as_byte_data_vec().as_slice()).unwrap(); stdin.write_all(id.as_byte_data_vec().as_slice()).unwrap();
stdin stdin
.write(msg.msgtype_id().as_byte_data_vec().as_slice()) .write_all(msg.msgtype_id().as_byte_data_vec().as_slice())
.unwrap(); .unwrap();
stdin.write(msg.as_byte_data_vec().as_slice()).unwrap(); stdin.write_all(msg.as_byte_data_vec().as_slice()).unwrap();
stdin.flush().unwrap(); stdin.flush().unwrap();
*id = id.wrapping_add(1); *id = id.wrapping_add(1);
recv recv
@ -209,12 +210,18 @@ impl Lib {
pub enum LaunchError { pub enum LaunchError {
NoStdio, NoStdio,
CouldNotSpawnProcess(io::Error), CouldNotSpawnProcess(io::Error),
StdioError(io::Error),
ErrorAddingEnumsOrTypes(ToRunnableError),
} }
impl std::fmt::Display for LaunchError { impl std::fmt::Display for LaunchError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Self::NoStdio => write!(f, "couldn't get stdio (stdin/stdout) from child process."), Self::NoStdio => write!(f, "couldn't get stdio (stdin/stdout) from child process."),
Self::CouldNotSpawnProcess(e) => write!(f, "couldn't spawn child process: {e}."), Self::CouldNotSpawnProcess(e) => write!(f, "couldn't spawn child process: {e}."),
Self::StdioError(e) => write!(f, "error from stdio: {e}"),
Self::ErrorAddingEnumsOrTypes(e) => {
write!(f, "error adding enums or types from library: {e}.")
}
} }
} }
} }

View File

@ -1,9 +1,7 @@
use std::{fs, time::Instant};
use lang::global_info::ColorFormatMode; use lang::global_info::ColorFormatMode;
use lang::global_info::GlobalScriptInfo; use lang::global_info::GlobalScriptInfo;
use lang::global_info::LogKind; use lang::global_info::LogKind;
use notify::Watcher as FsWatcher; use lang::val_data::VDataEnum;
use crate::lang::fmtgs::FormatGs; use crate::lang::fmtgs::FormatGs;
@ -13,6 +11,7 @@ mod libs;
#[cfg(feature = "nushell_plugin")] #[cfg(feature = "nushell_plugin")]
mod nushell_plugin; mod nushell_plugin;
mod parsing; mod parsing;
mod pathutil;
mod tutor; mod tutor;
fn main() { fn main() {
@ -113,7 +112,6 @@ fn normal_main() {
log: true, log: true,
} }
} }
info.log.vdata_clone = f();
info.log.vtype_fits_in = f(); info.log.vtype_fits_in = f();
info.log.vsingletype_fits_in = f(); info.log.vsingletype_fits_in = f();
} else { } else {
@ -144,7 +142,6 @@ fn normal_main() {
None => (verbose_arg, None), None => (verbose_arg, None),
}; };
match arg { match arg {
"vdata_clone" => info.log.vdata_clone = kind(val),
"vtype_fits_in" => info.log.vtype_fits_in = kind(val), "vtype_fits_in" => info.log.vtype_fits_in = kind(val),
"vsingletype_fits_in" => info.log.vsingletype_fits_in = kind(val), "vsingletype_fits_in" => info.log.vsingletype_fits_in = kind(val),
_ => eprintln!("Warn: -v+ unknown arg '{arg}'."), _ => eprintln!("Warn: -v+ unknown arg '{arg}'."),
@ -157,6 +154,7 @@ fn normal_main() {
_ => { _ => {
// basic: open file and watch for fs changes // basic: open file and watch for fs changes
interactive_mode::fs_watcher::playground(interactive_use_new_terminal) interactive_mode::fs_watcher::playground(interactive_use_new_terminal)
.unwrap()
} }
}; };
return; return;
@ -194,7 +192,12 @@ fn normal_main() {
match parsing::parse::parse_custom_info(&mut file, info) { match parsing::parse::parse_custom_info(&mut file, info) {
Ok(script) => { Ok(script) => {
if run { if run {
script.run(std::env::args().skip(args_to_skip).collect()); script.run(
std::env::args()
.skip(args_to_skip)
.map(|v| VDataEnum::String(v).to())
.collect(),
);
} }
} }
Err(e) => { Err(e) => {

View File

@ -1,12 +1,14 @@
use std::{fs, path::PathBuf}; use std::{fs, path::PathBuf};
use nu_plugin::{serve_plugin, MsgPackSerializer, Plugin}; use nu_plugin::{serve_plugin, MsgPackSerializer, Plugin};
use nu_protocol::{PluginExample, PluginSignature, ShellError, Span, Spanned, SyntaxShape, Value}; use nu_protocol::{PluginSignature, ShellError, Span, SyntaxShape, Value};
use crate::{ use crate::{
lang::{ lang::{
fmtgs::FormatGs,
global_info::GlobalScriptInfo, global_info::GlobalScriptInfo,
val_data::{VData, VDataEnum}, val_data::{VData, VDataEnum},
val_type::VType,
}, },
parsing, parsing,
}; };
@ -27,7 +29,24 @@ impl Plugin for MersNuPlugin {
) )
.optional( .optional(
"args", "args",
SyntaxShape::List(Box::new(SyntaxShape::String)), SyntaxShape::List(Box::new(SyntaxShape::OneOf(vec![
SyntaxShape::Boolean,
SyntaxShape::Int,
SyntaxShape::Decimal,
SyntaxShape::String,
SyntaxShape::List(Box::new(SyntaxShape::OneOf(vec![
SyntaxShape::Boolean,
SyntaxShape::Int,
SyntaxShape::Decimal,
SyntaxShape::String,
SyntaxShape::List(Box::new(SyntaxShape::OneOf(vec![
SyntaxShape::Boolean,
SyntaxShape::Int,
SyntaxShape::Decimal,
SyntaxShape::String,
]))),
]))),
]))),
"the arguments passed to the mers program. defaults to an empty list.", "the arguments passed to the mers program. defaults to an empty list.",
) )
.switch( .switch(
@ -38,9 +57,9 @@ impl Plugin for MersNuPlugin {
} }
fn run( fn run(
&mut self, &mut self,
name: &str, _name: &str,
call: &nu_plugin::EvaluatedCall, call: &nu_plugin::EvaluatedCall,
input: &nu_protocol::Value, _input: &nu_protocol::Value,
) -> Result<nu_protocol::Value, nu_plugin::LabeledError> { ) -> Result<nu_protocol::Value, nu_plugin::LabeledError> {
// no need to 'match name {...}' because we only register mers-nu and nothing else. // no need to 'match name {...}' because we only register mers-nu and nothing else.
let source: String = call.req(0)?; let source: String = call.req(0)?;
@ -52,7 +71,7 @@ impl Plugin for MersNuPlugin {
parsing::file::File::new( parsing::file::File::new(
match fs::read_to_string(&source) { match fs::read_to_string(&source) {
Ok(v) => v, Ok(v) => v,
Err(e) => { Err(_e) => {
return Ok(Value::Error { return Ok(Value::Error {
error: Box::new(ShellError::FileNotFound(source_span)), error: Box::new(ShellError::FileNotFound(source_span)),
}) })
@ -64,36 +83,62 @@ impl Plugin for MersNuPlugin {
Ok(match parsing::parse::parse(&mut file) { Ok(match parsing::parse::parse(&mut file) {
Ok(code) => { Ok(code) => {
let args = match call.opt(1)? { let args = match call.opt(1)? {
Some(v) => v, Some(v) => {
fn to_mers_val(v: Vec<Value>, info: &GlobalScriptInfo) -> Vec<VData> {
v.into_iter()
.map(|v| {
match v {
Value::Bool { val, .. } => VDataEnum::Bool(val),
Value::Int { val, .. } => VDataEnum::Int(val as _),
Value::Float { val, .. } => VDataEnum::Float(val),
Value::String { val, .. } => VDataEnum::String(val),
Value::List { vals, .. } => {
let mut t = VType::empty();
let mut vs = Vec::with_capacity(vals.len());
for v in to_mers_val(vals, info) {
t.add_types(v.out(), info);
vs.push(v);
}
VDataEnum::List(t, vs)
}
_ => unreachable!("invalid arg type"),
}
.to()
})
.collect()
}
if let Value::List { vals, .. } = v {
to_mers_val(vals, &code.info)
} else {
unreachable!("args not a list")
}
}
_ => vec![], _ => vec![],
}; };
fn to_nu_val(val: VData, info: &GlobalScriptInfo) -> Value { fn to_nu_val(val: &VData, info: &GlobalScriptInfo) -> Value {
let span = Span::unknown(); let span = Span::unknown();
match val.data { val.operate_on_data_immut(|val| match val {
VDataEnum::Bool(val) => Value::Bool { val, span }, VDataEnum::Bool(val) => Value::Bool { val: *val, span },
VDataEnum::Int(val) => Value::Int { VDataEnum::Int(val) => Value::Int {
val: val as _, val: *val as _,
span,
},
VDataEnum::Float(val) => Value::Float { val: *val, span },
VDataEnum::String(val) => Value::String {
val: val.to_owned(),
span, span,
}, },
VDataEnum::Float(val) => Value::Float { val, span },
VDataEnum::String(val) => Value::String { val, span },
VDataEnum::Tuple(vals) | VDataEnum::List(_, vals) => Value::List { VDataEnum::Tuple(vals) | VDataEnum::List(_, vals) => Value::List {
vals: vals.into_iter().map(|v| to_nu_val(v, info)).collect(), vals: vals.iter().map(|v| to_nu_val(v, info)).collect(),
span, span,
}, },
VDataEnum::Reference(r) => to_nu_val( VDataEnum::Reference(r) => to_nu_val(r, info),
std::mem::replace(
&mut *r.lock().unwrap(),
VDataEnum::Tuple(vec![]).to(),
),
info,
),
VDataEnum::EnumVariant(variant, val) => { VDataEnum::EnumVariant(variant, val) => {
let name = info let name = info
.enum_variants .enum_variants
.iter() .iter()
.find_map(|(name, id)| { .find_map(|(name, id)| {
if *id == variant { if *id == *variant {
Some(name.to_owned()) Some(name.to_owned())
} else { } else {
None None
@ -107,16 +152,16 @@ impl Plugin for MersNuPlugin {
val: name, val: name,
span: span, span: span,
}, },
to_nu_val(*val, info), to_nu_val(val, info),
], ],
span, span,
} }
} }
VDataEnum::Function(func) => Value::Nothing { span }, VDataEnum::Function(_func) => Value::Nothing { span },
VDataEnum::Thread(t, _) => to_nu_val(t.get(), info), VDataEnum::Thread(t, _) => to_nu_val(&t.get(), info),
} })
} }
to_nu_val(code.run(args), code.info().as_ref()) to_nu_val(&code.run(args), &code.info)
} }
Err(e) => Value::Error { Err(e) => Value::Error {
error: Box::new(ShellError::IncorrectValue { error: Box::new(ShellError::IncorrectValue {

View File

@ -1,11 +1,11 @@
use std::{fmt::Debug, process::Command, sync::Arc}; use std::{fmt::Debug, process::Command};
use crate::{ use crate::{
lang::{ lang::{
code_macro::MacroError, code_macro::MacroError,
code_parsed::*, code_parsed::*,
code_runnable::RScript, code_runnable::RScript,
fmtgs::{FormatGs, FormatWithGs}, fmtgs::FormatGs,
global_info::{GSInfo, GlobalScriptInfo}, global_info::{GSInfo, GlobalScriptInfo},
to_runnable::{self, ToRunnableError}, to_runnable::{self, ToRunnableError},
val_data::VDataEnum, val_data::VDataEnum,
@ -101,7 +101,7 @@ impl FormatGs for Error {
fn fmtgs( fn fmtgs(
&self, &self,
f: &mut std::fmt::Formatter, f: &mut std::fmt::Formatter,
info: Option<&GlobalScriptInfo>, _info: Option<&GlobalScriptInfo>,
form: &mut crate::lang::fmtgs::FormatInfo, form: &mut crate::lang::fmtgs::FormatInfo,
file: Option<&crate::parsing::file::File>, file: Option<&crate::parsing::file::File>,
) -> std::fmt::Result { ) -> std::fmt::Result {
@ -158,7 +158,7 @@ impl std::fmt::Display for CannotFindPathForLibrary {
} }
pub fn parse_step_lib_paths( pub fn parse_step_lib_paths(
file: &mut File, file: &mut File,
ginfo: &GlobalScriptInfo, _ginfo: &GlobalScriptInfo,
) -> Result<Vec<Command>, CannotFindPathForLibrary> { ) -> Result<Vec<Command>, CannotFindPathForLibrary> {
let mut libs = vec![]; let mut libs = vec![];
loop { loop {
@ -166,13 +166,14 @@ pub fn parse_step_lib_paths(
let pos = file.get_pos().clone(); let pos = file.get_pos().clone();
let line = file.next_line(); let line = file.next_line();
if line.starts_with("lib ") { if line.starts_with("lib ") {
let path_to_executable = match libs::path::path_from_string(&line[4..], file.path()) { let path_to_executable =
Some(v) => v, match crate::pathutil::path_from_string(&line[4..], file.path(), true) {
None => return Err(CannotFindPathForLibrary(line[4..].to_string())), Some(v) => v,
}; None => return Err(CannotFindPathForLibrary(line[4..].to_string())),
};
let mut cmd = Command::new(&path_to_executable); let mut cmd = Command::new(&path_to_executable);
if let Some(parent) = path_to_executable.parent() { if let Some(parent) = path_to_executable.parent() {
cmd.current_dir(parent.clone()); cmd.current_dir(parent);
} }
libs.push(cmd); libs.push(cmd);
} else { } else {
@ -190,7 +191,7 @@ pub fn parse_step_interpret(
let o = SFunction::new( let o = SFunction::new(
vec![( vec![(
"args".to_string(), "args".to_string(),
VSingleType::List(VSingleType::String.into()).to(), VSingleType::List(VSingleType::Any.into()).to(),
)], )],
SStatementEnum::Block(parse_block_advanced(file, Some(false), true, true, false)?).to(), SStatementEnum::Block(parse_block_advanced(file, Some(false), true, true, false)?).to(),
); );
@ -251,12 +252,12 @@ impl FormatGs for ParseError {
fn fmtgs( fn fmtgs(
&self, &self,
f: &mut std::fmt::Formatter, f: &mut std::fmt::Formatter,
info: Option<&GlobalScriptInfo>, _info: Option<&GlobalScriptInfo>,
form: &mut crate::lang::fmtgs::FormatInfo, form: &mut crate::lang::fmtgs::FormatInfo,
file: Option<&crate::parsing::file::File>, file: Option<&crate::parsing::file::File>,
) -> std::fmt::Result { ) -> std::fmt::Result {
self.err.fmtgs(f, self.info.as_ref(), form, file)?; self.err.fmtgs(f, self.info.as_ref(), form, file)?;
writeln!(f); writeln!(f)?;
if let Some(location_end) = self.location_end { if let Some(location_end) = self.location_end {
writeln!(f, " from {} to {}", self.location, location_end)?; writeln!(f, " from {} to {}", self.location, location_end)?;
if let Some(file) = file { if let Some(file) = file {
@ -849,7 +850,7 @@ pub mod implementation {
}; };
out.derefs = derefs; out.derefs = derefs;
out.force_output_type = force_opt; out.force_output_type = force_opt;
let err_end_of_original_statement = *file.get_pos(); let _err_end_of_original_statement = *file.get_pos();
// special characters that can follow a statement (loop because these can be chained) // special characters that can follow a statement (loop because these can be chained)
loop { loop {
file.skip_whitespaces(); file.skip_whitespaces();

View File

@ -1,6 +1,10 @@
use std::path::PathBuf; use std::path::PathBuf;
pub fn path_from_string(path: &str, script_path: &PathBuf) -> Option<PathBuf> { pub fn path_from_string(
path: &str,
script_path: &PathBuf,
fallback_to_lib_dir: bool,
) -> Option<PathBuf> {
let path = PathBuf::from(path); let path = PathBuf::from(path);
if path.is_absolute() { if path.is_absolute() {
return Some(path); return Some(path);
@ -19,10 +23,12 @@ pub fn path_from_string(path: &str, script_path: &PathBuf) -> Option<PathBuf> {
return Some(p); return Some(p);
} }
} }
if let Ok(mers_lib_dir) = std::env::var("MERS_LIB_DIR") { if fallback_to_lib_dir {
let p = PathBuf::from(mers_lib_dir).join(&path); if let Ok(mers_lib_dir) = std::env::var("MERS_LIB_DIR") {
if p.exists() { let p = PathBuf::from(mers_lib_dir).join(&path);
return Some(p); if p.exists() {
return Some(p);
}
} }
} }
None None

View File

@ -1,8 +1,8 @@
use std::{path::PathBuf, thread::JoinHandle, time::Instant}; use std::{path::PathBuf, thread::JoinHandle};
use crate::{ use crate::{
lang::{code_runnable::RScript, fmtgs::FormatGs, global_info::GSInfo, val_data::VDataEnum}, lang::{code_runnable::RScript, fmtgs::FormatGs, val_data::VDataEnum},
parsing::{self, file::File, parse::ScriptError}, parsing::{self, file::File},
}; };
mod base_comments; mod base_comments;