Permalink
Browse files

Implement Multiple Assignments

  • Loading branch information...
mmstick committed Jun 18, 2017
1 parent 5d3ca89 commit a6fd25147ac12685b3a650d8478724f7bff80fb1
Showing with 67 additions and 4 deletions.
  1. +9 −0 README.md
  2. +1 −2 examples/fibonacci.ion
  3. +12 −0 examples/let.ion
  4. +8 −0 examples/let.out
  5. +18 −2 src/parser/assignments.rs
  6. +19 −0 src/shell/assignments.rs
View
@@ -21,6 +21,7 @@ Ion is a shell for UNIX platforms, and is the default shell in Redox. It is stil
- [x] Executing Scripts with an @args Array
- [x] Aliases
- [x] Variables (**$variable**)
- [x] Multiple Variable Assignments
- [x] Substring Slicing of Variables
- [x] Arrays (**@array**)
- [x] Array Expressions (**[]**)
@@ -70,6 +71,14 @@ a similar action, only setting the variable globally as an environment variable
let git_branch = $(git rev-parse --abbrev-ref HEAD ^> /dev/null)
```
It is also possible to assign multiple variables at once, or swap variables.
```ion
let a b = 1 2
let a b = [1 2]
let a b = [$b $a]
```
If the command is executed without any arguments, it will simply list all available variables.
### Using Variables
View
@@ -2,8 +2,7 @@ fn fib n
if test $n -le 1
echo $n
else
let output = 1
let previous = 1
let output previous = 1 1
for _ in 2..$n
let temp = $output
let output += $previous
View
@@ -0,0 +1,12 @@
let a = 5
echo $a
let a b = [10 $a]
echo $a
echo $b
let b a = [$a $b]
echo $a
echo $b
let a b c = 1 2 3
echo $a
echo $b
echo $c
View
@@ -0,0 +1,8 @@
5
10
5
5
10
1
2
3
View
@@ -15,6 +15,7 @@ pub enum Binding {
KeyOnly(Identifier),
KeyValue(Identifier, VString),
Math(Identifier, Operator, VString),
MultipleKeys(Vec<Identifier>, VString)
}
#[derive(Debug, PartialEq, Clone)]
@@ -39,6 +40,7 @@ pub fn parse_assignment(arguments: &str) -> Binding {
// Find the key and advance the iterator until the equals operator is found.
let mut key = "".to_owned();
let mut keys: Vec<Identifier> = Vec::new();
let mut found_key = false;
let mut operator = None;
@@ -56,7 +58,10 @@ pub fn parse_assignment(arguments: &str) -> Binding {
while let Some(character) = char_iter.next() {
match character {
' ' if key.is_empty() => (),
' ' => found_key = true,
' ' => {
keys.push(key.clone().into());
key.clear();
},
'+' => {
match_operator!(Operator::Add);
break
@@ -78,6 +83,7 @@ pub fn parse_assignment(arguments: &str) -> Binding {
break
},
'=' => {
if !key.is_empty() { keys.push(key.into()); }
found_key = true;
break
},
@@ -86,9 +92,19 @@ pub fn parse_assignment(arguments: &str) -> Binding {
}
}
if !found_key && key.is_empty() {
if !found_key {
Binding::ListEntries
} else if keys.len() > 1 {
for key in &keys {
if !Variables::is_valid_variable_name(&key) {
return Binding::InvalidKey(key.clone());
}
}
Binding::MultipleKeys(keys, char_iter.skip_while(|&x| x == ' ').collect::<VString>())
} else if keys.is_empty() {
Binding::ListEntries
} else {
let key = keys.drain(..).next().unwrap();
let value = char_iter.skip_while(|&x| x == ' ').collect::<VString>();
if value.is_empty() {
Binding::KeyOnly(key.into())
View
@@ -23,6 +23,7 @@ use super::status::*;
enum Action {
UpdateString(Identifier, VString),
UpdateStrings(Vec<Identifier>, VArray),
UpdateArray(Identifier, VArray),
List
}
@@ -77,6 +78,14 @@ fn parse_assignment(binding: Binding,
Value::String(value) => Ok(Action::UpdateString(key, value)),
Value::Array(array) => Ok(Action::UpdateArray(key, array))
},
Binding::MultipleKeys(keys, value) => match parse_expression(&value, &expanders) {
Value::String(value) => {
let array = value.split_whitespace().map(String::from)
.collect::<VArray>();
Ok(Action::UpdateStrings(keys, array))
},
Value::Array(array) => Ok(Action::UpdateStrings(keys, array))
},
Binding::KeyOnly(key) => {
let stderr = io::stderr();
let _ = writeln!(&mut stderr.lock(), "ion: please provide value for variable '{}'", key);
@@ -120,6 +129,11 @@ pub fn let_assignment(binding: Binding, vars: &mut Variables, dir_stack: &Direct
match parse_assignment(binding, vars, dir_stack) {
Ok(Action::UpdateArray(key, array)) => vars.set_array(&key, array),
Ok(Action::UpdateString(key, string)) => vars.set_var(&key, &string),
Ok(Action::UpdateStrings(keys, array)) => {
for (key, value) in keys.iter().zip(array.iter()) {
vars.set_var(key, value);
}
},
Ok(Action::List) => {
print_vars(&vars.variables);
print_arrays(&vars.arrays);
@@ -136,6 +150,11 @@ pub fn export_variable(binding : Binding, vars: &mut Variables, dir_stack : &Dir
match parse_assignment(binding, vars, dir_stack) {
Ok(Action::UpdateArray(key, array)) => env::set_var(&key, array.join(" ")),
Ok(Action::UpdateString(key, string)) => env::set_var(&key, string),
Ok(Action::UpdateStrings(keys, array)) => {
for (key, value) in keys.iter().zip(array.iter()) {
env::set_var(key, value);
}
}
Ok(Action::List) => {
let stdout = io::stdout();
let stdout = &mut stdout.lock();

0 comments on commit a6fd251

Please sign in to comment.