feat: first working version with parameters

This commit is contained in:
2024-04-15 18:46:34 +02:00
parent e29cb11b81
commit 0254bc1ae5
45 changed files with 389 additions and 351 deletions

View File

@ -12,7 +12,6 @@
if (registerIndex > $sizes.length) {
$sizes = [...$sizes, "1fr"];
}
console.log("registering cell", registerIndex);
return index;
});

View File

@ -1,5 +1,20 @@
import { expect, test } from 'vitest'
import { decode, encode } from './flat_tree'
import { decode, encode, concat_encoded } from './flat_tree'
test("it correctly concats nested arrays", () => {
const input_a = encode([1, 2, 3]);
const input_b = 2;
const input_c = encode([4, 5, 6]);
const output = concat_encoded([input_a, input_b, input_c]);
const decoded = decode(output);
expect(decoded[0]).toEqual([1, 2, 3]);
});
// Original test case
test('it correctly decodes/encodes complex nested arrays', () => {
@ -55,7 +70,7 @@ test('it correctly handles sequential nesting', () => {
// If not, you can ignore or remove this test.
test('it correctly handles arrays with mixed data types', () => {
const input = [1, 'text', [true, [null, ['another text']]]];
// @ts-ignore
//@ts-ignore
const decoded = decode(encode(input));
expect(decoded).toEqual(input);
});

View File

@ -1,5 +1,34 @@
type SparseArray<T = number> = (T | T[] | SparseArray<T>)[];
export function concat_encoded(input: (number | number[])[]): number[] {
if (input.length === 1 && Array.isArray(input[0])) {
return input[0]
}
const result = [0, 1]; // opening bracket
let last_closing_bracket = 1;
for (let i = 0; i < input.length; i++) {
const item = input[i];
if (Array.isArray(item)) {
result.push(...item);
if (item.length > 2) {
if (item[item.length - 2] !== 1 && item[item.length - 1] !== 1) {
result.push(1, 1); // add closing bracket if missing
}
}
last_closing_bracket = result.length - 1;
} else {
result[last_closing_bracket]++;
result.push(item);
}
}
return result
}
// Encodes a nested array into a flat array with bracket and distance notation
export function encode(array: SparseArray): number[] {
const encoded = [0, 0]; // Initialize encoded array with root bracket notation
@ -16,7 +45,7 @@ export function encode(array: SparseArray): number[] {
} else {
// Recursively encode non-empty arrays
const child = encode(item);
encoded.push(...child, 1, 0); // Note: The trailing comma after 0 can be removed
encoded.push(...child, 1, 0);
}
// Update missingBracketIndex to the position of the newly added bracket
missingBracketIndex = encoded.length - 1;

View File

@ -19,7 +19,7 @@ const nodeTypes: NodeType[] = [
"b": { type: "float" },
},
outputs: ["float"],
execute: (op_type: number, a: number, b: number) => {
execute: ([op_type, a, b]: number[]) => {
switch (op_type) {
case 0: return a + b;
case 1: return a - b;
@ -47,39 +47,49 @@ export class RemoteNodeRegistry implements NodeRegistry {
constructor(private url: string) { }
private async loadNode(id: string) {
const nodeUrl = `${this.url}/n/${id}`;
const response = await fetch(nodeUrl);
const wasmResponse = await fetch(`${nodeUrl}/wasm`);
const wrapperReponse = await fetch(`${nodeUrl}/wrapper`);
if (!wrapperReponse.ok) {
this.status = "error";
throw new Error(`Failed to load node ${id}`);
}
let wrapperCode = await wrapperReponse.text();
wrapperCode = wrapperCode.replace("wasm = val;", `if(wasm) return;
wasm = val;`);
const wasmWrapper = await import(/*@vite-ignore*/`data:text/javascript;base64,${btoa(wrapperCode)}#${id}`);
const module = new WebAssembly.Module(await wasmResponse.arrayBuffer());
const instance = new WebAssembly.Instance(module, { ["./index_bg.js"]: wasmWrapper });
wasmWrapper.__wbg_set_wasm(instance.exports);
if (!response.ok) {
this.status = "error";
throw new Error(`Failed to load node ${id}`);
} else {
log.log("loaded node", id);
}
const node = await response.json();
node.execute = wasmWrapper.execute;
return node;
}
async load(nodeIds: string[]) {
const a = performance.now();
nodeIds.push("max/plantarium/random");
nodeIds.push("max/plantarium/float");
nodeIds.push("max/plantarium/output");
nodeIds.push("max/plantarium/array");
nodeIds.push("max/plantarium/sum");
for (const id of nodeIds) {
const nodeUrl = `${this.url}/n/${id}`;
const response = await fetch(nodeUrl);
const wasmResponse = await fetch(`${nodeUrl}/wasm`);
const wrapperReponse = await fetch(`${nodeUrl}/wrapper`);
if (!wrapperReponse.ok) {
this.status = "error";
throw new Error(`Failed to load node ${id}`);
}
const nodes = await Promise.all(nodeIds.map(id => this.loadNode(id)));
let wrapperCode = await wrapperReponse.text();
wrapperCode = wrapperCode.replace("wasm = val;", `if(wasm) return;
wasm = val;`);
const wasmWrapper = await import(/*@vite-ignore*/`data:text/javascript;base64,${btoa(wrapperCode)}`);
const module = new WebAssembly.Module(await wasmResponse.arrayBuffer());
const instance = new WebAssembly.Instance(module, { ["./index_bg.js"]: wasmWrapper });
wasmWrapper.__wbg_set_wasm(instance.exports);
if (!response.ok) {
this.status = "error";
throw new Error(`Failed to load node ${id}`);
}
const node = await response.json();
node.execute = wasmWrapper.execute;
this.nodes.set(id, node);
for (const node of nodes) {
this.nodes.set(node.id, node);
}
const duration = performance.now() - a;

View File

@ -1,4 +1,6 @@
import type { Graph, NodeRegistry, NodeType, RuntimeExecutor } from "@nodes/types";
import { encodeFloat } from "./helpers/encode";
import { concat_encoded, encode } from "./helpers/flat_tree";
export class MemoryRuntimeExecutor implements RuntimeExecutor {
@ -140,15 +142,21 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
// execute the node and store the result
try {
const node_inputs = Object.entries(inputs);
const transformed_inputs = node_inputs.map(([key, value]) => {
const input_type = node_type.inputs[key];
if (input.type === "float") {
return
const transformed_inputs = node_inputs.map(([key, value]: [string, any]) => {
const input_type = node_type.inputs?.[key]!;
if (value instanceof Int32Array) {
return [...value.slice(0, value.length)];
}
console.log(key, input_type);
if (input_type.type === "float") {
return encode(encodeFloat(value as number));
}
return value;
});
console.log(`Executing node ${node_type.id || node.id}`, node_inputs);
results[node.id] = node_type.execute(...Object.values(inputs)) as number;
const _inputs = concat_encoded(transformed_inputs);
// console.log(`Executing node ${node_type.id || node.id}`, { _inputs, inputs, node_type });
results[node.id] = node_type.execute(_inputs) as number;
// console.log("--> result", results[node.id]);
} catch (e) {
console.error(`Error executing node ${node_type.id || node.id}`, e);
}
@ -159,7 +167,6 @@ export class MemoryRuntimeExecutor implements RuntimeExecutor {
// return the result of the parent of the output node
const res = results[outputNode.id] as string
return res;
}