Skip to content
Snippets Groups Projects
Commit 2c20f84a authored by Jeremy Soller's avatar Jeremy Soller Committed by GitHub
Browse files

Merge pull request #237 from mmstick/let_arithmetic

Implement Basic Arithmetic for Let/Export
parents 95af8191 894afb88
No related branches found
No related tags found
No related merge requests found
......@@ -33,12 +33,31 @@ let git_branch = $(git rev-parse --abbrev-ref HEAD 2> /dev/null)
If the command is executed without any arguments, it will simply list all available variables.
#### Dropping variables
To drop a value from the shell, the `drop` keyword may be used:
```sh
```ion
drop git_branch
```
#### Arithmetic
The `let` command also supports basic arithmetic.
```ion
let a = 1
echo $a
let a += 4
echo $a
let a *= 10
echo $a
let a /= 2
echo $a
let a -= 5
echo $a
```
### Export
The `export` command works similarly to the `let` command, but instead of defining a local variable, it defines a global variable that other processes can access.
......@@ -46,3 +65,20 @@ The `export` command works similarly to the `let` command, but instead of defini
```sh
export PATH = "~/.cargo/bin:${PATH}"
```
#### Arithmetic
The `export` command also supports basic arithmetic.
```ion
export a = 1
echo $a
export a += 4
echo $a
export a *= 10
echo $a
export a /= 2
echo $a
export a -= 5
echo $a
```
......@@ -22,6 +22,15 @@ enum Binding {
ListEntries,
KeyOnly(String),
KeyValue(String, String),
Math(String, Operator, f32),
MathInvalid(String)
}
enum Operator {
Plus,
Minus,
Divide,
Multiply
}
/// Parses let bindings, `let VAR = KEY`, returning the result as a `(key, value)` tuple.
......@@ -37,6 +46,7 @@ fn parse_assignment<I: IntoIterator>(args: I)
// Find the key and advance the iterator until the equals operator is found.
let mut key = "".to_owned();
let mut found_key = false;
let mut operator = None;
// Scans through characters until the key is found, then continues to scan until
// the equals operator is found.
......@@ -44,6 +54,34 @@ fn parse_assignment<I: IntoIterator>(args: I)
match character {
' ' if key.is_empty() => (),
' ' => found_key = true,
'+' => {
if char_iter.next() == Some('=') {
operator = Some(Operator::Plus);
found_key = true;
}
break
},
'-' => {
if char_iter.next() == Some('=') {
operator = Some(Operator::Minus);
found_key = true;
}
break
},
'*' => {
if char_iter.next() == Some('=') {
operator = Some(Operator::Multiply);
found_key = true;
}
break
},
'/' => {
if char_iter.next() == Some('=') {
operator = Some(Operator::Divide);
found_key = true;
}
break
},
'=' => {
found_key = true;
break
......@@ -62,7 +100,15 @@ fn parse_assignment<I: IntoIterator>(args: I)
} else if !Variables::is_valid_variable_name(&key) {
Binding::InvalidKey(key)
} else {
Binding::KeyValue(key, value)
match operator {
Some(operator) => {
match value.parse::<f32>() {
Ok(value) => Binding::Math(key, operator, value),
Err(_) => Binding::MathInvalid(value)
}
},
None => Binding::KeyValue(key, value)
}
}
}
}
......@@ -84,6 +130,11 @@ pub fn alias<I: IntoIterator>(vars: &mut Variables, args: I) -> i32
let stderr = io::stderr();
let _ = writeln!(&mut stderr.lock(), "ion: please provide value for alias '{}'", key);
return FAILURE;
},
_ => {
let stderr = io::stderr();
let _ = writeln!(&mut stderr.lock(), "ion: invalid alias syntax");
return FAILURE;
}
}
SUCCESS
......@@ -127,6 +178,29 @@ pub fn let_<I: IntoIterator>(vars: &mut Variables, args: I) -> i32
let stderr = io::stderr();
let _ = writeln!(&mut stderr.lock(), "ion: please provide value for variable '{}'", key);
return FAILURE;
},
Binding::Math(key, operator, increment) => {
let value = vars.get_var_or_empty(&key);
let _ = match value.parse::<f32>() {
Ok(old_value) => match operator {
Operator::Plus => vars.variables.insert(key, (old_value + increment).to_string()),
Operator::Minus => vars.variables.insert(key, (old_value - increment).to_string()),
Operator::Multiply => vars.variables.insert(key, (old_value * increment).to_string()),
Operator::Divide => vars.variables.insert(key, (old_value / increment).to_string()),
},
Err(_) => {
let stderr = io::stderr();
let mut stderr = stderr.lock();
let _ = writeln!(stderr, "ion: original value, {}, is not a number", value);
return FAILURE;
}
};
},
Binding::MathInvalid(value) => {
let stderr = io::stderr();
let mut stderr = stderr.lock();
let _ = writeln!(stderr, "ion: supplied value, {}, is not a number", value);
return FAILURE;
}
}
SUCCESS
......@@ -174,6 +248,29 @@ pub fn export_variable<I: IntoIterator>(vars: &mut Variables, args: I) -> i32
return FAILURE;
}
},
Binding::Math(key, operator, increment) => {
let value = vars.get_var(&key).unwrap_or_else(|| "".to_owned());
match value.parse::<f32>() {
Ok(old_value) => match operator {
Operator::Plus => env::set_var(key, (old_value + increment).to_string()),
Operator::Minus => env::set_var(key, (old_value - increment).to_string()),
Operator::Multiply => env::set_var(key, (old_value * increment).to_string()),
Operator::Divide => env::set_var(key, (old_value / increment).to_string()),
},
Err(_) => {
let stderr = io::stderr();
let mut stderr = stderr.lock();
let _ = writeln!(stderr, "ion: original value, {}, is not a number", value);
return FAILURE;
}
}
},
Binding::MathInvalid(value) => {
let stderr = io::stderr();
let mut stderr = stderr.lock();
let _ = writeln!(stderr, "ion: supplied value, {}, is not a number", value);
return FAILURE;
},
_ => {
let stderr = io::stderr();
let _ = writeln!(&mut stderr.lock(), "ion usage: export KEY=VALUE");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment