added nushell support.

This commit is contained in:
Dummi26 2023-04-30 17:31:50 +02:00
parent 1a446248e4
commit 0feb1b8778
7 changed files with 1163 additions and 25 deletions

View File

@ -34,9 +34,12 @@ The compiler checks your program. It will guarantee type-safety. If a variable h
## building mers ## building mers
to use mers, clone this repo and compile it using cargo. (if you don't have rustc and cargo, get it from https://rustup.rs/. the mers project is in the mers subdirectory, one level deeper than this readme.) Build scripts can be found in build_scripts/ and compile mers using cargo. If you don't have rustc and cargo, install it using [rustup](https://rustup.rs/).
for simplicity, i will assume you have the executable in your path and it is named mers. Since this probably isn't the case, just know that `mers` can be replaced with `cargo run --release` in all of the following commands. If you're using [Nushell](https://www.nushell.sh/), there is a script that integrates mers, since most mers values can be converted to ones nu understands.
I would recommend that you put the normal mers binary in your PATH even if you want to use mers-nu, because it has more CLI options.
For simplicity, i will assume you have the executable in your path and it is named mers. Since this probably isn't the case, just know that `mers` can be replaced with `cargo run --release` in all of the following commands, assuming you are located in the mers/ directory.
### running from a file ### running from a file

1089
mers/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -14,3 +14,12 @@ edit = "0.1.4"
notify = "5.1.0" notify = "5.1.0"
regex = "1.7.2" regex = "1.7.2"
static_assertions = "1.1.0" static_assertions = "1.1.0"
nu-plugin = { version = "0.79.0", optional = true }
nu-protocol = { version = "0.79.0", features = ["plugin"], optional = true }
[features]
# default = ["nushell_plugin"]
nushell_plugin = ["dep:nu-plugin", "dep:nu-protocol"]
[profile.nushellplugin]
inherits = "release"

View File

@ -309,7 +309,7 @@ where
't' | 'l' => { 't' | 'l' => {
let mut v = vec![]; let mut v = vec![];
loop { loop {
if stdout.one_byte().unwrap() == '\n' as _ { if stdout.one_byte().unwrap() == '\n' as u8 {
break if id_byte == 't' { break if id_byte == 't' {
VDataEnum::Tuple(v) VDataEnum::Tuple(v)
} else { } else {

View File

@ -7,11 +7,20 @@ use notify::Watcher as FsWatcher;
mod interactive_mode; mod interactive_mode;
mod libs; mod libs;
#[cfg(feature = "nushell_plugin")]
mod nushell_plugin;
mod parse; mod parse;
mod script; mod script;
mod tutor; mod tutor;
fn main() { fn main() {
#[cfg(not(feature = "nushell_plugin"))]
normal_main();
#[cfg(feature = "nushell_plugin")]
nushell_plugin::main();
}
fn normal_main() {
let args: Vec<_> = std::env::args().skip(1).collect(); let args: Vec<_> = std::env::args().skip(1).collect();
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
let args = if args.len() == 0 { let args = if args.len() == 0 {
@ -125,7 +134,10 @@ fn main() {
println!("Output ({}s)\n{out}", elapsed.as_secs_f64()); println!("Output ({}s)\n{out}", elapsed.as_secs_f64());
} }
Err(e) => { Err(e) => {
println!("Couldn't compile:\n{}", e.0.with_file_and_gsinfo(&file, e.1.as_ref())); println!(
"Couldn't compile:\n{}",
e.0.with_file_and_gsinfo(&file, e.1.as_ref())
);
std::process::exit(99); std::process::exit(99);
} }
} }

View File

@ -8,7 +8,7 @@ use crate::libs;
use super::{ use super::{
code_runnable::RStatement, code_runnable::RStatement,
global_info::{GlobalScriptInfo, GSInfo}, global_info::{GSInfo, GlobalScriptInfo},
val_data::{thread::VDataThreadEnum, VData, VDataEnum}, val_data::{thread::VDataThreadEnum, VData, VDataEnum},
val_type::{VSingleType, VType}, val_type::{VSingleType, VType},
}; };
@ -276,14 +276,18 @@ impl BuiltinFunction {
Self::Sleep => { Self::Sleep => {
input.len() == 1 input.len() == 1
&& input[0] && input[0]
.fits_in(&VType { .fits_in(
types: vec![VSingleType::Int, VSingleType::Float], &VType {
}, info) types: vec![VSingleType::Int, VSingleType::Float],
},
info,
)
.is_empty() .is_empty()
} }
Self::Exit => { Self::Exit => {
input.len() == 0 input.len() == 0
|| (input.len() == 1 && input[0].fits_in(&VSingleType::Int.to(), info).is_empty()) || (input.len() == 1
&& input[0].fits_in(&VSingleType::Int.to(), info).is_empty())
} }
// TODO! // TODO!
Self::FsList => true, Self::FsList => true,
@ -307,7 +311,8 @@ impl BuiltinFunction {
input.len() == 1 && input[0].fits_in(&VSingleType::String.to(), info).is_empty() input.len() == 1 && input[0].fits_in(&VSingleType::String.to(), info).is_empty()
} }
Self::RunCommand | Self::RunCommandGetBytes => { Self::RunCommand | Self::RunCommandGetBytes => {
if input.len() >= 1 && input[0].fits_in(&VSingleType::String.to(), info).is_empty() { if input.len() >= 1 && input[0].fits_in(&VSingleType::String.to(), info).is_empty()
{
if input.len() == 1 { if input.len() == 1 {
true true
} else if input.len() == 2 { } else if input.len() == 2 {
@ -328,11 +333,15 @@ impl BuiltinFunction {
types: vec![VSingleType::Int, VSingleType::Float], types: vec![VSingleType::Int, VSingleType::Float],
}; };
let st = VSingleType::String.to(); let st = VSingleType::String.to();
(input[0].fits_in(&num, info).is_empty() && input[1].fits_in(&num, info).is_empty()) (input[0].fits_in(&num, info).is_empty()
|| (input[0].fits_in(&st, info).is_empty() && input[1].fits_in(&st, info).is_empty()) && input[1].fits_in(&num, info).is_empty())
|| (input[0].fits_in(&st, info).is_empty()
&& input[1].fits_in(&st, info).is_empty())
} }
} }
Self::Not => input.len() == 1 && input[0].fits_in(&VSingleType::Bool.to(), info).is_empty(), Self::Not => {
input.len() == 1 && input[0].fits_in(&VSingleType::Bool.to(), info).is_empty()
}
Self::And | Self::Or => { Self::And | Self::Or => {
input.len() == 2 input.len() == 2
&& input && input
@ -354,7 +363,8 @@ impl BuiltinFunction {
let num = VType { let num = VType {
types: vec![VSingleType::Int, VSingleType::Float], types: vec![VSingleType::Int, VSingleType::Float],
}; };
input[0].fits_in(&num, info).is_empty() && input[1].fits_in(&num, info).is_empty() input[0].fits_in(&num, info).is_empty()
&& input[1].fits_in(&num, info).is_empty()
} }
} }
// TODO! check that we pass a reference to a list! // TODO! check that we pass a reference to a list!
@ -462,12 +472,15 @@ impl BuiltinFunction {
Self::IndexOf => { Self::IndexOf => {
input.len() == 2 input.len() == 2
&& input.iter().all(|v| { && input.iter().all(|v| {
v.fits_in(&VType { v.fits_in(
types: vec![ &VType {
VSingleType::String, types: vec![
VSingleType::Reference(Box::new(VSingleType::String)), VSingleType::String,
], VSingleType::Reference(Box::new(VSingleType::String)),
}, info) ],
},
info,
)
.is_empty() .is_empty()
}) })
} }
@ -773,7 +786,10 @@ impl BuiltinFunction {
} }
BuiltinFunction::Println => { BuiltinFunction::Println => {
if let VDataEnum::String(arg) = args[0].run(vars, info).data { if let VDataEnum::String(arg) = args[0].run(vars, info).data {
#[cfg(not(feature = "nushell_plugin"))]
println!("{}", arg); println!("{}", arg);
#[cfg(feature = "nushell_plugin")]
eprintln!("{}", arg);
VDataEnum::Tuple(vec![]).to() VDataEnum::Tuple(vec![]).to()
} else { } else {
unreachable!() unreachable!()
@ -781,12 +797,20 @@ impl BuiltinFunction {
} }
BuiltinFunction::Debug => { BuiltinFunction::Debug => {
let val = args[0].run(vars, info); let val = args[0].run(vars, info);
#[cfg(not(feature = "nushell_plugin"))]
println!( println!(
"{} :: {} :: {}", "{} :: {} :: {}",
args[0].out(info).gsi(info.clone()), args[0].out(info).gsi(info.clone()),
val.out().gsi(info.clone()), val.out().gsi(info.clone()),
val.gsi(info.clone()) val.gsi(info.clone())
); );
#[cfg(feature = "nushell_plugin")]
eprintln!(
"{} :: {} :: {}",
args[0].out(info).gsi(info.clone()),
val.out().gsi(info.clone()),
val.gsi(info.clone())
);
VDataEnum::Tuple(vec![]).to() VDataEnum::Tuple(vec![]).to()
} }
Self::StdinReadLine => { Self::StdinReadLine => {

View File

@ -2,7 +2,7 @@ use std::sync::{Arc, Mutex};
use super::{ use super::{
builtins::BuiltinFunction, builtins::BuiltinFunction,
global_info::{GlobalScriptInfo, GSInfo}, global_info::{GSInfo, GlobalScriptInfo},
to_runnable::ToRunnableError, to_runnable::ToRunnableError,
val_data::{VData, VDataEnum}, val_data::{VData, VDataEnum},
val_type::{VSingleType, VType}, val_type::{VSingleType, VType},
@ -320,7 +320,9 @@ impl RStatementEnum {
} }
Self::Loop(c) => c.out(info).matches().1, Self::Loop(c) => c.out(info).matches().1,
Self::For(_, _, b) => VSingleType::Tuple(vec![]).to() | b.out(info).matches().1, Self::For(_, _, b) => VSingleType::Tuple(vec![]).to() | b.out(info).matches().1,
Self::BuiltinFunction(f, args) => f.returns(args.iter().map(|rs| rs.out(info)).collect(), info), Self::BuiltinFunction(f, args) => {
f.returns(args.iter().map(|rs| rs.out(info)).collect(), info)
}
Self::Switch(switch_on, cases) => { Self::Switch(switch_on, cases) => {
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 mut might_return_empty = switch_on.is_empty();
@ -371,7 +373,7 @@ impl RScript {
if main.inputs.len() != 1 { if main.inputs.len() != 1 {
return Err(ToRunnableError::MainWrongInput); return Err(ToRunnableError::MainWrongInput);
} }
Ok(Self { main, info: info }) Ok(Self { main, info })
} }
pub fn run(&self, args: Vec<String>) -> VData { pub fn run(&self, args: Vec<String>) -> VData {
let mut vars = Vec::with_capacity(self.info.vars); let mut vars = Vec::with_capacity(self.info.vars);
@ -387,4 +389,7 @@ impl RScript {
} }
self.main.run(&vars, &self.info) self.main.run(&vars, &self.info)
} }
pub fn info(&self) -> &GSInfo {
&self.info
}
} }