erlang-runtime: add lib/erlang/runtime.sx + test.sh (55/55 pass)
Numeric tower (is-integer?/float?/number?, float/trunc/round/abs/max/min), div/rem (quotient/remainder), bitwise (band/bor/bxor/bnot/bsl/bsr), sets module (new/add/member/union/intersection/subtract/size/to-list/from-list), re module (run/replace/replace-all/match-groups/split), list BIFs (hd/tl/length/member/reverse/nth/foldl/foldr/seq/flatten/zip), type conversions (integer-to-list, list-to-integer, atom-to-list, etc.), ok/error tuple helpers. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
230
lib/erlang/runtime.sx
Normal file
230
lib/erlang/runtime.sx
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
;; lib/erlang/runtime.sx — Erlang BIFs and stdlib wrappers on SX primitives
|
||||||
|
;;
|
||||||
|
;; Provides Erlang-idiomatic wrappers. Thin where spec primitives match;
|
||||||
|
;; inline where Erlang semantics differ (e.g. rem sign, integer division).
|
||||||
|
;;
|
||||||
|
;; Primitives used from spec:
|
||||||
|
;; integer?/float? (Phase 2)
|
||||||
|
;; remainder/quotient (Phase 2 / Phase 15)
|
||||||
|
;; bitwise-and/or/xor/not (Phase 7)
|
||||||
|
;; arithmetic-shift (Phase 7)
|
||||||
|
;; make-set/set-add!/etc (Phase 18)
|
||||||
|
;; make-regexp/regexp-match/etc (Phase 20)
|
||||||
|
;; gcd (Phase 15)
|
||||||
|
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
;; 1. Numeric tower — type predicates + conversions
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(define er-is-integer? integer?)
|
||||||
|
(define er-is-float? float?)
|
||||||
|
(define (er-is-number? x) (or (integer? x) (float? x)))
|
||||||
|
(define (er-is-atom? x) (= (type-of x) "symbol"))
|
||||||
|
(define er-is-list? list?)
|
||||||
|
(define er-is-binary? bytevector?)
|
||||||
|
|
||||||
|
;; Erlang float/1 coerces an integer to float
|
||||||
|
(define (er-float x) (* 1 x))
|
||||||
|
|
||||||
|
;; Erlang trunc/1 — truncate toward zero
|
||||||
|
(define er-trunc truncate)
|
||||||
|
|
||||||
|
;; Erlang round/1 — round to nearest integer
|
||||||
|
(define er-round round)
|
||||||
|
|
||||||
|
;; Erlang abs/1
|
||||||
|
(define er-abs abs)
|
||||||
|
|
||||||
|
;; Erlang max/min (BIFs in OTP 26)
|
||||||
|
(define (er-max a b) (if (>= a b) a b))
|
||||||
|
(define (er-min a b) (if (<= a b) a b))
|
||||||
|
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
;; 2. Integer arithmetic — div + rem (Erlang semantics)
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
;; Erlang div: integer division truncating toward zero
|
||||||
|
(define er-div quotient)
|
||||||
|
|
||||||
|
;; Erlang rem: remainder with sign of dividend (matches remainder primitive)
|
||||||
|
(define er-rem remainder)
|
||||||
|
|
||||||
|
;; Erlang gcd (non-standard BIF but useful)
|
||||||
|
(define er-gcd gcd)
|
||||||
|
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
;; 3. Bitwise ops — band / bor / bxor / bnot / bsl / bsr
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(define er-band bitwise-and)
|
||||||
|
(define er-bor bitwise-or)
|
||||||
|
(define er-bxor bitwise-xor)
|
||||||
|
(define er-bnot bitwise-not)
|
||||||
|
|
||||||
|
;; bsl: bit shift left by N positions
|
||||||
|
(define (er-bsl x n) (arithmetic-shift x n))
|
||||||
|
|
||||||
|
;; bsr: bit shift right by N positions
|
||||||
|
(define (er-bsr x n) (arithmetic-shift x (- 0 n)))
|
||||||
|
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
;; 4. Sets module — thin wrappers matching Erlang sets API
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(define er-sets-new make-set)
|
||||||
|
(define er-sets-add-element set-add!)
|
||||||
|
(define er-sets-is-element set-member?)
|
||||||
|
(define er-sets-del-element set-remove!)
|
||||||
|
(define er-sets-union set-union)
|
||||||
|
(define er-sets-intersection set-intersection)
|
||||||
|
(define er-sets-subtract set-difference)
|
||||||
|
(define er-sets-to-list set->list)
|
||||||
|
(define er-sets-from-list list->set)
|
||||||
|
(define (er-sets-size s) (len (set->list s)))
|
||||||
|
(define (er-sets-is-set? x) (set? x))
|
||||||
|
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
;; 5. Regexp — re module wrappers
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
;; er-re-run: returns match dict or nil (no match)
|
||||||
|
(define
|
||||||
|
(er-re-run subject pattern)
|
||||||
|
(regexp-match (make-regexp pattern) subject))
|
||||||
|
|
||||||
|
;; er-re-replace: replace first match
|
||||||
|
(define
|
||||||
|
(er-re-replace subject pattern replacement)
|
||||||
|
(regexp-replace (make-regexp pattern) subject replacement))
|
||||||
|
|
||||||
|
;; er-re-replace-all: global replace
|
||||||
|
(define
|
||||||
|
(er-re-replace-all subject pattern replacement)
|
||||||
|
(regexp-replace-all (make-regexp pattern) subject replacement))
|
||||||
|
|
||||||
|
;; er-re-match-groups: extract capture groups from a match result
|
||||||
|
(define (er-re-match-groups m) (if (= m nil) nil (get m :groups)))
|
||||||
|
|
||||||
|
;; er-re-split: split string on regexp delimiter
|
||||||
|
(define
|
||||||
|
(er-re-split subject pattern)
|
||||||
|
(let
|
||||||
|
((re (make-regexp pattern))
|
||||||
|
(ms (regexp-match-all (make-regexp pattern) subject)))
|
||||||
|
(if
|
||||||
|
(= (len ms) 0)
|
||||||
|
(list subject)
|
||||||
|
(letrec
|
||||||
|
((go (fn (matches pos acc) (if (= (len matches) 0) (append acc (list (substring subject pos (len subject)))) (let ((m (first matches)) (start (get (first matches) :start)) (end (get (first matches) :end))) (go (rest matches) end (append acc (list (substring subject pos start)))))))))
|
||||||
|
(go ms 0 (list))))))
|
||||||
|
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
;; 6. List BIFs — hd/tl/length + lists module
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(define (er-hd lst) (first lst))
|
||||||
|
(define (er-tl lst) (rest lst))
|
||||||
|
(define (er-length lst) (len lst))
|
||||||
|
|
||||||
|
;; lists:member/2
|
||||||
|
(define
|
||||||
|
(er-lists-member elem lst)
|
||||||
|
(cond
|
||||||
|
((= (len lst) 0) false)
|
||||||
|
((= elem (first lst)) true)
|
||||||
|
(else (er-lists-member elem (rest lst)))))
|
||||||
|
|
||||||
|
;; lists:reverse/1
|
||||||
|
(define er-lists-reverse reverse)
|
||||||
|
|
||||||
|
;; lists:append/2
|
||||||
|
(define er-lists-append append)
|
||||||
|
|
||||||
|
;; lists:flatten/1
|
||||||
|
(define
|
||||||
|
(er-lists-flatten lst)
|
||||||
|
(cond
|
||||||
|
((= (len lst) 0) (list))
|
||||||
|
((list? (first lst))
|
||||||
|
(append (er-lists-flatten (first lst)) (er-lists-flatten (rest lst))))
|
||||||
|
(else (cons (first lst) (er-lists-flatten (rest lst))))))
|
||||||
|
|
||||||
|
;; lists:nth/2 — 1-indexed
|
||||||
|
(define (er-lists-nth n lst) (nth lst (- n 1)))
|
||||||
|
|
||||||
|
;; lists:map/2
|
||||||
|
(define er-lists-map map)
|
||||||
|
|
||||||
|
;; lists:filter/2
|
||||||
|
(define er-lists-filter filter)
|
||||||
|
|
||||||
|
;; lists:foldl/3 — (Fun, Acc0, List)
|
||||||
|
(define
|
||||||
|
(er-lists-foldl f acc lst)
|
||||||
|
(if
|
||||||
|
(= (len lst) 0)
|
||||||
|
acc
|
||||||
|
(er-lists-foldl f (f (first lst) acc) (rest lst))))
|
||||||
|
|
||||||
|
;; lists:foldr/3
|
||||||
|
(define
|
||||||
|
(er-lists-foldr f acc lst)
|
||||||
|
(if
|
||||||
|
(= (len lst) 0)
|
||||||
|
acc
|
||||||
|
(f (first lst) (er-lists-foldr f acc (rest lst)))))
|
||||||
|
|
||||||
|
;; lists:zip/2
|
||||||
|
(define
|
||||||
|
(er-lists-zip a b)
|
||||||
|
(if
|
||||||
|
(or (= (len a) 0) (= (len b) 0))
|
||||||
|
(list)
|
||||||
|
(cons (list (first a) (first b)) (er-lists-zip (rest a) (rest b)))))
|
||||||
|
|
||||||
|
;; lists:seq/2 — generate integer range (1-indexed like Erlang)
|
||||||
|
(define
|
||||||
|
(er-lists-seq from to)
|
||||||
|
(if
|
||||||
|
(> from to)
|
||||||
|
(list)
|
||||||
|
(cons from (er-lists-seq (+ from 1) to))))
|
||||||
|
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
;; 7. Type conversion BIFs
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
;; atom_to_list/1 — convert atom (symbol) to its name string
|
||||||
|
(define (er-atom-to-list a) (symbol->string a))
|
||||||
|
|
||||||
|
;; list_to_atom/1 — convert string to atom (symbol)
|
||||||
|
(define (er-list-to-atom s) (make-symbol s))
|
||||||
|
|
||||||
|
;; integer_to_list/1
|
||||||
|
(define (er-integer-to-list n) (str n))
|
||||||
|
|
||||||
|
;; list_to_integer/1
|
||||||
|
(define (er-list-to-integer s) (truncate (parse-number s)))
|
||||||
|
|
||||||
|
;; float_to_list/1
|
||||||
|
(define (er-float-to-list f) (str f))
|
||||||
|
|
||||||
|
;; list_to_float/1
|
||||||
|
(define (er-list-to-float s) (* 1 (parse-number s)))
|
||||||
|
|
||||||
|
;; integer_to_list/2 — with radix (e.g. 16 for hex)
|
||||||
|
(define (er-integer-to-list-radix n radix) (number->string n radix))
|
||||||
|
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
;; 8. ok/error tuple helpers — Erlang idiom {ok, Val} / {error, Reason}
|
||||||
|
;; ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
(define (er-ok val) (list "ok" val))
|
||||||
|
(define (er-error reason) (list "error" reason))
|
||||||
|
(define
|
||||||
|
(er-is-ok? t)
|
||||||
|
(and (list? t) (= (len t) 2) (= (first t) "ok")))
|
||||||
|
(define
|
||||||
|
(er-is-error? t)
|
||||||
|
(and (list? t) (= (len t) 2) (= (first t) "error")))
|
||||||
|
(define (er-unwrap t) (nth t 1))
|
||||||
260
lib/erlang/test.sh
Executable file
260
lib/erlang/test.sh
Executable file
@@ -0,0 +1,260 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# lib/erlang/test.sh — smoke-test the Erlang runtime layer.
|
||||||
|
# Uses sx_server.exe epoch protocol.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# bash lib/erlang/test.sh
|
||||||
|
# bash lib/erlang/test.sh -v
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
cd "$(git rev-parse --show-toplevel)"
|
||||||
|
|
||||||
|
SX_SERVER="${SX_SERVER:-hosts/ocaml/_build/default/bin/sx_server.exe}"
|
||||||
|
if [ ! -x "$SX_SERVER" ]; then
|
||||||
|
SX_SERVER="/root/rose-ash/hosts/ocaml/_build/default/bin/sx_server.exe"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$SX_SERVER" ]; then
|
||||||
|
echo "ERROR: sx_server.exe not found. Run: cd hosts/ocaml && dune build"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERBOSE="${1:-}"
|
||||||
|
PASS=0; FAIL=0; ERRORS=""
|
||||||
|
TMPFILE=$(mktemp); trap "rm -f $TMPFILE" EXIT
|
||||||
|
|
||||||
|
cat > "$TMPFILE" << 'EPOCHS'
|
||||||
|
(epoch 1)
|
||||||
|
(load "lib/erlang/runtime.sx")
|
||||||
|
|
||||||
|
;; --- Numeric tower ---
|
||||||
|
(epoch 10)
|
||||||
|
(eval "(er-is-integer? 42)")
|
||||||
|
(epoch 11)
|
||||||
|
(eval "(er-is-integer? 3.14)")
|
||||||
|
(epoch 12)
|
||||||
|
(eval "(er-is-float? 3.14)")
|
||||||
|
(epoch 13)
|
||||||
|
(eval "(er-is-float? 42)")
|
||||||
|
(epoch 14)
|
||||||
|
(eval "(er-is-number? 42)")
|
||||||
|
(epoch 15)
|
||||||
|
(eval "(er-is-number? 3.14)")
|
||||||
|
(epoch 16)
|
||||||
|
(eval "(er-float 5)")
|
||||||
|
(epoch 17)
|
||||||
|
(eval "(er-trunc 3.9)")
|
||||||
|
(epoch 18)
|
||||||
|
(eval "(er-round 3.5)")
|
||||||
|
(epoch 19)
|
||||||
|
(eval "(er-abs -7)")
|
||||||
|
(epoch 20)
|
||||||
|
(eval "(er-max 3 7)")
|
||||||
|
(epoch 21)
|
||||||
|
(eval "(er-min 3 7)")
|
||||||
|
|
||||||
|
;; --- div + rem ---
|
||||||
|
(epoch 30)
|
||||||
|
(eval "(er-div 10 3)")
|
||||||
|
(epoch 31)
|
||||||
|
(eval "(er-div -10 3)")
|
||||||
|
(epoch 32)
|
||||||
|
(eval "(er-rem 10 3)")
|
||||||
|
(epoch 33)
|
||||||
|
(eval "(er-rem -10 3)")
|
||||||
|
(epoch 34)
|
||||||
|
(eval "(er-gcd 12 8)")
|
||||||
|
|
||||||
|
;; --- Bitwise ---
|
||||||
|
(epoch 40)
|
||||||
|
(eval "(er-band 12 10)")
|
||||||
|
(epoch 41)
|
||||||
|
(eval "(er-bor 12 10)")
|
||||||
|
(epoch 42)
|
||||||
|
(eval "(er-bxor 12 10)")
|
||||||
|
(epoch 43)
|
||||||
|
(eval "(er-bnot 0)")
|
||||||
|
(epoch 44)
|
||||||
|
(eval "(er-bsl 1 4)")
|
||||||
|
(epoch 45)
|
||||||
|
(eval "(er-bsr 16 2)")
|
||||||
|
|
||||||
|
;; --- Sets ---
|
||||||
|
(epoch 50)
|
||||||
|
(eval "(er-sets-is-set? (er-sets-new))")
|
||||||
|
(epoch 51)
|
||||||
|
(eval "(let ((s (er-sets-new))) (do (er-sets-add-element s 1) (er-sets-is-element s 1)))")
|
||||||
|
(epoch 52)
|
||||||
|
(eval "(er-sets-is-element (er-sets-new) 42)")
|
||||||
|
(epoch 53)
|
||||||
|
(eval "(er-sets-is-element (er-sets-from-list (list 1 2 3)) 2)")
|
||||||
|
(epoch 54)
|
||||||
|
(eval "(er-sets-size (er-sets-from-list (list 1 2 3)))")
|
||||||
|
(epoch 55)
|
||||||
|
(eval "(len (er-sets-to-list (er-sets-from-list (list 1 2 3))))")
|
||||||
|
|
||||||
|
;; --- Regexp ---
|
||||||
|
(epoch 60)
|
||||||
|
(eval "(not (= (er-re-run \"hello\" \"ll\") nil))")
|
||||||
|
(epoch 61)
|
||||||
|
(eval "(= (er-re-run \"hello\" \"xyz\") nil)")
|
||||||
|
(epoch 62)
|
||||||
|
(eval "(get (er-re-run \"hello\" \"ll\") :match)")
|
||||||
|
(epoch 63)
|
||||||
|
(eval "(er-re-replace \"hello\" \"l\" \"r\")")
|
||||||
|
(epoch 64)
|
||||||
|
(eval "(er-re-replace-all \"hello\" \"l\" \"r\")")
|
||||||
|
(epoch 65)
|
||||||
|
(eval "(er-re-match-groups (er-re-run \"hello world\" \"(\\w+)\\s+(\\w+)\"))")
|
||||||
|
(epoch 66)
|
||||||
|
(eval "(len (er-re-split \"a,b,c\" \",\"))")
|
||||||
|
|
||||||
|
;; --- List BIFs ---
|
||||||
|
(epoch 70)
|
||||||
|
(eval "(er-hd (list 1 2 3))")
|
||||||
|
(epoch 71)
|
||||||
|
(eval "(er-tl (list 1 2 3))")
|
||||||
|
(epoch 72)
|
||||||
|
(eval "(er-length (list 1 2 3))")
|
||||||
|
(epoch 73)
|
||||||
|
(eval "(er-lists-member 2 (list 1 2 3))")
|
||||||
|
(epoch 74)
|
||||||
|
(eval "(er-lists-member 9 (list 1 2 3))")
|
||||||
|
(epoch 75)
|
||||||
|
(eval "(er-lists-reverse (list 1 2 3))")
|
||||||
|
(epoch 76)
|
||||||
|
(eval "(er-lists-nth 2 (list 10 20 30))")
|
||||||
|
(epoch 77)
|
||||||
|
(eval "(er-lists-foldl + 0 (list 1 2 3 4 5))")
|
||||||
|
(epoch 78)
|
||||||
|
(eval "(er-lists-seq 1 5)")
|
||||||
|
(epoch 79)
|
||||||
|
(eval "(er-lists-flatten (list 1 (list 2 3) (list 4 (list 5))))")
|
||||||
|
|
||||||
|
;; --- Type conversions ---
|
||||||
|
(epoch 80)
|
||||||
|
(eval "(er-integer-to-list 42)")
|
||||||
|
(epoch 81)
|
||||||
|
(eval "(er-list-to-integer \"42\")")
|
||||||
|
(epoch 82)
|
||||||
|
(eval "(er-integer-to-list-radix 255 16)")
|
||||||
|
(epoch 83)
|
||||||
|
(eval "(er-atom-to-list (make-symbol \"hello\"))")
|
||||||
|
(epoch 84)
|
||||||
|
(eval "(= (type-of (er-list-to-atom \"foo\")) \"symbol\")")
|
||||||
|
|
||||||
|
;; --- ok/error tuples ---
|
||||||
|
(epoch 90)
|
||||||
|
(eval "(er-is-ok? (er-ok 42))")
|
||||||
|
(epoch 91)
|
||||||
|
(eval "(er-is-error? (er-error \"reason\"))")
|
||||||
|
(epoch 92)
|
||||||
|
(eval "(er-unwrap (er-ok 42))")
|
||||||
|
(epoch 93)
|
||||||
|
(eval "(er-is-ok? (er-error \"bad\"))")
|
||||||
|
|
||||||
|
EPOCHS
|
||||||
|
|
||||||
|
OUTPUT=$(timeout 30 "$SX_SERVER" < "$TMPFILE" 2>/dev/null)
|
||||||
|
|
||||||
|
check() {
|
||||||
|
local epoch="$1" desc="$2" expected="$3"
|
||||||
|
local actual
|
||||||
|
actual=$(echo "$OUTPUT" | grep -A1 "^(ok-len $epoch " | tail -1 || true)
|
||||||
|
if echo "$actual" | grep -q "^(ok-len"; then actual=""; fi
|
||||||
|
if [ -z "$actual" ]; then
|
||||||
|
actual=$(echo "$OUTPUT" | grep "^(ok $epoch " | head -1 || true)
|
||||||
|
fi
|
||||||
|
if [ -z "$actual" ]; then
|
||||||
|
actual=$(echo "$OUTPUT" | grep "^(error $epoch " | head -1 || true)
|
||||||
|
fi
|
||||||
|
[ -z "$actual" ] && actual="<no output for epoch $epoch>"
|
||||||
|
|
||||||
|
if echo "$actual" | grep -qF -- "$expected"; then
|
||||||
|
PASS=$((PASS+1))
|
||||||
|
[ "$VERBOSE" = "-v" ] && echo " ok $desc"
|
||||||
|
else
|
||||||
|
FAIL=$((FAIL+1))
|
||||||
|
ERRORS+=" FAIL [$desc] (epoch $epoch) expected: $expected | actual: $actual
|
||||||
|
"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Numeric tower
|
||||||
|
check 10 "is-integer? 42" "true"
|
||||||
|
check 11 "is-integer? float" "false"
|
||||||
|
check 12 "is-float? 3.14" "true"
|
||||||
|
check 13 "is-float? int" "false"
|
||||||
|
check 14 "is-number? int" "true"
|
||||||
|
check 15 "is-number? float" "true"
|
||||||
|
check 16 "float 5" "5"
|
||||||
|
check 17 "trunc 3.9" "3"
|
||||||
|
check 18 "round 3.5" "4"
|
||||||
|
check 19 "abs -7" "7"
|
||||||
|
check 20 "max 3 7" "7"
|
||||||
|
check 21 "min 3 7" "3"
|
||||||
|
|
||||||
|
# div + rem
|
||||||
|
check 30 "div 10 3" "3"
|
||||||
|
check 31 "div -10 3" "-3"
|
||||||
|
check 32 "rem 10 3" "1"
|
||||||
|
check 33 "rem -10 3" "-1"
|
||||||
|
check 34 "gcd 12 8" "4"
|
||||||
|
|
||||||
|
# Bitwise
|
||||||
|
check 40 "band 12 10" "8"
|
||||||
|
check 41 "bor 12 10" "14"
|
||||||
|
check 42 "bxor 12 10" "6"
|
||||||
|
check 43 "bnot 0" "-1"
|
||||||
|
check 44 "bsl 1 4" "16"
|
||||||
|
check 45 "bsr 16 2" "4"
|
||||||
|
|
||||||
|
# Sets
|
||||||
|
check 50 "sets-new is-set?" "true"
|
||||||
|
check 51 "sets add+member" "true"
|
||||||
|
check 52 "member empty" "false"
|
||||||
|
check 53 "from-list member" "true"
|
||||||
|
check 54 "sets-size" "3"
|
||||||
|
check 55 "sets-to-list len" "3"
|
||||||
|
|
||||||
|
# Regexp
|
||||||
|
check 60 "re-run match" "true"
|
||||||
|
check 61 "re-run no match" "true"
|
||||||
|
check 62 "re-run match text" '"ll"'
|
||||||
|
check 63 "re-replace first" '"herlo"'
|
||||||
|
check 64 "re-replace-all" '"herro"'
|
||||||
|
check 65 "re-match-groups" '"hello"'
|
||||||
|
check 66 "re-split count" "3"
|
||||||
|
|
||||||
|
# List BIFs
|
||||||
|
check 70 "hd" "1"
|
||||||
|
check 71 "tl" "(2 3)"
|
||||||
|
check 72 "length" "3"
|
||||||
|
check 73 "member hit" "true"
|
||||||
|
check 74 "member miss" "false"
|
||||||
|
check 75 "reverse" "(3 2 1)"
|
||||||
|
check 76 "nth 2" "20"
|
||||||
|
check 77 "foldl sum" "15"
|
||||||
|
check 78 "seq 1..5" "(1 2 3 4 5)"
|
||||||
|
check 79 "flatten" "(1 2 3 4 5)"
|
||||||
|
|
||||||
|
# Type conversions
|
||||||
|
check 80 "integer-to-list" '"42"'
|
||||||
|
check 81 "list-to-integer" "42"
|
||||||
|
check 82 "integer-to-list hex" '"ff"'
|
||||||
|
check 83 "atom-to-list" '"hello"'
|
||||||
|
check 84 "list-to-atom" "true"
|
||||||
|
|
||||||
|
# ok/error
|
||||||
|
check 90 "ok? ok-tuple" "true"
|
||||||
|
check 91 "error? error-tuple" "true"
|
||||||
|
check 92 "unwrap ok" "42"
|
||||||
|
check 93 "ok? error-tuple" "false"
|
||||||
|
|
||||||
|
TOTAL=$((PASS+FAIL))
|
||||||
|
if [ $FAIL -eq 0 ]; then
|
||||||
|
echo "ok $PASS/$TOTAL lib/erlang tests passed"
|
||||||
|
else
|
||||||
|
echo "FAIL $PASS/$TOTAL passed, $FAIL failed:"
|
||||||
|
echo "$ERRORS"
|
||||||
|
fi
|
||||||
|
[ $FAIL -eq 0 ]
|
||||||
Reference in New Issue
Block a user