From 1aaa5618de711367f7b0c471aba8fa0128770715 Mon Sep 17 00:00:00 2001 From: Leah Neukirchen Date: Fri, 6 Mar 2020 10:53:34 +0100 Subject: [PATCH 01/13] Make alt-backspace behave like ctrl-w. Another common binding in readline and its clones. --- src/mainclient/shell.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/mainclient/shell.c b/src/mainclient/shell.c index 9b736627..b9b843d2 100644 --- a/src/mainclient/shell.c +++ b/src/mainclient/shell.c @@ -765,6 +765,9 @@ static int line() { case '.': /* Alt-. */ historymove(-JANET_HISTORY_MAX); break; + case 127: /* Alt-backspace */ + kbackspacew(); + break; } } break; From 6123c41f132471f7ff3bb05e732ac055db1e569f Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 6 Mar 2020 08:36:21 -0600 Subject: [PATCH 02/13] Harden semantics for and and or macros. There was perviously a bit of fuzziness on returning false/nil from these macros that has been removed. --- src/boot/boot.janet | 20 ++++++++++++-------- test/suite8.janet | 5 +++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 1b61e6df..5de7dc00 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -244,26 +244,30 @@ [(,not= :error (,fiber/status ,f)) ,r]))) (defmacro and - "Evaluates to the last argument if all preceding elements are true, otherwise - evaluates to false." + "Evaluates to the last argument if all preceding elements are truthy, otherwise + evaluates to the first falsey argument." [& forms] (var ret true) (def len (length forms)) (var i len) (while (> i 0) (-- i) + (def v (in forms i)) (set ret (if (= ret true) - (in forms i) - (tuple 'if (in forms i) ret)))) + v + (if (idempotent? v) + ['if v ret v] + (do (def s (gensym)) + ['if ['def s v] ret s]))))) ret) (defmacro or - "Evaluates to the last argument if all preceding elements are false, otherwise - evaluates to true." + "Evaluates to the last argument if all preceding elements are falsey, otherwise + evaluates to the first truthy element." [& forms] - (var ret nil) (def len (length forms)) - (var i len) + (var i (- len 1)) + (var ret (in forms i)) (while (> i 0) (-- i) (def fi (in forms i)) diff --git a/test/suite8.janet b/test/suite8.janet index 4c948511..f314a53e 100644 --- a/test/suite8.janet +++ b/test/suite8.janet @@ -107,4 +107,9 @@ (assert (= nil (match [1 2] [a b c] a)) "match 4") (assert (= 2 (match [1 2] [a b] b)) "match 5") +# And/or checks + +(assert (= false (and false false)) "and 1") +(assert (= false (or false false)) "or 1") + (end-suite) From f9e9c70b6ce40974207e175a90c4b976cce20a4e Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 6 Mar 2020 08:40:51 -0600 Subject: [PATCH 03/13] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d167fb2..38f3edd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. ## Unreleased +- Fix `and` and `or` macros returning nil instead of false in some cases. +- Allow matching successfully against nil values in the `match` macro. - Improve `janet_formatc` and `janet_panicf` formatters to be more like `string/format`. This makes it easier to make nice error messages from C. - Add `signal` From 714bd61d56efb57d536b293b01c6c828d402b274 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 6 Mar 2020 10:01:04 -0600 Subject: [PATCH 04/13] Address #300 Check for empty capture stack in replace rule. --- src/core/peg.c | 14 +++++++++----- test/suite8.janet | 5 +++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/core/peg.c b/src/core/peg.c index 6e839f9e..fc05c9b7 100644 --- a/src/core/peg.c +++ b/src/core/peg.c @@ -369,19 +369,23 @@ tail: s->mode = oldmode; if (!result) return NULL; - Janet cap; + Janet cap = janet_wrap_nil(); Janet constant = s->constants[rule[2]]; switch (janet_type(constant)) { default: cap = constant; break; case JANET_STRUCT: - cap = janet_struct_get(janet_unwrap_struct(constant), - s->captures->data[s->captures->count - 1]); + if (s->captures->count) { + cap = janet_struct_get(janet_unwrap_struct(constant), + s->captures->data[s->captures->count - 1]); + } break; case JANET_TABLE: - cap = janet_table_get(janet_unwrap_table(constant), - s->captures->data[s->captures->count - 1]); + if (s->captures->count) { + cap = janet_table_get(janet_unwrap_table(constant), + s->captures->data[s->captures->count - 1]); + } break; case JANET_CFUNCTION: cap = janet_unwrap_cfunction(constant)(s->captures->count - cs.cap, diff --git a/test/suite8.janet b/test/suite8.janet index f314a53e..242d80db 100644 --- a/test/suite8.janet +++ b/test/suite8.janet @@ -112,4 +112,9 @@ (assert (= false (and false false)) "and 1") (assert (= false (or false false)) "or 1") +# #300 Regression test + +# Just don't segfault +(assert (peg/match '{:main (replace "S" {"S" :spade})} "S7") "regression #300") + (end-suite) From e351dde651618472106026fef19ec9efca4f4ba6 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 6 Mar 2020 17:12:06 -0600 Subject: [PATCH 05/13] Update CHANGELOG.md and docs for loop and pp. --- CHANGELOG.md | 1 + src/boot/boot.janet | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38f3edd7..7c9150e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. - Correct arity for `marshal` - Add `flush` and `eflush` - Add `prompt` and `return` on top of signal for user friendly delimited continuations. +- Fix possible segfault with malformed pegs. ## 1.7.0 - 2020-02-01 - Remove `file/fileno` and `file/fdopen`. diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 5de7dc00..b87dfe6a 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -481,7 +481,8 @@ \t:iterate - repeatedly evaluate and bind to the expression while it is truthy.\n \t:range - loop over a range. The object should be two element tuple with a start and end value, and an optional positive step. The range is half open, [start, end).\n - \t:down - Same as range, but loops in reverse.\n + \t:down - Same as range, but breaks the loop when the binding is less than or equal to end. + Step should still be a positive integer.\n \t:keys - Iterate over the keys in a data structure.\n \t:pairs - Iterate over the keys value pairs in a data structure.\n \t:in - Iterate over the values in an indexed data structure or byte sequence.\n @@ -1280,7 +1281,7 @@ nil) (defn pp - "Pretty print to stdout or (dyn :out)." + `Pretty print to stdout or (dyn :out). The format string used is (dyn :pretty-format "%q").` [x] (printf (dyn :pretty-format "%q") x) (flush)) From 6010b95fca1fb5cf3214f5ba7fe1a74b9a1aa405 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 6 Mar 2020 17:30:36 -0600 Subject: [PATCH 06/13] Remove spaces from build manifests for sourcehut. --- .builds/.freebsd.yaml | 16 ++++++++-------- .builds/.openbsd.yaml | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.builds/.freebsd.yaml b/.builds/.freebsd.yaml index a2b4b589..027ef74a 100644 --- a/.builds/.freebsd.yaml +++ b/.builds/.freebsd.yaml @@ -1,12 +1,12 @@ image: freebsd/latest sources: - - https://git.sr.ht/~bakpakin/janet +- https://git.sr.ht/~bakpakin/janet packages: - - gmake +- gmake tasks: - - build: | - cd janet - gmake - gmake test - sudo gmake install - gmake test-install +- build: | + cd janet + gmake + gmake test + sudo gmake install + gmake test-install diff --git a/.builds/.openbsd.yaml b/.builds/.openbsd.yaml index 89d411f0..b7f6f4ce 100644 --- a/.builds/.openbsd.yaml +++ b/.builds/.openbsd.yaml @@ -1,12 +1,12 @@ image: openbsd/6.5 sources: - - https://git.sr.ht/~bakpakin/janet +- https://git.sr.ht/~bakpakin/janet packages: - - gmake +- gmake tasks: - - build: | - cd janet - gmake - gmake test - doas gmake install - gmake test-install +- build: | + cd janet + gmake + gmake test + doas gmake install + gmake test-install From cbdb700edfdc146a850aa3766b1f34eccfdfde31 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 6 Mar 2020 17:35:03 -0600 Subject: [PATCH 07/13] No need for doubly hidden files. --- .builds/{.freebsd.yaml => freebsd.yaml} | 0 .builds/{.openbsd.yaml => openbsd.yaml} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename .builds/{.freebsd.yaml => freebsd.yaml} (100%) rename .builds/{.openbsd.yaml => openbsd.yaml} (100%) diff --git a/.builds/.freebsd.yaml b/.builds/freebsd.yaml similarity index 100% rename from .builds/.freebsd.yaml rename to .builds/freebsd.yaml diff --git a/.builds/.openbsd.yaml b/.builds/openbsd.yaml similarity index 100% rename from .builds/.openbsd.yaml rename to .builds/openbsd.yaml From d3af50e4cc9dd28fb55c77d6086b98a3c4fc4b11 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 6 Mar 2020 17:42:35 -0600 Subject: [PATCH 08/13] Rename: s/yaml/yml/g --- .builds/{freebsd.yaml => freebsd.yml} | 0 .builds/{openbsd.yaml => openbsd.yml} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename .builds/{freebsd.yaml => freebsd.yml} (100%) rename .builds/{openbsd.yaml => openbsd.yml} (100%) diff --git a/.builds/freebsd.yaml b/.builds/freebsd.yml similarity index 100% rename from .builds/freebsd.yaml rename to .builds/freebsd.yml diff --git a/.builds/openbsd.yaml b/.builds/openbsd.yml similarity index 100% rename from .builds/openbsd.yaml rename to .builds/openbsd.yml From e62f12426b018e956c522cb6e243205c7a1dd0a2 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Fri, 6 Mar 2020 18:11:29 -0600 Subject: [PATCH 09/13] Update ci build files. --- .builds/freebsd.yml | 2 +- .builds/openbsd.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 027ef74a..fede2621 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -1,4 +1,4 @@ -image: freebsd/latest +image: freebsd/12.x sources: - https://git.sr.ht/~bakpakin/janet packages: diff --git a/.builds/openbsd.yml b/.builds/openbsd.yml index b7f6f4ce..27ad30a1 100644 --- a/.builds/openbsd.yml +++ b/.builds/openbsd.yml @@ -1,4 +1,4 @@ -image: openbsd/6.5 +image: openbsd/latest sources: - https://git.sr.ht/~bakpakin/janet packages: From e0c9910d851784fac24ffe7b0fd9771480b6c709 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 7 Mar 2020 09:31:52 -0600 Subject: [PATCH 10/13] Add :range-to and :down-to to loop. Fully inclusive ranges are generally useful and do not complicate implementation much. --- CHANGELOG.md | 1 + src/boot/boot.janet | 38 +++++++++++++++++++++++--------------- test/suite1.janet | 6 +++++- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c9150e8..0dc68a30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ All notable changes to this project will be documented in this file. ## Unreleased +- Add `:range-to` and `:down-to` verbs in the `loop` macro. - Fix `and` and `or` macros returning nil instead of false in some cases. - Allow matching successfully against nil values in the `match` macro. - Improve `janet_formatc` and `janet_panicf` formatters to be more like `string/format`. diff --git a/src/boot/boot.janet b/src/boot/boot.janet index b87dfe6a..317d08ec 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -366,6 +366,16 @@ ,;body (set ,i (,delta ,i ,step)))))) +(defn- check-indexed [x] + (if (indexed? x) + x + (error (string "expected tuple for range, got " x)))) + +(defn- range-template + [binding object rest op comparison] + (let [[start stop step] (check-indexed object)] + (for-template binding start stop (or step 1) comparison op [rest]))) + (defn- each-template [binding inx body] (with-syms [k] @@ -399,11 +409,6 @@ (def ,binding ,i) ,body)))) -(defn- check-indexed [x] - (if (indexed? x) - x - (error (string "expected tuple for range, got " x)))) - (defn- loop1 [body head i] @@ -433,12 +438,12 @@ (def {(+ i 2) object} head) (let [rest (loop1 body head (+ i 3))] (case verb - :range (let [[start stop step] (check-indexed object)] - (for-template binding start stop (or step 1) < + [rest])) + :range (range-template binding object rest + <) + :range-to (range-template binding object rest + <=) + :down (range-template binding object rest - >) + :down-to (range-template binding object rest - >=) :keys (keys-template binding object false [rest]) :pairs (keys-template binding object true [rest]) - :down (let [[start stop step] (check-indexed object)] - (for-template binding start stop (or step 1) > - [rest])) :in (each-template binding object [rest]) :iterate (iterate-template binding object rest) :generate (with-syms [f s] @@ -481,12 +486,14 @@ \t:iterate - repeatedly evaluate and bind to the expression while it is truthy.\n \t:range - loop over a range. The object should be two element tuple with a start and end value, and an optional positive step. The range is half open, [start, end).\n - \t:down - Same as range, but breaks the loop when the binding is less than or equal to end. - Step should still be a positive integer.\n - \t:keys - Iterate over the keys in a data structure.\n - \t:pairs - Iterate over the keys value pairs in a data structure.\n - \t:in - Iterate over the values in an indexed data structure or byte sequence.\n - \t:generate - Iterate over values yielded from a fiber. Can be paired with the generator + \t:range-to - same as :range, but the range is inclusive [start, end].\n + \t:down - loop over a range, stepping downwards. The object should be two element tuple + with a start and (exclusive) end value, and an optional (positive!) step size.\n + \t:down-to - same :as down, but the range is inclusive [start, end].\n + \t:keys - iterate over the keys in a data structure.\n + \t:pairs - iterate over the keys value pairs as tuples in a data structure.\n + \t:in - iterate over the values in a data structure.\n + \t:generate - iterate over values yielded from a fiber. Can be paired with the generator function for the producer/consumer pattern.\n\n loop also accepts conditionals to refine the looping further. Conditionals are of the form:\n\n @@ -510,6 +517,7 @@ (put _env 'iterate-template nil) (put _env 'each-template nil) (put _env 'keys-template nil) +(put _env 'range-template nil) (defmacro seq "Similar to loop, but accumulates the loop body into an array and returns that. diff --git a/test/suite1.janet b/test/suite1.janet index 3541f227..5b9f4f4f 100644 --- a/test/suite1.janet +++ b/test/suite1.janet @@ -212,13 +212,17 @@ (assert (= 7 (case :a :b 5 :c 6 :u 10 7)) "case with default") -# Testing the loop and for macros +# Testing the loop and seq macros (def xs (apply tuple (seq [x :range [0 10] :when (even? x)] (tuple (/ x 2) x)))) (assert (= xs '((0 0) (1 2) (2 4) (3 6) (4 8))) "seq macro 1") (def xs (apply tuple (seq [x :down [8 -2] :when (even? x)] (tuple (/ x 2) x)))) (assert (= xs '((4 8) (3 6) (2 4) (1 2) (0 0))) "seq macro 2") +# :range-to and :down-to +(assert (deep= (seq [x :range-to [0 10]] x) (seq [x :range [0 11]] x)) "loop :range-to") +(assert (deep= (seq [x :down-to [10 0]] x) (seq [x :down [10 -1]] x)) "loop :down-to") + # Some testing for not= (assert (not= 1 1 0) "not= 1") (assert (not= 0 1 1) "not= 2") From c864828735bef98e5b9a18015167133b75ee5662 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 7 Mar 2020 09:38:37 -0600 Subject: [PATCH 11/13] Address #293 - wildcard to match macro. The _ symbol will match any value without creating a binding. --- CHANGELOG.md | 2 ++ src/boot/boot.janet | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dc68a30..72aa429f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. ## Unreleased +- Allow `_` in the `match` macro to match anything without creating a binding + or doing unification. - Add `:range-to` and `:down-to` verbs in the `loop` macro. - Fix `and` and `or` macros returning nil instead of false in some cases. - Allow matching successfully against nil values in the `match` macro. diff --git a/src/boot/boot.janet b/src/boot/boot.janet index 317d08ec..e7bd9491 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -1325,6 +1325,9 @@ [pattern expr onmatch seen] (cond + (= '_ pattern) + (onmatch) + (symbol? pattern) (if (in seen pattern) ~(if (= ,pattern ,expr) ,(onmatch) ,sentinel) @@ -1374,14 +1377,15 @@ (defmacro match "Pattern matching. Match an expression x against - any number of cases. Easy case is a pattern to match against, followed + any number of cases. Each case is a pattern to match against, followed by an expression to evaluate to if that case is matched. A pattern that is a symbol will match anything, binding x's value to that symbol. An array will match only if all of it's elements match the corresponding elements in x. A table or struct will match if all values match with the corresponding values in x. A tuple pattern will match if it's first element matches, and the following - elements are treated as predicates and are true. Any other value pattern will only - match if it is equal to x." + elements are treated as predicates and are true. The last special case is + the '_ symbol, which is a wildcard that will match any value without creating a binding. + Any other value pattern will only match if it is equal to x." [x & cases] (with-idemp $x x (def len (length cases)) From 390c042027a66c297def005b867b30e8dd3a4734 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 7 Mar 2020 09:49:25 -0600 Subject: [PATCH 12/13] Update README.md --- README.md | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 3e98903f..a9ddd76c 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ The language also supports bridging to native code written in C, meta-programmin There is a repl for trying out the language, as well as the ability to run script files. This client program is separate from the core runtime, so -janet could be embedded into other programs. Try janet in your browser at +janet can be embedded into other programs. Try janet in your browser at [https://janet-lang.org](https://janet-lang.org).
@@ -61,7 +61,9 @@ documentation for symbols in the core library. For example, Shows documentation for the doc macro. To get a list of all bindings in the default -environment, use the `(all-bindings)` function. +environment, use the `(all-bindings)` function. You +can also use the `(doc)` macro with no arguments if you are in the repl +to show bound symbols. ## Source @@ -122,7 +124,7 @@ is maybe more convenient and flexible for integrating into existing pipelines. Meson also provides much better IDE integration than Make or batch files, as well as support for cross compilation. -For the impatient, building with Meson is as simple as follows. The options provided to +For the impatient, building with Meson is as follows. The options provided to `meson setup` below emulate Janet's Makefile. ```sh @@ -152,7 +154,7 @@ Emacs, and Atom will have syntax packages for the Janet language, though. ## Installation See [the Introduction](https://janet-lang.org/introduction.html) for more details. If you just want -to try out the language, you don't need to install anything. You can also simply move the `janet` executable wherever you want on your system and run it. +to try out the language, you don't need to install anything. You can also move the `janet` executable wherever you want on your system and run it. ## Usage @@ -163,35 +165,38 @@ If you are looking to explore, you can print a list of all available macros, fun by entering the command `(all-bindings)` into the repl. ``` -$ ./janet -Janet 0.0.0 alpha Copyright (C) 2017-2018 Calvin Rose +$ janet +Janet 1.7.1-dev-951e10f Copyright (C) 2017-2020 Calvin Rose janet:1:> (+ 1 2 3) 6 janet:2:> (print "Hello, World!") Hello, World! nil janet:3:> (os/exit) -$ ./janet -h -usage: ./janet [options] scripts... +$ janet -h +usage: build/janet [options] script args... Options are: - -h Show this help - -v Print the version string - -s Use raw stdin instead of getline like functionality - -e Execute a string of janet - -r Enter the repl after running all scripts - -p Keep on executing if there is a top level error (persistent) - -- Stop handling option -$ + -h : Show this help + -v : Print the version string + -s : Use raw stdin instead of getline like functionality + -e code : Execute a string of janet + -r : Enter the repl after running all scripts + -p : Keep on executing if there is a top level error (persistent) + -q : Hide prompt, logo, and repl output (quiet) + -k : Compile scripts but do not execute (flycheck) + -m syspath : Set system path for loading global modules + -c source output : Compile janet source code into an image + -n : Disable ANSI color output in the repl + -l path : Execute code in a file before running the main script + -- : Stop handling options ``` -If installed, you can also run `man janet` to get usage information. +If installed, you can also run `man janet` and `man jpm` to get usage information. ## Embedding -The C API for Janet is not yet documented but coming soon. - -Janet can be embedded in a host program very easily. There is a make target -`make amalg` which creates the file `build/janet.c`, which is a single C file +Janet can be embedded in a host program very easily. The normal build +will create a file `build/janet.c`, which is a single C file that contains all the source to Janet. This file, along with `src/include/janet.h` and `src/include/janetconf.h` can dragged into any C project and compiled into the project. Janet should be compiled with `-std=c99` @@ -200,6 +205,8 @@ the dynamic linker, `-ldl`, if one wants to be able to load dynamic modules. If there is no need for dynamic modules, add the define `-DJANET_NO_DYNAMIC_MODULES` to the compiler options. +See the [Embedding Section](https://janet-lang.org/capi/embedding.html) on the website for more information. + ## Examples See the examples directory for some example janet code. From d3b9b8d4528e45d3f59636656351ad545d26a94b Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sat, 7 Mar 2020 10:13:10 -0600 Subject: [PATCH 13/13] For #293, correct wildcards in dictinoaries. --- src/boot/boot.janet | 4 +++- test/suite8.janet | 9 +++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/boot/boot.janet b/src/boot/boot.janet index e7bd9491..c5036e6c 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -1368,9 +1368,11 @@ ~(if (,dictionary? ,$dict) ,((fn aux [] (set key (next pattern key)) + (def $val (gensym)) (if (= key nil) (onmatch) - (match-1 [(in pattern key) [not= (in pattern key) nil]] [in $dict key] aux seen)))) + ~(do (def ,$val (,get ,$dict ,key)) + ,(match-1 [(in pattern key) [not= nil $val]] $val aux seen))))) ,sentinel))) :else ~(if (= ,pattern ,expr) ,(onmatch) ,sentinel))) diff --git a/test/suite8.janet b/test/suite8.janet index 242d80db..4c976289 100644 --- a/test/suite8.janet +++ b/test/suite8.janet @@ -117,4 +117,13 @@ # Just don't segfault (assert (peg/match '{:main (replace "S" {"S" :spade})} "S7") "regression #300") +# Test cases for #293 +(assert (= :yes (match [1 2 3] [_ a _] :yes :no)) "match wildcard 1") +(assert (= :no (match [1 2 3] [__ a __] :yes :no)) "match wildcard 2") +(assert (= :yes (match [1 2 [1 2 3]] [_ a [_ _ _]] :yes :no)) "match wildcard 3") +(assert (= :yes (match [1 2 3] (_ (even? 2)) :yes :no)) "match wildcard 4") +(assert (= :yes (match {:a 1} {:a _} :yes :no)) "match wildcard 5") +(assert (= false (match {:a 1 :b 2 :c 3} {:a a :b _ :c _ :d _} :no {:a _ :b _ :c _} false :no)) "match wildcard 6") +(assert (= nil (match {:a 1 :b 2 :c 3} {:a a :b _ :c _ :d _} :no {:a _ :b _ :c _} nil :no)) "match wildcard 7") + (end-suite)