7e2f5a3b849f694c21ac6794c30829e49af4a56d
1 /* This program is free software: you can redistribute it and/or modify
2 it under the terms of the GNU General Public License as published by
3 the Free Software Foundation, either version 3 of the License, or
4 (at your option) any later version.
6 This program is distributed in the hope that it will be useful,
7 but WITHOUT ANY WARRANTY; without even the implied warranty of
8 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 GNU General Public License for more details.
11 You should have received a copy of the GNU General Public License
12 along with this program. If not, see <http://www.gnu.org/licenses/>. */
14 let txtdiv = document.createElement("div")
15 document.body.appendChild(txtdiv)
17 print: (string) => txtdiv.textContent += string
24 document
.addEventListener('keydown', (event
) => {
25 console
.log(`keydown: ${event.key}`)
26 if (event
.key
!= "F5") {
27 event
.preventDefault()
28 event
.stopPropagation()
31 txtdiv
= document
.createElement("div")
32 document
.body
.appendChild(txtdiv
)
35 txtdiv
= document
.createElement("div")
36 document
.body
.appendChild(txtdiv
)
39 stdin
= stdin
.substring(0, stdin
.length
- 1)
40 txtdiv
.textContent
= txtdiv
.textContent
.substring(0, txtdiv
.textContent
.length
- 1)
43 if (event
.key
.length
== 1) {
45 output
.print(event
.key
)
53 read
: (writeAddr
, maxBytes
) => {
54 const maxChars
= maxBytes
>> 1
55 const bufView
= new Uint16Array(wasmMem
.buffer
, writeAddr
, maxChars
)
57 for (i
= 0; i
< maxChars
&& i
< stdin
.length
; i
++)
58 bufView
[i
] = stdin
.charCodeAt(i
)
59 stdin
= stdin
.substring(maxChars
)
62 write
: (readAddr
, maxBytes
) =>
63 output
.print(String
.fromCharCode
.apply(
65 new Uint16Array(wasmMem
.buffer
, readAddr
, maxBytes
>> 1)
111 'EXECUTE-MODE': 16680,
117 pop
: () => simstack
.pop(),
118 push
: (val
) => simstack
.push(val
),
119 rinit
: () => rstack
.length
= 0,
120 rpop
: () => rstack
.pop(),
121 rpush
: (val
) => rstack
.push(val
),
122 sys_write
: (channel
, addr
, u
) => {
123 if (channels
[channel
] === undefined)
125 console
.log(`write ch:${channel} addr:${addr} len:${u}`)
126 channels
[channel
].write(addr
, u
)
128 sys_read
: (channel
, toBuffer
) => {
129 console
.log(`read ch:${channel} buf:${toBuffer} current: ${stdin}`)
130 const lenView
= new DataView(wasmMem
.buffer
, toBuffer
, 8)
131 const maxBytes
= lenView
.getUint32(0,true)
132 console
.log(`read blen:${lenView.getUint32(0,true)} cstrlen:${lenView.getUint32(4,true)}`)
133 /* If the channel is undefined, or if there isn't enough room in
134 * toBuffer for even one character, then, if there is enough
135 * room for an int write a zero, exit */
136 if (channels
[channel
] === undefined || maxBytes
< 6) {
138 lenView
.setUint32(4,0,true)
140 const numBytes
= channels
[channel
].read(toBuffer
+ 8, maxBytes
- 4)
141 lenView
.setUint32(4,numBytes
,true);
142 console
.log(`read wrote ${lenView.getUint32(4,true)} bytes, remainder: ${stdin}`)
143 console
.log(`read blen:${lenView.getUint32(0,true)} cstrlen:${lenView.getUint32(4,true)}`) },
144 sys_listen
: (reqAddr
, cbAddr
) => {
145 //TODO: call into the module to wasm fn "event" to push an event
146 //to forth, which pushes esi to the return stack and queues the
147 //callback function provided from listen. reqaddr could be
148 //"fetch", in which case no channel is used. otherwise very
149 //similar to sys_fetch.
151 sys_fetch
: (channel
, reqAddr
) => {
152 //TODO: map to fetch promise, write to channel buffer,
153 //javascript "fetch" as fallback, explicit handles for
154 //"textEntry" or any third party protocols like activitypub
155 console
.log(`fetch ${channel} ${reqAddr}`)
157 sys_echo
: (val
) => output
.print(`${val} `),
158 sys_echochar
: (val
) => output
.print(String
.fromCharCode(val
)),
159 sys_reflect
: (addr
) => {
160 console
.log(`reflect: ${addr}: ${
161 new DataView(wasmMem.buffer, addr, 4)
165 vocab_get
: (addr
, u
) => {
166 const word
= String
.fromCharCode
.apply(
168 new Uint16Array(wasmMem
.buffer
, addr
, u
>> 1)
170 const answer
= dictionary
[word
.toUpperCase()]
171 console
.log(`vocab_get ${word}: ${answer}`)
172 if (answer
=== undefined)
176 vocab_set
: (addr
, u
, num
) => {
177 console
.log(`vocab set ${addr} ${u} ${num}`)
178 const word
= String
.fromCharCode
.apply(
180 new Uint16Array(wasmMem
.buffer
, addr
, u
>> 1)
182 console
.log(`vocab_set ${word}: ${num}`)
183 dictionary
[word
.toUpperCase()] = num
186 is_whitespace
: (key
) => /\s/.test(String
.fromCharCode(key
)),
187 sys_stack
: () => console
.log(`[${simstack}]`),
188 sys_parsenum
: (addr
, u
, base
) => {
189 const word
= String
.fromCharCode
.apply(
191 new Uint16Array(wasmMem
.buffer
, addr
, u
>> 1)
193 const answer
= Number
.parseInt(word
, base
)
194 console
.log(`parsenum: ${addr} ${u} ${base}`)
195 console
.log(`parsenum: ${word} ${answer}`)
196 console
.log(`parsenum: ${Number.isNaN(answer)}`)
197 if (Number
.isNaN(answer
))
199 new DataView(wasmMem
.buffer
, addr
, 4).setUint32(0,answer
,true)
203 output
.print(Object
.getOwnPropertyNames(dictionary
).toString().split(',').join(' '))
208 fetch('forth.forth').then((re
) => re
.text()).then((txt
) => {
211 .then(re
=> re
.arrayBuffer())
212 .then(buf
=> WebAssembly
.instantiate(buf
, wasmImport
))
214 wasmMem
= result
.instance
.exports
.memory
215 forth
= result
.instance
.exports
.main
216 console
.log('wasm loaded');