Multiple implementations (JS, Wasm, C) of a Lisp.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
4.0 KiB

function testFloats() {
const nums = new Array(100_00).fill(0).map(_ => Math.random());
const strings = nums.map(num => num.toString());
const indexes = strings.map(num => {
const str = new TextEncoder().encode(num);
const index = instance.exports.alloc(str.length);
for (let i = 0; i < str.length; i++) {
buffer[index + i] = str[i];
}
return {index, length: str.length};
});
let start = Date.now();
for (let i = 0; i < indexes.length; i++) {
const buf = indexes[i];
const result = instance.exports.parse_float(buf.index, buf.length);
}
let end = Date.now();
console.log(`WASM elasped: ${end - start}`);
for (let i = 0; i < indexes.length; i++) {
const buf = indexes[i];
instance.exports.free(buf.index, buf.length);
}
start = Date.now();
for (let i = 0; i < strings.length; i++) {
const result = parseFloat(strings[i]);
}
end = Date.now();
console.log(`JS elasped: ${end - start}`);
}
async function main() {
// WASM
// const response = await fetch('./lisp.wasm');
// const bytes = await response.arrayBuffer();
var fs = require('fs');
const bytes = await fs.readFileSync('./lisp.wasm')
const results = await WebAssembly.instantiate(bytes, {
env: {
jsprint: (byteOffset) => {
let s = '';
const a = new Uint8Array(memory.buffer);
for (var i = byteOffset; a[i]; i++) {
s += String.fromCharCode(a[i]);
}
console.log(s)
}
}
});
const instance = results.instance;
const memory = instance.exports.pagememory;
const buffer = new Uint8Array(memory.buffer);
// const str = new TextEncoder().encode('(let ((a 1) (b 2) (c (+ 1 a))) (+ a b c))\0');
// const str = new TextEncoder().encode(`
// (set-macro-character #\\' (fn (c) (list (quote quote) (read))))
// (car (list 1 2))
// \0`);
const str = new TextEncoder().encode(`
(set-macro-character #\\' (fn (c) (list (quote quote) (read))))
(defmacro defn (name args &body body) (list def name (cons fn (cons args body))))
(defn reverse (lst)
(let ((lp (fn (lst rslt)
(if (car lst)
(lp (cdr lst) (cons (car lst) rslt))
rslt))))
(lp lst nil)))
(defn map (lst f)
(let ((lp
(fn (lst rslt)
(if (car lst)
(lp (cdr lst) (cons (f (car lst)) rslt))
rslt))))
(reverse (lp lst nil))))
(set-macro-character #\\\` (fn (c) (list (quote quote) (read))))
(defn fact (n)
(if (= n 0)
1
(* n (fact (- n 1)))))
(fact 6)
(defn fact* (n)
(let ((i 0) (fact 1))
(loop (if (= i n) break)
(set i (+ i 1))
(set fact (* fact i)))
fact))
(fact* 6)
(defn fact** (n)
(let ((fact-tail (fn (n fact)
(if (<= n 1)
fact
(fact-tail (- n 1) (* n fact))))))
(fact-tail n 1)))
(fact** 6)
(defn fact*** (n)
(let ((fact 1))
(loop (if (<= n 1) break)
(set fact (* fact n))
(set n (- n 1)))
fact))
(fact*** 6)
(let ((count 0))
(loop (set count (+ count 1))
(print count)
(if (>= count 5) break nil)))
\0`);
// const str = new TextEncoder().encode('+');
const index = instance.exports.alloc(str.length);
for (let i = 0; i < str.length; i++) {
buffer[index + i] = str[i];
}
let result = 0;
try {
result = instance.exports.rep(index);
} catch(e) {
console.error(e);
result = instance.exports.outputStream();
}
let print = '';
for (let i = 0, c = buffer[result + i];
c != 0;
i++, c = buffer[result + i]){
print += String.fromCharCode(c);
}
console.log(print);
let string = '';
let dept = 64;
for (let i = 0; i < dept; i += 4) {
// string += `0x${buffer[i].toString(16)} `;
for (let col = 0; col < 4; col++) {
string += `${i + col * dept}:\t`;
for (let x = 0; x < 4; x++) {
string += ` ${buffer[i + x + col * dept].toString(16).padStart(2, '0').toUpperCase()}`;
}
string += '\t';
}
string += '\n';
}
// console.log(string);
//instance.exports.helloworld();
// console.log(instance.exports.align(parseInt(process.argv[2]), 8));
}
main();