mirror of
https://github.com/Dummi26/mers.git
synced 2025-03-10 14:13:52 +01:00
fixed warnings, cargo clippy, and mers-nu
This commit is contained in:
parent
50e11dc967
commit
46dbb13e0f
@ -1,12 +1,9 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
io::{BufRead, Stdin, StdinLock, Stdout, StdoutLock, Write},
|
||||
};
|
||||
use std::io::{Stdin, StdinLock, Write};
|
||||
|
||||
use crate::lang::{val_data::VData, val_type::VType};
|
||||
use crate::lang::val_type::VType;
|
||||
|
||||
use super::{
|
||||
comms::{self, ByteData, ByteDataA, Message, MessageResponse, RespondableMessage},
|
||||
use super::libs::{
|
||||
comms::{self, ByteData, ByteDataA, Message, RespondableMessage},
|
||||
LibInitInfo, LibInitReq,
|
||||
};
|
||||
|
||||
@ -18,6 +15,7 @@ pub struct MyLib {
|
||||
pub callbacks: Callbacks,
|
||||
enum_variants: Vec<(String, usize)>,
|
||||
stdin: StdinLock<'static>,
|
||||
#[allow(unused)]
|
||||
stdin_no_lock: Stdin,
|
||||
}
|
||||
impl MyLib {
|
||||
@ -32,12 +30,14 @@ impl MyLib {
|
||||
let mut stdout = stdout_no_lock.lock();
|
||||
let mut stdin = stdin_no_lock.lock();
|
||||
// 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);
|
||||
stdout
|
||||
.write(init_req.as_byte_data_vec().as_slice())
|
||||
.write_all(init_req.as_byte_data_vec().as_slice())
|
||||
.unwrap();
|
||||
stdout.flush();
|
||||
stdout.flush().unwrap();
|
||||
let enum_variants = LibInitInfo::from_byte_data(&mut stdin).unwrap();
|
||||
Self {
|
||||
// name: name.clone(),
|
||||
@ -56,10 +56,13 @@ impl MyLib {
|
||||
fn get_one_msg(&mut self) -> Result<Result<(), Message>, std::io::Error> {
|
||||
let id = u128::from_byte_data(&mut self.stdin)?;
|
||||
let message = Message::from_byte_data(&mut self.stdin)?;
|
||||
match message {
|
||||
Message::RunFunction(msg) => self.callbacks.run_function.run(Respondable::new(id, msg)),
|
||||
};
|
||||
Ok(Ok(()))
|
||||
Ok(match message {
|
||||
Message::RunFunction(msg) => self
|
||||
.callbacks
|
||||
.run_function
|
||||
.run(Respondable::new(id, msg))
|
||||
.map_err(|e| Message::RunFunction(e.msg)),
|
||||
})
|
||||
}
|
||||
pub fn get_next_unhandled_message(&mut self) -> Result<(), Message> {
|
||||
loop {
|
||||
@ -68,7 +71,7 @@ impl MyLib {
|
||||
// unhandled message. return it to be handeled or included in the error
|
||||
Ok(Err(msg)) => return Err(msg),
|
||||
// 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) {
|
||||
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
|
||||
.write(&self.msg.respond(with).as_byte_data_vec())
|
||||
.write_all(&self.msg.respond(with).as_byte_data_vec())
|
||||
.unwrap();
|
||||
stdout.flush().unwrap();
|
||||
}
|
||||
@ -117,14 +120,14 @@ impl Callbacks {
|
||||
}
|
||||
pub struct Callback<M>
|
||||
where
|
||||
M: super::comms::RespondableMessage,
|
||||
M: RespondableMessage,
|
||||
{
|
||||
pub nonconsuming: Vec<Box<dyn FnMut(&M)>>,
|
||||
pub consuming: Option<Box<dyn FnMut(Respondable<M>)>>,
|
||||
}
|
||||
impl<M> Callback<M>
|
||||
where
|
||||
M: super::comms::RespondableMessage,
|
||||
M: RespondableMessage,
|
||||
{
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
@ -1,11 +1,4 @@
|
||||
use std::{
|
||||
io::Write,
|
||||
path::PathBuf,
|
||||
sync::{Arc, Mutex},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::libs;
|
||||
use std::{io::Write, path::PathBuf, sync::Arc, time::Duration};
|
||||
|
||||
use super::{
|
||||
code_runnable::RStatement,
|
||||
@ -42,6 +35,7 @@ pub enum BuiltinFunction {
|
||||
Run,
|
||||
Thread,
|
||||
Await,
|
||||
TryAwait,
|
||||
Sleep,
|
||||
Exit,
|
||||
// FS
|
||||
@ -109,6 +103,7 @@ impl BuiltinFunction {
|
||||
"run" => Self::Run,
|
||||
"thread" => Self::Thread,
|
||||
"await" => Self::Await,
|
||||
"try_await" => Self::TryAwait,
|
||||
"sleep" => Self::Sleep,
|
||||
"exit" => Self::Exit,
|
||||
// "command" => Self::Command,
|
||||
@ -271,7 +266,7 @@ impl BuiltinFunction {
|
||||
false
|
||||
}
|
||||
}
|
||||
Self::Await => {
|
||||
Self::Await | Self::TryAwait => {
|
||||
input.len() == 1
|
||||
&& input[0]
|
||||
.types
|
||||
@ -594,7 +589,7 @@ impl BuiltinFunction {
|
||||
unreachable!("run or thread called without args")
|
||||
}
|
||||
}
|
||||
Self::Await => {
|
||||
Self::Await | Self::TryAwait => {
|
||||
if let Some(v) = input.first() {
|
||||
let mut out = VType { types: vec![] };
|
||||
for v in &v.types {
|
||||
@ -604,7 +599,13 @@ impl BuiltinFunction {
|
||||
unreachable!("await called with non-thread arg")
|
||||
}
|
||||
}
|
||||
if let Self::TryAwait = self {
|
||||
let mut o = VSingleType::Tuple(vec![out]).to();
|
||||
o.add_type(VSingleType::Tuple(vec![]), info);
|
||||
o
|
||||
} else {
|
||||
out
|
||||
}
|
||||
} else {
|
||||
unreachable!("await called without args")
|
||||
}
|
||||
@ -795,7 +796,7 @@ impl BuiltinFunction {
|
||||
pub fn run(&self, args: &Vec<RStatement>, info: &GSInfo) -> VData {
|
||||
match self {
|
||||
Self::Assume1 => {
|
||||
let mut a0 = args[0].run(info);
|
||||
let a0 = args[0].run(info);
|
||||
match a0.operate_on_data_immut(|v| {
|
||||
if let VDataEnum::Tuple(v) = v {
|
||||
if let Some(v) = v.get(0) {
|
||||
@ -877,12 +878,12 @@ impl BuiltinFunction {
|
||||
#[cfg(not(feature = "nushell_plugin"))]
|
||||
{
|
||||
print!("{}", arg);
|
||||
std::io::stdout().flush();
|
||||
_ = std::io::stdout().flush();
|
||||
}
|
||||
#[cfg(feature = "nushell_plugin")]
|
||||
{
|
||||
eprint!("{}", arg);
|
||||
std::io::stderr().flush();
|
||||
_ = std::io::stderr().flush();
|
||||
}
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
} else {
|
||||
@ -991,7 +992,7 @@ impl BuiltinFunction {
|
||||
var.lock().unwrap().0 = val;
|
||||
}
|
||||
let out_type = f
|
||||
.out(
|
||||
.out_by_map(
|
||||
&run_input_types.iter().map(|v| v.clone().into()).collect(),
|
||||
&info,
|
||||
)
|
||||
@ -1014,6 +1015,18 @@ impl BuiltinFunction {
|
||||
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| {
|
||||
match v {
|
||||
VDataEnum::Int(v) => std::thread::sleep(Duration::from_secs(*v as _)),
|
||||
|
@ -5,7 +5,9 @@ use crate::parsing::{
|
||||
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 [...])
|
||||
|
||||
@ -30,7 +32,11 @@ pub fn parse_macro(file: &mut File) -> Result<Macro, MacroError> {
|
||||
}
|
||||
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() {
|
||||
val
|
||||
} else {
|
||||
@ -57,7 +63,7 @@ fn parse_mers_code(file: &mut File) -> Result<RScript, MacroError> {
|
||||
let path = parse_string_val(file);
|
||||
#[cfg(debug_assertions)]
|
||||
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");
|
||||
let mut file = File::new(
|
||||
fs::read_to_string(&path)
|
||||
|
@ -1,6 +1,4 @@
|
||||
use std::fmt::{self, Display, Formatter, Pointer};
|
||||
|
||||
use crate::lang::global_info::ColorFormatMode;
|
||||
use std::fmt::{self, Display, Formatter};
|
||||
|
||||
use super::{
|
||||
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
|
||||
}
|
||||
// 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.
|
||||
@ -115,7 +108,7 @@ impl FormatGs for SStatementEnum {
|
||||
}
|
||||
Self::List(v) => {
|
||||
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)?;
|
||||
write!(f, " ")?;
|
||||
}
|
||||
@ -136,7 +129,7 @@ impl FormatGs for SStatementEnum {
|
||||
)?;
|
||||
for (i, arg) in args.iter().enumerate() {
|
||||
if i != 0 {
|
||||
write!(f, " ");
|
||||
write!(f, " ")?;
|
||||
}
|
||||
arg.fmtgs(f, info, form, file)?;
|
||||
}
|
||||
|
@ -1,8 +1,4 @@
|
||||
use std::{
|
||||
assert_eq, eprintln,
|
||||
ops::Deref,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use super::{
|
||||
builtins::BuiltinFunction,
|
||||
@ -66,7 +62,7 @@ pub struct RFunction {
|
||||
pub out_map: Vec<(Vec<VType>, VType)>,
|
||||
}
|
||||
impl PartialEq for RFunction {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
fn eq(&self, _other: &Self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
@ -77,7 +73,7 @@ impl RFunction {
|
||||
pub fn run(&self, info: &GSInfo) -> VData {
|
||||
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.
|
||||
let mut empty = true;
|
||||
let out = self
|
||||
@ -101,15 +97,30 @@ impl RFunction {
|
||||
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.out_map.iter().fold(VType::empty(), |mut t, (_, v)| {
|
||||
t.add_typesr(v, info);
|
||||
t
|
||||
})
|
||||
}
|
||||
pub fn in_types(&self) -> &Vec<VType> {
|
||||
&self.input_types
|
||||
pub fn out_by_statement(&self, input_types: &Vec<VType>, info: &GlobalScriptInfo) -> VType {
|
||||
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 {
|
||||
pub fn run(&self, info: &GSInfo) -> VData {
|
||||
let out = self.statement.run(info);
|
||||
let mut o = if let Some((v, is_init)) = &self.output_to {
|
||||
'init: {
|
||||
let mut o = if let Some((v, _is_init)) = &self.output_to {
|
||||
// // 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)
|
||||
// if *is_init && *derefs == 0 {
|
||||
// Self::assign_to(out, v.run(info), info);
|
||||
// break 'init;
|
||||
// }
|
||||
let mut val = v.run(info);
|
||||
let val = v.run(info);
|
||||
out.assign_to(val, info);
|
||||
// val.assign(out);
|
||||
}
|
||||
VDataEnum::Tuple(vec![]).to()
|
||||
} else {
|
||||
out
|
||||
@ -226,7 +235,7 @@ impl RStatementEnum {
|
||||
Self::For(v, c, b) => {
|
||||
// matching values also break with value from a for loop.
|
||||
let vv = v.run(info);
|
||||
let mut in_loop = |c: VData| {
|
||||
let in_loop = |c: VData| {
|
||||
c.assign_to(vv.clone_mut(), info);
|
||||
b.run(info)
|
||||
};
|
||||
@ -270,7 +279,7 @@ impl RStatementEnum {
|
||||
break;
|
||||
}
|
||||
},
|
||||
VDataEnum::Reference(r) => return None,
|
||||
VDataEnum::Reference(_r) => return None,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Some(oval)
|
||||
@ -355,7 +364,7 @@ impl RStatementEnum {
|
||||
}
|
||||
}
|
||||
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"),
|
||||
Self::LibFunctionCall(.., out) => out.clone(),
|
||||
Self::Block(b) => b.out(info),
|
||||
@ -379,13 +388,13 @@ impl RStatementEnum {
|
||||
}
|
||||
Self::Switch(switch_on, cases, force) => {
|
||||
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 {
|
||||
VType::empty()
|
||||
} else {
|
||||
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() {
|
||||
out.add_types(case.out(info), info);
|
||||
}
|
||||
@ -423,7 +432,7 @@ impl RStatementEnum {
|
||||
|
||||
pub struct RScript {
|
||||
main: RFunction,
|
||||
info: GSInfo,
|
||||
pub info: GSInfo,
|
||||
}
|
||||
impl RScript {
|
||||
pub fn new(main: RFunction, info: GSInfo) -> Result<Self, ToRunnableError> {
|
||||
@ -432,20 +441,8 @@ impl RScript {
|
||||
}
|
||||
Ok(Self { main, info })
|
||||
}
|
||||
pub fn run(&self, args: Vec<String>) -> VData {
|
||||
let mut vars = vec![];
|
||||
vars.push(
|
||||
VDataEnum::List(
|
||||
VSingleType::String.into(),
|
||||
args.into_iter()
|
||||
.map(|v| VDataEnum::String(v).to())
|
||||
.collect(),
|
||||
)
|
||||
.to(),
|
||||
);
|
||||
pub fn run(&self, args: Vec<VData>) -> VData {
|
||||
self.main.inputs[0].lock().unwrap().0 = VDataEnum::List(VSingleType::Any.into(), args).to();
|
||||
self.main.run(&self.info)
|
||||
}
|
||||
pub fn info(&self) -> &GSInfo {
|
||||
&self.info
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use super::global_info::{ColorFormatMode, ColorFormatter, GlobalScriptInfo};
|
||||
use colorize::AnsiColor;
|
||||
|
||||
pub enum Color {
|
||||
Keep,
|
||||
// Keep,
|
||||
Grey,
|
||||
Red,
|
||||
Yellow,
|
||||
@ -17,7 +17,7 @@ pub enum Color {
|
||||
impl Color {
|
||||
pub fn colorize(&self, s: String) -> String {
|
||||
match self {
|
||||
Self::Keep => s,
|
||||
// Self::Keep => s,
|
||||
Self::Grey => s.grey().to_string(),
|
||||
Self::Red => s.red().to_string(),
|
||||
Self::Yellow => s.yellow().to_string(),
|
||||
@ -72,7 +72,7 @@ impl FormatInfo {
|
||||
pub fn go_shallower(&mut self) {
|
||||
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
|
||||
}
|
||||
pub fn variable(&self, info: Option<&GlobalScriptInfo>, s: String) -> String {
|
||||
|
@ -1,23 +1,19 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
default,
|
||||
fmt::Display,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use crate::libs;
|
||||
|
||||
use super::{
|
||||
builtins,
|
||||
fmtgs::Color,
|
||||
val_data::VDataEnum,
|
||||
val_type::{VSingleType, VType},
|
||||
};
|
||||
|
||||
pub type GSInfo = Arc<GlobalScriptInfo>;
|
||||
|
||||
pub struct GlobalScriptInfo {
|
||||
pub libs: Vec<libs::Lib>,
|
||||
pub libs: Vec<crate::libs::Lib>,
|
||||
pub lib_fns: HashMap<String, (usize, usize)>,
|
||||
|
||||
pub enum_variants: HashMap<String, usize>,
|
||||
@ -121,7 +117,6 @@ pub struct Logger {
|
||||
|
||||
pub after_parse: LogKind,
|
||||
|
||||
pub vdata_clone: LogKind,
|
||||
pub vtype_fits_in: LogKind,
|
||||
pub vsingletype_fits_in: LogKind,
|
||||
}
|
||||
@ -130,7 +125,6 @@ impl Logger {
|
||||
Self {
|
||||
logs: Arc::new(Mutex::new(vec![])),
|
||||
after_parse: Default::default(),
|
||||
vdata_clone: Default::default(),
|
||||
vtype_fits_in: Default::default(),
|
||||
vsingletype_fits_in: Default::default(),
|
||||
}
|
||||
@ -140,7 +134,6 @@ impl Logger {
|
||||
#[derive(Debug)]
|
||||
pub enum LogMsg {
|
||||
AfterParse(String),
|
||||
VDataClone(Option<String>, VDataEnum, usize, usize),
|
||||
VTypeFitsIn(VType, VType, Vec<VSingleType>),
|
||||
VSingleTypeFitsIn(VSingleType, VSingleType, bool),
|
||||
}
|
||||
@ -148,7 +141,6 @@ impl Logger {
|
||||
pub fn log(&self, msg: LogMsg) {
|
||||
let kind = match msg {
|
||||
LogMsg::AfterParse(..) => &self.after_parse,
|
||||
LogMsg::VDataClone(..) => &self.vdata_clone,
|
||||
LogMsg::VTypeFitsIn(..) => &self.vtype_fits_in,
|
||||
LogMsg::VSingleTypeFitsIn(..) => &self.vsingletype_fits_in,
|
||||
};
|
||||
@ -168,17 +160,6 @@ impl Display for LogMsg {
|
||||
Self::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::VSingleTypeFitsIn(a, b, fits) => {
|
||||
write!(f, "VSingleTypeFitsIn :: {a} in {b} ? -> {fits}")
|
||||
|
@ -1,20 +1,14 @@
|
||||
use core::panic;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
eprintln,
|
||||
fmt::{Debug, Display},
|
||||
sync::{Arc, Mutex},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
lang::{
|
||||
builtins,
|
||||
use crate::lang::{
|
||||
global_info::GlobalScriptInfo,
|
||||
val_data::{VData, VDataEnum},
|
||||
val_type::{VSingleType, VType},
|
||||
},
|
||||
libs,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -84,12 +78,12 @@ impl FormatGs for ToRunnableError {
|
||||
write!(f, "Cannot dereference type ")?;
|
||||
og_type.fmtgs(f, info, form, file)?;
|
||||
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, ")")?;
|
||||
Ok(())
|
||||
}
|
||||
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() {
|
||||
if i > 0 {
|
||||
write!(f, ", ")?;
|
||||
@ -277,25 +271,7 @@ fn function(
|
||||
}
|
||||
}
|
||||
}
|
||||
// let out = o.out(¤t_types, ginfo).expect("invalid args????");
|
||||
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
|
||||
};
|
||||
let out = o.out_by_statement(¤t_types, &ginfo);
|
||||
map.push((current_types, out));
|
||||
if was_last {
|
||||
break map;
|
||||
@ -627,11 +603,11 @@ fn statement_adv(
|
||||
RStatementEnum::Switch(switch_on, ncases, *force).to()
|
||||
}
|
||||
SStatementEnum::Match(cases) => {
|
||||
let mut ncases: Vec<(RStatement, RStatement, RStatement)> =
|
||||
let _ncases: Vec<(RStatement, RStatement, RStatement)> =
|
||||
Vec::with_capacity(cases.len());
|
||||
let mut ncases = Vec::with_capacity(cases.len());
|
||||
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() {
|
||||
let mut linfo = linfo.clone();
|
||||
let condition = statement(condition, ginfo, &mut linfo)?;
|
||||
|
@ -1,10 +1,8 @@
|
||||
use std::{
|
||||
fmt::{self, Debug, Display, Formatter},
|
||||
ops::Deref,
|
||||
sync::{Arc, Mutex, MutexGuard},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use super::global_info::LogMsg;
|
||||
use super::{
|
||||
code_runnable::RFunction,
|
||||
fmtgs::FormatGs,
|
||||
@ -68,14 +66,14 @@ impl VData {
|
||||
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.
|
||||
return self.operate_on_data_immut(|v| v.clone()).to();
|
||||
match &mut *self.0.lock().unwrap() {
|
||||
VDataInner::Data(cloned, _data) => {
|
||||
*cloned += 1;
|
||||
VDataInner::ClonedFrom(self.clone_arc()).to()
|
||||
}
|
||||
VDataInner::Mut(inner) => inner.lock().unwrap().clone_data(),
|
||||
VDataInner::ClonedFrom(inner) => inner.clone_data(),
|
||||
}
|
||||
// match &mut *self.0.lock().unwrap() {
|
||||
// VDataInner::Data(cloned, _data) => {
|
||||
// *cloned += 1;
|
||||
// VDataInner::ClonedFrom(self.clone_arc()).to()
|
||||
// }
|
||||
// VDataInner::Mut(inner) => inner.lock().unwrap().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.
|
||||
pub fn clone_mut(&self) -> Self {
|
||||
@ -87,7 +85,7 @@ impl VData {
|
||||
#[cfg(debug_assertions)]
|
||||
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
|
||||
F: FnOnce(&VDataEnum) -> O,
|
||||
{
|
||||
@ -100,7 +98,7 @@ impl VData {
|
||||
/// 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,
|
||||
/// 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
|
||||
F: FnOnce(&mut VDataEnum) -> O,
|
||||
{
|
||||
@ -170,7 +168,7 @@ impl VData {
|
||||
impl Drop for VDataInner {
|
||||
fn drop(&mut 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);
|
||||
}
|
||||
}
|
||||
@ -340,7 +338,7 @@ impl VDataEnum {
|
||||
pub fn noenum(&self) -> Option<VData> {
|
||||
match self {
|
||||
Self::EnumVariant(_, v) => Some(v.clone_data()),
|
||||
v => None,
|
||||
_v => None,
|
||||
}
|
||||
}
|
||||
pub fn get(&self, i: usize) -> Option<VData> {
|
||||
@ -372,19 +370,12 @@ impl VDataEnum {
|
||||
| Self::Function(..)
|
||||
| Self::Thread(..) => None,
|
||||
// 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::Reference(r) => r.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
|
||||
pub fn matches(&self) -> Option<Option<VData>> {
|
||||
match self {
|
||||
@ -397,7 +388,7 @@ impl VDataEnum {
|
||||
}
|
||||
}
|
||||
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 {
|
||||
match &*self.lock() {
|
||||
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) => {
|
||||
write!(f, "[")?;
|
||||
for (i, v) in v.iter().enumerate() {
|
||||
for (_i, v) in v.iter().enumerate() {
|
||||
v.fmtgs(f, info, form, file)?;
|
||||
write!(f, " ")?;
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt::{self, Debug, Display, Formatter},
|
||||
ops::BitOr,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use super::{
|
||||
code_runnable::{RFunction, RStatementEnum},
|
||||
fmtgs::FormatGs,
|
||||
global_info::{self, GSInfo, GlobalScriptInfo},
|
||||
global_info::{GSInfo, GlobalScriptInfo},
|
||||
val_data::VDataEnum,
|
||||
};
|
||||
|
||||
@ -173,7 +171,7 @@ impl VType {
|
||||
Some(out)
|
||||
}
|
||||
pub fn reference(&self) -> Self {
|
||||
let mut out = Self::empty();
|
||||
let _out = Self::empty();
|
||||
Self {
|
||||
types: self
|
||||
.types
|
||||
@ -474,7 +472,7 @@ impl VSingleType {
|
||||
};
|
||||
for (ins, out) in 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() {
|
||||
// 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;
|
||||
@ -572,7 +570,7 @@ impl FormatGs for VSingleType {
|
||||
write!(f, "(")?;
|
||||
for i in inputs {
|
||||
i.fmtgs(f, info, form, file)?;
|
||||
write!(f, " ");
|
||||
write!(f, " ")?;
|
||||
}
|
||||
output.fmtgs(f, info, form, file)?;
|
||||
write!(f, ")")?;
|
||||
|
@ -1,12 +1,12 @@
|
||||
mod inlib;
|
||||
mod lang;
|
||||
mod libs;
|
||||
mod parsing;
|
||||
mod pathutil;
|
||||
|
||||
pub use inlib::MyLib;
|
||||
pub use lang::{global_info::GlobalScriptInfo, val_data::*, val_type::*};
|
||||
pub use libs::{
|
||||
comms::{ByteData, ByteDataA, Message, RespondableMessage},
|
||||
inlib::MyLib,
|
||||
};
|
||||
pub use libs::comms::{ByteData, ByteDataA, Message, RespondableMessage};
|
||||
pub use parsing::*;
|
||||
|
||||
pub mod prelude {
|
||||
|
@ -42,10 +42,10 @@ impl ByteData for Message {
|
||||
where
|
||||
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 {
|
||||
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 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();
|
||||
Ok(str)
|
||||
}
|
||||
@ -503,7 +503,7 @@ impl ByteDataA for VDataEnum {
|
||||
// TODO?
|
||||
Self::Function(_) => vec.push(b'F'),
|
||||
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) => {
|
||||
vec.push(b'E');
|
||||
enum_id.as_byte_data(vec);
|
||||
|
@ -1,26 +1,17 @@
|
||||
pub mod comms;
|
||||
pub mod inlib;
|
||||
pub mod path;
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
io::{self, BufRead, BufReader, Read, Write},
|
||||
path::PathBuf,
|
||||
io::{self, BufReader, Write},
|
||||
process::{Child, ChildStdin, ChildStdout, Command, Stdio},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
lang::{
|
||||
global_info::GlobalScriptInfo,
|
||||
val_data::{VData, VDataEnum},
|
||||
val_type::VType,
|
||||
},
|
||||
libs::comms::{ByteData, ByteDataA},
|
||||
parsing::{file::File, parse},
|
||||
use crate::lang::{
|
||||
global_info::GlobalScriptInfo, to_runnable::ToRunnableError, val_data::VData, val_type::VType,
|
||||
};
|
||||
|
||||
use self::comms::{MessageResponse, RespondableMessage};
|
||||
use self::comms::{ByteData, ByteDataA, RespondableMessage};
|
||||
|
||||
// Libraries are processes that communicate via stdout/stdin.
|
||||
|
||||
@ -59,6 +50,8 @@ pub type LibInitReq<'a> = (
|
||||
);
|
||||
/// Sent by mers to finish initializing a library.
|
||||
/// [enum variants]
|
||||
// used by crate::inlib
|
||||
#[allow(unused)]
|
||||
pub type LibInitInfo = Vec<(String, 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 (args, out) in func.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 {
|
||||
@ -104,13 +101,17 @@ impl Lib {
|
||||
}
|
||||
}
|
||||
let si: LibInitInfoRef = enum_variants.iter().collect();
|
||||
stdin.write(si.as_byte_data_vec().as_slice());
|
||||
stdin.flush();
|
||||
if let Err(e) = stdin.write_all(si.as_byte_data_vec().as_slice()) {
|
||||
return Err(LaunchError::StdioError(e));
|
||||
};
|
||||
if let Err(e) = stdin.flush() {
|
||||
return Err(LaunchError::StdioError(e));
|
||||
};
|
||||
let (task_sender, recv) = std::sync::mpsc::channel::<(
|
||||
u128,
|
||||
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 mut pending = HashMap::new();
|
||||
loop {
|
||||
@ -192,11 +193,11 @@ impl Lib {
|
||||
))
|
||||
.unwrap();
|
||||
// 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
|
||||
.write(msg.msgtype_id().as_byte_data_vec().as_slice())
|
||||
.write_all(msg.msgtype_id().as_byte_data_vec().as_slice())
|
||||
.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();
|
||||
*id = id.wrapping_add(1);
|
||||
recv
|
||||
@ -209,12 +210,18 @@ impl Lib {
|
||||
pub enum LaunchError {
|
||||
NoStdio,
|
||||
CouldNotSpawnProcess(io::Error),
|
||||
StdioError(io::Error),
|
||||
ErrorAddingEnumsOrTypes(ToRunnableError),
|
||||
}
|
||||
impl std::fmt::Display for LaunchError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
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::StdioError(e) => write!(f, "error from stdio: {e}"),
|
||||
Self::ErrorAddingEnumsOrTypes(e) => {
|
||||
write!(f, "error adding enums or types from library: {e}.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
use std::{fs, time::Instant};
|
||||
|
||||
use lang::global_info::ColorFormatMode;
|
||||
use lang::global_info::GlobalScriptInfo;
|
||||
use lang::global_info::LogKind;
|
||||
use notify::Watcher as FsWatcher;
|
||||
use lang::val_data::VDataEnum;
|
||||
|
||||
use crate::lang::fmtgs::FormatGs;
|
||||
|
||||
@ -13,6 +11,7 @@ mod libs;
|
||||
#[cfg(feature = "nushell_plugin")]
|
||||
mod nushell_plugin;
|
||||
mod parsing;
|
||||
mod pathutil;
|
||||
mod tutor;
|
||||
|
||||
fn main() {
|
||||
@ -113,7 +112,6 @@ fn normal_main() {
|
||||
log: true,
|
||||
}
|
||||
}
|
||||
info.log.vdata_clone = f();
|
||||
info.log.vtype_fits_in = f();
|
||||
info.log.vsingletype_fits_in = f();
|
||||
} else {
|
||||
@ -144,7 +142,6 @@ fn normal_main() {
|
||||
None => (verbose_arg, None),
|
||||
};
|
||||
match arg {
|
||||
"vdata_clone" => info.log.vdata_clone = kind(val),
|
||||
"vtype_fits_in" => info.log.vtype_fits_in = kind(val),
|
||||
"vsingletype_fits_in" => info.log.vsingletype_fits_in = kind(val),
|
||||
_ => eprintln!("Warn: -v+ unknown arg '{arg}'."),
|
||||
@ -157,6 +154,7 @@ fn normal_main() {
|
||||
_ => {
|
||||
// basic: open file and watch for fs changes
|
||||
interactive_mode::fs_watcher::playground(interactive_use_new_terminal)
|
||||
.unwrap()
|
||||
}
|
||||
};
|
||||
return;
|
||||
@ -194,7 +192,12 @@ fn normal_main() {
|
||||
match parsing::parse::parse_custom_info(&mut file, info) {
|
||||
Ok(script) => {
|
||||
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) => {
|
||||
|
@ -1,12 +1,14 @@
|
||||
use std::{fs, path::PathBuf};
|
||||
|
||||
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::{
|
||||
lang::{
|
||||
fmtgs::FormatGs,
|
||||
global_info::GlobalScriptInfo,
|
||||
val_data::{VData, VDataEnum},
|
||||
val_type::VType,
|
||||
},
|
||||
parsing,
|
||||
};
|
||||
@ -27,7 +29,24 @@ impl Plugin for MersNuPlugin {
|
||||
)
|
||||
.optional(
|
||||
"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.",
|
||||
)
|
||||
.switch(
|
||||
@ -38,9 +57,9 @@ impl Plugin for MersNuPlugin {
|
||||
}
|
||||
fn run(
|
||||
&mut self,
|
||||
name: &str,
|
||||
_name: &str,
|
||||
call: &nu_plugin::EvaluatedCall,
|
||||
input: &nu_protocol::Value,
|
||||
_input: &nu_protocol::Value,
|
||||
) -> Result<nu_protocol::Value, nu_plugin::LabeledError> {
|
||||
// no need to 'match name {...}' because we only register mers-nu and nothing else.
|
||||
let source: String = call.req(0)?;
|
||||
@ -52,7 +71,7 @@ impl Plugin for MersNuPlugin {
|
||||
parsing::file::File::new(
|
||||
match fs::read_to_string(&source) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
Err(_e) => {
|
||||
return Ok(Value::Error {
|
||||
error: Box::new(ShellError::FileNotFound(source_span)),
|
||||
})
|
||||
@ -64,36 +83,62 @@ impl Plugin for MersNuPlugin {
|
||||
Ok(match parsing::parse::parse(&mut file) {
|
||||
Ok(code) => {
|
||||
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![],
|
||||
};
|
||||
fn to_nu_val(val: VData, info: &GlobalScriptInfo) -> Value {
|
||||
fn to_nu_val(val: &VData, info: &GlobalScriptInfo) -> Value {
|
||||
let span = Span::unknown();
|
||||
match val.data {
|
||||
VDataEnum::Bool(val) => Value::Bool { val, span },
|
||||
val.operate_on_data_immut(|val| match val {
|
||||
VDataEnum::Bool(val) => Value::Bool { val: *val, span },
|
||||
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,
|
||||
},
|
||||
VDataEnum::Float(val) => Value::Float { val, span },
|
||||
VDataEnum::String(val) => Value::String { val, span },
|
||||
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,
|
||||
},
|
||||
VDataEnum::Reference(r) => to_nu_val(
|
||||
std::mem::replace(
|
||||
&mut *r.lock().unwrap(),
|
||||
VDataEnum::Tuple(vec![]).to(),
|
||||
),
|
||||
info,
|
||||
),
|
||||
VDataEnum::Reference(r) => to_nu_val(r, info),
|
||||
VDataEnum::EnumVariant(variant, val) => {
|
||||
let name = info
|
||||
.enum_variants
|
||||
.iter()
|
||||
.find_map(|(name, id)| {
|
||||
if *id == variant {
|
||||
if *id == *variant {
|
||||
Some(name.to_owned())
|
||||
} else {
|
||||
None
|
||||
@ -107,16 +152,16 @@ impl Plugin for MersNuPlugin {
|
||||
val: name,
|
||||
span: span,
|
||||
},
|
||||
to_nu_val(*val, info),
|
||||
to_nu_val(val, info),
|
||||
],
|
||||
span,
|
||||
}
|
||||
}
|
||||
VDataEnum::Function(func) => Value::Nothing { span },
|
||||
VDataEnum::Thread(t, _) => to_nu_val(t.get(), info),
|
||||
VDataEnum::Function(_func) => Value::Nothing { span },
|
||||
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 {
|
||||
error: Box::new(ShellError::IncorrectValue {
|
||||
|
@ -1,11 +1,11 @@
|
||||
use std::{fmt::Debug, process::Command, sync::Arc};
|
||||
use std::{fmt::Debug, process::Command};
|
||||
|
||||
use crate::{
|
||||
lang::{
|
||||
code_macro::MacroError,
|
||||
code_parsed::*,
|
||||
code_runnable::RScript,
|
||||
fmtgs::{FormatGs, FormatWithGs},
|
||||
fmtgs::FormatGs,
|
||||
global_info::{GSInfo, GlobalScriptInfo},
|
||||
to_runnable::{self, ToRunnableError},
|
||||
val_data::VDataEnum,
|
||||
@ -101,7 +101,7 @@ impl FormatGs for Error {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
_info: Option<&GlobalScriptInfo>,
|
||||
form: &mut crate::lang::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
@ -158,7 +158,7 @@ impl std::fmt::Display for CannotFindPathForLibrary {
|
||||
}
|
||||
pub fn parse_step_lib_paths(
|
||||
file: &mut File,
|
||||
ginfo: &GlobalScriptInfo,
|
||||
_ginfo: &GlobalScriptInfo,
|
||||
) -> Result<Vec<Command>, CannotFindPathForLibrary> {
|
||||
let mut libs = vec![];
|
||||
loop {
|
||||
@ -166,13 +166,14 @@ pub fn parse_step_lib_paths(
|
||||
let pos = file.get_pos().clone();
|
||||
let line = file.next_line();
|
||||
if line.starts_with("lib ") {
|
||||
let path_to_executable = match libs::path::path_from_string(&line[4..], file.path()) {
|
||||
let path_to_executable =
|
||||
match crate::pathutil::path_from_string(&line[4..], file.path(), true) {
|
||||
Some(v) => v,
|
||||
None => return Err(CannotFindPathForLibrary(line[4..].to_string())),
|
||||
};
|
||||
let mut cmd = Command::new(&path_to_executable);
|
||||
if let Some(parent) = path_to_executable.parent() {
|
||||
cmd.current_dir(parent.clone());
|
||||
cmd.current_dir(parent);
|
||||
}
|
||||
libs.push(cmd);
|
||||
} else {
|
||||
@ -190,7 +191,7 @@ pub fn parse_step_interpret(
|
||||
let o = SFunction::new(
|
||||
vec![(
|
||||
"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(),
|
||||
);
|
||||
@ -251,12 +252,12 @@ impl FormatGs for ParseError {
|
||||
fn fmtgs(
|
||||
&self,
|
||||
f: &mut std::fmt::Formatter,
|
||||
info: Option<&GlobalScriptInfo>,
|
||||
_info: Option<&GlobalScriptInfo>,
|
||||
form: &mut crate::lang::fmtgs::FormatInfo,
|
||||
file: Option<&crate::parsing::file::File>,
|
||||
) -> std::fmt::Result {
|
||||
self.err.fmtgs(f, self.info.as_ref(), form, file)?;
|
||||
writeln!(f);
|
||||
writeln!(f)?;
|
||||
if let Some(location_end) = self.location_end {
|
||||
writeln!(f, " from {} to {}", self.location, location_end)?;
|
||||
if let Some(file) = file {
|
||||
@ -849,7 +850,7 @@ pub mod implementation {
|
||||
};
|
||||
out.derefs = derefs;
|
||||
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)
|
||||
loop {
|
||||
file.skip_whitespaces();
|
||||
|
@ -1,6 +1,10 @@
|
||||
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);
|
||||
if path.is_absolute() {
|
||||
return Some(path);
|
||||
@ -19,11 +23,13 @@ pub fn path_from_string(path: &str, script_path: &PathBuf) -> Option<PathBuf> {
|
||||
return Some(p);
|
||||
}
|
||||
}
|
||||
if fallback_to_lib_dir {
|
||||
if let Ok(mers_lib_dir) = std::env::var("MERS_LIB_DIR") {
|
||||
let p = PathBuf::from(mers_lib_dir).join(&path);
|
||||
if p.exists() {
|
||||
return Some(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
use std::{path::PathBuf, thread::JoinHandle, time::Instant};
|
||||
use std::{path::PathBuf, thread::JoinHandle};
|
||||
|
||||
use crate::{
|
||||
lang::{code_runnable::RScript, fmtgs::FormatGs, global_info::GSInfo, val_data::VDataEnum},
|
||||
parsing::{self, file::File, parse::ScriptError},
|
||||
lang::{code_runnable::RScript, fmtgs::FormatGs, val_data::VDataEnum},
|
||||
parsing::{self, file::File},
|
||||
};
|
||||
|
||||
mod base_comments;
|
||||
|
Loading…
Reference in New Issue
Block a user