# Wipforth Wipforth is a Forth implementation that runs in the WebAssembly virtual machine. The system is bootstrapped from source on page load: the only non-text file is the favicon :) I/O is done via memory-mapped peripherals, which are emulated in JavaScript. - For the Forth kernel, see [wipforth.ws](./wipforth.ws) - For the emulator, see [emu.js](./emu.js) - For the assembler, see [asm.js](./asm.js) - For the prelude (Forth code loaded right after the kernel boots), see [prelude.f](./prelude.f) - For a description of the peripherals, see the [Peripherals](#peripherals) section below. ## Building and Running Locally There's a [Guile](https://www.gnu.org/software/guile/) script in the repo you can use for this: ``` guile server.scm ``` You should then be able to open in a browser and use the system from there. However, since everything is bootstrapped on the client, basically any HTTP server will do as long as it sets the appropriate response headers for `SharedArrayBuffer` use: - `Cross-Origin-Opener-Policy: same-origin` - `Cross-Origin-Embedder-Policy: require-corp` So, if you don't have Guile on your system you can use something else like Python's `http.server`. **NOTE**: You should **definitely not** use `server.scm` to serve the application on the open internet or anything like that; I just hacked it together for testing on localhost during development and it's probably hilariously insecure. ## End-to-End Tests There's a (fairly minimal at the moment) end-to-end test suite defined in [tests.scm](./tests.scm). To run it you'll need: - [Guile](https://www.gnu.org/software/guile/) again (no substitute this time, sorry) - [guile-json](https://github.com/aconchillo/guile-json) - Firefox I'm also pretty sure it won't work on a non-POSIX system, though I haven't tried it. Given that's all sorted, you should be able to run: ``` guile tests.scm ``` It will print a JUnit XML report to standard out. You can pretty-print it with `xmllint` if you have it installed: ``` guile tests.scm | xmllint --format - ``` ## Peripherals ### Terminal | Name | Address | Size / B | Access | |--------|---------|----------|--------------| | TXBUF | 000h | 32 | write | | RXBUF | 080h | 32 | read | | TXHEAD | 100h | 4 | atomic read | | TXTAIL | 104h | 4 | atomic write | | RXHEAD | 108h | 4 | atomic write | | RXTAIL | 10Ch | 4 | atomic read | For both sending (`TX`) and receiving (`RX`), there are three registers: `xBUF`, `xHEAD` and `xTAIL`: - `xBUF` registers are 128-byte FIFO ring buffers used for data - The `xHEAD` and `xTAIL` registers specify the start and end of data in the ring buffer, `xHEAD` being the offset of the first byte of data, and `xTAIL` being the offset of the first byte *after* the data. In order to be distinguishable from the empty state, the ring buffers must never be completely full -- there must always be *at least one* unoccupied byte between the tail and the head. ### System status | Name | Address | Size / B | Access | |----------|---------|----------|--------------| | SYSREADY | 110h | 4 | atomic write | | SYSINTER | 114h | 4 | atomic read | The `SYSREADY` register is used to indicate when the system has booted up and is ready for user input. `SYSINTER` is set (and notified on) once the emulator has enabled user input and the system is interactive.