72 lines
2.3 KiB
JavaScript
72 lines
2.3 KiB
JavaScript
import 'xterm/css/xterm.css'
|
|
import './app.css'
|
|
import { Terminal } from 'xterm'
|
|
import { Readline } from 'xterm-readline'
|
|
import init, { WasmCPU, NovaForth } from '../pkg/vweb.js'
|
|
|
|
const term = new Terminal()
|
|
const rl = new Readline()
|
|
const TIB = 80000 // Just a convenient place to stick a terminal input buffer for the repl. Could be any otherwise-unused address.
|
|
const OUT = 0x10000 // A place that NovaForth will use for its output buffer
|
|
let syms
|
|
|
|
term.loadAddon(rl)
|
|
term.open(document.getElementsByClassName('terminal')[0])
|
|
term.write('Loading...\r\n')
|
|
|
|
const handleKey = ({key, domEvent: { key: mnemonic }}) => {
|
|
if (mnemonic === 'Enter') {
|
|
console.log(mnemonic)
|
|
} else {
|
|
term.write(key)
|
|
}
|
|
}
|
|
|
|
init().then(async () => {
|
|
const cpu = new WasmCPU()
|
|
syms = JSON.parse(NovaForth.symbols()) // Grab the symbol table for the ROM so we can poke things by name
|
|
|
|
NovaForth.rom().forEach((byte, idx) => {
|
|
cpu.poke(0x400 + idx, byte)
|
|
})
|
|
|
|
term.write(`Loaded ${NovaForth.rom().length} bytes\r\n`)
|
|
NovaForth.prelude().split(/\n/).forEach((line) => {
|
|
const result = eval4th(cpu, line) // If there's anything wrong with the prelude, say so
|
|
if (result !== '') {
|
|
console.log(`Error with "${line}": ${result}`)
|
|
}
|
|
})
|
|
term.write(`Loaded NovaForth Prelude\r\n`)
|
|
document.getElementsByClassName('prelude')[0].appendChild(document.createTextNode(NovaForth.prelude()))
|
|
|
|
term.focus()
|
|
|
|
while (true) {
|
|
const line = await rl.read('> ') // Read the line of input
|
|
const str = eval4th(cpu, line) // Run it on the CPU
|
|
rl.println(str) // Println the result
|
|
}
|
|
})
|
|
|
|
function eval4th(cpu, line) {
|
|
// Copy the line to TIB and null-terminate it
|
|
for (let i = 0; i < line.length; i++) {
|
|
cpu.poke(TIB + i, line.charCodeAt(i))
|
|
}
|
|
cpu.poke(TIB + line.length, 0)
|
|
|
|
cpu.push_call(syms.stop) // Tell the CPU to stop once we're done
|
|
cpu.push_data(TIB) // Push the TIB and call eval
|
|
cpu.set_pc(syms.eval)
|
|
cpu.run() // Run it!
|
|
|
|
const len = cpu.peek24(syms.emit_cursor) // Find the length of the output
|
|
let str = '' // Copy the output from the memory to a JS string
|
|
for (let i = OUT; i < OUT + len; i++) {
|
|
str = str + String.fromCharCode(cpu.peek(i))
|
|
}
|
|
cpu.poke24(syms.emit_cursor, 0) // Re-clear the output buffer
|
|
|
|
return str
|
|
} |