Commit 627cef17 authored by matt's avatar matt Committed by AdminXVII
Browse files

Lifetime Removal

parent fbe1b8e3
......@@ -82,6 +82,7 @@ xdg = "2.1"
nix = { git = "https://github.com/AdminXVII/nix", branch = "add-redox-support-bis" }
mktemp = "0.4"
# window example
piston-ai_behavior = { version = "0.31", optional = true }
piston_window = { version = "0.105", optional = true }
......
......@@ -76,3 +76,10 @@ end
echo one two three four five | format_with "-"
```
## Library usage:
When using Ion as a shell library, it is possible you may want to change the builtin functions associated with a Shell.
If you do this, all function calls will use the new buildtins to run. meaning that if you removed the builtin function it the shell will try to find the command, and if you added a builtin, that will override any other command.
......@@ -107,9 +107,7 @@ impl<'a> Action<'a> {
) -> Result<Action<'a>, AssignmentError<'a>> {
match var.kind {
Primitive::Indexed(..) | Primitive::Str => Ok(Action(var, operator, value)),
Primitive::Array(_)
| Primitive::HashMap(_)
| Primitive::BTreeMap(_) => {
Primitive::Array(_) | Primitive::HashMap(_) | Primitive::BTreeMap(_) => {
if is_array {
Ok(Action(var, operator, value))
} else {
......@@ -117,7 +115,10 @@ impl<'a> Action<'a> {
}
}
_ if !is_array => Ok(Action(var, operator, value)),
_ => Err(AssignmentError::InvalidValue(var.kind, Primitive::Array(Box::new(Primitive::Str)))),
_ => Err(AssignmentError::InvalidValue(
var.kind,
Primitive::Array(Box::new(Primitive::Str)),
)),
}
}
}
......@@ -183,7 +184,11 @@ mod tests {
assert_eq!(actions.len(), 3);
assert_eq!(
actions[0],
Ok(Action(Key { name: "a", kind: Primitive::Array(Box::new(Primitive::Str)) }, Operator::Equal, "[one two]",))
Ok(Action(
Key { name: "a", kind: Primitive::Array(Box::new(Primitive::Str)) },
Operator::Equal,
"[one two]",
))
);
assert_eq!(
actions[1],
......
......@@ -46,7 +46,7 @@ fn get_map_of<E: Expander>(
primitive_type: &Primitive,
shell: &mut E,
expression: &str,
) -> expansion::Result<Value<Rc<types::Function<'static>>>, E::Error> {
) -> expansion::Result<Value<Rc<types::Function>>, E::Error> {
let array = shell.expand_string(expression)?;
let inner_kind = match primitive_type {
......@@ -95,7 +95,7 @@ pub fn value_check<E: Expander>(
shell: &mut E,
value: &str,
expected: &Primitive,
) -> expansion::Result<Value<Rc<types::Function<'static>>>, E::Error> {
) -> expansion::Result<Value<Rc<types::Function>>, E::Error> {
if is_array(value) {
let extracted = shell.get_array(value)?;
match expected {
......@@ -173,13 +173,23 @@ mod test {
#[test]
fn is_integer_array_() {
assert_eq!(
value_check(&mut DummyExpander, "[1 2 3]", &Primitive::Array(Box::new(Primitive::Integer))).unwrap(),
value_check(
&mut DummyExpander,
"[1 2 3]",
&Primitive::Array(Box::new(Primitive::Integer))
)
.unwrap(),
Value::Array(vec![
Value::Str("1".into()),
Value::Str("2".into()),
Value::Str("3".into())
])
);
assert!(value_check(&mut DummyExpander, "[1 2 three]", &Primitive::Array(Box::new(Primitive::Integer))).is_err());
assert!(value_check(
&mut DummyExpander,
"[1 2 three]",
&Primitive::Array(Box::new(Primitive::Integer))
)
.is_err());
}
}
......@@ -58,7 +58,7 @@ impl Status {
pub fn toggle(&mut self) { self.0 = if self.is_success() { 1 } else { 0 }; }
}
impl<'a> From<Status> for Value<Rc<types::Function<'a>>> {
impl From<Status> for Value<Rc<types::Function>> {
fn from(status: Status) -> Self { Value::Str(status.into()) }
}
......
......@@ -7,7 +7,7 @@ use crate as ion_shell;
use crate::{shell::variables::Variables, types, Shell};
use builtins_proc::builtin;
fn print_list(vars: &Variables<'_>) {
fn print_list(vars: &Variables) {
let stdout = io::stdout();
let stdout = &mut stdout.lock();
......
......@@ -127,7 +127,7 @@ impl<'a> PipeItem<RefinedJob<'a>> {
pub fn command(&self) -> &types::Str { self.job.command() }
}
impl<'a> PipeItem<Job<'a>> {
impl<'a> PipeItem<Job> {
/// Expand a single job to argument literals for execution
pub fn expand(
&self,
......@@ -160,7 +160,7 @@ impl<'a> PipeItem<Job<'a>> {
}
/// Create a new pipeitem with the given job and redirections
pub const fn new(job: Job<'a>, outputs: Vec<Redirection>, inputs: Vec<Input>) -> Self {
pub const fn new(job: Job, outputs: Vec<Redirection>, inputs: Vec<Input>) -> Self {
Self { job, outputs, inputs }
}
}
......@@ -197,7 +197,7 @@ impl<'a> Pipeline<RefinedJob<'a>> {
}
}
impl<'a> Pipeline<Job<'a>> {
impl<'a> Pipeline<Job> {
/// A useless, empty pipeline
pub const fn new() -> Self { Pipeline { pipe: PipeType::Normal, items: Vec::new() } }
......
......@@ -171,10 +171,16 @@ mod tests {
p:bmap[hmap[bool]] d:a",
);
assert_eq!(parser.next().unwrap(), Ok(Key { name: "a", kind: Primitive::Integer },));
assert_eq!(parser.next().unwrap(), Ok(Key { name: "b", kind: Primitive::Array(Box::new(Primitive::Str)) },));
assert_eq!(
parser.next().unwrap(),
Ok(Key { name: "b", kind: Primitive::Array(Box::new(Primitive::Str)) },)
);
assert_eq!(parser.next().unwrap(), Ok(Key { name: "c", kind: Primitive::Boolean },));
assert_eq!(parser.next().unwrap(), Ok(Key { name: "d", kind: Primitive::Str },));
assert_eq!(parser.next().unwrap(), Ok(Key { name: "e", kind: Primitive::Array(Box::new(Primitive::Integer)) },));
assert_eq!(
parser.next().unwrap(),
Ok(Key { name: "e", kind: Primitive::Array(Box::new(Primitive::Integer)) },)
);
assert_eq!(
parser.next().unwrap(),
Ok(Key { name: "f", kind: Primitive::Indexed("0".into(), Box::new(Primitive::Str)) },)
......@@ -203,15 +209,18 @@ mod tests {
);
assert_eq!(
parser.next().unwrap(),
Ok(Key { name: "k", kind: Primitive::HashMap(Box::new(Primitive::Array(Box::new(Primitive::Integer)))) },)
Ok(Key {
name: "k",
kind: Primitive::HashMap(Box::new(Primitive::Array(Box::new(Primitive::Integer)))),
},)
);
assert_eq!(
parser.next().unwrap(),
Ok(Key {
name: "l",
kind: Primitive::HashMap(Box::new(Primitive::HashMap(Box::new(
Primitive::Array(Box::new(Primitive::Boolean))
)))),
kind: Primitive::HashMap(Box::new(Primitive::HashMap(Box::new(Primitive::Array(
Box::new(Primitive::Boolean)
))))),
},)
);
assert_eq!(
......@@ -224,7 +233,10 @@ mod tests {
);
assert_eq!(
parser.next().unwrap(),
Ok(Key { name: "o", kind: Primitive::BTreeMap(Box::new(Primitive::Array(Box::new(Primitive::Float)))) },)
Ok(Key {
name: "o",
kind: Primitive::BTreeMap(Box::new(Primitive::Array(Box::new(Primitive::Float)))),
},)
);
assert_eq!(
parser.next().unwrap(),
......
......@@ -54,22 +54,20 @@ trait AddItem<'a> {
args: Args,
outputs: Vec<Redirection>,
inputs: Vec<Input>,
builtin: &BuiltinMap<'a>,
);
}
impl<'a> AddItem<'a> for Pipeline<Job<'a>> {
impl<'a> AddItem<'a> for Pipeline<Job> {
fn add_item(
&mut self,
redirection: RedirectFrom,
args: Args,
outputs: Vec<Redirection>,
inputs: Vec<Input>,
builtins: &BuiltinMap<'a>,
) {
if !args.is_empty() {
let builtin = builtins.get(&args[0]);
self.items.push(PipeItem::new(Job::new(args, redirection, builtin), outputs, inputs));
// let builtin = builtins.contains(&args[0]);
self.items.push(PipeItem::new(Job::new(args, redirection), outputs, inputs));
}
}
}
......@@ -117,10 +115,7 @@ impl<'a> Collector<'a> {
.map(|file| outputs.push(Redirection { from, file: file.into(), append }))
}
fn parse<'builtins>(
&self,
builtins: &BuiltinMap<'builtins>,
) -> Result<Pipeline<Job<'builtins>>, PipelineParsingError> {
fn parse<'builtins>(&self) -> Result<Pipeline<Job>, PipelineParsingError> {
let mut bytes = self.data.bytes().enumerate().peekable();
let mut args = Args::with_capacity(ARG_DEFAULT_SIZE);
let mut pipeline = Pipeline::new();
......@@ -150,7 +145,6 @@ impl<'a> Collector<'a> {
std::mem::replace(&mut args, Args::with_capacity(ARG_DEFAULT_SIZE)),
std::mem::replace(&mut outputs, Vec::new()),
std::mem::replace(&mut inputs, Vec::new()),
builtins,
);
}
Some(&(_, b'!')) => {
......@@ -185,7 +179,6 @@ impl<'a> Collector<'a> {
std::mem::replace(&mut args, Args::with_capacity(ARG_DEFAULT_SIZE)),
std::mem::replace(&mut outputs, Vec::new()),
std::mem::replace(&mut inputs, Vec::new()),
builtins,
);
}
Some(_) | None => self.push_arg(&mut args, &mut bytes)?,
......@@ -198,7 +191,6 @@ impl<'a> Collector<'a> {
std::mem::replace(&mut args, Args::with_capacity(ARG_DEFAULT_SIZE)),
std::mem::replace(&mut outputs, Vec::new()),
std::mem::replace(&mut inputs, Vec::new()),
builtins,
);
}
b'>' => {
......@@ -237,7 +229,7 @@ impl<'a> Collector<'a> {
}
}
pipeline.add_item(RedirectFrom::None, args, outputs, inputs, builtins);
pipeline.add_item(RedirectFrom::None, args, outputs, inputs);
Ok(pipeline)
}
......@@ -417,9 +409,9 @@ impl<'a> Collector<'a> {
/// Collect a pipeline on the given data
pub fn run<'builtins>(
data: &'a str,
builtins: &BuiltinMap<'builtins>,
) -> Result<Pipeline<Job<'builtins>>, PipelineParsingError> {
Collector::new(data).parse(builtins)
_builtins: &BuiltinMap<'builtins>,
) -> Result<Pipeline<Job>, PipelineParsingError> {
Collector::new(data).parse()
}
const fn new(data: &'a str) -> Self { Self { data } }
......@@ -841,7 +833,7 @@ mod tests {
let expected = Pipeline {
items: vec![
PipeItem {
job: Job::new(args!["cat"], RedirectFrom::Stdout, None),
job: Job::new(args!["cat"], RedirectFrom::Stdout),
inputs: vec![
Input::File("file1".into()),
Input::HereString("\"herestring\"".into()),
......@@ -849,7 +841,7 @@ mod tests {
outputs: Vec::new(),
},
PipeItem {
job: Job::new(args!["tr", "'x'", "'y'"], RedirectFrom::None, None),
job: Job::new(args!["tr", "'x'", "'y'"], RedirectFrom::None),
inputs: Vec::new(),
outputs: vec![
Redirection {
......@@ -883,20 +875,17 @@ mod tests {
let expected = Pipeline {
items: vec![
PipeItem {
job: Job::new(args!["cat"], RedirectFrom::Stdout, None),
job: Job::new(args!["cat"], RedirectFrom::Stdout),
inputs: Vec::new(),
outputs: Vec::new(),
},
PipeItem {
job: Job::new(args!["echo", "hello"], RedirectFrom::Stdout, None),
job: Job::new(args!["echo", "hello"], RedirectFrom::Stdout),
inputs: Vec::new(),
outputs: Vec::new(),
},
PipeItem {
job: Job::new(args!["cat"], RedirectFrom::None, None),
job: Job::new(args!["cat"], RedirectFrom::None),
inputs: vec![Input::File("stuff".into())],
outputs: vec![Redirection {
from: RedirectFrom::Stderr,
......@@ -918,19 +907,19 @@ mod tests {
let expected = Pipeline {
items: vec![
PipeItem {
job: Job::new(args!["cat"], RedirectFrom::Stdout, None),
job: Job::new(args!["cat"], RedirectFrom::Stdout),
inputs: Vec::new(),
outputs: Vec::new(),
},
PipeItem {
job: Job::new(args!["echo", "hello"], RedirectFrom::Stdout, None),
job: Job::new(args!["echo", "hello"], RedirectFrom::Stdout),
inputs: Vec::new(),
outputs: Vec::new(),
},
PipeItem {
job: Job::new(args!["cat"], RedirectFrom::None, None),
job: Job::new(args!["cat"], RedirectFrom::None),
inputs: vec![Input::File("stuff".into())],
outputs: vec![Redirection {
......@@ -991,7 +980,7 @@ mod tests {
let input = "math <<< $(cat math.txt)";
let expected = Pipeline {
items: vec![PipeItem {
job: Job::new(args!["math"], RedirectFrom::None, None),
job: Job::new(args!["math"], RedirectFrom::None),
inputs: vec![Input::HereString("$(cat math.txt)".into())],
outputs: vec![],
......@@ -1009,13 +998,13 @@ mod tests {
let expected = Pipeline {
items: vec![
PipeItem {
job: Job::new(args!["cat"], RedirectFrom::Stdout, None),
job: Job::new(args!["cat"], RedirectFrom::Stdout),
inputs: Vec::new(),
outputs: Vec::new(),
},
PipeItem {
job: Job::new(args!["tr", "'o'", "'x'"], RedirectFrom::None, None),
job: Job::new(args!["tr", "'o'", "'x'"], RedirectFrom::None),
inputs: vec![Input::HereString("$VAR".into())],
outputs: vec![Redirection {
......@@ -1051,7 +1040,7 @@ mod tests {
let input = "echo zardoz >> foo\\'bar";
let expected = Pipeline {
items: vec![PipeItem {
job: Job::new(args!["echo", "zardoz"], RedirectFrom::None, None),
job: Job::new(args!["echo", "zardoz"], RedirectFrom::None),
inputs: Vec::new(),
outputs: vec![Redirection {
......@@ -1066,7 +1055,7 @@ mod tests {
}
fn assert_parse_error(s: &str) {
assert!(super::Collector::new(s).parse(&BuiltinMap::new()).is_err());
assert!(super::Collector::new(s).parse().is_err());
}
#[test]
......
......@@ -14,7 +14,7 @@ pub enum Error {
ExtraVar(String),
}
impl<'a> FromStr for Case<'a> {
impl FromStr for Case {
type Err = Error;
fn from_str(data: &str) -> Result<Self, Self::Err> {
......
......@@ -15,7 +15,7 @@ use crate::{builtins::BuiltinMap, shell::flow_control::Statement};
use err_derive::Error;
use std::char;
pub type Result<'a> = std::result::Result<Statement<'a>, Error>;
pub type Result = std::result::Result<Statement, Error>;
/// An Error occured during parsing
#[derive(Debug, Error, PartialEq, Eq, Hash, Clone)]
......@@ -92,10 +92,7 @@ impl From<PipelineParsingError> for Error {
/// Parses a given statement string and return's the corresponding mapped
/// `Statement`
pub fn parse_and_validate<'b>(
statement: StatementVariant<'_>,
builtins: &BuiltinMap<'b>,
) -> Result<'b> {
pub fn parse_and_validate<'b>(statement: StatementVariant, builtins: &BuiltinMap<'b>) -> Result {
match statement {
StatementVariant::And(statement) => {
Ok(Statement::And(Box::new(parse(statement, builtins)?)))
......
......@@ -14,7 +14,7 @@ use crate::{
};
use std::char;
pub fn parse<'a>(code: &str, builtins: &BuiltinMap<'a>) -> super::Result<'a> {
pub fn parse(code: &str, builtins: &BuiltinMap<'_>) -> super::Result {
let cmd = code.trim();
match cmd {
"return" => Ok(Statement::Return(None)),
......@@ -195,7 +195,6 @@ mod tests {
.into_iter()
.collect(),
RedirectFrom::None,
None,
),
outputs: Vec::new(),
inputs: Vec::new(),
......
......@@ -32,26 +32,28 @@ fn list_vars(shell: &Shell<'_>) -> Result<(), io::Error> {
vals.map(|v| write!(buffer, ", '{}'", v)).collect::<Result<Vec<_>, _>>()?;
}
writeln!(buffer, " ]")?;
},
}
Value::HashMap(ref s) => {
write!(buffer, "[")?;
let mut vals = s.iter();
if let Some((key, val)) = vals.next() {
write!(buffer, " '{}'='{}'", key, val)?;
vals.map(|(k, v)| write!(buffer, ", '{}'='{}'", k, v)).collect::<Result<Vec<_>, _>>()?;
vals.map(|(k, v)| write!(buffer, ", '{}'='{}'", k, v))
.collect::<Result<Vec<_>, _>>()?;
}
writeln!(buffer, " ]")?;
},
}
Value::BTreeMap(ref s) => {
write!(buffer, "[")?;
let mut vals = s.iter();
if let Some((key, val)) = vals.next() {
write!(buffer, " '{}'='{}'", key, val)?;
vals.map(|(k, v)| write!(buffer, ", '{}'='{}'", k, v)).collect::<Result<Vec<_>, _>>()?;
vals.map(|(k, v)| write!(buffer, ", '{}'='{}'", k, v))
.collect::<Result<Vec<_>, _>>()?;
}
writeln!(buffer, " ]")?;
},
_ => unsafe { std::hint::unreachable_unchecked() }
}
_ => unsafe { std::hint::unreachable_unchecked() },
}
}
Ok(())
......@@ -122,7 +124,7 @@ impl<'b> Shell<'b> {
pub(crate) fn calculate<'a>(
&mut self,
actions: AssignmentActions<'a>,
) -> Result<Vec<(Key<'a>, Value<Rc<Function<'b>>>)>, String> {
) -> Result<Vec<(Key<'a>, Value<Rc<Function>>)>, String> {
let mut backup: Vec<_> = Vec::with_capacity(4);
for action in actions {
let Action(key, operator, expression) = action.map_err(|e| e.to_string())?;
......@@ -204,9 +206,9 @@ impl<'b> Shell<'b> {
// parsed
fn apply<'a>(
op: Operator,
lhs: &Value<Rc<Function<'a>>>,
rhs: Value<Rc<Function<'a>>>,
) -> Result<Value<Rc<Function<'a>>>, OpError> {
lhs: &Value<Rc<Function>>,
rhs: Value<Rc<Function>>,
) -> Result<Value<Rc<Function>>, OpError> {
match op {
Operator::Add => lhs + rhs,
Operator::Divide => lhs / rhs,
......
......@@ -69,8 +69,8 @@ pub enum BlockError {
impl<'a> Shell<'a> {
fn insert_into_block(
block: &mut Block<'a>,
statement: Statement<'a>,
block: &mut Block,
statement: Statement,
) -> std::result::Result<(), BlockError> {
let block = match block.last_mut().expect("Should not insert statement if stack is empty!")
{
......@@ -124,9 +124,9 @@ impl<'a> Shell<'a> {
}
fn insert_statement(
block: &mut Block<'a>,
statement: Statement<'a>,
) -> std::result::Result<Option<Statement<'a>>, BlockError> {
block: &mut Block,
statement: Statement,
) -> std::result::Result<Option<Statement>, BlockError> {
match statement {
// Push new block to stack
Statement::For { .. }
......@@ -250,10 +250,10 @@ impl<'a> Shell<'a> {
/// expressions
fn execute_if(
&mut self,
expression: &[Statement<'a>],
success: &[Statement<'a>],
else_if: &[ElseIf<'a>],
failure: &[Statement<'a>],
expression: &[Statement],
success: &[Statement],
else_if: &[ElseIf],
failure: &[Statement],
) -> Result {
// Try execute success branch
self.execute_statements(expression)?;
......@@ -279,7 +279,7 @@ impl<'a> Shell<'a> {
&mut self,
variables: &[types::Str],
values: &[types::Str],
statements: &[Statement<'a>],
statements: &[Statement],
) -> Result {
macro_rules! set_vars_then_exec {
($chunk:expr, $def:expr) => {
......@@ -324,11 +324,7 @@ impl<'a> Shell<'a> {
/// Executes all of the statements within a while block until a certain
/// condition is met.
fn execute_while(
&mut self,
expression: &[Statement<'a>],
statements: &[Statement<'a>],
) -> Result {
fn execute_while(&mut self, expression: &[Statement], statements: &[Statement]) -> Result {
loop {
self.execute_statements(expression)?;
if self.previous_status.is_failure() {
......@@ -345,7 +341,7 @@ impl<'a> Shell<'a> {
}
/// Executes a single statement
pub fn execute_statement(&mut self, statement: &Statement<'a>) -> Result {
pub fn execute_statement(&mut self, statement: &Statement) -> Result {
match statement {
Statement::Let(action) => {
self.previous_status = self.local(action);
......@@ -475,7 +471,7 @@ impl<'a> Shell<'a> {
}
/// Simply executes all supplied statements.
pub fn execute_statements(&mut self, statements: &[Statement<'a>]) -> Result {
pub fn execute_statements(&mut self, statements: &[Statement]) -> Result {
self.variables.new_scope(false);
let condition = statements
......@@ -491,7 +487,7 @@ impl<'a> Shell<'a> {
/// Expand an expression and run a branch based on the value of the
/// expanded expression
fn execute_match<T: AsRef<str>>(&mut self, expression: T, cases: &[Case<'a>]) -> Result {
fn execute_match<T: AsRef<str>>(&mut self, expression: T, cases: &[Case]) -> Result {
use regex::RegexSet;
// Logic for determining if the LHS of a match-case construct (the value we are
// matching against) matches the RHS of a match-case construct (a value
......@@ -599,10 +595,10 @@ impl<'a> Shell<'a> {
// TODO: If the aliases are made standard functions, the error type must be changed
fn expand_pipeline<'a>(
shell: &Shell<'a>,
pipeline: &Pipeline<Job<'a>>,
) -> std::result::Result<(Pipeline<Job<'a>>, Vec<Statement<'a>>), IonError> {
pipeline: &Pipeline<Job>,
) -> std::result::Result<(Pipeline<Job>, Vec<Statement>), IonError> {
let mut item_iter = pipeline.items.iter();
let mut items: Vec<PipeItem<Job<'a>>> = Vec::with_capacity(item_iter.size_hint().0);
let mut items: Vec<PipeItem<Job>> = Vec::with_capacity(item_iter.size_hint().0);
let mut statements = Vec::new();
while let Some(item) = item_iter.next() {
......@@ -672,10 +668,10 @@ fn expand_pipeline<'a>(
mod tests {