From 5ac2fd749600f2071020a67ea4d79337b1ff4af5 Mon Sep 17 00:00:00 2001
From: Michael Aaron Murphy <mmstickman@gmail.com>
Date: Sun, 15 Jul 2018 00:17:19 +0000
Subject: [PATCH] Conditional Improvements

---
 examples/if_with_builtins.ion     |  9 +++++++++
 examples/if_with_builtins.out     |  2 ++
 examples/not.ion                  |  8 ++++++--
 examples/not.out                  |  4 ++++
 src/lib/parser/statement/parse.rs | 23 ++++++++++++-----------
 src/lib/shell/flow.rs             | 12 ++++++++----
 src/lib/shell/flow_control.rs     |  4 ++--
 7 files changed, 43 insertions(+), 19 deletions(-)
 create mode 100644 examples/if_with_builtins.ion
 create mode 100644 examples/if_with_builtins.out

diff --git a/examples/if_with_builtins.ion b/examples/if_with_builtins.ion
new file mode 100644
index 00000000..3c1ec3e8
--- /dev/null
+++ b/examples/if_with_builtins.ion
@@ -0,0 +1,9 @@
+if not false
+    echo a
+end
+
+if not true
+    echo b
+else if not false
+    echo c
+end
diff --git a/examples/if_with_builtins.out b/examples/if_with_builtins.out
new file mode 100644
index 00000000..0f7bc766
--- /dev/null
+++ b/examples/if_with_builtins.out
@@ -0,0 +1,2 @@
+a
+c
diff --git a/examples/not.ion b/examples/not.ion
index ef5f4b36..8c2444c5 100644
--- a/examples/not.ion
+++ b/examples/not.ion
@@ -1,6 +1,10 @@
 not true || echo not true
+! true || echo not true
 not false && echo not false
-true && not false && echo true and not false 
+! false && echo not false
+true && not false && echo true and not false
+true && ! false && echo true and not false
 not test -z "a" && echo not test
+! test -z "a" && echo not test
 not echo hello
-echo $?
\ No newline at end of file
+echo $?
diff --git a/examples/not.out b/examples/not.out
index 471a3051..bbc2a417 100644
--- a/examples/not.out
+++ b/examples/not.out
@@ -1,6 +1,10 @@
 not true
+not true
+not false
 not false
 true and not false
+true and not false
+not test
 not test
 hello
 1
diff --git a/src/lib/parser/statement/parse.rs b/src/lib/parser/statement/parse.rs
index 33b31535..cae756f2 100644
--- a/src/lib/parser/statement/parse.rs
+++ b/src/lib/parser/statement/parse.rs
@@ -81,12 +81,12 @@ pub(crate) fn parse(code: &str) -> Statement {
             return Statement::Export(ExportAction::Assign(keys, op, values));
         }
         _ if cmd.starts_with("if ") => {
-            return collect(cmd[3..].trim_left(), |pipeline| Statement::If {
-                expression: pipeline,
+            return Statement::If {
+                expression: Box::new(parse(cmd[3..].trim_left())),
                 success:    Vec::new(),
                 else_if:    Vec::new(),
                 failure:    Vec::new(),
-            })
+            }
         }
         "else" => return Statement::Else,
         _ if cmd.starts_with("else") => {
@@ -94,11 +94,9 @@ pub(crate) fn parse(code: &str) -> Statement {
             if cmd.is_empty() {
                 return Statement::Else;
             } else if cmd.starts_with("if ") {
-                return collect(cmd[3..].trim_left(), |pipeline| {
-                    Statement::ElseIf(ElseIf {
-                        expression: pipeline,
-                        success:    Vec::new(),
-                    })
+                return Statement::ElseIf(ElseIf {
+                    expression: Box::new(parse(cmd[3..].trim_left())),
+                    success: Vec::new()
                 });
             }
         }
@@ -209,7 +207,10 @@ pub(crate) fn parse(code: &str) -> Statement {
         _ if cmd.starts_with("not ") => {
             return Statement::Not(Box::new(parse(cmd[3..].trim_left())))
         }
-        _ if cmd.eq("not") => return Statement::Not(Box::new(Statement::Default)),
+        _ if cmd.starts_with("! ") => {
+            return Statement::Not(Box::new(parse(cmd[1..].trim_left())))
+        }
+        _ if cmd.eq("not") | cmd.eq("!") => return Statement::Not(Box::new(Statement::Default)),
         _ => (),
     }
 
@@ -232,7 +233,7 @@ mod tests {
         // Default case where spaced normally
         let parsed_if = parse("if test 1 -eq 2");
         let correct_parse = Statement::If {
-            expression: Pipeline {
+            expression: Box::new(Statement::Pipeline(Pipeline {
                 items: vec![PipeItem {
                     job: Job::new(
                         vec![
@@ -247,7 +248,7 @@ mod tests {
                     outputs: Vec::new(),
                     inputs:  Vec::new(),
                 }],
-            },
+            })),
             success:    vec![],
             else_if:    vec![],
             failure:    vec![],
diff --git a/src/lib/shell/flow.rs b/src/lib/shell/flow.rs
index 7da5dd09..a0cfe827 100644
--- a/src/lib/shell/flow.rs
+++ b/src/lib/shell/flow.rs
@@ -56,7 +56,7 @@ pub(crate) trait FlowLogic {
     /// expressions
     fn execute_if(
         &mut self,
-        expression: Pipeline,
+        expression: Box<Statement>,
         success: Vec<Statement>,
         else_if: Vec<ElseIf>,
         failure: Vec<Statement>,
@@ -335,7 +335,7 @@ impl FlowLogic for Shell {
 
     fn execute_if(
         &mut self,
-        expression: Pipeline,
+        expression: Box<Statement>,
         success: Vec<Statement>,
         else_if: Vec<ElseIf>,
         failure: Vec<Statement>,
@@ -345,8 +345,12 @@ impl FlowLogic for Shell {
             .into_iter()
             .map(|cond| (cond.expression, cond.success));
 
-        for (mut condition, statements) in first_condition.chain(else_conditions) {
-            if self.run_pipeline(&mut condition) == Some(SUCCESS) {
+        for (condition, statements) in first_condition.chain(else_conditions) {
+            if let Condition::SigInt = self.execute_statements(vec![*condition]) {
+                return Condition::SigInt;
+            }
+
+            if self.previous_status == 0 {
                 return self.execute_statements(statements);
             }
         }
diff --git a/src/lib/shell/flow_control.rs b/src/lib/shell/flow_control.rs
index f6831ba4..40226401 100644
--- a/src/lib/shell/flow_control.rs
+++ b/src/lib/shell/flow_control.rs
@@ -8,7 +8,7 @@ use lexers::assignments::{KeyBuf, Operator, Primitive};
 
 #[derive(Debug, PartialEq, Clone)]
 pub(crate) struct ElseIf {
-    pub expression: Pipeline,
+    pub expression: Box<Statement>,
     pub success:    Vec<Statement>,
 }
 
@@ -63,7 +63,7 @@ pub(crate) enum Statement {
     Case(Case),
     Export(ExportAction),
     If {
-        expression: Pipeline,
+        expression: Box<Statement>,
         success:    Vec<Statement>,
         else_if:    Vec<ElseIf>,
         failure:    Vec<Statement>,
-- 
GitLab