rename crates/ to engrams/; add el-compiler el package with bootstrap artifact
- crates/ → engrams/ (Rust engrams live here)
- el-compiler/ added: el self-hosting compiler as an el package
- src/{compiler,lexer,parser,codegen}.el
- bootstrap/el-compiler.elc (114KB, Rust-compiled seed)
- el.toml Cargo.toml workspace paths updated
- neuron-rs cross-repo path deps fixed (were pointing to products/ instead of foundation/)
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Neuron",
|
||||
"short_name": "Neuron",
|
||||
"description": "Neuron — AI companion powered by el",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#0a0a0f",
|
||||
"theme_color": "#6c7fff",
|
||||
"orientation": "portrait-primary",
|
||||
"icons": [
|
||||
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any maskable" },
|
||||
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }
|
||||
],
|
||||
"categories": ["productivity", "utilities"],
|
||||
"lang": "en-US"
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Engram-lang WASM runtime loader
|
||||
// Include this in any web app to run .el programs natively in the browser.
|
||||
//
|
||||
// Usage:
|
||||
// import { initRuntime, runElc, evalSource } from '/js/runtime.js';
|
||||
//
|
||||
// await initRuntime();
|
||||
// const result = await runElc('/programs/main.elc');
|
||||
|
||||
let wasmModule = null;
|
||||
|
||||
/**
|
||||
* Initialise the el WASM runtime. Safe to call multiple times —
|
||||
* subsequent calls return the already-loaded module immediately.
|
||||
*
|
||||
* @param {string} wasmUrl - Path to the .wasm file (default: /pkg/el_wasm_bg.wasm)
|
||||
* @returns {Promise<object>} The loaded runtime API
|
||||
*/
|
||||
export async function initRuntime(wasmUrl = '/pkg/el_wasm_bg.wasm') {
|
||||
if (wasmModule) return wasmModule;
|
||||
|
||||
const { default: init, compile_source, load_and_run, eval: elEval, version } =
|
||||
await import('/pkg/el_wasm.js');
|
||||
|
||||
await init(wasmUrl);
|
||||
|
||||
wasmModule = { compile_source, load_and_run, eval: elEval, version };
|
||||
console.log(`el WASM runtime v${version()} loaded`);
|
||||
return wasmModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a pre-compiled .elc file from the server and execute it.
|
||||
*
|
||||
* The browser caches the .elc file automatically based on Cache-Control
|
||||
* headers set by the server. New bytecode is available immediately on the
|
||||
* next fetch — no app-store review required.
|
||||
*
|
||||
* @param {string} elcUrl - URL of the .elc bytecode file
|
||||
* @returns {Promise<any>} The JSON-deserialised result value
|
||||
*/
|
||||
export async function runElc(elcUrl) {
|
||||
const rt = await initRuntime();
|
||||
const response = await fetch(elcUrl);
|
||||
if (!response.ok) throw new Error(`Failed to fetch ${elcUrl}: ${response.status}`);
|
||||
const bytes = new Uint8Array(await response.arrayBuffer());
|
||||
return JSON.parse(rt.load_and_run(bytes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile el source and run it immediately. Useful for REPL and
|
||||
* developer-mode execution where source is available at runtime.
|
||||
*
|
||||
* @param {string} source - Engram-lang source code
|
||||
* @returns {Promise<any>} The JSON-deserialised result value
|
||||
*/
|
||||
export async function evalSource(source) {
|
||||
const rt = await initRuntime();
|
||||
return JSON.parse(rt.eval(source));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile el source to bytecode bytes without running it.
|
||||
* The returned Uint8Array can be stored or uploaded as a .elc file.
|
||||
*
|
||||
* @param {string} source - Engram-lang source code
|
||||
* @returns {Promise<Uint8Array>} Compiled bytecode bytes
|
||||
*/
|
||||
export async function compileSource(source) {
|
||||
const rt = await initRuntime();
|
||||
return rt.compile_source(source);
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
// Service worker for the Neuron PWA powered by el.
|
||||
//
|
||||
// Caching strategy:
|
||||
// /pkg/ — WASM runtime files, cache-first (content-addressed, change on version bump)
|
||||
// *.elc — compiled bytecode, stale-while-revalidate (instant load, background update)
|
||||
//
|
||||
// The WASM runtime is fetched once and cached indefinitely.
|
||||
// Engram programs (.elc) are served from cache immediately, then refreshed in
|
||||
// the background so the next load gets the newest version — no user action needed.
|
||||
|
||||
const CACHE_NAME = 'engram-v1';
|
||||
const WASM_CACHE = 'engram-wasm-v1';
|
||||
|
||||
// Files to pre-cache during service worker installation.
|
||||
const PRECACHE = [
|
||||
'/pkg/el_wasm_bg.wasm',
|
||||
'/pkg/el_wasm.js',
|
||||
];
|
||||
|
||||
self.addEventListener('install', event => {
|
||||
event.waitUntil(
|
||||
caches.open(WASM_CACHE).then(cache => cache.addAll(PRECACHE))
|
||||
);
|
||||
// Take control immediately — don't wait for existing tabs to close.
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', event => {
|
||||
const url = new URL(event.request.url);
|
||||
|
||||
// WASM runtime files: cache-first.
|
||||
// These are large and rarely change; the version bump forces a new URL.
|
||||
if (url.pathname.startsWith('/pkg/')) {
|
||||
event.respondWith(
|
||||
caches.match(event.request).then(cached =>
|
||||
cached || fetch(event.request).then(response => {
|
||||
caches.open(WASM_CACHE).then(cache =>
|
||||
cache.put(event.request, response.clone())
|
||||
);
|
||||
return response;
|
||||
})
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Compiled bytecode (.elc): stale-while-revalidate.
|
||||
// Respond immediately from cache, update in background.
|
||||
if (url.pathname.endsWith('.elc')) {
|
||||
event.respondWith(
|
||||
caches.open(CACHE_NAME).then(async cache => {
|
||||
const cached = await cache.match(event.request);
|
||||
const fetchPromise = fetch(event.request).then(response => {
|
||||
cache.put(event.request, response.clone());
|
||||
return response;
|
||||
});
|
||||
return cached || fetchPromise;
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
self.addEventListener('activate', event => {
|
||||
// Purge old cache versions to reclaim storage.
|
||||
event.waitUntil(
|
||||
caches.keys().then(keys =>
|
||||
Promise.all(
|
||||
keys
|
||||
.filter(k => k !== CACHE_NAME && k !== WASM_CACHE)
|
||||
.map(k => caches.delete(k))
|
||||
)
|
||||
)
|
||||
);
|
||||
// Claim all clients immediately.
|
||||
self.clients.claim();
|
||||
});
|
||||
Reference in New Issue
Block a user