forth: String word set COMPARE/SEARCH/SLITERAL (+9)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
This commit is contained in:
@@ -793,6 +793,53 @@
|
||||
(let
|
||||
((w (forth-pop s)))
|
||||
(forth-push s (or (get w "body-addr") 0)))))
|
||||
(forth-def-prim-imm!
|
||||
state
|
||||
"SLITERAL"
|
||||
(fn
|
||||
(s)
|
||||
(let
|
||||
((u (forth-pop s)) (c-addr (forth-pop s)))
|
||||
(let
|
||||
((content (forth-mem-read-string s c-addr u)))
|
||||
(let
|
||||
((new-addr (forth-alloc-bytes! s u)))
|
||||
(forth-mem-write-string! s new-addr content)
|
||||
(forth-def-append! s (fn (ss) (forth-push ss new-addr)))
|
||||
(forth-def-append! s (fn (ss) (forth-push ss u))))))))
|
||||
(forth-def-prim!
|
||||
state
|
||||
"COMPARE"
|
||||
(fn
|
||||
(s)
|
||||
(let
|
||||
((u2 (forth-pop s))
|
||||
(a2 (forth-pop s))
|
||||
(u1 (forth-pop s))
|
||||
(a1 (forth-pop s)))
|
||||
(forth-push s (forth-compare-bytes-loop s a1 u1 a2 u2 0)))))
|
||||
(forth-def-prim!
|
||||
state
|
||||
"SEARCH"
|
||||
(fn
|
||||
(s)
|
||||
(let
|
||||
((u2 (forth-pop s))
|
||||
(a2 (forth-pop s))
|
||||
(u1 (forth-pop s))
|
||||
(a1 (forth-pop s)))
|
||||
(let
|
||||
((idx (forth-search-bytes s a1 u1 a2 u2 0)))
|
||||
(if
|
||||
(< idx 0)
|
||||
(begin
|
||||
(forth-push s a1)
|
||||
(forth-push s u1)
|
||||
(forth-push s 0))
|
||||
(begin
|
||||
(forth-push s (+ a1 idx))
|
||||
(forth-push s (- u1 idx))
|
||||
(forth-push s -1)))))))
|
||||
(forth-def-prim! state "R/O" (fn (s) (forth-push s 0)))
|
||||
(forth-def-prim! state "W/O" (fn (s) (forth-push s 1)))
|
||||
(forth-def-prim! state "R/W" (fn (s) (forth-push s 2)))
|
||||
|
||||
@@ -381,6 +381,46 @@
|
||||
(dict-set! state "hold" (cons ch (get state "hold")))
|
||||
(forth-double-push-u state rest)))))))
|
||||
|
||||
(define
|
||||
forth-compare-bytes-loop
|
||||
(fn
|
||||
(state a1 u1 a2 u2 i)
|
||||
(cond
|
||||
((and (= i u1) (= i u2)) 0)
|
||||
((= i u1) -1)
|
||||
((= i u2) 1)
|
||||
(else
|
||||
(let
|
||||
((b1 (forth-mem-read state (+ a1 i)))
|
||||
(b2 (forth-mem-read state (+ a2 i))))
|
||||
(cond
|
||||
((< b1 b2) -1)
|
||||
((> b1 b2) 1)
|
||||
(else (forth-compare-bytes-loop state a1 u1 a2 u2 (+ i 1)))))))))
|
||||
|
||||
(define
|
||||
forth-match-at
|
||||
(fn
|
||||
(state a1 start a2 u2 j)
|
||||
(cond
|
||||
((= j u2) true)
|
||||
((not
|
||||
(=
|
||||
(forth-mem-read state (+ a1 (+ start j)))
|
||||
(forth-mem-read state (+ a2 j))))
|
||||
false)
|
||||
(else (forth-match-at state a1 start a2 u2 (+ j 1))))))
|
||||
|
||||
(define
|
||||
forth-search-bytes
|
||||
(fn
|
||||
(state a1 u1 a2 u2 i)
|
||||
(cond
|
||||
((= u2 0) 0)
|
||||
((> (+ i u2) u1) -1)
|
||||
((forth-match-at state a1 i a2 u2 0) i)
|
||||
(else (forth-search-bytes state a1 u1 a2 u2 (+ i 1))))))
|
||||
|
||||
(define
|
||||
forth-pic-S-loop
|
||||
(fn
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"source": "gerryjackson/forth2012-test-suite src/core.fr",
|
||||
"generated_at": "2026-04-25T02:24:33Z",
|
||||
"generated_at": "2026-04-25T02:53:26Z",
|
||||
"chunks_available": 638,
|
||||
"chunks_fed": 638,
|
||||
"total": 638,
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
| percent | 76% |
|
||||
|
||||
- **Source**: `gerryjackson/forth2012-test-suite` `src/core.fr`
|
||||
- **Generated**: 2026-04-25T02:24:33Z
|
||||
- **Generated**: 2026-04-25T02:53:26Z
|
||||
- **Note**: completed
|
||||
|
||||
A "chunk" is any preprocessed segment ending at a `}T` (every Hayes test
|
||||
|
||||
@@ -268,6 +268,38 @@
|
||||
"S\" /tmp/nope.fxf\" R/O OPEN-FILE SWAP DROP 0 ="
|
||||
0)))
|
||||
|
||||
(define
|
||||
forth-p5-string-tests
|
||||
(fn
|
||||
()
|
||||
(forth-p5-check-top "COMPARE equal" "S\" ABC\" S\" ABC\" COMPARE" 0)
|
||||
(forth-p5-check-top "COMPARE less" "S\" ABC\" S\" ABD\" COMPARE" -1)
|
||||
(forth-p5-check-top "COMPARE greater" "S\" ABD\" S\" ABC\" COMPARE" 1)
|
||||
(forth-p5-check-top
|
||||
"COMPARE prefix less"
|
||||
"S\" AB\" S\" ABC\" COMPARE"
|
||||
-1)
|
||||
(forth-p5-check-top
|
||||
"COMPARE prefix greater"
|
||||
"S\" ABC\" S\" AB\" COMPARE"
|
||||
1)
|
||||
(forth-p5-check-top
|
||||
"SEARCH found flag"
|
||||
"S\" HELLO WORLD\" S\" WORLD\" SEARCH"
|
||||
-1)
|
||||
(forth-p5-check-top
|
||||
"SEARCH not found flag"
|
||||
"S\" HELLO\" S\" XYZ\" SEARCH"
|
||||
0)
|
||||
(forth-p5-check-top
|
||||
"SEARCH empty needle flag"
|
||||
"S\" HELLO\" S\" \" SEARCH"
|
||||
-1)
|
||||
(forth-p5-check-top
|
||||
"SLITERAL via [ S\" ... \" ]"
|
||||
": A [ S\" HI\" ] SLITERAL ; A SWAP DROP"
|
||||
2)))
|
||||
|
||||
(define
|
||||
forth-p4-check-output-passthrough
|
||||
(fn
|
||||
@@ -291,6 +323,7 @@
|
||||
(forth-p5-state-tests)
|
||||
(forth-p5-misc-tests)
|
||||
(forth-p5-fa-tests)
|
||||
(forth-p5-string-tests)
|
||||
(dict
|
||||
"passed"
|
||||
forth-p5-passed
|
||||
|
||||
@@ -94,7 +94,7 @@ Representation:
|
||||
- [x] Source/state: `EVALUATE`, `STATE`, `[`, `]` (`SOURCE`/`>IN` stubbed; tokenized input means the exact byte/offset semantics aren't useful here)
|
||||
- [x] Misc Core: `WITHIN`, `MAX`/`MIN` (already), `ABORT`, `ABORT"`, `EXIT`, `UNLOOP`
|
||||
- [x] File Access word set (in-memory — `read-file` is not reachable from the epoch eval env)
|
||||
- [ ] String word set (`SLITERAL`, `COMPARE`, `SEARCH`)
|
||||
- [x] String word set (`SLITERAL`, `COMPARE`, `SEARCH`)
|
||||
- [ ] Target: 100% Hayes Core
|
||||
|
||||
### Phase 6 — speed
|
||||
@@ -106,6 +106,17 @@ Representation:
|
||||
|
||||
_Newest first._
|
||||
|
||||
- **Phase 5 — String word set `COMPARE`/`SEARCH`/`SLITERAL` (+9).**
|
||||
`COMPARE` walks bytes via the new `forth-compare-bytes-loop`,
|
||||
returning -1/0/1 with standard prefix semantics (shorter string
|
||||
compares less than its extension). `SEARCH` scans the haystack
|
||||
with a helper `forth-search-bytes` and `forth-match-at`, returning
|
||||
the tail after the first match or the original string with flag=0.
|
||||
Empty needle returns at offset 0 with flag=-1 per ANS. `SLITERAL`
|
||||
is IMMEDIATE: pops `(c-addr u)` at compile time, copies the bytes
|
||||
into a fresh allocation, and emits the two pushes so the compiled
|
||||
word yields the interned string at runtime.
|
||||
|
||||
- **Phase 5 — File Access word set (in-memory backing; +4).**
|
||||
`OPEN-FILE`/`CREATE-FILE`/`CLOSE-FILE`/`READ-FILE`/`WRITE-FILE`/
|
||||
`FILE-POSITION`/`FILE-SIZE`/`REPOSITION-FILE`/`DELETE-FILE` plus
|
||||
|
||||
Reference in New Issue
Block a user