From 0adc1abd5088fd51068edda9afa859b6da6b8b1b Mon Sep 17 00:00:00 2001 From: Veit Heller Date: Thu, 8 Jul 2021 20:43:48 +0200 Subject: [PATCH] feat: allow for multibranches in case (#1276) --- core/ControlMacros.carp | 18 ++++++++++++++---- core/Gensym.carp | 2 +- test/macros.carp | 9 +++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/core/ControlMacros.carp b/core/ControlMacros.carp index 327f56bf..fed5d864 100644 --- a/core/ControlMacros.carp +++ b/core/ControlMacros.carp @@ -141,6 +141,12 @@ Example: (defmacro unless [condition form] (list 'if condition (list) form)) +(hidden treat-case-handler) +(defndynamic treat-case-handler [name handler] + (if (and (list? handler) (> (length handler) 1) (= ':or (car handler))) + (cons 'or (map (fn [val] (list '= name val)) (cdr handler))) + (list '= name handler))) + (hidden case-internal) (defndynamic case-internal [name xs] (if (= (length xs) 0) @@ -150,24 +156,28 @@ Example: (if (= (length xs) 1) (car xs) (list 'if - (list '= name (car xs)) + (treat-case-handler name (car xs)) (cadr xs) (case-internal name (cddr xs))))))) (doc case "takes a form and a list of branches which are value and operation -pairs. If a value matches, the operation is executed. It takes a catch-all else -branch that is executed if nothing matches. +pairs. If a value matches (or any in a list of values preced by `:or`), the +operation is executed. It takes a catch-all else branch that is executed if +nothing matches. Example: ``` (case (+ 10 1) 10 (println* \"nope\") 11 (println* \"yup\") + (:or 12 13) (println* \"multibranch, but nope\") (println* \"else branch\") ) ```") (defmacro case [form :rest branches] - (case-internal form branches)) + (let [name (gensym)] + (list 'let [name form] + (case-internal name branches)))) (defmodule Dynamic (doc flip diff --git a/core/Gensym.carp b/core/Gensym.carp index 78b91bd6..438c17ef 100644 --- a/core/Gensym.carp +++ b/core/Gensym.carp @@ -7,7 +7,7 @@ (doc gensym-with "Generates symbols dynamically, based on a symbol name.") (defndynamic gensym-with [x] (do - (set! *gensym-counter* (inc *gensym-counter*)) + (set! *gensym-counter* (+ *gensym-counter* 1)) (Symbol.concat [x (Symbol.from *gensym-counter*)]))) (doc gensym "Generates symbols dynamically as needed.") diff --git a/test/macros.carp b/test/macros.carp index 44734f2e..e4466ad6 100644 --- a/test/macros.carp +++ b/test/macros.carp @@ -34,6 +34,12 @@ 1 true false)) +(defn test-case-multi [] + (case 1 + 2 false + (:or 1 3) true + false)) + (defmacro test-not [a] (not a)) (defmacro test-< [a b] (< a b)) (defmacro test-> [a b] (> a b)) @@ -84,6 +90,9 @@ (assert-true test (test-case-select) "case correctly selects branch") + (assert-true test + (test-case-multi) + "case correctly selects multibranch") (assert-true test (test-comment) "comment ignores input")