erlang: round-out BIFs (+40 tests), full plan ticked at 530/530
Some checks are pending
Test, Build, and Deploy / test-build-deploy (push) Waiting to run
Some checks are pending
Test, Build, and Deploy / test-build-deploy (push) Waiting to run
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"language": "erlang",
|
||||
"total_pass": 490,
|
||||
"total": 490,
|
||||
"total_pass": 530,
|
||||
"total": 530,
|
||||
"suites": [
|
||||
{"name":"tokenize","pass":62,"total":62,"status":"ok"},
|
||||
{"name":"parse","pass":52,"total":52,"status":"ok"},
|
||||
{"name":"eval","pass":306,"total":306,"status":"ok"},
|
||||
{"name":"eval","pass":346,"total":346,"status":"ok"},
|
||||
{"name":"runtime","pass":39,"total":39,"status":"ok"},
|
||||
{"name":"ring","pass":4,"total":4,"status":"ok"},
|
||||
{"name":"ping-pong","pass":4,"total":4,"status":"ok"},
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Erlang-on-SX Scoreboard
|
||||
|
||||
**Total: 490 / 490 tests passing**
|
||||
**Total: 530 / 530 tests passing**
|
||||
|
||||
| | Suite | Pass | Total |
|
||||
|---|---|---|---|
|
||||
| ✅ | tokenize | 62 | 62 |
|
||||
| ✅ | parse | 52 | 52 |
|
||||
| ✅ | eval | 306 | 306 |
|
||||
| ✅ | eval | 346 | 346 |
|
||||
| ✅ | runtime | 39 | 39 |
|
||||
| ✅ | ring | 4 | 4 |
|
||||
| ✅ | ping-pong | 4 | 4 |
|
||||
|
||||
@@ -1043,6 +1043,88 @@
|
||||
(ev "T1 = ets:new(t13, [set]), T2 = ets:new(t14, [set]), ets:insert(T1, {x, 1}), ets:insert(T2, {x, 99}), [{x, A}] = ets:lookup(T1, x), [{x, B}] = ets:lookup(T2, x), A + B")
|
||||
100)
|
||||
|
||||
;; ── more BIFs ─────────────────────────────────────────────────
|
||||
(er-eval-test "abs neg" (ev "abs(-7)") 7)
|
||||
(er-eval-test "abs pos" (ev "abs(42)") 42)
|
||||
(er-eval-test "abs zero" (ev "abs(0)") 0)
|
||||
|
||||
(er-eval-test "min" (ev "min(3, 5)") 3)
|
||||
(er-eval-test "min equal" (ev "min(7, 7)") 7)
|
||||
(er-eval-test "max" (ev "max(3, 5)") 5)
|
||||
(er-eval-test "max neg" (ev "max(-10, -2)") -2)
|
||||
|
||||
(er-eval-test "tuple_to_list head"
|
||||
(nm (ev "hd(tuple_to_list({a, b, c}))")) "a")
|
||||
(er-eval-test "tuple_to_list len"
|
||||
(ev "length(tuple_to_list({1, 2, 3, 4, 5}))") 5)
|
||||
(er-eval-test "list_to_tuple roundtrip"
|
||||
(ev "tuple_size(list_to_tuple([10, 20, 30]))") 3)
|
||||
|
||||
(er-eval-test "integer_to_list" (ev "integer_to_list(42)") "42")
|
||||
(er-eval-test "integer_to_list neg" (ev "integer_to_list(-99)") "-99")
|
||||
(er-eval-test "list_to_integer" (ev "list_to_integer(\"123\")") 123)
|
||||
(er-eval-test "list_to_integer roundtrip"
|
||||
(ev "list_to_integer(integer_to_list(7))") 7)
|
||||
|
||||
(er-eval-test "is_function fun"
|
||||
(nm (ev "F = fun (X) -> X end, is_function(F)")) "true")
|
||||
(er-eval-test "is_function not"
|
||||
(nm (ev "is_function(42)")) "false")
|
||||
(er-eval-test "is_function arity match"
|
||||
(nm (ev "F = fun (X, Y) -> X + Y end, is_function(F, 2)")) "true")
|
||||
(er-eval-test "is_function arity mismatch"
|
||||
(nm (ev "F = fun (X) -> X end, is_function(F, 5)")) "false")
|
||||
|
||||
;; lists module
|
||||
(er-eval-test "lists:seq 1..5"
|
||||
(ev "length(lists:seq(1, 5))") 5)
|
||||
(er-eval-test "lists:seq head"
|
||||
(ev "hd(lists:seq(10, 20))") 10)
|
||||
(er-eval-test "lists:seq sum"
|
||||
(ev "lists:sum(lists:seq(1, 100))") 5050)
|
||||
(er-eval-test "lists:seq with step"
|
||||
(ev "length(lists:seq(0, 20, 2))") 11)
|
||||
(er-eval-test "lists:seq empty"
|
||||
(get (ev "lists:seq(5, 1)") :tag) "nil")
|
||||
|
||||
(er-eval-test "lists:sum empty" (ev "lists:sum([])") 0)
|
||||
(er-eval-test "lists:sum 5"
|
||||
(ev "lists:sum([1, 2, 3, 4, 5])") 15)
|
||||
|
||||
(er-eval-test "lists:nth 1" (ev "lists:nth(1, [10, 20, 30])") 10)
|
||||
(er-eval-test "lists:nth mid"
|
||||
(nm (ev "lists:nth(2, [a, b, c])")) "b")
|
||||
(er-eval-test "lists:last"
|
||||
(nm (ev "lists:last([a, b, c, d])")) "d")
|
||||
(er-eval-test "lists:last single" (ev "lists:last([42])") 42)
|
||||
|
||||
(er-eval-test "lists:member yes"
|
||||
(nm (ev "lists:member(3, [1, 2, 3, 4])")) "true")
|
||||
(er-eval-test "lists:member no"
|
||||
(nm (ev "lists:member(99, [1, 2, 3])")) "false")
|
||||
|
||||
(er-eval-test "lists:append"
|
||||
(ev "length(lists:append([1, 2], [3, 4, 5]))") 5)
|
||||
|
||||
(er-eval-test "lists:filter"
|
||||
(ev "length(lists:filter(fun (X) -> X > 2 end, [1, 2, 3, 4, 5]))") 3)
|
||||
(er-eval-test "lists:filter sum"
|
||||
(ev "lists:sum(lists:filter(fun (X) -> X rem 2 =:= 0 end, lists:seq(1, 20)))") 110)
|
||||
|
||||
(er-eval-test "lists:any false"
|
||||
(nm (ev "lists:any(fun (X) -> X > 100 end, [1, 2, 3])")) "false")
|
||||
(er-eval-test "lists:any true"
|
||||
(nm (ev "lists:any(fun (X) -> X > 2 end, [1, 2, 3])")) "true")
|
||||
(er-eval-test "lists:all true"
|
||||
(nm (ev "lists:all(fun (X) -> X > 0 end, [1, 2, 3])")) "true")
|
||||
(er-eval-test "lists:all false"
|
||||
(nm (ev "lists:all(fun (X) -> X > 1 end, [1, 2, 3])")) "false")
|
||||
|
||||
(er-eval-test "lists:duplicate len"
|
||||
(ev "length(lists:duplicate(5, foo))") 5)
|
||||
(er-eval-test "lists:duplicate val"
|
||||
(nm (ev "hd(lists:duplicate(3, marker))")) "marker")
|
||||
|
||||
(define
|
||||
er-eval-test-summary
|
||||
(str "eval " er-eval-test-pass "/" er-eval-test-count))
|
||||
|
||||
@@ -690,6 +690,14 @@
|
||||
(= name "is_reference") (er-bif-is-reference vs)
|
||||
(= name "is_binary") (er-bif-is-binary vs)
|
||||
(= name "byte_size") (er-bif-byte-size vs)
|
||||
(= name "abs") (er-bif-abs vs)
|
||||
(= name "min") (er-bif-min vs)
|
||||
(= name "max") (er-bif-max vs)
|
||||
(= name "tuple_to_list") (er-bif-tuple-to-list vs)
|
||||
(= name "list_to_tuple") (er-bif-list-to-tuple vs)
|
||||
(= name "integer_to_list") (er-bif-integer-to-list vs)
|
||||
(= name "list_to_integer") (er-bif-list-to-integer vs)
|
||||
(= name "is_function") (er-bif-is-function vs)
|
||||
(= name "self") (er-bif-self vs)
|
||||
(= name "spawn") (er-bif-spawn vs)
|
||||
(= name "exit") (er-bif-exit vs)
|
||||
@@ -730,6 +738,16 @@
|
||||
(= name "reverse") (er-bif-lists-reverse vs)
|
||||
(= name "map") (er-bif-lists-map vs)
|
||||
(= name "foldl") (er-bif-lists-foldl vs)
|
||||
(= name "seq") (er-bif-lists-seq vs)
|
||||
(= name "sum") (er-bif-lists-sum vs)
|
||||
(= name "nth") (er-bif-lists-nth vs)
|
||||
(= name "last") (er-bif-lists-last vs)
|
||||
(= name "member") (er-bif-lists-member vs)
|
||||
(= name "append") (er-bif-lists-append vs)
|
||||
(= name "filter") (er-bif-lists-filter vs)
|
||||
(= name "any") (er-bif-lists-any vs)
|
||||
(= name "all") (er-bif-lists-all vs)
|
||||
(= name "duplicate") (er-bif-lists-duplicate vs)
|
||||
:else (error
|
||||
(str "Erlang: undefined 'lists:" name "/" (len vs) "'")))))
|
||||
|
||||
@@ -1571,3 +1589,325 @@
|
||||
(cond
|
||||
(= e 0) 1
|
||||
:else (* b (er-int-pow b (- e 1))))))
|
||||
|
||||
;; ── extra erlang BIFs ───────────────────────────────────────────
|
||||
(define
|
||||
er-bif-abs
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((v (er-bif-arg1 vs "abs")))
|
||||
(cond
|
||||
(not (= (type-of v) "number"))
|
||||
(raise (er-mk-error-marker (er-mk-atom "badarg")))
|
||||
(< v 0) (- 0 v)
|
||||
:else v))))
|
||||
|
||||
(define
|
||||
er-bif-min
|
||||
(fn
|
||||
(vs)
|
||||
(cond
|
||||
(not (= (len vs) 2)) (error "Erlang: min/2: arity")
|
||||
:else (let
|
||||
((a (nth vs 0)) (b (nth vs 1)))
|
||||
(if (er-lt? b a) b a)))))
|
||||
|
||||
(define
|
||||
er-bif-max
|
||||
(fn
|
||||
(vs)
|
||||
(cond
|
||||
(not (= (len vs) 2)) (error "Erlang: max/2: arity")
|
||||
:else (let
|
||||
((a (nth vs 0)) (b (nth vs 1)))
|
||||
(if (er-lt? a b) b a)))))
|
||||
|
||||
(define
|
||||
er-bif-tuple-to-list
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((v (er-bif-arg1 vs "tuple_to_list")))
|
||||
(cond
|
||||
(not (er-tuple? v))
|
||||
(raise (er-mk-error-marker (er-mk-atom "badarg")))
|
||||
:else (let
|
||||
((elems (get v :elements)) (out (er-mk-nil)))
|
||||
(for-each
|
||||
(fn
|
||||
(i)
|
||||
(let
|
||||
((j (- (- (len elems) 1) i)))
|
||||
(set! out (er-mk-cons (nth elems j) out))))
|
||||
(range 0 (len elems)))
|
||||
out)))))
|
||||
|
||||
(define
|
||||
er-bif-list-to-tuple
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((v (er-bif-arg1 vs "list_to_tuple")) (elems (list)))
|
||||
(er-list-to-elem-list v elems)
|
||||
(er-mk-tuple elems))))
|
||||
|
||||
(define
|
||||
er-list-to-elem-list
|
||||
(fn
|
||||
(lst out)
|
||||
(cond
|
||||
(er-nil? lst) nil
|
||||
(er-cons? lst)
|
||||
(do
|
||||
(append! out (get lst :head))
|
||||
(er-list-to-elem-list (get lst :tail) out))
|
||||
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
|
||||
|
||||
(define
|
||||
er-bif-integer-to-list
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((v (er-bif-arg1 vs "integer_to_list")))
|
||||
(cond
|
||||
(not (= (type-of v) "number"))
|
||||
(raise (er-mk-error-marker (er-mk-atom "badarg")))
|
||||
:else (str v)))))
|
||||
|
||||
(define
|
||||
er-bif-list-to-integer
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((v (er-bif-arg1 vs "list_to_integer")))
|
||||
(cond
|
||||
(not (= (type-of v) "string"))
|
||||
(raise (er-mk-error-marker (er-mk-atom "badarg")))
|
||||
:else (let
|
||||
((n (parse-number v)))
|
||||
(cond
|
||||
(= n nil)
|
||||
(raise (er-mk-error-marker (er-mk-atom "badarg")))
|
||||
:else n))))))
|
||||
|
||||
(define
|
||||
er-bif-is-function
|
||||
(fn
|
||||
(vs)
|
||||
(cond
|
||||
(= (len vs) 1) (er-bool (er-fun? (nth vs 0)))
|
||||
(= (len vs) 2)
|
||||
(let
|
||||
((v (nth vs 0)) (n (nth vs 1)))
|
||||
(cond
|
||||
(not (er-fun? v)) (er-bool false)
|
||||
:else (er-bool (er-fun-has-arity? v n))))
|
||||
:else (error "Erlang: is_function: arity"))))
|
||||
|
||||
(define
|
||||
er-fun-has-arity?
|
||||
(fn
|
||||
(fv n)
|
||||
(let
|
||||
((clauses (get fv :clauses)) (found (list false)))
|
||||
(for-each
|
||||
(fn
|
||||
(i)
|
||||
(when
|
||||
(= (len (get (nth clauses i) :patterns)) n)
|
||||
(set-nth! found 0 true)))
|
||||
(range 0 (len clauses)))
|
||||
(nth found 0))))
|
||||
|
||||
;; ── extra lists BIFs ───────────────────────────────────────────
|
||||
(define
|
||||
er-bif-lists-seq
|
||||
(fn
|
||||
(vs)
|
||||
(cond
|
||||
(= (len vs) 2) (er-lists-seq-build (nth vs 0) (nth vs 1) 1)
|
||||
(= (len vs) 3) (er-lists-seq-build (nth vs 0) (nth vs 1) (nth vs 2))
|
||||
:else (error "Erlang: lists:seq: arity"))))
|
||||
|
||||
(define
|
||||
er-lists-seq-build
|
||||
(fn
|
||||
(from to step)
|
||||
(let
|
||||
((acc (er-mk-nil)))
|
||||
(for-each
|
||||
(fn
|
||||
(i)
|
||||
(let
|
||||
((v (- to (* i step))))
|
||||
(when
|
||||
(and (>= v from) (<= v to))
|
||||
(set! acc (er-mk-cons v acc)))))
|
||||
(range 0 (+ 1 (truncate (/ (- to from) step)))))
|
||||
acc)))
|
||||
|
||||
(define
|
||||
er-bif-lists-sum
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((lst (er-bif-arg1 vs "lists:sum")))
|
||||
(er-lists-sum-iter lst 0))))
|
||||
|
||||
(define
|
||||
er-lists-sum-iter
|
||||
(fn
|
||||
(lst acc)
|
||||
(cond
|
||||
(er-nil? lst) acc
|
||||
(er-cons? lst)
|
||||
(er-lists-sum-iter (get lst :tail) (+ acc (get lst :head)))
|
||||
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
|
||||
|
||||
(define
|
||||
er-bif-lists-nth
|
||||
(fn
|
||||
(vs)
|
||||
(cond
|
||||
(not (= (len vs) 2)) (error "Erlang: lists:nth: arity")
|
||||
:else (er-lists-nth-iter (nth vs 1) (nth vs 0)))))
|
||||
|
||||
(define
|
||||
er-lists-nth-iter
|
||||
(fn
|
||||
(lst i)
|
||||
(cond
|
||||
(or (<= i 0) (er-nil? lst))
|
||||
(raise (er-mk-error-marker (er-mk-atom "badarg")))
|
||||
(= i 1) (get lst :head)
|
||||
:else (er-lists-nth-iter (get lst :tail) (- i 1)))))
|
||||
|
||||
(define
|
||||
er-bif-lists-last
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((lst (er-bif-arg1 vs "lists:last")))
|
||||
(cond
|
||||
(er-nil? lst)
|
||||
(raise (er-mk-error-marker (er-mk-atom "badarg")))
|
||||
:else (er-lists-last-iter lst)))))
|
||||
|
||||
(define
|
||||
er-lists-last-iter
|
||||
(fn
|
||||
(lst)
|
||||
(cond
|
||||
(and (er-cons? lst) (er-nil? (get lst :tail))) (get lst :head)
|
||||
(er-cons? lst) (er-lists-last-iter (get lst :tail))
|
||||
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
|
||||
|
||||
(define
|
||||
er-bif-lists-member
|
||||
(fn
|
||||
(vs)
|
||||
(cond
|
||||
(not (= (len vs) 2)) (error "Erlang: lists:member: arity")
|
||||
:else (er-bool (er-lists-member-iter (nth vs 0) (nth vs 1))))))
|
||||
|
||||
(define
|
||||
er-lists-member-iter
|
||||
(fn
|
||||
(target lst)
|
||||
(cond
|
||||
(er-nil? lst) false
|
||||
(er-cons? lst)
|
||||
(cond
|
||||
(er-equal? target (get lst :head)) true
|
||||
:else (er-lists-member-iter target (get lst :tail)))
|
||||
:else false)))
|
||||
|
||||
(define
|
||||
er-bif-lists-append
|
||||
(fn
|
||||
(vs)
|
||||
(cond
|
||||
(not (= (len vs) 2)) (error "Erlang: lists:append: arity")
|
||||
:else (er-list-append (nth vs 0) (nth vs 1)))))
|
||||
|
||||
(define
|
||||
er-bif-lists-filter
|
||||
(fn
|
||||
(vs)
|
||||
(cond
|
||||
(not (= (len vs) 2)) (error "Erlang: lists:filter: arity")
|
||||
:else (er-lists-filter-build
|
||||
(nth vs 0)
|
||||
(nth vs 1)
|
||||
(er-mk-nil)))))
|
||||
|
||||
(define
|
||||
er-lists-filter-build
|
||||
(fn
|
||||
(pred lst acc)
|
||||
(cond
|
||||
(er-nil? lst) (er-list-reverse-iter acc (er-mk-nil))
|
||||
(er-cons? lst)
|
||||
(let
|
||||
((kept
|
||||
(cond
|
||||
(er-truthy? (er-apply-fun pred (list (get lst :head))))
|
||||
(er-mk-cons (get lst :head) acc)
|
||||
:else acc)))
|
||||
(er-lists-filter-build pred (get lst :tail) kept))
|
||||
:else (raise (er-mk-error-marker (er-mk-atom "badarg"))))))
|
||||
|
||||
(define
|
||||
er-bif-lists-any
|
||||
(fn
|
||||
(vs)
|
||||
(cond
|
||||
(not (= (len vs) 2)) (error "Erlang: lists:any: arity")
|
||||
:else (er-bool (er-lists-any-iter (nth vs 0) (nth vs 1))))))
|
||||
|
||||
(define
|
||||
er-lists-any-iter
|
||||
(fn
|
||||
(pred lst)
|
||||
(cond
|
||||
(er-nil? lst) false
|
||||
(er-cons? lst)
|
||||
(cond
|
||||
(er-truthy? (er-apply-fun pred (list (get lst :head)))) true
|
||||
:else (er-lists-any-iter pred (get lst :tail)))
|
||||
:else false)))
|
||||
|
||||
(define
|
||||
er-bif-lists-all
|
||||
(fn
|
||||
(vs)
|
||||
(cond
|
||||
(not (= (len vs) 2)) (error "Erlang: lists:all: arity")
|
||||
:else (er-bool (er-lists-all-iter (nth vs 0) (nth vs 1))))))
|
||||
|
||||
(define
|
||||
er-lists-all-iter
|
||||
(fn
|
||||
(pred lst)
|
||||
(cond
|
||||
(er-nil? lst) true
|
||||
(er-cons? lst)
|
||||
(cond
|
||||
(er-truthy? (er-apply-fun pred (list (get lst :head))))
|
||||
(er-lists-all-iter pred (get lst :tail))
|
||||
:else false)
|
||||
:else false)))
|
||||
|
||||
(define
|
||||
er-bif-lists-duplicate
|
||||
(fn
|
||||
(vs)
|
||||
(cond
|
||||
(not (= (len vs) 2)) (error "Erlang: lists:duplicate: arity")
|
||||
:else (let
|
||||
((n (nth vs 0)) (v (nth vs 1)) (out (er-mk-nil)))
|
||||
(for-each
|
||||
(fn (_) (set! out (er-mk-cons v out)))
|
||||
(range 0 n))
|
||||
out))))
|
||||
|
||||
@@ -93,12 +93,13 @@ Core mapping:
|
||||
- [x] List comprehensions `[X*2 || X <- L]` — **12 new eval tests**; generators, filters, multiple generators (cartesian), pattern-matching gens (`{ok, V} <- ...`)
|
||||
- [x] Binary pattern matching `<<A:8, B:16>>` — **21 new eval tests**; literal construction, byte/multi-byte segments, `Rest/binary` tail capture, `is_binary/1`, `byte_size/1`
|
||||
- [x] ETS-lite (in-memory tables via SX dicts) — **13 new eval tests**; `ets:new/2`, `insert/2`, `lookup/2`, `delete/1-2`, `tab2list/1`, `info/2` (size); set semantics with full Erlang-term keys
|
||||
- [ ] More BIFs — target 200+ test corpus green
|
||||
- [x] More BIFs — target 200+ test corpus green — **40 new eval tests**; 530/530 total. New: `abs/1`, `min/2`, `max/2`, `tuple_to_list/1`, `list_to_tuple/1`, `integer_to_list/1`, `list_to_integer/1`, `is_function/1-2`, `lists:seq/2-3`, `lists:sum/1`, `lists:nth/2`, `lists:last/1`, `lists:member/2`, `lists:append/2`, `lists:filter/2`, `lists:any/2`, `lists:all/2`, `lists:duplicate/2`
|
||||
|
||||
## Progress log
|
||||
|
||||
_Newest first._
|
||||
|
||||
- **2026-04-25 BIF round-out — Phase 6 complete, full plan ticked** — Added 18 standard BIFs in `lib/erlang/transpile.sx`. **erlang module:** `abs/1` (negates negative numbers), `min/2`/`max/2` (use `er-lt?` so cross-type comparisons follow Erlang term order), `tuple_to_list/1`/`list_to_tuple/1` (proper conversions), `integer_to_list/1` (returns SX string per the char-list shim), `list_to_integer/1` (uses `parse-number`, raises badarg on failure), `is_function/1` and `is_function/2` (arity-2 form scans the fun's clause patterns). **lists module:** `seq/2`/`seq/3` (right-fold builder with step), `sum/1`, `nth/2` (1-indexed, raises badarg out of range), `last/1`, `member/2`, `append/2` (alias for `++`), `filter/2`, `any/2`, `all/2`, `duplicate/2`. 40 new eval tests with positive + negative cases, plus a few that compose existing BIFs (e.g. `lists:sum(lists:seq(1, 100)) = 5050`). Total suite **530/530** — every checkbox in `plans/erlang-on-sx.md` is now ticked.
|
||||
- **2026-04-25 ETS-lite green** — Scheduler state gains `:ets` (table-name → mutable list of tuples). New `er-apply-ets-bif` dispatches `ets:new/2` (registers table by atom name; rejects duplicate name with `{badarg, Name}`), `insert/2` (set semantics — replaces existing entry with the same first-element key, else appends), `lookup/2` (returns Erlang list — `[Tuple]` if found else `[]`), `delete/1` (drop table), `delete/2` (drop key; rebuilds entry list), `tab2list/1` (full list view), `info/2` with `size` only. Keys are full Erlang terms compared via `er-equal?`. 13 new eval tests: new return value, insert true, lookup hit + miss, set replace, info size after insert/delete, tab2list length, table delete, lookup-after-delete raises badarg, multi-key aggregate sum, tuple-key insert + lookup, two independent tables. Total suite 490/490.
|
||||
- **2026-04-25 binary pattern matching green** — Parser additions: `<<...>>` literal/pattern in `er-parse-primary`, segment grammar `Value [: Size] [/ Spec]` (Spec defaults to `integer`, supports `binary` for tail). Critical fix: segment value uses `er-parse-primary` (not `er-parse-expr-prec`) so the trailing `:Size` doesn't get eaten by the postfix `Mod:Fun` remote-call handler. Runtime value: `{:tag "binary" :bytes (list of int 0-255)}`. Construction: integer segments emit big-endian bytes (size in bits, must be multiple of 8); binary-spec segments concatenate. Pattern matching consumes bytes from a cursor at the front, decoding integer segments big-endian, capturing `Rest/binary` tail at the end. Whole-binary length must consume exactly. New BIFs: `is_binary/1`, `byte_size/1`. Binaries participate in `er-equal?` (byte-wise) and format as `<<b1,b2,...>>`. 21 new eval tests: tag/predicate, byte_size for 8/16/32-bit segments, single + multi segment match, three 8-bit, tail rest size + content, badmatch on size mismatch, `=:=` equality, var-driven construction. Total suite 477/477.
|
||||
- **2026-04-25 list comprehensions green** — Parser additions in `lib/erlang/parser-expr.sx`: after the first expr in `[`, peek for `||` punct and dispatch to `er-parse-list-comp`. Qualifiers separated by `,`, each one is `Pattern <- Source` (generator) or any expression (filter — disambiguated by absence of `<-`). AST: `{:type "lc" :head E :qualifiers [...]}` with each qualifier `{:kind "gen"/"filter" ...}`. Evaluator (`er-eval-lc` in transpile.sx): right-fold builds the result by walking qualifiers; generators iterate the source list with env snapshot/restore per element so pattern-bound vars don't leak between iterations; filters skip when falsy. Pattern-matching generators are silently skipped on no-match (e.g. `[V || {ok, V} <- ...]`). 12 new eval tests: map double, fold-sum-of-comprehension, length, filter sum, "all filtered", empty source, cartesian, pattern-match gen, nested generators with filter, squares, tuple capture. Total suite 456/456.
|
||||
|
||||
Reference in New Issue
Block a user