Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
279 lines
7.4 KiB
Plaintext
279 lines
7.4 KiB
Plaintext
;; Phase 5 — Core Extension + memory primitives.
|
|
|
|
(define forth-p5-passed 0)
|
|
(define forth-p5-failed 0)
|
|
(define forth-p5-failures (list))
|
|
|
|
(define
|
|
forth-p5-assert
|
|
(fn
|
|
(label expected actual)
|
|
(if
|
|
(= expected actual)
|
|
(set! forth-p5-passed (+ forth-p5-passed 1))
|
|
(begin
|
|
(set! forth-p5-failed (+ forth-p5-failed 1))
|
|
(set!
|
|
forth-p5-failures
|
|
(concat
|
|
forth-p5-failures
|
|
(list
|
|
(str label ": expected " (str expected) " got " (str actual)))))))))
|
|
|
|
(define
|
|
forth-p5-check-stack
|
|
(fn
|
|
(label src expected)
|
|
(let ((r (forth-run src))) (forth-p5-assert label expected (nth r 2)))))
|
|
|
|
(define
|
|
forth-p5-check-top
|
|
(fn
|
|
(label src expected)
|
|
(let
|
|
((r (forth-run src)))
|
|
(let
|
|
((stk (nth r 2)))
|
|
(forth-p5-assert label expected (nth stk (- (len stk) 1)))))))
|
|
|
|
(define
|
|
forth-p5-create-tests
|
|
(fn
|
|
()
|
|
(forth-p5-check-top
|
|
"CREATE pushes HERE-at-creation"
|
|
"HERE CREATE FOO FOO ="
|
|
-1)
|
|
(forth-p5-check-top
|
|
"CREATE + ALLOT advances HERE"
|
|
"HERE 5 ALLOT HERE SWAP -"
|
|
5)
|
|
(forth-p5-check-top
|
|
"CREATE + , stores cell"
|
|
"CREATE FOO 42 , FOO @"
|
|
42)
|
|
(forth-p5-check-stack
|
|
"CREATE multiple ,"
|
|
"CREATE TBL 1 , 2 , 3 , TBL @ TBL CELL+ @ TBL CELL+ CELL+ @"
|
|
(list 1 2 3))
|
|
(forth-p5-check-top
|
|
"C, stores byte"
|
|
"CREATE B 65 C, 66 C, B C@"
|
|
65)))
|
|
|
|
(define
|
|
forth-p5-unsigned-tests
|
|
(fn
|
|
()
|
|
(forth-p5-check-top "1 2 U<" "1 2 U<" -1)
|
|
(forth-p5-check-top "2 1 U<" "2 1 U<" 0)
|
|
(forth-p5-check-top "0 1 U<" "0 1 U<" -1)
|
|
(forth-p5-check-top "-1 1 U< (since -1 unsigned is huge)" "-1 1 U<" 0)
|
|
(forth-p5-check-top "1 -1 U<" "1 -1 U<" -1)
|
|
(forth-p5-check-top "1 2 U>" "1 2 U>" 0)
|
|
(forth-p5-check-top "-1 1 U>" "-1 1 U>" -1)))
|
|
|
|
(define
|
|
forth-p5-2bang-tests
|
|
(fn
|
|
()
|
|
(forth-p5-check-stack
|
|
"2! / 2@"
|
|
"CREATE X 0 , 0 , 11 22 X 2! X 2@"
|
|
(list 11 22))))
|
|
|
|
(define
|
|
forth-p5-mixed-tests
|
|
(fn
|
|
()
|
|
(forth-p5-check-stack "S>D positive" "5 S>D" (list 5 0))
|
|
(forth-p5-check-stack "S>D negative" "-5 S>D" (list -5 -1))
|
|
(forth-p5-check-stack "S>D zero" "0 S>D" (list 0 0))
|
|
(forth-p5-check-top "D>S keeps low" "5 0 D>S" 5)
|
|
(forth-p5-check-stack "M* small positive" "3 4 M*" (list 12 0))
|
|
(forth-p5-check-stack "M* negative" "-3 4 M*" (list -12 -1))
|
|
(forth-p5-check-stack
|
|
"M* negative * negative"
|
|
"-3 -4 M*"
|
|
(list 12 0))
|
|
(forth-p5-check-stack "UM* small" "3 4 UM*" (list 12 0))
|
|
(forth-p5-check-stack
|
|
"UM/MOD: 100 0 / 5"
|
|
"100 0 5 UM/MOD"
|
|
(list 0 20))
|
|
(forth-p5-check-stack
|
|
"FM/MOD: -7 / 2 floored"
|
|
"-7 -1 2 FM/MOD"
|
|
(list 1 -4))
|
|
(forth-p5-check-stack
|
|
"SM/REM: -7 / 2 truncated"
|
|
"-7 -1 2 SM/REM"
|
|
(list -1 -3))
|
|
(forth-p5-check-top "*/ truncated" "7 11 13 */" 5)
|
|
(forth-p5-check-stack "*/MOD" "7 11 13 */MOD" (list 12 5))))
|
|
|
|
(define
|
|
forth-p5-double-tests
|
|
(fn
|
|
()
|
|
(forth-p5-check-stack "D+ small" "5 0 7 0 D+" (list 12 0))
|
|
(forth-p5-check-stack "D+ negative" "-5 -1 -3 -1 D+" (list -8 -1))
|
|
(forth-p5-check-stack "D- small" "10 0 3 0 D-" (list 7 0))
|
|
(forth-p5-check-stack "DNEGATE positive" "5 0 DNEGATE" (list -5 -1))
|
|
(forth-p5-check-stack "DNEGATE negative" "-5 -1 DNEGATE" (list 5 0))
|
|
(forth-p5-check-stack "DABS negative" "-7 -1 DABS" (list 7 0))
|
|
(forth-p5-check-stack "DABS positive" "7 0 DABS" (list 7 0))
|
|
(forth-p5-check-top "D= equal" "5 0 5 0 D=" -1)
|
|
(forth-p5-check-top "D= unequal lo" "5 0 7 0 D=" 0)
|
|
(forth-p5-check-top "D= unequal hi" "5 0 5 1 D=" 0)
|
|
(forth-p5-check-top "D< lt" "5 0 7 0 D<" -1)
|
|
(forth-p5-check-top "D< gt" "7 0 5 0 D<" 0)
|
|
(forth-p5-check-top "D0= zero" "0 0 D0=" -1)
|
|
(forth-p5-check-top "D0= nonzero" "5 0 D0=" 0)
|
|
(forth-p5-check-top "D0< neg" "-5 -1 D0<" -1)
|
|
(forth-p5-check-top "D0< pos" "5 0 D0<" 0)
|
|
(forth-p5-check-stack "DMAX" "5 0 7 0 DMAX" (list 7 0))
|
|
(forth-p5-check-stack "DMIN" "5 0 7 0 DMIN" (list 5 0))))
|
|
|
|
(define
|
|
forth-p5-format-tests
|
|
(fn
|
|
()
|
|
(forth-p4-check-output-passthrough
|
|
"U. prints with trailing space"
|
|
"123 U."
|
|
"123 ")
|
|
(forth-p4-check-output-passthrough
|
|
"<# #S #> TYPE — decimal"
|
|
"123 0 <# #S #> TYPE"
|
|
"123")
|
|
(forth-p4-check-output-passthrough
|
|
"<# #S #> TYPE — hex"
|
|
"255 HEX 0 <# #S #> TYPE"
|
|
"FF")
|
|
(forth-p4-check-output-passthrough
|
|
"<# # # #> partial"
|
|
"1234 0 <# # # #> TYPE"
|
|
"34")
|
|
(forth-p4-check-output-passthrough
|
|
"SIGN holds minus"
|
|
"<# -1 SIGN -1 SIGN 0 0 #> TYPE"
|
|
"--")
|
|
(forth-p4-check-output-passthrough
|
|
".R right-justifies"
|
|
"42 5 .R"
|
|
" 42")
|
|
(forth-p4-check-output-passthrough
|
|
".R negative"
|
|
"-42 5 .R"
|
|
" -42")
|
|
(forth-p4-check-output-passthrough
|
|
"U.R"
|
|
"42 5 U.R"
|
|
" 42")
|
|
(forth-p4-check-output-passthrough
|
|
"HOLD char"
|
|
"<# 0 0 65 HOLD #> TYPE"
|
|
"A")))
|
|
|
|
(define
|
|
forth-p5-dict-tests
|
|
(fn
|
|
()
|
|
(forth-p5-check-top
|
|
"EXECUTE via tick"
|
|
": INC 1+ ; 9 ' INC EXECUTE"
|
|
10)
|
|
(forth-p5-check-top
|
|
"['] inside def"
|
|
": DUB 2* ; : APPLY ['] DUB EXECUTE ; 5 APPLY"
|
|
10)
|
|
(forth-p5-check-top
|
|
">BODY of CREATE word"
|
|
"CREATE C 99 , ' C >BODY @"
|
|
99)
|
|
(forth-p5-check-stack
|
|
"WORD parses next token to counted-string"
|
|
": A 5 ; BL WORD A COUNT TYPE"
|
|
(list))
|
|
(forth-p5-check-top
|
|
"FIND on known word -> non-zero"
|
|
": A 5 ; BL WORD A FIND SWAP DROP"
|
|
-1)))
|
|
|
|
(define
|
|
forth-p5-state-tests
|
|
(fn
|
|
()
|
|
(forth-p5-check-top
|
|
"STATE @ in interpret mode"
|
|
"STATE @"
|
|
0)
|
|
(forth-p5-check-top
|
|
"STATE @ via IMMEDIATE inside compile"
|
|
": GT8 STATE @ ; IMMEDIATE : T GT8 LITERAL ; T"
|
|
-1)
|
|
(forth-p5-check-top
|
|
"[ ] LITERAL captures"
|
|
": SEVEN [ 7 ] LITERAL ; SEVEN"
|
|
7)
|
|
(forth-p5-check-top
|
|
"EVALUATE in interpret mode"
|
|
"S\" 5 7 +\" EVALUATE"
|
|
12)
|
|
(forth-p5-check-top
|
|
"EVALUATE inside def"
|
|
": A 100 ; : B S\" A\" EVALUATE ; B"
|
|
100)))
|
|
|
|
(define
|
|
forth-p5-misc-tests
|
|
(fn
|
|
()
|
|
(forth-p5-check-top "WITHIN inclusive lower" "3 2 10 WITHIN" -1)
|
|
(forth-p5-check-top "WITHIN exclusive upper" "10 2 10 WITHIN" 0)
|
|
(forth-p5-check-top "WITHIN below range" "1 2 10 WITHIN" 0)
|
|
(forth-p5-check-top "WITHIN at lower" "2 2 10 WITHIN" -1)
|
|
(forth-p5-check-top
|
|
"EXIT leaves colon-def early"
|
|
": F 5 EXIT 99 ; F"
|
|
5)
|
|
(forth-p5-check-stack
|
|
"EXIT in IF branch"
|
|
": F 5 0 IF DROP 99 EXIT THEN ; F"
|
|
(list 5))
|
|
(forth-p5-check-top
|
|
"UNLOOP + EXIT in DO"
|
|
": SUM 0 10 0 DO I 5 = IF I UNLOOP EXIT THEN LOOP ; SUM"
|
|
5)))
|
|
|
|
(define
|
|
forth-p4-check-output-passthrough
|
|
(fn
|
|
(label src expected)
|
|
(let ((r (forth-run src))) (forth-p5-assert label expected (nth r 1)))))
|
|
|
|
(define
|
|
forth-p5-run-all
|
|
(fn
|
|
()
|
|
(set! forth-p5-passed 0)
|
|
(set! forth-p5-failed 0)
|
|
(set! forth-p5-failures (list))
|
|
(forth-p5-create-tests)
|
|
(forth-p5-unsigned-tests)
|
|
(forth-p5-2bang-tests)
|
|
(forth-p5-mixed-tests)
|
|
(forth-p5-double-tests)
|
|
(forth-p5-format-tests)
|
|
(forth-p5-dict-tests)
|
|
(forth-p5-state-tests)
|
|
(forth-p5-misc-tests)
|
|
(dict
|
|
"passed"
|
|
forth-p5-passed
|
|
"failed"
|
|
forth-p5-failed
|
|
"failures"
|
|
forth-p5-failures)))
|