diff --git a/lib/erlang/scoreboard.json b/lib/erlang/scoreboard.json index fac8aff3..8b2827f2 100644 --- a/lib/erlang/scoreboard.json +++ b/lib/erlang/scoreboard.json @@ -1,11 +1,11 @@ { "language": "erlang", - "total_pass": 738, - "total": 738, + "total_pass": 750, + "total": 750, "suites": [ {"name":"tokenize","pass":62,"total":62,"status":"ok"}, {"name":"parse","pass":52,"total":52,"status":"ok"}, - {"name":"eval","pass":385,"total":385,"status":"ok"}, + {"name":"eval","pass":397,"total":397,"status":"ok"}, {"name":"runtime","pass":93,"total":93,"status":"ok"}, {"name":"ring","pass":4,"total":4,"status":"ok"}, {"name":"ping-pong","pass":4,"total":4,"status":"ok"}, diff --git a/lib/erlang/scoreboard.md b/lib/erlang/scoreboard.md index 75cac040..13ad1a7c 100644 --- a/lib/erlang/scoreboard.md +++ b/lib/erlang/scoreboard.md @@ -1,12 +1,12 @@ # Erlang-on-SX Scoreboard -**Total: 738 / 738 tests passing** +**Total: 750 / 750 tests passing** | | Suite | Pass | Total | |---|---|---|---| | ✅ | tokenize | 62 | 62 | | ✅ | parse | 52 | 52 | -| ✅ | eval | 385 | 385 | +| ✅ | eval | 397 | 397 | | ✅ | runtime | 93 | 93 | | ✅ | ring | 4 | 4 | | ✅ | ping-pong | 4 | 4 | diff --git a/lib/erlang/tests/eval.sx b/lib/erlang/tests/eval.sx index 4bd322db..7ff48aed 100644 --- a/lib/erlang/tests/eval.sx +++ b/lib/erlang/tests/eval.sx @@ -1341,6 +1341,23 @@ (get (nth (get er-rt-cap-result :elements) 4) :name) "true") + +;; ── $X char literals (Step 3b substrate fix 2026-06-04) ────────── +(er-eval-test "char $A" (ev "$A") 65) +(er-eval-test "char $a" (ev "$a") 97) +(er-eval-test "char $0 is digit, not escape-NUL" (ev "$0") 48) +(er-eval-test "char $\\n is newline (10)" (ev "$\\n") 10) +(er-eval-test "char $\\t is tab (9)" (ev "$\\t") 9) +(er-eval-test "char $\\r is CR (13)" (ev "$\\r") 13) +(er-eval-test "char $\\s is space (32)" (ev "$\\s") 32) +(er-eval-test "char $\\0 is NUL (0)" (ev "$\\0") 0) +(er-eval-test "char $\\\\ is backslash (92)" (ev "$\\\\") 92) +(er-eval-test "[$h,$i] head is 104" (ev "hd([$h, $i])") 104) +(er-eval-test "list_to_binary char-list -> bytes" + (ev "byte_size(list_to_binary([$f, $e, $d]))") 3) +(er-eval-test "list_to_binary char-list round-trip" + (nm (ev "list_to_binary([$h, $i]) =:= <<104, 105>>")) "true") + (define er-eval-test-summary (str "eval " er-eval-test-pass "/" er-eval-test-count)) diff --git a/lib/erlang/tokenizer.sx b/lib/erlang/tokenizer.sx index c46e7bc6..8a70bde4 100644 --- a/lib/erlang/tokenizer.sx +++ b/lib/erlang/tokenizer.sx @@ -229,13 +229,37 @@ (= ch "$") (do (er-advance! 1) - (if - (and (< pos src-len) (= (er-cur) "\\")) - (do - (er-advance! 1) - (when (< pos src-len) (er-advance! 1))) - (when (< pos src-len) (er-advance! 1))) - (er-emit! "integer" (slice src start pos) start) + ;; Emit the char's decimal code as the integer token value + ;; (was: raw "$X" text — parse-number then returned nil). + (let + ((code (cond + (>= pos src-len) 0 + (= (er-cur) "\\") + (do + (er-advance! 1) + (let ((esc (if (< pos src-len) (er-cur) ""))) + (when (< pos src-len) (er-advance! 1)) + (cond + (= esc "n") 10 + (= esc "t") 9 + (= esc "r") 13 + (= esc "s") 32 + (= esc "b") 8 + (= esc "e") 27 + (= esc "f") 12 + (= esc "v") 11 + (= esc "d") 127 + (= esc "0") 0 + (= esc "\\") 92 + (= esc "\"") 34 + (= esc "'") 39 + (= esc "") 0 + :else (char->integer (nth (string->list esc) 0))))) + :else + (let ((c (er-cur))) + (er-advance! 1) + (char->integer (nth (string->list c) 0)))))) + (er-emit! "integer" (str code) start)) (scan!)) (er-lower? ch) (do