WebAssembly Integration Guide
AILANG can run entirely in the browser using WebAssembly, enabling interactive demonstrations and online playgrounds without requiring server-side execution.
Overview
The AILANG WebAssembly build provides:
- Full Language Support: Complete AILANG interpreter compiled to WASM
- Client-Side Execution: No server needed after initial load
- Small Bundle Size: ~5.7MB uncompressed (~1-2MB with gzip)
- React Integration: Ready-made component for easy integration
- Offline Capable: Works offline after first load
Quick Start
1. Build WASM Binary
cd ailang
make build-wasm
This produces bin/ailang.wasm
.
2. Integration Options
Option A: Docusaurus (Recommended)
- Copy assets:
cp bin/ailang.wasm docs/static/wasm/
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" docs/static/wasm/
cp web/ailang-repl.js docs/src/components/
cp web/AilangRepl.jsx docs/src/components/
- Add to
docusaurus.config.js
:
module.exports = {
scripts: [
{
src: '/wasm/wasm_exec.js',
async: false,
},
],
// ... rest of config
};
- Use in MDX:
---
title: Try AILANG
---
import AilangRepl from '@site/src/components/AilangRepl';
<AilangRepl />
Option B: Vanilla HTML
<!DOCTYPE html>
<html>
<head>
<title>AILANG REPL</title>
<script src="wasm_exec.js"></script>
<script src="ailang-repl.js"></script>
</head>
<body>
<div id="repl-container"></div>
<script>
const repl = new AilangREPL();
repl.init('/path/to/ailang.wasm').then(() => {
console.log('AILANG ready!');
// Evaluate expressions
const result = repl.eval('1 + 2');
console.log(result); // "3 :: Int"
});
</script>
</body>
</html>
Option C: React (Custom)
import { useEffect, useState } from 'react';
import AilangREPL from './ailang-repl';
export default function MyReplComponent() {
const [repl, setRepl] = useState(null);
const [result, setResult] = useState('');
useEffect(() => {
const replInstance = new AilangREPL();
replInstance.init('/wasm/ailang.wasm').then(() => {
setRepl(replInstance);
});
}, []);
const handleEval = (input) => {
if (repl) {
const output = repl.eval(input);
setResult(output);
}
};
return (
<div>
<input onKeyDown={(e) => {
if (e.key === 'Enter') handleEval(e.target.value);
}} />
<pre>{result}</pre>
</div>
);
}
JavaScript API
AilangREPL
Class
const repl = new AilangREPL();
Methods
init(wasmPath)
Initialize the WASM module.
await repl.init('/wasm/ailang.wasm');
Parameters:
wasmPath
(string): Path toailang.wasm
file
Returns: Promise that resolves when REPL is ready
eval(input)
Evaluate an AILANG expression.
const result = repl.eval('1 + 2');
// Returns: "3 :: Int"
Parameters:
input
(string): AILANG code to evaluate
Returns: Result string (includes value and type)
command(cmd)
Execute a REPL command.
const type = repl.command(':type \x. x');
// Returns: "\x. x :: a -> a"
Parameters:
cmd
(string): REPL command (e.g.,:type
,:help
)
Returns: Command output string
reset()
Reset the REPL environment.
repl.reset();
Returns: Status message
onReady(callback)
Register callback for when REPL is ready.
repl.onReady(() => {
console.log('REPL initialized!');
});
REPL Commands
The WebAssembly REPL supports the same commands as the CLI:
Command | Description |
---|---|
:help | Show available commands |
:type <expr> | Display expression type |
:instances | Show type class instances |
:reset | Clear environment |
Limitations
The browser version has these limitations compared to the CLI:
Feature | CLI | WASM |
---|---|---|
Expression evaluation | Yes | Yes |
Type inference | Yes | Yes |
Pattern matching | Yes | Yes |
Type classes | Yes | Yes |
File I/O (FS effect) | Yes | No |
Module imports | Yes | No |
History persistence | Yes | No |
Deployment
Static Hosting
WASM files work on any static host:
# Build and deploy
make build-wasm
cp bin/ailang.wasm your-site/static/wasm/
# Deploy your-site/ to Netlify/Vercel/GitHub Pages
CDN Optimization
- Enable Compression:
# nginx.conf
gzip_types application/wasm;
- Set Cache Headers:
location ~* \.wasm$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
- Use HTTP/2: WASM benefits from HTTP/2 multiplexing for faster loading.
Performance Tips
- Lazy Loading: Only load WASM when user navigates to playground
- Service Worker: Cache WASM for offline use
- CDN: Serve from edge locations
- Preload: Add
<link rel="preload" href="ailang.wasm" as="fetch">
CI/CD Integration
GitHub Actions
WASM is automatically built and released:
# .github/workflows/release.yml (excerpt)
- name: Build WASM binary
run: make build-wasm
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: bin/ailang-wasm.tar.gz
Docusaurus Deployment
WASM is included in documentation builds:
# .github/workflows/docusaurus-deploy.yml (excerpt)
- name: Build WASM binary
run: make build-wasm
- name: Copy static assets
run: |
cp bin/ailang.wasm docs/static/wasm/
cp web/ailang-repl.js docs/src/components/
Troubleshooting
"WebAssembly not supported"
Solution: Use a modern browser:
- Chrome 57+
- Firefox 52+
- Safari 11+
- Edge 16+
"Failed to load AILANG WASM"
Solutions:
- Check browser console for network errors
- Verify
ailang.wasm
path is correct - Ensure
wasm_exec.js
loaded first - Check CORS headers if serving from different domain
"REPL not initialized"
Solution: Wait for init()
promise or use onReady()
:
repl.init('/wasm/ailang.wasm').then(() => {
// Safe to use repl here
repl.eval('1 + 2');
});
Slow Loading
Solutions:
- Enable gzip compression (reduces to ~1-2MB)
- Use CDN
- Add preload hints:
<link rel="preload" href="/wasm/ailang.wasm" as="fetch" crossorigin>
Examples
See:
- Live Playground - Try it now
- Integration Example
- Component Source