Compare commits
16 Commits
1ebe07b863
...
ee4c0d1d8c
| Author | SHA1 | Date | |
|---|---|---|---|
| ee4c0d1d8c | |||
| acaf198fae | |||
| 1a9702ea5c | |||
| 5d704d3bde | |||
| 047d09260c | |||
| fac6c4d3b8 | |||
| a9fd395a94 | |||
| 922a0e6e31 | |||
| d60708645d | |||
| 8785c01f9e | |||
| 53d3a308cd | |||
| fde6429d4f | |||
| c06ef248b7 | |||
| f6a24ee3cf | |||
| b372ae3d5f | |||
| 9f1be9ad2f |
@@ -46,3 +46,12 @@ registers: `xBUF`, `xHEAD` and `xTAIL`:
|
|||||||
In order to be distinguishable from the empty state, the ring buffers
|
In order to be distinguishable from the empty state, the ring buffers
|
||||||
must never be completely full -- there must always be *at least one*
|
must never be completely full -- there must always be *at least one*
|
||||||
unoccupied byte between the tail and the head.
|
unoccupied byte between the tail and the head.
|
||||||
|
|
||||||
|
# System status
|
||||||
|
|
||||||
|
| Name | Offset | Size / B | Access |
|
||||||
|
|----------|--------|----------|--------------|
|
||||||
|
| SYSREADY | 68 | 1 | atomic write |
|
||||||
|
|
||||||
|
The `SYSREADY` register is used to indicate when the system has booted
|
||||||
|
up and is ready for user input.
|
||||||
|
|||||||
29
emu.js
29
emu.js
@@ -4,10 +4,11 @@ const TXHEAD = 64;
|
|||||||
const TXTAIL = 65;
|
const TXTAIL = 65;
|
||||||
const RXHEAD = 66;
|
const RXHEAD = 66;
|
||||||
const RXTAIL = 67;
|
const RXTAIL = 67;
|
||||||
|
const SYSREADY = 68;
|
||||||
|
|
||||||
const TXBUF_SIZE = 32;
|
const TXBUF_SIZE = 32;
|
||||||
const RXBUF_SIZE = 32;
|
const RXBUF_SIZE = 32;
|
||||||
const PERIPHS_SIZE = 68;
|
const PERIPHS_SIZE = 69; // Nice
|
||||||
|
|
||||||
const POLL_INTERVAL_MS = 20;
|
const POLL_INTERVAL_MS = 20;
|
||||||
|
|
||||||
@@ -44,13 +45,18 @@ class Emulator {
|
|||||||
end: { x: 0, y: 0 }
|
end: { x: 0, y: 0 }
|
||||||
};
|
};
|
||||||
this.idle_timer = null;
|
this.idle_timer = null;
|
||||||
|
this.input_enable = false;
|
||||||
document.addEventListener('keydown', (e) => this.handle_keydown(e));
|
document.addEventListener('keydown', (e) => this.handle_keydown(e));
|
||||||
|
|
||||||
this.flush_output();
|
|
||||||
document.getElementById('cursor').classList.add('blinking');
|
|
||||||
|
|
||||||
this.worker = new Worker('boot.js');
|
this.worker = new Worker('boot.js');
|
||||||
this.worker.postMessage(this.mem);
|
this.worker.postMessage(this.mem);
|
||||||
|
|
||||||
|
fetch('prelude.f')
|
||||||
|
.then(res => res.text())
|
||||||
|
.then(text => {
|
||||||
|
for (const cu of this.encoder.encode(text))
|
||||||
|
this.rx_queue.push(cu);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
poll() {
|
poll() {
|
||||||
@@ -65,6 +71,15 @@ class Emulator {
|
|||||||
if (this.fifo_next(rxtail) != rxhead)
|
if (this.fifo_next(rxtail) != rxhead)
|
||||||
this.handle_rx_data(rxhead, rxtail);
|
this.handle_rx_data(rxhead, rxtail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.input_enable) {
|
||||||
|
const sysready = Atomics.load(this.mem_u8, SYSREADY);
|
||||||
|
if (sysready != 0) {
|
||||||
|
this.input_enable = true;
|
||||||
|
this.flush_output();
|
||||||
|
document.getElementById('cursor').classList.add('blinking');
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fifo_next(idx) {
|
fifo_next(idx) {
|
||||||
@@ -118,6 +133,9 @@ class Emulator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handle_keydown(e) {
|
handle_keydown(e) {
|
||||||
|
if (!this.input_enable)
|
||||||
|
return;
|
||||||
|
|
||||||
if (e.key.length == 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
if (e.key.length == 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
||||||
this.shift_up(this.cursor);
|
this.shift_up(this.cursor);
|
||||||
this.grid[this.cursor.y][this.cursor.x] = e.key;
|
this.grid[this.cursor.y][this.cursor.x] = e.key;
|
||||||
@@ -239,7 +257,8 @@ class Emulator {
|
|||||||
const html = this.grid.map((row, y) => {
|
const html = this.grid.map((row, y) => {
|
||||||
return row.map((c, x) => {
|
return row.map((c, x) => {
|
||||||
const ec = this.html_escape(c);
|
const ec = this.html_escape(c);
|
||||||
if (x == this.cursor.x && y == this.cursor.y)
|
if (this.input_enable
|
||||||
|
&& x == this.cursor.x && y == this.cursor.y)
|
||||||
return '<span id="cursor">' + ec + '</span>';
|
return '<span id="cursor">' + ec + '</span>';
|
||||||
else
|
else
|
||||||
return ec;
|
return ec;
|
||||||
|
|||||||
270
prelude.f
Normal file
270
prelude.f
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
76 EMIT 111 EMIT 97 EMIT 100 EMIT 105 EMIT 110 EMIT 103 EMIT 32 EMIT
|
||||||
|
112 EMIT 114 EMIT 101 EMIT 108 EMIT 117 EMIT 100 EMIT 101 EMIT 32 EMIT
|
||||||
|
|
||||||
|
: \ KEY 10 = 0BRANCH [ -20 , ] ; IMMEDIATE \ Now we have line comments :)
|
||||||
|
|
||||||
|
\ We'll periodically sprinkle these in so that it's clear to the user
|
||||||
|
\ that things are happening.
|
||||||
|
46 EMIT
|
||||||
|
|
||||||
|
\ Conditionals
|
||||||
|
|
||||||
|
: IF
|
||||||
|
LIT 0BRANCH ,
|
||||||
|
HERE @ 0 ,
|
||||||
|
; IMMEDIATE
|
||||||
|
|
||||||
|
: THEN
|
||||||
|
DUP HERE @ SWAP -
|
||||||
|
SWAP !
|
||||||
|
; IMMEDIATE
|
||||||
|
|
||||||
|
: ELSE
|
||||||
|
LIT BRANCH ,
|
||||||
|
HERE @ 0 ,
|
||||||
|
SWAP
|
||||||
|
DUP HERE @ SWAP -
|
||||||
|
SWAP !
|
||||||
|
; IMMEDIATE
|
||||||
|
|
||||||
|
46 EMIT
|
||||||
|
|
||||||
|
\ Loops
|
||||||
|
|
||||||
|
: BEGIN HERE @ ; IMMEDIATE
|
||||||
|
|
||||||
|
: UNTIL
|
||||||
|
LIT 0BRANCH ,
|
||||||
|
HERE @ - ,
|
||||||
|
; IMMEDIATE
|
||||||
|
|
||||||
|
: AGAIN
|
||||||
|
LIT BRANCH ,
|
||||||
|
HERE @ - ,
|
||||||
|
; IMMEDIATE
|
||||||
|
|
||||||
|
46 EMIT
|
||||||
|
|
||||||
|
\ Recursive calls
|
||||||
|
|
||||||
|
: RECURSE LATEST @ >CFA , ; IMMEDIATE
|
||||||
|
|
||||||
|
\ Block comments (with nesting)
|
||||||
|
|
||||||
|
: (
|
||||||
|
BEGIN
|
||||||
|
KEY DUP
|
||||||
|
40 = IF RECURSE THEN
|
||||||
|
41 =
|
||||||
|
UNTIL
|
||||||
|
; IMMEDIATE
|
||||||
|
|
||||||
|
( ( Take that, C ) )
|
||||||
|
|
||||||
|
46 EMIT
|
||||||
|
|
||||||
|
\ Peripheral register addresses
|
||||||
|
|
||||||
|
: TXBUF 0 ;
|
||||||
|
: RXBUF 32 ;
|
||||||
|
: TXHEAD 64 ;
|
||||||
|
: TXTAIL 65 ;
|
||||||
|
: RXHEAD 66 ;
|
||||||
|
: RXTAIL 67 ;
|
||||||
|
: SYSREADY 68 ;
|
||||||
|
|
||||||
|
46 EMIT
|
||||||
|
|
||||||
|
\ Printing utilities
|
||||||
|
|
||||||
|
: CR 10 EMIT ;
|
||||||
|
: SPACE 32 EMIT ;
|
||||||
|
|
||||||
|
: CHAR
|
||||||
|
KEY
|
||||||
|
STATE @ 0<> IF
|
||||||
|
LIT LIT , , \ Append LIT <key> to definition if compiling
|
||||||
|
THEN
|
||||||
|
; IMMEDIATE
|
||||||
|
|
||||||
|
: EMIT-DIGIT
|
||||||
|
DUP 10 < IF CHAR 0 ELSE CHAR A THEN
|
||||||
|
+ EMIT
|
||||||
|
;
|
||||||
|
|
||||||
|
CHAR . EMIT
|
||||||
|
|
||||||
|
: .
|
||||||
|
\ Handle negatives
|
||||||
|
DUP 0< IF CHAR - EMIT NEGATE THEN
|
||||||
|
|
||||||
|
\ Determine starting place value
|
||||||
|
1 BEGIN BASE @ * 2DUP / 0= UNTIL
|
||||||
|
|
||||||
|
\ Print leading non-zero digits
|
||||||
|
BEGIN
|
||||||
|
BASE @ /
|
||||||
|
2DUP / EMIT-DIGIT
|
||||||
|
TUCK MOD SWAP
|
||||||
|
OVER 0=
|
||||||
|
UNTIL
|
||||||
|
|
||||||
|
\ Print any trailing zeros
|
||||||
|
BASE @ /
|
||||||
|
DUP 0<> IF
|
||||||
|
BEGIN CHAR 0 EMIT BASE @ / 0= UNTIL
|
||||||
|
THEN
|
||||||
|
|
||||||
|
2DROP
|
||||||
|
;
|
||||||
|
|
||||||
|
CHAR . EMIT
|
||||||
|
|
||||||
|
: TYPE ( addr len -- )
|
||||||
|
BEGIN
|
||||||
|
DUP 0= IF 2DROP EXIT THEN
|
||||||
|
SWAP DUP C@ EMIT 1+
|
||||||
|
SWAP 1-
|
||||||
|
AGAIN
|
||||||
|
;
|
||||||
|
|
||||||
|
CHAR . EMIT
|
||||||
|
|
||||||
|
: C, HERE @ C! 1 HERE +! ;
|
||||||
|
|
||||||
|
: ."
|
||||||
|
STATE @ IF
|
||||||
|
LIT BRANCH , \ Compile BRANCH for jumping over string data
|
||||||
|
HERE @ 0 , \ Compile placeholder offset and push offset cell address
|
||||||
|
0 BEGIN
|
||||||
|
KEY
|
||||||
|
DUP CHAR " = IF
|
||||||
|
DROP
|
||||||
|
HERE @ ALIGN HERE ! \ Pad to alignment
|
||||||
|
SWAP DUP HERE @ SWAP - \ Compute offset
|
||||||
|
OVER ! \ Update branch offset to skip data
|
||||||
|
4+ LIT LIT , , \ Append LIT <addr>
|
||||||
|
LIT LIT , , \ Append LIT <len>
|
||||||
|
LIT TYPE , \ Append TYPE
|
||||||
|
EXIT
|
||||||
|
THEN
|
||||||
|
C, 1+ \ Write byte and increment length
|
||||||
|
AGAIN
|
||||||
|
ELSE
|
||||||
|
BEGIN
|
||||||
|
KEY
|
||||||
|
DUP CHAR " = IF DROP EXIT THEN
|
||||||
|
EMIT
|
||||||
|
AGAIN
|
||||||
|
THEN
|
||||||
|
; IMMEDIATE
|
||||||
|
|
||||||
|
CHAR . EMIT
|
||||||
|
|
||||||
|
\ Misc utilities
|
||||||
|
|
||||||
|
: NIP SWAP DROP ;
|
||||||
|
|
||||||
|
: '
|
||||||
|
WORD FIND DUP 0<> IF
|
||||||
|
>CFA
|
||||||
|
ELSE
|
||||||
|
DROP WNFHOOK EXECUTE
|
||||||
|
THEN
|
||||||
|
;
|
||||||
|
|
||||||
|
: [COMPILE] ' , ; IMMEDIATE
|
||||||
|
|
||||||
|
CHAR . EMIT
|
||||||
|
|
||||||
|
\ Constants, variables and values
|
||||||
|
|
||||||
|
: CONSTANT
|
||||||
|
WORD CREATE
|
||||||
|
DOCOL ,
|
||||||
|
LIT LIT ,
|
||||||
|
,
|
||||||
|
LIT EXIT ,
|
||||||
|
;
|
||||||
|
|
||||||
|
: VARIABLE
|
||||||
|
WORD CREATE
|
||||||
|
DOVAR ,
|
||||||
|
0 ,
|
||||||
|
;
|
||||||
|
|
||||||
|
: VALUE
|
||||||
|
WORD CREATE
|
||||||
|
DOVAL , ,
|
||||||
|
;
|
||||||
|
|
||||||
|
: TO
|
||||||
|
' 4+
|
||||||
|
STATE @ IF
|
||||||
|
LIT LIT , ,
|
||||||
|
LIT ! ,
|
||||||
|
ELSE
|
||||||
|
!
|
||||||
|
THEN
|
||||||
|
; IMMEDIATE
|
||||||
|
|
||||||
|
CHAR . EMIT
|
||||||
|
|
||||||
|
\ A better word-not-found handler
|
||||||
|
|
||||||
|
: ANY-RX? RXHEAD AC@ RXTAIL AC@ <> ;
|
||||||
|
|
||||||
|
: WNF-HANDLER
|
||||||
|
." Unknown word: "
|
||||||
|
WORDBUF SWAP TYPE CR
|
||||||
|
STATE @ IF
|
||||||
|
\ Remove incomplete definition and switch back to interpret mode
|
||||||
|
LATEST @ HERE !
|
||||||
|
LATEST @ @ LATEST !
|
||||||
|
[COMPILE] [
|
||||||
|
THEN
|
||||||
|
\ We only consume to the next newline if there is RX data available,
|
||||||
|
\ because if the offending word was at the end of the line then the
|
||||||
|
\ newline would have already been consumed by WORD.
|
||||||
|
ANY-RX? IF BEGIN KEY 10 = UNTIL THEN
|
||||||
|
QUIT
|
||||||
|
;
|
||||||
|
|
||||||
|
' WNF-HANDLER TO WNFHOOK
|
||||||
|
|
||||||
|
CHAR . EMIT
|
||||||
|
|
||||||
|
\ Version number
|
||||||
|
|
||||||
|
: VERSION-MAJOR 0 ;
|
||||||
|
: VERSION-MINOR 1 ;
|
||||||
|
: VERSION-PATCH 0 ;
|
||||||
|
|
||||||
|
: VERSION-PRINT
|
||||||
|
." v" VERSION-MAJOR .
|
||||||
|
." ." VERSION-MINOR .
|
||||||
|
." ." VERSION-PATCH .
|
||||||
|
;
|
||||||
|
|
||||||
|
CHAR . EMIT
|
||||||
|
|
||||||
|
\ Welcome banner
|
||||||
|
|
||||||
|
: BANNER
|
||||||
|
." _ __ " CR
|
||||||
|
." _ __(_)__ ___ / / " CR
|
||||||
|
." | |/|/ / / _ \_ (_-./ _ \" CR
|
||||||
|
." |__,__/_/ .__(_)___/_//_/" CR
|
||||||
|
." /_/ " CR
|
||||||
|
CR
|
||||||
|
." Wipforth " VERSION-PRINT CR
|
||||||
|
CR
|
||||||
|
;
|
||||||
|
|
||||||
|
." done" CR
|
||||||
|
BANNER
|
||||||
|
|
||||||
|
\ Set SYSREADY high to indicate prelude has finished and enable user
|
||||||
|
\ input on the JS side.
|
||||||
|
|
||||||
|
1 SYSREADY AC!
|
||||||
101
wipforth.wat
101
wipforth.wat
@@ -96,7 +96,7 @@
|
|||||||
|
|
||||||
call $next)
|
call $next)
|
||||||
|
|
||||||
(func $doconst
|
(func $doval
|
||||||
global.get $cfa
|
global.get $cfa
|
||||||
i32.const 4
|
i32.const 4
|
||||||
i32.add
|
i32.add
|
||||||
@@ -720,7 +720,7 @@
|
|||||||
;; dictionary entries so that the definition of the index isn't too
|
;; dictionary entries so that the definition of the index isn't too
|
||||||
;; far from its use.
|
;; far from its use.
|
||||||
;;
|
;;
|
||||||
;; The exceptions are the special inner interpreters, DOCOL, DOCONST
|
;; The exceptions are the special inner interpreters, DOCOL, DOVAL
|
||||||
;; and DOVAR, which I've put here in indices 0, 1 and 2 for
|
;; and DOVAR, which I've put here in indices 0, 1 and 2 for
|
||||||
;; convenience.
|
;; convenience.
|
||||||
|
|
||||||
@@ -728,7 +728,7 @@
|
|||||||
(table $codewords 100 funcref)
|
(table $codewords 100 funcref)
|
||||||
|
|
||||||
(elem (i32.const 0x00) $docol)
|
(elem (i32.const 0x00) $docol)
|
||||||
(elem (i32.const 0x01) $doconst)
|
(elem (i32.const 0x01) $doval)
|
||||||
(elem (i32.const 0x02) $dovar)
|
(elem (i32.const 0x02) $dovar)
|
||||||
|
|
||||||
;; Dictionary time D:
|
;; Dictionary time D:
|
||||||
@@ -1053,7 +1053,7 @@
|
|||||||
"\070BRANCH"
|
"\070BRANCH"
|
||||||
"\37\00\00\00")
|
"\37\00\00\00")
|
||||||
|
|
||||||
;; Built-in constants and variables
|
;; Built-in values and variables
|
||||||
|
|
||||||
(data (i32.const 0x04b8)
|
(data (i32.const 0x04b8)
|
||||||
"\a8\04\00\00"
|
"\a8\04\00\00"
|
||||||
@@ -1063,7 +1063,7 @@
|
|||||||
|
|
||||||
(data (i32.const 0x04cc)
|
(data (i32.const 0x04cc)
|
||||||
"\b8\04\00\00"
|
"\b8\04\00\00"
|
||||||
"\07DOCONST"
|
"\05DOVAL\00\00"
|
||||||
"\01\00\00\00"
|
"\01\00\00\00"
|
||||||
"\01\00\00\00")
|
"\01\00\00\00")
|
||||||
|
|
||||||
@@ -1119,13 +1119,13 @@
|
|||||||
"\64\05\00\00"
|
"\64\05\00\00"
|
||||||
"\04HERE\00\00\00"
|
"\04HERE\00\00\00"
|
||||||
"\02\00\00\00"
|
"\02\00\00\00"
|
||||||
"\e0\0d\00\00")
|
"\60\0e\00\00")
|
||||||
|
|
||||||
(data (i32.const 0x058c)
|
(data (i32.const 0x058c)
|
||||||
"\78\05\00\00"
|
"\78\05\00\00"
|
||||||
"\06LATEST\00"
|
"\06LATEST\00"
|
||||||
"\02\00\00\00"
|
"\02\00\00\00"
|
||||||
"\b4\0d\00\00")
|
"\30\0e\00\00")
|
||||||
|
|
||||||
(data (i32.const 0x05a0)
|
(data (i32.const 0x05a0)
|
||||||
"\8c\05\00\00"
|
"\8c\05\00\00"
|
||||||
@@ -1136,9 +1136,9 @@
|
|||||||
|
|
||||||
(data (i32.const 0x05d0)
|
(data (i32.const 0x05d0)
|
||||||
"\a0\05\00\00"
|
"\a0\05\00\00"
|
||||||
"\05ERROR\00\00"
|
"\07WNFHOOK"
|
||||||
"\02\00\00\00"
|
"\01\00\00\00"
|
||||||
"\00\00\00\00")
|
"\f0\0d\00\00")
|
||||||
|
|
||||||
;; And now, it's time for some hand-compiled colon words. It
|
;; And now, it's time for some hand-compiled colon words. It
|
||||||
;; probably would have made more sense to write most of these
|
;; probably would have made more sense to write most of these
|
||||||
@@ -1287,11 +1287,7 @@
|
|||||||
|
|
||||||
;; => 0x78 bytes
|
;; => 0x78 bytes
|
||||||
|
|
||||||
;; : NAME-LEN 4+ C@ 63 AND ;
|
;; : NAME-LEN 4+ C@ 31 AND ;
|
||||||
|
|
||||||
;; The 0x3f mask we use here includes the hidden flag, so that FIND
|
|
||||||
;; never matches a hidden entry as its length will appear to be
|
|
||||||
;; greater than the maximum length returned by WORD.
|
|
||||||
|
|
||||||
(data (i32.const 0x0760)
|
(data (i32.const 0x0760)
|
||||||
"\e8\06\00\00"
|
"\e8\06\00\00"
|
||||||
@@ -1300,7 +1296,7 @@
|
|||||||
"\a8\02\00\00" ;; 4+
|
"\a8\02\00\00" ;; 4+
|
||||||
"\fc\03\00\00" ;; C@
|
"\fc\03\00\00" ;; C@
|
||||||
"\18\04\00\00" ;; LIT
|
"\18\04\00\00" ;; LIT
|
||||||
"\3f\00\00\00" ;; 63
|
"\1f\00\00\00" ;; 31
|
||||||
"\8c\03\00\00" ;; AND
|
"\8c\03\00\00" ;; AND
|
||||||
"\0c\04\00\00") ;; EXIT
|
"\0c\04\00\00") ;; EXIT
|
||||||
|
|
||||||
@@ -1309,7 +1305,7 @@
|
|||||||
;; : FIND ( len -- entry )
|
;; : FIND ( len -- entry )
|
||||||
;; LATEST @ \ Initial entry
|
;; LATEST @ \ Initial entry
|
||||||
;;
|
;;
|
||||||
;; TUCK NAME-LEN \ Get name length
|
;; TUCK FIND-NAME-LEN \ Get name length
|
||||||
;; OVER = 0BRANCH [52] \ Check for length mismatch
|
;; OVER = 0BRANCH [52] \ Check for length mismatch
|
||||||
;; OVER 5 + \ Get name address
|
;; OVER 5 + \ Get name address
|
||||||
;; OVER SWAP WORDBUF STRING= \ Check if name matches
|
;; OVER SWAP WORDBUF STRING= \ Check if name matches
|
||||||
@@ -1329,7 +1325,7 @@
|
|||||||
"\98\05\00\00" ;; LATEST
|
"\98\05\00\00" ;; LATEST
|
||||||
"\cc\03\00\00" ;; @
|
"\cc\03\00\00" ;; @
|
||||||
"\f0\05\00\00" ;; TUCK
|
"\f0\05\00\00" ;; TUCK
|
||||||
"\70\07\00\00" ;; NAME-LEN
|
"\44\0e\00\00" ;; FIND-NAME-LEN
|
||||||
"\54\02\00\00" ;; OVER
|
"\54\02\00\00" ;; OVER
|
||||||
"\fc\02\00\00" ;; =
|
"\fc\02\00\00" ;; =
|
||||||
"\b4\04\00\00" ;; 0BRANCH
|
"\b4\04\00\00" ;; 0BRANCH
|
||||||
@@ -1637,11 +1633,8 @@
|
|||||||
;; LIT-CFA , , \ If compiling, append LIT and the value
|
;; LIT-CFA , , \ If compiling, append LIT and the value
|
||||||
;; EXIT
|
;; EXIT
|
||||||
;;
|
;;
|
||||||
;; \ Word was not found and also not a number. Ideally we'd print the
|
;; \ Word was not found
|
||||||
;; \ word that wasn't found here but I haven't implemented such things
|
;; WNFHOOK EXECUTE
|
||||||
;; \ yet so for now we'll just discard the word's length, set ERROR to
|
|
||||||
;; \ 1 and exit.
|
|
||||||
;; DROP 1 ERROR !
|
|
||||||
;; ;
|
;; ;
|
||||||
|
|
||||||
(data (i32.const 0x0ac0)
|
(data (i32.const 0x0ac0)
|
||||||
@@ -1686,14 +1679,15 @@
|
|||||||
"\5c\0a\00\00" ;; ,
|
"\5c\0a\00\00" ;; ,
|
||||||
"\5c\0a\00\00" ;; ,
|
"\5c\0a\00\00" ;; ,
|
||||||
"\0c\04\00\00" ;; EXIT
|
"\0c\04\00\00" ;; EXIT
|
||||||
"\18\02\00\00" ;; DROP
|
"\dc\05\00\00" ;; WNFHOOK
|
||||||
"\18\04\00\00" ;; LIT
|
"\bc\0b\00\00" ;; EXECUTE
|
||||||
"\01\00\00\00" ;; 1
|
|
||||||
"\dc\05\00\00" ;; ERROR
|
|
||||||
"\c0\03\00\00" ;; !
|
|
||||||
"\0c\04\00\00") ;; EXIT
|
"\0c\04\00\00") ;; EXIT
|
||||||
|
|
||||||
;; => 0xc4 bytes
|
;; => 0xb8 bytes
|
||||||
|
|
||||||
|
;; The previous version of INTERPRET was 0xc4 bytes, so we have 12
|
||||||
|
;; unused bytes here. Could fit an extra codeword definition in
|
||||||
|
;; here, if the name is less than 4 bytes long.
|
||||||
|
|
||||||
;; : QUIT R0 RSP! INTERPRET BRANCH [-8] ;
|
;; : QUIT R0 RSP! INTERPRET BRANCH [-8] ;
|
||||||
|
|
||||||
@@ -1928,7 +1922,7 @@
|
|||||||
;; [
|
;; [
|
||||||
;; ; IMMEDIATE
|
;; ; IMMEDIATE
|
||||||
|
|
||||||
(data (i32.const 0xdb4)
|
(data (i32.const 0x0db4)
|
||||||
"\78\0d\00\00"
|
"\78\0d\00\00"
|
||||||
"\81;\00\00"
|
"\81;\00\00"
|
||||||
"\00\00\00\00"
|
"\00\00\00\00"
|
||||||
@@ -1943,6 +1937,53 @@
|
|||||||
|
|
||||||
;; => 0x2c bytes
|
;; => 0x2c bytes
|
||||||
|
|
||||||
|
;; : WNF-HANDLER
|
||||||
|
;; DROP \ Discard word length
|
||||||
|
;; 87 EMIT 78 EMIT 70 EMIT 10 EMIT \ Print WNF
|
||||||
|
;; QUIT \ Reset return stack
|
||||||
|
;; ;
|
||||||
|
|
||||||
|
(data (i32.const 0x0de0)
|
||||||
|
"\b4\0d\00\00"
|
||||||
|
"\0bWNF-HANDLER"
|
||||||
|
"\00\00\00\00"
|
||||||
|
"\18\02\00\00" ;; DROP
|
||||||
|
"\18\04\00\00" ;; LIT
|
||||||
|
"\57\00\00\00" ;; 87
|
||||||
|
"\94\04\00\00" ;; EMIT
|
||||||
|
"\18\04\00\00" ;; LIT
|
||||||
|
"\4e\00\00\00" ;; 78
|
||||||
|
"\94\04\00\00" ;; EMIT
|
||||||
|
"\18\04\00\00" ;; LIT
|
||||||
|
"\46\00\00\00" ;; 70
|
||||||
|
"\94\04\00\00" ;; EMIT
|
||||||
|
"\18\04\00\00" ;; LIT
|
||||||
|
"\0a\00\00\00" ;; 10
|
||||||
|
"\94\04\00\00" ;; EMIT
|
||||||
|
"\90\0b\00\00" ;; QUIT
|
||||||
|
"\0c\04\00\00") ;; EXIT
|
||||||
|
|
||||||
|
;; => 0x50 bytes
|
||||||
|
|
||||||
|
;; : FIND-NAME-LEN 4+ C@ 63 AND ;
|
||||||
|
|
||||||
|
;; The 0x3f mask we use here includes the hidden flag, so that FIND
|
||||||
|
;; never matches a hidden entry as its length will appear to be
|
||||||
|
;; greater than the maximum length returned by WORD.
|
||||||
|
|
||||||
|
(data (i32.const 0x0e30)
|
||||||
|
"\e0\0d\00\00"
|
||||||
|
"\0dFIND-NAME-LEN\00\00"
|
||||||
|
"\00\00\00\00"
|
||||||
|
"\a8\02\00\00" ;; 4+
|
||||||
|
"\fc\03\00\00" ;; C@
|
||||||
|
"\18\04\00\00" ;; LIT
|
||||||
|
"\3f\00\00\00" ;; 63
|
||||||
|
"\8c\03\00\00" ;; AND
|
||||||
|
"\0c\04\00\00") ;; EXIT
|
||||||
|
|
||||||
|
;; => 0x30 bytes
|
||||||
|
|
||||||
;; The trampoline is a workaround for WebAssembly's lack of indirect
|
;; The trampoline is a workaround for WebAssembly's lack of indirect
|
||||||
;; jumps and code addresses. Instead of jumping into the next
|
;; jumps and code addresses. Instead of jumping into the next
|
||||||
;; codeword, NEXT sets the $fn global to the function index of the
|
;; codeword, NEXT sets the $fn global to the function index of the
|
||||||
|
|||||||
Reference in New Issue
Block a user