Browse Source

reinstate case expr

Getty Ritter 1 year ago
parent
commit
2e10db3831
3 changed files with 40 additions and 28 deletions
  1. 15 15
      src/ast.rs
  2. 17 5
      src/grammar.lalrpop
  3. 8 8
      src/interp.rs

+ 15 - 15
src/ast.rs

@@ -228,20 +228,20 @@ impl ASTArena {
                 writeln!(f, ")")
             }
 
-            // Expr::Case(expr, cases) => {
-            //     writeln!(f, "Case(")?;
-            //     self.indent(f, depth)?;
-            //     self.show_expr(&self[*expr], f, depth)?;
-            //     for case in cases {
-            //         self.indent(f, depth + 2)?;
-            //         self.show_pat(&case.pat, f)?;
-            //         writeln!(f, " =>")?;
-            //         self.indent(f, depth + 4)?;
-            //         self.show_expr(&self[case.expr], f, depth + 4)?;
-            //     }
-            //     self.indent(f, depth)?;
-            //     writeln!(f, ")")
-            // }
+            Expr::Case(expr, cases) => {
+                writeln!(f, "Case(")?;
+                self.indent(f, depth)?;
+                self.show_expr(&self[*expr], f, depth)?;
+                for case in cases {
+                    self.indent(f, depth + 2)?;
+                    self.show_pat(&case.pats[0], f)?;
+                    writeln!(f, " =>")?;
+                    self.indent(f, depth + 4)?;
+                    self.show_expr(&self[case.expr], f, depth + 4)?;
+                }
+                self.indent(f, depth)?;
+                writeln!(f, ")")
+            }
         }
     }
 }
@@ -325,7 +325,7 @@ pub enum Expr {
     Let(bool, Name, ExprRef, ExprRef),
     Fun(Vec<Case>),
     Range(ExprRef, ExprRef),
-    // Case(ExprRef, Vec<Case>),
+    Case(ExprRef, Vec<Case>),
     Nil,
 }
 

+ 17 - 5
src/grammar.lalrpop

@@ -131,21 +131,33 @@ pub Leaf: ExprId = {
     },
     "let" <fixed:"fix"?> <name:Name> ":=" <e1:Located<Expr>> "in" "{" <e2:Located<Expr>> "}" =>
         ast.add_expr(Expr::Let(fixed.is_some(), name, e1, e2)),
-    "{" <cs:Cases> "}" =>
+    "{" <cs:FunCases> "}" =>
         ast.add_expr(Expr::Fun(cs)),
-//    "case" <e:Located<Expr>> "in" "{" <cs:Cases> "}" =>
-//        ast.add_expr(Expr::Case(e, cs)),
+    "case" <e:Located<Expr>> "in" "{" <cs:Cases> "}" =>
+        ast.add_expr(Expr::Case(e, cs)),
     "(" <e:Expr> ")" => e,
 };
 
 pub Cases: Vec<Case> = {
-    <mut cs:(<Case> ";")*> <c:Case> => {
+  <mut cs:(<Case> ";")*> <c:Case> => {
+    cs.push(c);
+    cs
+  }
+};
+
+pub Case: Case = {
+  <pat:Pat> "=>" <expr:Located<Expr>> =>
+    Case { pats: vec![pat], expr }
+};
+
+pub FunCases: Vec<Case> = {
+    <mut cs:(<FunCase> ";")*> <c:FunCase> => {
         cs.push(c);
         cs
     }
 };
 
-pub Case: Case = {
+pub FunCase: Case = {
     "[" <mut pats:(<Pat> ",")*> <pat:Pat> "]" "=>" <expr:Located<Expr>> => {
         pats.push(pat);
         Case { pats, expr }

+ 8 - 8
src/interp.rs

@@ -571,13 +571,13 @@ impl State {
                 self.eval(*body, &Some(new_scope))
             }
 
-            // Expr::Case(scrut, _) => {
-            //     let closure = Closure {
-            //         func: expr_ref,
-            //         scope: env.clone(),
-            //     };
-            //     self.eval_closure(&closure, Thunk::Expr(*scrut, env.clone()))
-            // }
+            Expr::Case(scrut, _) => {
+                let closure = Closure {
+                    func: expr_ref,
+                    scope: env.clone(),
+                };
+                self.eval_closure(&closure, vec![Thunk::Expr(*scrut, env.clone())])
+            }
         }
     }
 
@@ -628,7 +628,7 @@ impl State {
         let ast = self.ast.borrow();
         let cases = match &ast[closure.func] {
             Expr::Fun(cases) => cases,
-            // Expr::Case(_, cases) => cases,
+            Expr::Case(_, cases) => cases,
             // see the note attached to the definition of `Closure`
             _ => bail!("INVARIANT FAILED"),
         };