1 stable release
| 2024.0.0 | Feb 24, 2026 |
|---|
#446 in Programming languages
82KB
2.5K
SLoC
wasc - WebAssembly Single-file Compiler
A C-like language compiler specifically designed for WebAssembly with first-class support for references, tables, and direct memory management.
Features
- C-like syntax - Familiar to C programmers
- First-class externref and funcref types - Easy interop with JavaScript
- Direct memory and table management - Explicit control over WASM resources
- Zero-overhead external function calls - Import and call JS functions directly
- No standard library - You control everything, no hidden overhead
- Single-file implementation - The entire compiler is in one Rust file
Usage
wasc <input.wasc> [options]
Options:
-o, --output <file> Output file (default: input.wasm)
-v, --verbose Verbose output
-h, --help Show this help
Example
// Declare memory
memory 1;
// Declare table for function references
table funcref 10;
// Import external JS function
extern i32 js_add(i32 a, i32 b);
// Simple function
export i32 add(i32 a, i32 b) {
return a + b;
}
// Main entry point
export i32 main() {
i32 x = 10;
i32 y = 32;
return add(x, y);
}
Compile:
wasc example.wasc -o example.wasm
Language Features
Types
void- No return valuei32,i64- Integer typesf32,f64- Floating point typesexternref- External reference (JS objects, etc.)funcref- Function reference for indirect calls
Memory
memory 1; // 1 page (64KB)
memory 1, 10; // Min 1 page, max 10 pages
memory 1 shared; // Shared memory for threads
Tables
table funcref 10; // Table of function references
table funcref 10, 100; // Min 10, max 100
table externref 64; // Table of external references
Imports
extern externref console_log(externref msg);
extern i32 js_add(i32 a, i32 b);
extern void do_something();
Exports
export i32 main() {
return 42;
}
Variables and Assignment
i32 x = 10;
i32 y;
y = 20;
externref obj = ref.null externref;
Control Flow
if (x > 0) {
return x;
} else {
return 0;
}
while (i < 10) {
i = i + 1;
}
for (i32 i = 0; i < 10; i = i + 1) {
// loop body
}
return 42;
Reference Operations
// Create null reference
externref null_ref = ref.null externref;
// Check if null
if (ref.is_null(null_ref)) {
return 1;
}
// Get function reference
funcref my_func = &add;
// Table operations
table[0] = &my_callback;
funcref callback = table[0];
Operators
- Arithmetic:
+,-,*,/,% - Comparison:
==,!=,<,>,<=,>= - Logical:
&&,||,! - Bitwise:
&,|,^,~,<<,>>
Building
cargo build --release
The binary will be at target/release/wasc.
WebAssembly Output
The compiler generates valid WebAssembly binary format that can be run in browsers, Node.js, or other WASM runtimes.
Example JavaScript usage:
const wasmModule = await WebAssembly.instantiateStreaming(
fetch("example.wasm"),
{
env: {
js_add: (a, b) => a + b,
memory: new WebAssembly.Memory({ initial: 1 })
}
}
);
const result = wasmModule.instance.exports.main();
console.log(result); // 42
Architecture
The compiler consists of three main parts:
- Lexer - Tokenizes the source code into tokens
- Parser - Builds an AST from the tokens
- Code Generator - Emits WebAssembly binary code
All implemented in a single Rust file with no_std support for minimal dependencies.
License
MIT License - See LICENSE file for details
Dependencies
~150KB