Readme and clippy cleanups

This commit is contained in:
Ava Apples Affine 2023-05-28 23:22:49 +00:00
parent cbd52de91b
commit 8cc0202a7b
13 changed files with 159 additions and 197 deletions

View file

@ -25,8 +25,7 @@ The purpose of Relish is to create a highly portable, easy to integrate language
* Contact * Contact
[[https://matrix.to/#/#relish:matrix.sunnypup.io][Matrix chat: #relish:matrix.sunnypup.io]] [[https://matrix.to/#/#relish:matrix.sunnypup.io][Matrix chat: #relish:matrix.sunnypup.io]]
If you like Relish and want to support me in working on it consider donating: If you like Relish and want to support me in working on it consider donating: [[https://ko-fi.com/avaaffine][Ava's Ko-Fi]].
https://ko-fi.com/avaaffine
* Documentation * Documentation
** Writing in Relish ** Writing in Relish

View file

@ -10,11 +10,11 @@ Readers should be able to run the Relish repl to follow along with this guide an
* Syntax * Syntax
** Data types ** Data types
Relish leverages the following data types: Relish leverages the following data types:
- Strings: delimited by ~'~, ~"~, or ~`~ - Strings: delimited by one of the following: ~' " `~
- Integers: up to 128 bit signed integers - Integers: up to 128 bit signed integers
- Floats: all floats are stored as 64 bit floats - Floats: all floats are stored as 64 bit floats
- Booleans: ~true~ or ~false~ - Booleans: ~true~ or ~false~
- Symbols: an un-delimited chunk of text containing alphanumerics, ~-~, ~_~, or ~?~ - Symbols: an un-delimited chunk of text containing alphanumerics or one of the following: ~- _ ?~
Symbols and Functions can contain data of any type. there is no immediate restriction on what can be set/passed to what..... However, internally Relish is typed, and many builtin functions will get picky about what types are passed to them. Symbols and Functions can contain data of any type. there is no immediate restriction on what can be set/passed to what..... However, internally Relish is typed, and many builtin functions will get picky about what types are passed to them.
** S-Expressions ** S-Expressions

View file

@ -56,9 +56,10 @@ impl fmt::Display for Traceback {
} }
} }
impl std::convert::Into<String> for Traceback {
fn into(self) -> String { impl std::convert::From<Traceback> for String {
format!("{}", self) fn from(arg: Traceback) -> Self {
format!("{}", arg)
} }
} }

View file

@ -49,7 +49,7 @@ pub fn eval(ast: &Seg, syms: &mut SymTable) -> Result<Box<Ctr>, Traceback> {
} }
}, },
Ctr::Lambda(ref l) => return Ok(call_lambda(l, arg_cdr, syms)?.clone()), Ctr::Lambda(ref l) => return Ok(call_lambda(l, arg_cdr, syms)?),
Ctr::Symbol(ref tok) => { Ctr::Symbol(ref tok) => {
let outer_scope_seg_holder: Seg; let outer_scope_seg_holder: Seg;

View file

@ -43,14 +43,12 @@ pub fn lex(document: &String) -> Result<Box<Seg>, Traceback> {
let document_normal = document.clone() + " "; let document_normal = document.clone() + " ";
let tree = process(&document_normal); let tree = process(&document_normal);
// TODO: Make multiple forms of Ok() match tree {
// To represent the multiple passable outcomes
return match tree {
Err(e) => Err(start_trace( Err(e) => Err(start_trace(
("<lex>", format!("Problem lexing document: {:?}", e)) ("<lex>", format!("Problem lexing document: {:?}", e))
.into())), .into())),
Ok(t) => Ok(t), Ok(t) => Ok(t),
}; }
} }
/* The logic used in lex /* The logic used in lex

View file

@ -27,7 +27,7 @@ use std::env::{var, current_dir};
fn get_paths() -> Vec<String> { fn get_paths() -> Vec<String> {
Vec::from_iter(var("PATH") Vec::from_iter(var("PATH")
.unwrap_or("".to_string().into()) .unwrap_or("".to_string())
.split(':') .split(':')
.map(String::from)) .map(String::from))
} }
@ -69,7 +69,7 @@ pub fn run_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
if let Ctr::String(ref filename) = *ast.car { if let Ctr::String(ref filename) = *ast.car {
if filename.ends_with(".rls") { if filename.ends_with(".rls") {
if let Some(filepath) = find_on_path(filename.to_string()) { if let Some(filepath) = find_on_path(filename.to_string()) {
return run(filepath, syms) run(filepath, syms)
.and(Ok(Ctr::None)) .and(Ok(Ctr::None))
} else { } else {
let canonical_path_res = fs::canonicalize(filename); let canonical_path_res = fs::canonicalize(filename);
@ -90,7 +90,7 @@ pub fn run_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
).and(Ok(Ctr::None)) ).and(Ok(Ctr::None))
} }
} else { } else {
return Err(start_trace( Err(start_trace(
("<call script>", "binary called, unimplemented!") ("<call script>", "binary called, unimplemented!")
.into())) .into()))
} }

View file

@ -110,7 +110,7 @@ Example: (pop (1 2 3)) -> (1 (2 3)).
The head can then be accessed by car and the rest can be accessed by cdr."; The head can then be accessed by car and the rest can be accessed by cdr.";
fn pop_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> { fn pop_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> {
if let Ctr::Seg(ref s) = *ast.car { if let Ctr::Seg(ref s) = *ast.car {
if s.len() < 1 { if s.is_empty() {
return Err(start_trace(("pop", "input is empty").into())); return Err(start_trace(("pop", "input is empty").into()));
} }
let mut ret = Seg::new(); let mut ret = Seg::new();
@ -134,7 +134,7 @@ Example: (dq (1 2 3)) -> (3 (1 2)).
The last element can then be accessed by car and the rest can be accessed by cdr."; The last element can then be accessed by car and the rest can be accessed by cdr.";
fn dequeue_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> { fn dequeue_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> {
if let Ctr::Seg(ref s) = *ast.car { if let Ctr::Seg(ref s) = *ast.car {
if s.len() < 1 { if s.is_empty() {
return Err(start_trace(("dequeue", "expected an input").into())); return Err(start_trace(("dequeue", "expected an input").into()));
} }
let mut rest = Seg::new(); let mut rest = Seg::new();

View file

@ -183,7 +183,7 @@ fn let_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
name.clone(), name.clone(),
Symbol::from_ast( Symbol::from_ast(
name, &"variable used in let form".to_string(), name, &"variable used in let form".to_string(),
&Seg::from_mono(Box::new(*var_val_res.unwrap().clone())), &Seg::from_mono(Box::new(*var_val_res.unwrap())),
None), None),
); );
locals.push(name.clone()); locals.push(name.clone());
@ -214,7 +214,7 @@ fn let_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
if !eval_forms.circuit(&mut |eval_form: &Ctr| -> bool { if !eval_forms.circuit(&mut |eval_form: &Ctr| -> bool {
let res: Result<Box<Ctr>, Traceback>; let res: Result<Box<Ctr>, Traceback>;
if let Ctr::Seg(ref eval_tree) = eval_form { if let Ctr::Seg(ref eval_tree) = eval_form {
res = eval(&eval_tree, &mut localsyms); res = eval(eval_tree, &mut localsyms);
} else { } else {
let eval_tree = Seg::from_mono(Box::new(eval_form.clone())); let eval_tree = Seg::from_mono(Box::new(eval_form.clone()));
let intermediate = eval(&eval_tree, &mut localsyms); let intermediate = eval(&eval_tree, &mut localsyms);
@ -234,7 +234,7 @@ fn let_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
return false; return false;
} }
result = res.unwrap().clone(); result = res.unwrap();
true true
}) { }) {
assert!(err_trace.depth() > 0); assert!(err_trace.depth() > 0);
@ -314,7 +314,7 @@ fn while_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
} }
} }
Ok(*(result.unwrap()).clone()) Ok(*(result.unwrap()))
} }
const CIRCUIT_DOCSTRING: &str = "traverses a list of N un-evaluated forms. const CIRCUIT_DOCSTRING: &str = "traverses a list of N un-evaluated forms.

View file

@ -48,7 +48,7 @@ fn eval_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
Err(e) => Err(e.with_trace( Err(e) => Err(e.with_trace(
("eval", "evaluation failure") ("eval", "evaluation failure")
.into())), .into())),
Ok(s) => Ok(*s.clone()), Ok(s) => Ok(*s),
} }
} }
@ -65,7 +65,7 @@ fn eval_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
Err(e) => Err(e.with_trace( Err(e) => Err(e.with_trace(
("eval", "evaluation failure") ("eval", "evaluation failure")
.into())), .into())),
Ok(s) => Ok(*s.clone()), Ok(s) => Ok(*s),
} }
} else { } else {
Ok(res) Ok(res)
@ -101,7 +101,7 @@ fn help_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
return Err(start_trace(("help", "expected one input").into())); return Err(start_trace(("help", "expected one input").into()));
} }
if let Ctr::Symbol(ref symbol) = *ast.car { if let Ctr::Symbol(ref symbol) = *ast.car {
if let Some(ref sym) = syms.get(symbol) { if let Some(sym) = syms.get(symbol) {
let args_str: String; let args_str: String;
if let ValueType::VarForm(_) = sym.value { if let ValueType::VarForm(_) = sym.value {
args_str = "(its a variable)".to_string(); args_str = "(its a variable)".to_string();
@ -132,18 +132,12 @@ returns true or false according to whether or not the symbol is found in the sym
fn isset_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> { fn isset_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
if ast.len() != 1 { if ast.len() != 1 {
Err(start_trace(("set?", "expcted one input").into())) Err(start_trace(("set?", "expcted one input").into()))
} else { } else if let Ctr::Symbol(ref symbol) = *ast.car {
if let Ctr::Symbol(ref symbol) = *ast.car { Ok(Ctr::Bool(syms.get(symbol).is_some()))
if let Some(_) = syms.get(symbol) {
Ok(Ctr::Bool(true))
} else {
Ok(Ctr::Bool(false))
}
} else { } else {
Err(start_trace(("set?", "expected argument to be a input").into())) Err(start_trace(("set?", "expected argument to be a input").into()))
} }
} }
}
const ENV_DOCSTRING: &str = "takes no arguments const ENV_DOCSTRING: &str = "takes no arguments
prints out all available symbols and their associated values"; prints out all available symbols and their associated values";
@ -166,12 +160,11 @@ fn env_callback(_ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
let mut variables = vec![]; let mut variables = vec![];
for (name, val) in syms.iter() { for (name, val) in syms.iter() {
if let ValueType::VarForm(l) = &val.value { if let ValueType::VarForm(l) = &val.value {
let token: String; let token: String = match l.to_type() {
match l.to_type() { Type::Lambda => format!("{}: <lambda>", name),
Type::Lambda => token = format!("{}: <lambda>", name), Type::Seg => format!("{}: <form>", name),
Type::Seg => token = format!("{}: <form>", name), _ => format!("{}: {}", name, val.value),
_ => token = format!("{}: {}", name, val.value.to_string()), };
}
if token.len() > v_col_len && token.len() < xdim as usize { if token.len() > v_col_len && token.len() < xdim as usize {
v_col_len = token.len(); v_col_len = token.len();
@ -203,7 +196,7 @@ fn env_callback(_ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
print!("{:v_col_len$}", var); print!("{:v_col_len$}", var);
col_iter += 1; col_iter += 1;
if col_iter % n_v_cols == 0 { if col_iter % n_v_cols == 0 {
print!("\n"); println!();
} else { } else {
print!(" "); print!(" ");
} }
@ -214,7 +207,7 @@ fn env_callback(_ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
print!("{:f_col_len$}", func); print!("{:f_col_len$}", func);
col_iter += 1; col_iter += 1;
if col_iter % n_f_cols == 0 { if col_iter % n_f_cols == 0 {
print!("\n"); println!();
} else { } else {
print!(" "); print!(" ");
} }
@ -250,8 +243,7 @@ fn lambda_callback(
} }
}) { }) {
Err(start_trace(("lambda", "lambda inputs should all be symbols").into())) Err(start_trace(("lambda", "lambda inputs should all be symbols").into()))
} else { } else if let Ctr::Seg(ref eval_head) = *ast.cdr {
if let Ctr::Seg(ref eval_head) = *ast.cdr {
if let Ctr::Seg(_) = *eval_head.car { if let Ctr::Seg(_) = *eval_head.car {
Ok(Ctr::Lambda(UserFn{ Ok(Ctr::Lambda(UserFn{
ast: Box::new(eval_head.clone()), ast: Box::new(eval_head.clone()),
@ -263,7 +255,6 @@ fn lambda_callback(
} else { } else {
Err(start_trace(("lambda", "not enough args").into())) Err(start_trace(("lambda", "not enough args").into()))
} }
}
} else { } else {
Err(start_trace(("lambda", "expected list of lambda inputs").into())) Err(start_trace(("lambda", "expected list of lambda inputs").into()))
} }
@ -296,8 +287,7 @@ fn setdoc_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
Err(start_trace( Err(start_trace(
("set-doc", "expected two inputs") ("set-doc", "expected two inputs")
.into())) .into()))
} else { } else if let Ctr::Symbol(ref symbol) = *ast.car {
if let Ctr::Symbol(ref symbol) = *ast.car {
if let Some(mut sym) = syms.remove(symbol) { if let Some(mut sym) = syms.remove(symbol) {
if let Ctr::Seg(ref doc_node) = *ast.cdr { if let Ctr::Seg(ref doc_node) = *ast.cdr {
if let Ctr::String(ref doc) = *doc_node.car { if let Ctr::String(ref doc) = *doc_node.car {
@ -320,14 +310,12 @@ fn setdoc_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
("set-doc", format!("{symbol} is undefined")) ("set-doc", format!("{symbol} is undefined"))
.into())) .into()))
} }
} else { } else {
Err(start_trace( Err(start_trace(
("set-doc", "first input must be a symbol") ("set-doc", "first input must be a symbol")
.into())) .into()))
} }
} }
}
const STORE_DOCSTRING: &str = "allows user to define functions and variables. const STORE_DOCSTRING: &str = "allows user to define functions and variables.
A call may take one of three forms: A call may take one of three forms:
@ -377,11 +365,9 @@ fn store_callback(ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Result<Ctr,
} }
return Ok(Ctr::None) return Ok(Ctr::None)
} else { } else if ast.len() < 3 || ast.len() > 4 {
if ast.len() < 3 || ast.len() > 4 {
return Err(start_trace(("def", "expected 3 or 4 inputs").into())) return Err(start_trace(("def", "expected 3 or 4 inputs").into()))
} }
}
let mut iter: &Seg; let mut iter: &Seg;
if let Ctr::Seg(ref s) = *ast.cdr { if let Ctr::Seg(ref s) = *ast.cdr {
@ -394,7 +380,7 @@ fn store_callback(ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Result<Ctr,
Ctr::String(ref s) => docs = s.clone(), Ctr::String(ref s) => docs = s.clone(),
Ctr::Symbol(ref s) => match syms.call_symbol(s, &Seg::new(), true) { Ctr::Symbol(ref s) => match syms.call_symbol(s, &Seg::new(), true) {
Ok(d) => if let Ctr::String(doc) = *d { Ok(d) => if let Ctr::String(doc) = *d {
docs = doc.clone(); docs = doc;
} else { } else {
return Err(start_trace(("def", "expected docs input to evaluate to a string").into())) return Err(start_trace(("def", "expected docs input to evaluate to a string").into()))
}, },
@ -432,7 +418,6 @@ fn store_callback(ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Result<Ctr,
} }
if is_var { if is_var {
let var_val: Ctr;
let var_eval_result = eval(var_val_form, syms); let var_eval_result = eval(var_val_form, syms);
if let Err(e) = var_eval_result { if let Err(e) = var_eval_result {
return Err(e.with_trace( return Err(e.with_trace(
@ -440,11 +425,11 @@ fn store_callback(ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Result<Ctr,
.into())) .into()))
} }
let var_eval_final = *var_eval_result?; let var_eval_final = *var_eval_result?;
match var_eval_final { let var_val: Ctr = match var_eval_final {
Ctr::Seg(ref s) if expand => var_val = *s.car.clone(), Ctr::Seg(ref s) if expand => *s.car.clone(),
Ctr::Seg(ref s) if !expand => var_val = Ctr::Seg(s.clone()), Ctr::Seg(ref s) if !expand => Ctr::Seg(s.clone()),
_ => var_val = var_eval_final, _ => var_eval_final,
} };
let outer_seg = Seg::from_mono(Box::new(var_val.clone())); let outer_seg = Seg::from_mono(Box::new(var_val.clone()));
syms.insert( syms.insert(

View file

@ -20,11 +20,7 @@ use crate::error::{Traceback, start_trace};
use std::rc::Rc; use std::rc::Rc;
fn isnumeric(arg: &Ctr) -> bool { fn isnumeric(arg: &Ctr) -> bool {
match arg { matches!(arg, Ctr::Integer(_) | Ctr::Float(_))
Ctr::Integer(_) => true,
Ctr::Float(_) => true,
_ => false,
}
} }
const ADD_DOCSTRING: &str = const ADD_DOCSTRING: &str =
@ -175,7 +171,7 @@ fn floatcast_callback(ast: &Seg, _: &mut SymTable) -> Result<Ctr, Traceback> {
if let Ctr::Integer(i) = *ast.car { if let Ctr::Integer(i) = *ast.car {
Ok(Ctr::Float(i as f64)) Ok(Ctr::Float(i as f64))
} else if let Ctr::String(ref s) = *ast.car { } else if let Ctr::String(ref s) = *ast.car {
let flt = str::parse::<f64>(&s); let flt = str::parse::<f64>(s);
if flt.is_err() { if flt.is_err() {
Err(start_trace( Err(start_trace(
("float", flt.err().unwrap().to_string()) ("float", flt.err().unwrap().to_string())
@ -452,7 +448,7 @@ fn inc_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
let sym_ret = syms let sym_ret = syms
.remove(&var_name); .remove(&var_name);
if let None = sym_ret { if sym_ret.is_none() {
return Err(start_trace( return Err(start_trace(
("inc", format!("input ({var_name}) is not defined")) ("inc", format!("input ({var_name}) is not defined"))
.into())) .into()))
@ -499,7 +495,7 @@ fn dec_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, Traceback> {
let sym_ret = syms let sym_ret = syms
.remove(&var_name); .remove(&var_name);
if let None = sym_ret { if sym_ret.is_none() {
return Err(start_trace( return Err(start_trace(
("dec", format!("input ({var_name}) is not defined")) ("dec", format!("input ({var_name}) is not defined"))
.into())) .into()))

View file

@ -37,10 +37,7 @@ use {
}, },
std::{ std::{
collections::VecDeque, collections::VecDeque,
cell::{ cell::RefCell,
RefCell, RefMut,
BorrowMutError,
},
io::Result as IOResult, io::Result as IOResult,
rc::Rc, rc::Rc,
fs::{ fs::{
@ -109,9 +106,9 @@ pub fn unign_sigs() {
// TODO: trigger this on SIGCHLD instead of traditional shell once per input // TODO: trigger this on SIGCHLD instead of traditional shell once per input
pub fn check_jobs(state: &mut ShellState) { pub fn check_jobs(state: &mut ShellState) {
let mut idx = 0 as usize; let mut idx = 0usize;
while idx < state.children.len() { while idx < state.children.len() {
if let Ok(_) = state.children[idx].try_wait() { if state.children[idx].try_wait().is_ok() {
state.children.remove(idx); state.children.remove(idx);
continue; continue;
} }
@ -134,7 +131,7 @@ pub fn args_from_ast(ast: &Seg, syms: &mut SymTable) -> Vec<String> {
match *res_ctr { match *res_ctr {
Ctr::Lambda(_) => false, Ctr::Lambda(_) => false,
Ctr::Seg(_) => false, Ctr::Seg(_) => false,
Ctr::String(s) => args.push(s.clone()) == (), Ctr::String(s) => args.push(s) == (),
_ => args.push(res_ctr.to_string()) == (), _ => args.push(res_ctr.to_string()) == (),
} }
} else { } else {
@ -178,15 +175,13 @@ fn launch_command(
newchld = Command::new(path) newchld = Command::new(path)
.pre_exec(move || -> IOResult<()> { .pre_exec(move || -> IOResult<()> {
let pid = unistd::getpid(); let pid = unistd::getpid();
if let Err(_) = unistd::setpgid(pid, pid) { if unistd::setpgid(pid, pid).is_err() {
// crying would be nice... if you had eyes // crying would be nice... if you had eyes
} }
if !background { if !background &&unistd::tcsetpgrp(0, pid).is_err() {
if let Err(_) = unistd::tcsetpgrp(0, pid) {
// you wish to scream, but fork() has taken from you your throat // you wish to scream, but fork() has taken from you your throat
} }
}
unign_sigs(); unign_sigs();
Ok(()) Ok(())
@ -255,8 +250,7 @@ fn make_foreground(pid: u32, state: &mut ShellState) -> Result<(), String>{
state.last_exit_code = exit state.last_exit_code = exit
.code() .code()
.or(Some(-1)) .unwrap_or(-1);
.unwrap();
break; break;
} }
@ -298,8 +292,7 @@ fn load_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Resu
Err(start_trace( Err(start_trace(
("load", "empty command") ("load", "empty command")
.into())) .into()))
} else { } else if let Some(filepath) = run::find_on_path(args.pop_front().unwrap()) {
if let Some(filepath) = run::find_on_path(args.pop_front().unwrap()) {
if let Err(e) = launch_command( if let Err(e) = launch_command(
filepath, filepath,
&Vec::from(args.make_contiguous()), &Vec::from(args.make_contiguous()),
@ -322,7 +315,6 @@ fn load_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Resu
} }
} }
} }
}
const PIPE_DOCSTRING: &str = "Calls a sequence of shell commands. const PIPE_DOCSTRING: &str = "Calls a sequence of shell commands.
Each one has their output redirected to the input of the next one. Each one has their output redirected to the input of the next one.
@ -385,8 +377,7 @@ fn pipe_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Resu
Err(start_trace( Err(start_trace(
("pipe", err) ("pipe", err)
.into())) .into()))
} else { } else if lastpid > 0 {
if lastpid > 0 {
if let Some(pos) = state.children if let Some(pos) = state.children
.iter() .iter()
.position(|x| x.id() == lastpid) .position(|x| x.id() == lastpid)
@ -396,7 +387,7 @@ fn pipe_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Resu
.expect("failed to wait on last child"); .expect("failed to wait on last child");
state.last_exit_code = exit.status state.last_exit_code = exit.status
.code() .code()
.or_else(|| {Some(-1)}) .or(Some(-1))
.unwrap(); .unwrap();
println!("{}", String::from_utf8_lossy(&exit.stdout)); println!("{}", String::from_utf8_lossy(&exit.stdout));
@ -412,7 +403,6 @@ fn pipe_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Resu
.into())) .into()))
} }
} }
}
const LOAD_TO_STRING_DOCSTRING: &str = "Calls a binary off disk with given arguments. const LOAD_TO_STRING_DOCSTRING: &str = "Calls a binary off disk with given arguments.
Arguments may be of any type except lambda. If a symbol is not defined it will be passed as a string. Arguments may be of any type except lambda. If a symbol is not defined it will be passed as a string.
@ -437,8 +427,7 @@ fn load_to_string_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellStat
Err(start_trace( Err(start_trace(
("load-to-string", "command is empty") ("load-to-string", "command is empty")
.into())) .into()))
} else { } else if let Some(filepath) = run::find_on_path(args.pop_front().unwrap()) {
if let Some(filepath) = run::find_on_path(args.pop_front().unwrap()) {
let res = Command::new(filepath).args(args).output(); let res = Command::new(filepath).args(args).output();
if let Ok(output) = res { if let Ok(output) = res {
if let Some(code) = output.status.code() { if let Some(code) = output.status.code() {
@ -448,7 +437,7 @@ fn load_to_string_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellStat
Ok(Ctr::String(string.trim_end().to_string())) Ok(Ctr::String(string.trim_end().to_string()))
} else { } else {
Err(start_trace( Err(start_trace(
("load-to-string", format!("couldn't marshall utf-8 command output into a string")) ("load-to-string", "couldn't marshall utf-8 command output into a string")
.into())) .into()))
} }
} else { } else {
@ -463,7 +452,6 @@ fn load_to_string_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellStat
} }
} }
} }
}
// TODO: rework this callback to reduce spaghett // TODO: rework this callback to reduce spaghett
const LOAD_WITH_DOCSTRING: &str = "Takes two arguments. const LOAD_WITH_DOCSTRING: &str = "Takes two arguments.
@ -514,7 +502,7 @@ fn load_with_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) ->
return false return false
} }
stdin = Some(Stdio::from(input.ok().unwrap())); stdin = Some(Stdio::from(input.ok().unwrap()));
return true true
}, },
"stdout" => { "stdout" => {
if !stdout.is_none() { if !stdout.is_none() {
@ -531,7 +519,7 @@ fn load_with_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) ->
return false return false
} }
stdout = Some(Stdio::from(out.ok().unwrap())); stdout = Some(Stdio::from(out.ok().unwrap()));
return true true
}, },
"stderr" => { "stderr" => {
if !stderr.is_none() { if !stderr.is_none() {
@ -548,7 +536,7 @@ fn load_with_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) ->
return false return false
} }
stderr = Some(Stdio::from(err.ok().unwrap())); stderr = Some(Stdio::from(err.ok().unwrap()));
return true true
}, },
_ => { _ => {
e = Some(format!("can only override stdin, stdout, or stderr")); e = Some(format!("can only override stdin, stdout, or stderr"));
@ -668,8 +656,7 @@ fn bg_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Result
Err(start_trace( Err(start_trace(
("bg", "empty command") ("bg", "empty command")
.into())) .into()))
} else { } else if let Some(filepath) = run::find_on_path(args.pop_front().unwrap()) {
if let Some(filepath) = run::find_on_path(args.pop_front().unwrap()) {
if let Err(e) = launch_command( if let Err(e) = launch_command(
filepath, filepath,
&Vec::from(args.make_contiguous()), &Vec::from(args.make_contiguous()),
@ -692,7 +679,6 @@ fn bg_callback(ast: &Seg, syms: &mut SymTable, state: &mut ShellState) -> Result
} }
} }
} }
}
const FG_DOCSTRING: &str = "takes one argument (an integer). const FG_DOCSTRING: &str = "takes one argument (an integer).
Integer is presumed to be a PID of a running background job. Integer is presumed to be a PID of a running background job.
@ -727,7 +713,7 @@ const CD_DOCSTRING: &str =
fn cd_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> { fn cd_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> {
if let Ctr::String(ref dir) = *ast.car { if let Ctr::String(ref dir) = *ast.car {
let dirp = Path::new(dir); let dirp = Path::new(dir);
if let Err(s) = set_current_dir(&dirp) { if let Err(s) = set_current_dir(dirp) {
Err(start_trace( Err(start_trace(
("cd", s.to_string()) ("cd", s.to_string())
.into())) .into()))
@ -746,7 +732,7 @@ pub fn load_posix_shell(syms: &mut SymTable, shell_state: Rc<RefCell<ShellState>
let pgid_res = unistd::getpgid(Some(pid)); let pgid_res = unistd::getpgid(Some(pid));
let sid_res = unistd::getsid(Some(pid)); let sid_res = unistd::getsid(Some(pid));
if !pgid_res.is_ok() || !sid_res.is_ok() { if pgid_res.is_err() || sid_res.is_err() {
panic!("couldn't get pgid") panic!("couldn't get pgid")
} }
let pgid = pgid_res.ok().unwrap(); let pgid = pgid_res.ok().unwrap();
@ -760,14 +746,14 @@ pub fn load_posix_shell(syms: &mut SymTable, shell_state: Rc<RefCell<ShellState>
state.parent_sid = sid; state.parent_sid = sid;
if let Ok(attr) = tcgetattr(0) { if let Ok(attr) = tcgetattr(0) {
state.attr = Some(attr.clone()); state.attr = Some(attr.clone());
shattr = attr.clone(); shattr = attr;
} else { } else {
panic!("couldn't get term attrs"); panic!("couldn't get term attrs");
} }
} }
let term_pgrp_res = unistd::tcgetpgrp(0); let term_pgrp_res = unistd::tcgetpgrp(0);
if !term_pgrp_res.is_ok() { if term_pgrp_res.is_err() {
panic!("couldn't get terminal's pgrp: {:?}", term_pgrp_res) panic!("couldn't get terminal's pgrp: {:?}", term_pgrp_res)
} }
@ -898,16 +884,13 @@ pub fn load_posix_shell(syms: &mut SymTable, shell_state: Rc<RefCell<ShellState>
symtable, symtable,
&mut lts_ss &mut lts_ss
.try_borrow_mut() .try_borrow_mut()
.or(Ok::<RefMut<'_, ShellState>, BorrowMutError>( .unwrap_or(RefCell::from(ShellState{
RefCell::from(ShellState{
parent_pid: pid, parent_pid: pid,
parent_sid: pgid, parent_sid: pgid,
children: vec![], children: vec![],
last_exit_code: 0, last_exit_code: 0,
attr: Some(shattr.clone()), attr: Some(shattr.clone()),
}).borrow_mut())) }).borrow_mut()))
.unwrap()
)
})), })),
..Default::default() ..Default::default()
}, },

View file

@ -42,7 +42,7 @@ fn concat_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> {
match arg { match arg {
// should be a thing here // should be a thing here
Ctr::Symbol(_) => return false, Ctr::Symbol(_) => return false,
Ctr::String(s) => string.push_str(&s), Ctr::String(s) => string.push_str(s),
Ctr::Integer(i) => string.push_str(&i.to_string()), Ctr::Integer(i) => string.push_str(&i.to_string()),
Ctr::Float(f) => string.push_str(&f.to_string()), Ctr::Float(f) => string.push_str(&f.to_string()),
Ctr::Bool(b) => string.push_str(&b.to_string()), Ctr::Bool(b) => string.push_str(&b.to_string()),
@ -56,7 +56,7 @@ fn concat_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> {
("concat", "highly suspicious that an input was an unevaluated symbol") ("concat", "highly suspicious that an input was an unevaluated symbol")
.into())) .into()))
} }
return Ok(Ctr::String(string)); Ok(Ctr::String(string))
} }
const STRLEN_DOCSTRING: &str = "Takes a single arg of any type. const STRLEN_DOCSTRING: &str = "Takes a single arg of any type.
@ -147,7 +147,7 @@ fn split_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> {
.into())) .into()))
} }
if let Ctr::String(ref s) = &*second_arg_obj { if let Ctr::String(ref s) = second_arg_obj {
delim_str = s.clone(); delim_str = s.clone();
} else { } else {
return Err(start_trace( return Err(start_trace(
@ -174,7 +174,7 @@ fn input_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, Traceback> {
io::stdin().read_line(&mut input).expect("couldnt read user input"); io::stdin().read_line(&mut input).expect("couldnt read user input");
Ok(Ctr::String(input.trim().to_string())) Ok(Ctr::String(input.trim().to_string()))
} else { } else {
return Err(start_trace( Err(start_trace(
("input", "expected a string input to prompt user with") ("input", "expected a string input to prompt user with")
.into())) .into()))
} }

View file

@ -143,13 +143,13 @@ impl SymTable {
if let ValueType::VarForm(ref val) = symbol.value { if let ValueType::VarForm(ref val) = symbol.value {
match **val { match **val {
Ctr::Lambda(ref l) if call_func => { Ctr::Lambda(ref l) if call_func => {
return call_lambda( call_lambda(
l, l,
&Box::new(Ctr::Seg(args.clone())), &Box::new(Ctr::Seg(args.clone())),
self self
) )
}, },
_ => return Ok(val.clone()), _ => Ok(val.clone()),
} }
} else if call_func { } else if call_func {
symbol.call(args, self) symbol.call(args, self)
@ -343,7 +343,7 @@ impl Symbol {
errcon = eval_res.err().unwrap(); errcon = eval_res.err().unwrap();
return false return false
} }
outer_scope_seg_storage.append(eval_res.unwrap().clone()); outer_scope_seg_storage.append(eval_res.unwrap());
} else if let Ctr::Symbol(ref s) = arg { } else if let Ctr::Symbol(ref s) = arg {
let eval_res = syms.call_symbol( let eval_res = syms.call_symbol(
s, s,
@ -354,7 +354,7 @@ impl Symbol {
errcon = eval_res.err().unwrap(); errcon = eval_res.err().unwrap();
return false return false
} }
outer_scope_seg_storage.append(eval_res.unwrap().clone()); outer_scope_seg_storage.append(eval_res.unwrap());
} else { } else {
outer_scope_seg_storage.append(Box::new(arg.clone())); outer_scope_seg_storage.append(Box::new(arg.clone()));
} }