From 835ca15052a1cf28b28bbd59ed4bca9ffe6d8a50 Mon Sep 17 00:00:00 2001
From: Hunter Goldstein <hunter.d.goldstein@gmail.com>
Date: Wed, 19 Jul 2017 12:28:18 -0400
Subject: [PATCH] case statements are now implicitly ended

---
 examples/match.ion        | 24 ++++++++----------
 src/shell/flow_control.rs | 53 +++++++++++++++++----------------------
 2 files changed, 34 insertions(+), 43 deletions(-)

diff --git a/examples/match.ion b/examples/match.ion
index cdefb7fb..78c2d290 100644
--- a/examples/match.ion
+++ b/examples/match.ion
@@ -1,7 +1,7 @@
 for i in [1 2 3 4 5 6]
   match $((i % 2))
-    case 0; echo "Even!"; end
-    case 1; echo "Odd!" ; end
+    case 0; echo "Even!"
+    case 1; echo "Odd!" 
   end
 end
 
@@ -10,8 +10,8 @@ let out2 = "/foo/bar/baz.quxx: application/quxx-archive";
 
 fn analyze output
   match @split(output)[1]
-    case application/x-gzip; echo "Use tar -xzf"; end
-    case _ ; echo "Unknown file type"; end
+    case application/x-gzip; echo "Use tar -xzf"
+    case _ ; echo "Unknown file type"
   end
 end
 
@@ -20,8 +20,8 @@ analyze $out2
 
 fn wildcard input
   match $input
-    case _; echo "WILDCARD!"; end
-    case huh; echo "U N R E A C H A B L E"; end
+    case _; echo "WILDCARD!"
+    case huh; echo "U N R E A C H A B L E"
   end
 end
 
@@ -30,11 +30,11 @@ wildcard "huh"
 
 fn report usage
   match $usage
-    case @(seq 0 25); echo "Plenty of space my guy"; end
-    case @(seq 26 50); echo "Almost half full (or half empty)"; end
-    case @(seq 51 75); echo "Getting close to full :O"; end
-    case @(seq 76 99); echo "Time for spring cleaning, almost full!"; end
-    case _; echo "How did you even do this..."; end
+    case @(seq 0 25); echo "Plenty of space my guy"
+    case @(seq 26 50); echo "Almost half full (or half empty)"
+    case @(seq 51 75); echo "Getting close to full :O"
+    case @(seq 76 99); echo "Time for spring cleaning, almost full!"
+    case _; echo "How did you even do this..."
   end
 end
 
@@ -47,10 +47,8 @@ fn animated filetype
   match $filetype
     case ["image/jpeg" "image/png"]
       echo "Static :("
-    end
     case "image/gif"
       echo "Animated :D"
-    end
   end
 end
 
diff --git a/src/shell/flow_control.rs b/src/shell/flow_control.rs
index 2683db65..c3d9190a 100644
--- a/src/shell/flow_control.rs
+++ b/src/shell/flow_control.rs
@@ -133,32 +133,32 @@ pub struct Function {
     pub statements: Vec<Statement>
 }
 
-macro_rules! add_to_case {
-    ($cases:expr, $statement:expr) => {
-        match $cases.last_mut() {
-            // XXX: When does this actually happen? What syntax error is this???
-            None => return Err(["ion: syntax error: encountered ",
-                                 $statement.short(),
-                                 " outside of `case ... end` block"].concat()),
-            Some(ref mut case) => case.statements.push($statement),
-        }
-    }
-}
-
 pub fn collect_cases<I>(iterator: &mut I, cases: &mut Vec<Case>, level: &mut usize) -> Result<(), String>
     where I : Iterator<Item=Statement>
 {
+
+    macro_rules! add_to_case {
+        ($statement:expr) => {
+            match cases.last_mut() {
+                // XXX: When does this actually happen? What syntax error is this???
+                None => return Err(["ion: syntax error: encountered ",
+                                     $statement.short(),
+                                     " outside of `case ...` block"].concat()),
+                Some(ref mut case) => case.statements.push($statement),
+            }
+        }
+    }
+
     while let Some(statement) = iterator.next() {
         match statement {
             Statement::Case(case) => {
-                *level += 1;
-                if *level == 2 {
-                    // When the control flow level equals two, this means we are inside the
-                    // body of the match statement and should treat this as the new case of _this_
-                    // match. Otherwise we will just add it to the current case.
+                if *level == 1 {
+                    // If the level is 1, then we are at a top-level case
+                    // statement for this match block and should push this case
                     cases.push(case);
                 } else {
-                    add_to_case!(cases, Statement::Case(case));
+                    // This is just part of the current case block
+                    add_to_case!(Statement::Case(case));
                 }
             },
             Statement::End => {
@@ -172,15 +172,8 @@ pub fn collect_cases<I>(iterator: &mut I, cases: &mut Vec<Case>, level: &mut usi
             Statement::If { .. } |
             Statement::Match { .. } |
             Statement::Function { .. } => {
-                if *level < 2 {
-                    // If the level is less than two, then this statement has appeared outside
-                    // of a block delimited by a case...end pair
-                    return Err(["ion: syntax error: expected end or case, got ", statement.short()].concat());
-                } else {
-                    // Otherwise it means we've hit a case statement for some other match construct
-                    *level += 1;
-                    add_to_case!(cases, statement);
-                }
+                *level += 1;
+                add_to_case!(statement);
             },
             Statement::Default |
             Statement::Else |
@@ -192,7 +185,7 @@ pub fn collect_cases<I>(iterator: &mut I, cases: &mut Vec<Case>, level: &mut usi
             Statement::Pipeline(_) |
             Statement::Break => {
                 // This is the default case with all of the other statements explicitly listed
-                add_to_case!(cases, statement);
+                add_to_case!(statement);
             },
         }
     }
@@ -208,7 +201,7 @@ pub fn collect_loops <I: Iterator<Item = Statement>> (
     while let Some(statement) = iterator.next() {
         match statement {
             Statement::While{..} | Statement::For{..} | Statement::If{..} |
-                Statement::Function{..} | Statement::Match{..} | Statement::Case{..} => *level += 1,
+                Statement::Function{..} | Statement::Match{..} => *level += 1,
             Statement::End if *level == 1 => { *level = 0; break },
             Statement::End => *level -= 1,
             _ => (),
@@ -226,7 +219,7 @@ pub fn collect_if<I>(iterator: &mut I, success: &mut Vec<Statement>, else_if: &m
     while let Some(statement) = iterator.next() {
         match statement {
             Statement::While{..} | Statement::For{..} | Statement::If{..} |
-                Statement::Function{..} | Statement::Match{..} | Statement::Case{..} => *level += 1,
+                Statement::Function{..} | Statement::Match{..} => *level += 1,
             Statement::ElseIf(ref elseif) if *level == 1 => {
                 if current_block == 1 {
                     return Err("ion: syntax error: else block already given");
-- 
GitLab