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::{
|
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 {
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if let Self::TryAwait = self {
|
||||||
|
let mut o = VSingleType::Tuple(vec![out]).to();
|
||||||
|
o.add_type(VSingleType::Tuple(vec![]), info);
|
||||||
|
o
|
||||||
|
} else {
|
||||||
out
|
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 _)),
|
||||||
|
@ -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)
|
||||||
|
@ -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)?;
|
||||||
}
|
}
|
||||||
|
@ -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 mut val = v.run(info);
|
let 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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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}")
|
||||||
|
@ -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::{
|
|
||||||
builtins,
|
|
||||||
global_info::GlobalScriptInfo,
|
global_info::GlobalScriptInfo,
|
||||||
val_data::{VData, VDataEnum},
|
val_data::{VData, VDataEnum},
|
||||||
val_type::{VSingleType, VType},
|
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(¤t_types, ginfo).expect("invalid args????");
|
let out = o.out_by_statement(¤t_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)?;
|
||||||
|
@ -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, " ")?;
|
||||||
}
|
}
|
||||||
|
@ -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, ")")?;
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
@ -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}.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) => {
|
||||||
|
@ -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)
|
||||||
to_nu_val(code.run(args), code.info().as_ref())
|
|
||||||
}
|
}
|
||||||
Err(e) => Value::Error {
|
Err(e) => Value::Error {
|
||||||
error: Box::new(ShellError::IncorrectValue {
|
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::{
|
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 =
|
||||||
|
match crate::pathutil::path_from_string(&line[4..], file.path(), true) {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => return Err(CannotFindPathForLibrary(line[4..].to_string())),
|
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();
|
||||||
|
@ -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,11 +23,13 @@ pub fn path_from_string(path: &str, script_path: &PathBuf) -> Option<PathBuf> {
|
|||||||
return Some(p);
|
return Some(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if fallback_to_lib_dir {
|
||||||
if let Ok(mers_lib_dir) = std::env::var("MERS_LIB_DIR") {
|
if let Ok(mers_lib_dir) = std::env::var("MERS_LIB_DIR") {
|
||||||
let p = PathBuf::from(mers_lib_dir).join(&path);
|
let p = PathBuf::from(mers_lib_dir).join(&path);
|
||||||
if p.exists() {
|
if p.exists() {
|
||||||
return Some(p);
|
return Some(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user