erlang: lists zip/2 + zipwith/3 + unzip/1 (841/841)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s
Zip family in lib/erlang/lists-ext.sx; length mismatch and malformed pairs raise badarg. lists_ext suite 62 -> 70. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -366,6 +366,62 @@
|
|||||||
(fn (a b) (er-ext-lt? b a)))
|
(fn (a b) (er-ext-lt? b a)))
|
||||||
(raise (er-mk-error-marker (er-mk-atom "badarg")))))))
|
(raise (er-mk-error-marker (er-mk-atom "badarg")))))))
|
||||||
|
|
||||||
|
;; ── zip family (zip / zipwith / unzip) ────────────────────────────
|
||||||
|
;; Length mismatch raises badarg (real Erlang raises function_clause;
|
||||||
|
;; badarg is the closest in-port equivalent).
|
||||||
|
(define
|
||||||
|
er-ext-zip
|
||||||
|
(fn (a b)
|
||||||
|
(cond
|
||||||
|
(and (er-nil? a) (er-nil? b)) (er-mk-nil)
|
||||||
|
(and (er-cons? a) (er-cons? b))
|
||||||
|
(er-mk-cons
|
||||||
|
(er-mk-tuple (list (get a :head) (get b :head)))
|
||||||
|
(er-ext-zip (get a :tail) (get b :tail)))
|
||||||
|
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
er-bif-lists-zip
|
||||||
|
(fn (vs) (er-ext-zip (nth vs 0) (nth vs 1))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
er-ext-zipwith
|
||||||
|
(fn (f a b)
|
||||||
|
(cond
|
||||||
|
(and (er-nil? a) (er-nil? b)) (er-mk-nil)
|
||||||
|
(and (er-cons? a) (er-cons? b))
|
||||||
|
(er-mk-cons
|
||||||
|
(er-apply-fun f (list (get a :head) (get b :head)))
|
||||||
|
(er-ext-zipwith f (get a :tail) (get b :tail)))
|
||||||
|
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
er-bif-lists-zipwith
|
||||||
|
(fn (vs) (er-ext-zipwith (nth vs 0) (nth vs 1) (nth vs 2))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
er-ext-unzip
|
||||||
|
(fn (lst as bs)
|
||||||
|
(cond
|
||||||
|
(er-nil? lst)
|
||||||
|
(er-mk-tuple
|
||||||
|
(list
|
||||||
|
(er-list-reverse-iter as (er-mk-nil))
|
||||||
|
(er-list-reverse-iter bs (er-mk-nil))))
|
||||||
|
(and (er-cons? lst) (er-tuple? (get lst :head)))
|
||||||
|
(let ((es (get (get lst :head) :elements)))
|
||||||
|
(if (= (len es) 2)
|
||||||
|
(er-ext-unzip (get lst :tail)
|
||||||
|
(er-mk-cons (nth es 0) as)
|
||||||
|
(er-mk-cons (nth es 1) bs))
|
||||||
|
(raise (er-mk-error-marker (er-mk-atom "badarg")))))
|
||||||
|
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
er-bif-lists-unzip
|
||||||
|
(fn (vs)
|
||||||
|
(er-ext-unzip (er-bif-arg1 vs "lists:unzip") (er-mk-nil) (er-mk-nil))))
|
||||||
|
|
||||||
;; ── register ──────────────────────────────────────────────────────
|
;; ── register ──────────────────────────────────────────────────────
|
||||||
;; Hook into er-register-builtin-bifs! rather than registering once:
|
;; Hook into er-register-builtin-bifs! rather than registering once:
|
||||||
;; the registry can be reset + rebuilt mid-run (tests/runtime.sx does
|
;; the registry can be reset + rebuilt mid-run (tests/runtime.sx does
|
||||||
@@ -390,7 +446,10 @@
|
|||||||
(er-register-pure-bif! "lists" "splitwith" 2 er-bif-lists-splitwith)
|
(er-register-pure-bif! "lists" "splitwith" 2 er-bif-lists-splitwith)
|
||||||
(er-register-pure-bif! "lists" "flatten" 1 er-bif-lists-flatten)
|
(er-register-pure-bif! "lists" "flatten" 1 er-bif-lists-flatten)
|
||||||
(er-register-pure-bif! "lists" "max" 1 er-bif-lists-max)
|
(er-register-pure-bif! "lists" "max" 1 er-bif-lists-max)
|
||||||
(er-register-pure-bif! "lists" "min" 1 er-bif-lists-min)))
|
(er-register-pure-bif! "lists" "min" 1 er-bif-lists-min)
|
||||||
|
(er-register-pure-bif! "lists" "zip" 2 er-bif-lists-zip)
|
||||||
|
(er-register-pure-bif! "lists" "zipwith" 3 er-bif-lists-zipwith)
|
||||||
|
(er-register-pure-bif! "lists" "unzip" 1 er-bif-lists-unzip)))
|
||||||
|
|
||||||
(define er-ext-prev-register-builtins er-register-builtin-bifs!)
|
(define er-ext-prev-register-builtins er-register-builtin-bifs!)
|
||||||
(define er-register-builtin-bifs!
|
(define er-register-builtin-bifs!
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"language": "erlang",
|
"language": "erlang",
|
||||||
"total_pass": 833,
|
"total_pass": 841,
|
||||||
"total": 833,
|
"total": 841,
|
||||||
"suites": [
|
"suites": [
|
||||||
{"name":"tokenize","pass":62,"total":62,"status":"ok"},
|
{"name":"tokenize","pass":62,"total":62,"status":"ok"},
|
||||||
{"name":"parse","pass":52,"total":52,"status":"ok"},
|
{"name":"parse","pass":52,"total":52,"status":"ok"},
|
||||||
@@ -15,6 +15,6 @@
|
|||||||
{"name":"ffi","pass":37,"total":37,"status":"ok"},
|
{"name":"ffi","pass":37,"total":37,"status":"ok"},
|
||||||
{"name":"vm","pass":78,"total":78,"status":"ok"},
|
{"name":"vm","pass":78,"total":78,"status":"ok"},
|
||||||
{"name":"send_after","pass":10,"total":10,"status":"ok"},
|
{"name":"send_after","pass":10,"total":10,"status":"ok"},
|
||||||
{"name":"lists_ext","pass":62,"total":62,"status":"ok"}
|
{"name":"lists_ext","pass":70,"total":70,"status":"ok"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Erlang-on-SX Scoreboard
|
# Erlang-on-SX Scoreboard
|
||||||
|
|
||||||
**Total: 833 / 833 tests passing**
|
**Total: 841 / 841 tests passing**
|
||||||
|
|
||||||
| | Suite | Pass | Total |
|
| | Suite | Pass | Total |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
| ✅ | ffi | 37 | 37 |
|
| ✅ | ffi | 37 | 37 |
|
||||||
| ✅ | vm | 78 | 78 |
|
| ✅ | vm | 78 | 78 |
|
||||||
| ✅ | send_after | 10 | 10 |
|
| ✅ | send_after | 10 | 10 |
|
||||||
| ✅ | lists_ext | 62 | 62 |
|
| ✅ | lists_ext | 70 | 70 |
|
||||||
|
|
||||||
|
|
||||||
Generated by `lib/erlang/conformance.sh`.
|
Generated by `lib/erlang/conformance.sh`.
|
||||||
|
|||||||
@@ -238,3 +238,32 @@
|
|||||||
|
|
||||||
(er-lx-test "min mixed term order"
|
(er-lx-test "min mixed term order"
|
||||||
(er-lx-nm "lists:min([a,1,b]) =:= 1") "true")
|
(er-lx-nm "lists:min([a,1,b]) =:= 1") "true")
|
||||||
|
|
||||||
|
;; ── lists:zip/2 ───────────────────────────────────────────────────
|
||||||
|
(er-lx-test "zip pairs"
|
||||||
|
(er-lx-nm "lists:zip([a,b,c],[1,2,3]) =:= [{a,1},{b,2},{c,3}]") "true")
|
||||||
|
|
||||||
|
(er-lx-test "zip empty"
|
||||||
|
(er-lx-nm "lists:zip([],[]) =:= []") "true")
|
||||||
|
|
||||||
|
(er-lx-test "zip length"
|
||||||
|
(erlang-eval-ast "length(lists:zip([1,2],[3,4]))") 2)
|
||||||
|
|
||||||
|
;; ── lists:zipwith/3 ───────────────────────────────────────────────
|
||||||
|
(er-lx-test "zipwith sum"
|
||||||
|
(er-lx-nm
|
||||||
|
"lists:zipwith(fun(X,Y) -> X+Y end, [1,2,3], [10,20,30]) =:= [11,22,33]")
|
||||||
|
"true")
|
||||||
|
|
||||||
|
(er-lx-test "zipwith tuple"
|
||||||
|
(er-lx-nm "lists:zipwith(fun(X,Y) -> {X,Y} end, [a], [1]) =:= [{a,1}]") "true")
|
||||||
|
|
||||||
|
;; ── lists:unzip/1 ─────────────────────────────────────────────────
|
||||||
|
(er-lx-test "unzip"
|
||||||
|
(er-lx-nm "lists:unzip([{a,1},{b,2},{c,3}]) =:= {[a,b,c],[1,2,3]}") "true")
|
||||||
|
|
||||||
|
(er-lx-test "unzip empty"
|
||||||
|
(er-lx-nm "lists:unzip([]) =:= {[],[]}") "true")
|
||||||
|
|
||||||
|
(er-lx-test "zip/unzip roundtrip"
|
||||||
|
(er-lx-nm "lists:unzip(lists:zip([1,2],[3,4])) =:= {[1,2],[3,4]}") "true")
|
||||||
|
|||||||
@@ -159,6 +159,8 @@ The Phase 9 opcodes are registered, tested, and bridged SX↔OCaml, but inert: n
|
|||||||
|
|
||||||
_Newest first._
|
_Newest first._
|
||||||
|
|
||||||
|
- **2026-06-30 stdlib hardening — `lists` zip family** — Added `zip/2`, `zipwith/3`, `unzip/1` to `lib/erlang/lists-ext.sx`. Length mismatch (zip/zipwith) and malformed/non-pair elements (unzip) raise `badarg` (port equivalent of Erlang's `function_clause`). `lists_ext` suite 62→**70** (+8, incl. a zip/unzip roundtrip). Conformance **833 → 841/841**. loops/erlang only.
|
||||||
|
|
||||||
- **2026-06-30 stdlib hardening — `lists` flatten/max/min** — Added `flatten/1` (deep recursive flatten via `er-list-append`), `max/1`, `min/1` (full term order via `er-ext-lt?`, `badarg` on empty) to `lib/erlang/lists-ext.sx`. Gotcha caught: `er-ext-lt?` returns a raw SX boolean, so the extreme-finder uses it directly in `if` rather than wrapping in `er-truthy?` (which only recognises Erlang bool atoms, not SX booleans — the first cut wrapped it and silently never updated the running best). `lists_ext` suite 52→**62** (+10). Conformance **823 → 833/833**. loops/erlang only.
|
- **2026-06-30 stdlib hardening — `lists` flatten/max/min** — Added `flatten/1` (deep recursive flatten via `er-list-append`), `max/1`, `min/1` (full term order via `er-ext-lt?`, `badarg` on empty) to `lib/erlang/lists-ext.sx`. Gotcha caught: `er-ext-lt?` returns a raw SX boolean, so the extreme-finder uses it directly in `if` rather than wrapping in `er-truthy?` (which only recognises Erlang bool atoms, not SX booleans — the first cut wrapped it and silently never updated the running best). `lists_ext` suite 52→**62** (+10). Conformance **823 → 833/833**. loops/erlang only.
|
||||||
|
|
||||||
- **2026-06-30 stdlib hardening — `lists` higher-order traversal** — Added `foldr/3`, `partition/2`, `takewhile/2`, `dropwhile/2`, `splitwith/2` to `lib/erlang/lists-ext.sx`, registered pure through the `er-register-builtin-bifs!` wrapper (consistent with the existing pure `map`/`filter`/`foldl`). `foldr` right-folds (order-preserving when consing); `partition` returns `{Satisfying, NotSatisfying}` order-preserved via `er-list-reverse-iter`; `splitwith` = `{takewhile, dropwhile}`. `lists_ext` suite 38→**52** (+14). Conformance **809 → 823/823**. loops/erlang only.
|
- **2026-06-30 stdlib hardening — `lists` higher-order traversal** — Added `foldr/3`, `partition/2`, `takewhile/2`, `dropwhile/2`, `splitwith/2` to `lib/erlang/lists-ext.sx`, registered pure through the `er-register-builtin-bifs!` wrapper (consistent with the existing pure `map`/`filter`/`foldl`). `foldr` right-folds (order-preserving when consing); `partition` returns `{Satisfying, NotSatisfying}` order-preserved via `er-list-reverse-iter`; `splitwith` = `{takewhile, dropwhile}`. `lists_ext` suite 38→**52** (+14). Conformance **809 → 823/823**. loops/erlang only.
|
||||||
|
|||||||
Reference in New Issue
Block a user