All Projects → remko → Waforth

remko / Waforth

Licence: mit
A bootstrapping dynamic Forth Interpreter/Compiler for WebAssembly

Programming Languages

forth
179 projects

Projects that are alternatives of or similar to Waforth

Binaryen
Compiler infrastructure and toolchain library for WebAssembly
Stars: ✭ 5,294 (+2907.95%)
Mutual labels:  compilers, webassembly
Wasm Micro Runtime
WebAssembly Micro Runtime (WAMR)
Stars: ✭ 2,440 (+1286.36%)
Mutual labels:  webassembly
Docs
📖 Documentation for Windi CSS
Stars: ✭ 145 (-17.61%)
Mutual labels:  compilers
Fshistory
Play and Enjoy the History of Microsoft Flight Simulator
Stars: ✭ 163 (-7.39%)
Mutual labels:  webassembly
Crosswindow
💻📱 A cross platform system abstraction library written in C++ for managing windows and performing OS tasks.
Stars: ✭ 155 (-11.93%)
Mutual labels:  webassembly
Logging
Microsoft Extension Logging implementation for Blazor
Stars: ✭ 165 (-6.25%)
Mutual labels:  webassembly
Pychat
webchat via WebSockets/WebRTC that allows messaging/video call/screen sharing
Stars: ✭ 152 (-13.64%)
Mutual labels:  webassembly
Serde Wasm Bindgen
Native integration of Serde with wasm-bindgen
Stars: ✭ 176 (+0%)
Mutual labels:  webassembly
Vecty
Vecty lets you build responsive and dynamic web frontends in Go using WebAssembly, competing with modern web frameworks like React & VueJS.
Stars: ✭ 2,161 (+1127.84%)
Mutual labels:  webassembly
Pytket
Python module for interfacing with the CQC t|ket> library of quantum software
Stars: ✭ 162 (-7.95%)
Mutual labels:  compilers
Opus Media Recorder
MediaRecorder polyfill for Opus recording using WebAssembly
Stars: ✭ 159 (-9.66%)
Mutual labels:  webassembly
Esm Integration
ECMAScript module integration
Stars: ✭ 157 (-10.8%)
Mutual labels:  webassembly
S3m Spec
Stars: ✭ 165 (-6.25%)
Mutual labels:  webassembly
Blazor Samples
Explore and learn Syncfusion Blazor components using large collection of demos, example applications and tutorial samples
Stars: ✭ 156 (-11.36%)
Mutual labels:  webassembly
Carton
📦 Watcher, bundler, and test runner for your SwiftWasm apps
Stars: ✭ 171 (-2.84%)
Mutual labels:  webassembly
Duet
A tiny language, a subset of Haskell aimed at aiding teachers teach Haskell
Stars: ✭ 155 (-11.93%)
Mutual labels:  compilers
Wain
WebAssembly implementation from scratch in Safe Rust with zero dependencies
Stars: ✭ 160 (-9.09%)
Mutual labels:  webassembly
Wasm Pdf
Generate PDF files with JavaScript and WASM (WebAssembly)
Stars: ✭ 163 (-7.39%)
Mutual labels:  webassembly
Alchemyvm
WebAssembly Virtual Machine Built In Elixir
Stars: ✭ 176 (+0%)
Mutual labels:  webassembly
Edit Text
Collaborative rich text editor for the web. Written in Rust + WebAssembly.
Stars: ✭ 171 (-2.84%)
Mutual labels:  webassembly

WAForth: Forth Interpreter+Compiler for WebAssembly

WAForth is a bootstrapping Forth interpreter and dynamic compiler for WebAssembly. You can see it in a demo here.

It is entirely written in (raw) WebAssembly, and the compiler generates WebAssembly code on the fly. The only parts for which it relies on external (JavaScript) code is to dynamically load modules (since WebAssembly doesn't support JIT yet), and the I/O primitives to read and write a character to a screen.

Parts of the implementation were influenced by jonesforth.

WAForth is still in an experimental stage. It implements most of the ANS Core Words, and passes most of the Forth 200x Test Suite core word tests.

Install Dependencies

The build uses the WebAssembly Binary Toolkit for converting raw WebAssembly text format into the binary format, and Yarn for managing the dependencies of the shell.

brew install wabt yarn
yarn

Building & Running

To build everything:

make

To run the development server:

make dev-server

Testing

The tests are served from /tests by the development server.

You can also run the tests in Node.JS by running

make check

Design

The WAForth core is written as a single module in WebAssembly's text format.

The Interpreter

The interpreter runs a loop that processes commands, and switches to and from compiler mode.

Contrary to some other Forth systems, this system doesn't use direct threading for executing code. WebAssembly doesn't allow unstructured jumps, let alone dynamic jumps. Instead, WAForth uses subroutine threading, where each word is implemented as a single WebAssembly function, and the system uses calls and indirect calls (see below) to execute words.

The Compiler

While in compile mode for a word, the compiler generates WebAssembly instructions in binary format (since there is no assembler infrastructure in the browser). Since WebAssembly doesn't support JIT compilation yet, a finished word is bundled into a separate binary WebAssembly module, and sent to the loader, which dynamically loads it and registers it with a shared function table at the next offset, which in turn is recorded in the word dictionary.

Because words reside in different modules, all calls to and from the words need to happen as indirect call_indirect calls through the shared function table. This of course introduces some overhead, although it appears limited.

As WebAssembly doesn't support unstructured jumps, control flow words (IF/ELSE/THEN, LOOP, REPEAT, ...) can't be implemented in terms of more basic words, unlike in jonesforth. However, since Forth only requires structured jumps, the compiler can easily be implemented using the loop and branch instructions available in WebAssembly.

Finally, the compiler adds minimal debug information about the compiled word in the name section, making it easier for doing some debugging in the browser.

Debugger view of a compiled word

The Loader

The loader is a small bit of JavaScript that uses the WebAssembly JavaScript API to dynamically load a compiled word (in the form of a WebAssembly module), and ensuring that the shared function table is large enough for the module to register itself.

The Shell

The shell is a JavaScript class that wraps the WebAssembly module, and loads it in the browser. It provides the I/O primitives to the WebAssembly module to read and write characters to a terminal, and externally provides a run() function to execute a fragment of Forth code.

To tie everything together into an interactive system, there's a small console-based interface around this shell to type Forth code, which you can see in action here.

WAForth Console

Misc notes

  • The exposed return stack isn't used. Control flow is kept implicitly in the code (e.g. through branches, indirect calls, ...). This also means that control flow can't be influenced by code.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].