Monorepo for Aesthetic.Computer aesthetic.computer
at main 45 lines 1.5 kB view raw
1#!/usr/bin/env node 2// Render KidLisp pieces to PNG via self-contained WASM. 3 4import { readFileSync, mkdirSync } from "fs"; 5import { basename } from "path"; 6import sharp from "sharp"; 7import { Compiler } from "./compiler.mjs"; 8 9const OUT_DIR = new URL("./output/", import.meta.url).pathname; 10mkdirSync(OUT_DIR, { recursive: true }); 11 12const pieces = process.argv.slice(2); 13if (pieces.length === 0) pieces.push("hello.lisp"); 14 15const WIDTH = 256; 16const HEIGHT = 256; 17 18for (const input of pieces) { 19 const path = new URL(input, import.meta.url).pathname; 20 const source = readFileSync(path, "utf-8"); 21 const name = basename(input, ".lisp"); 22 23 const compiler = new Compiler(); 24 const wasmBytes = compiler.compile(source); 25 const mathImports = { 26 math: { 27 sin: (x) => Math.fround(Math.sin(x)), 28 cos: (x) => Math.fround(Math.cos(x)), 29 random: () => Math.fround(Math.random()), 30 }, 31 }; 32 const { instance } = await WebAssembly.instantiate(wasmBytes, mathImports); 33 instance.exports.paint(WIDTH, HEIGHT, 0); 34 35 const mem = new Uint8Array(instance.exports.memory.buffer); 36 const pixels = mem.slice(0, WIDTH * HEIGHT * 4); 37 38 const png = await sharp(Buffer.from(pixels), { 39 raw: { width: WIDTH, height: HEIGHT, channels: 4 }, 40 }).png().toBuffer(); 41 42 const outPath = `${OUT_DIR}${name}.png`; 43 await sharp(png).toFile(outPath); 44 console.log(`${name}.png (${WIDTH}x${HEIGHT}, ${wasmBytes.length}B wasm → ${png.length}B png)`); 45}