Assemble kernel on the client #1

Merged
cdo merged 72 commits from client-side-assembler into main 2026-03-18 15:21:33 +00:00
Showing only changes of commit d35b13fed0 - Show all commits

89
asm.js
View File

@@ -97,6 +97,9 @@ const State = Object.freeze({
DEF_VALUE: 25,
BLOCK_NAME: 26,
BLOCK_TYPE: 27,
TYPE_NAME: 28,
TYPE_PARAM: 29,
TYPE_RESULT: 30,
});
const Action = Object.freeze({
@@ -118,12 +121,14 @@ const Action = Object.freeze({
ENTER: 16,
EXIT: 17,
ELSE: 18,
TYPE: 19,
});
const types = {
"void": 0x40,
"func": 0x60,
"i32": 0x7f,
"void": 0x40,
"func": 0x60,
"funcref": 0x70,
"i32": 0x7f,
};
const opcodes = {
@@ -208,6 +213,7 @@ class Parser {
".utf8": State.UTF8,
".align": State.ALIGN,
".def": State.DEF_NAME,
".type": State.TYPE_NAME,
};
this.blocks = new Set(["block", "loop", "if"]);
this.handlers = {
@@ -239,6 +245,9 @@ class Parser {
[State.DEF_VALUE]: (token) => this.token_def_value(token),
[State.BLOCK_NAME]: (token) => this.token_block_name(token),
[State.BLOCK_TYPE]: (token) => this.token_block_type(token),
[State.TYPE_NAME]: (token) => this.token_type_name(token),
[State.TYPE_PARAM]: (token) => this.token_type_param(token),
[State.TYPE_RESULT]: (token) => this.token_type_result(token),
};
this.results = [];
@@ -669,6 +678,68 @@ class Parser {
return action;
}
token_type_name(token) {
if (token == LINE_END) {
console.error(
"ERROR: Unexpected end of line in .type, expected name");
this.state = State.TOP;
return;
}
this.type = { name: token, params: [] };
this.state = State.TYPE_PARAM;
}
token_type_param(token) {
if (token == LINE_END) {
console.error(
"ERROR: Unexpected end of line in .type, expected "
+ "parameter type");
this.type = undefined;
this.state = State.TOP;
return;
}
if (token == "result") {
this.type.results = [];
this.state = State.TYPE_RESULT;
return;
}
const type = types[token];
if (type == undefined) {
console.error(
`ERROR: Unexpected token ${token} in .type, expected `
+ "parameter type");
this.type = undefined;
this.state = State.TOP;
return;
}
this.type.params.push(type);
}
token_type_result(token) {
if (token == LINE_END) {
const action = { type: Action.TYPE, the_type: this.type };
this.type = undefined;
this.state = State.TOP;
return action;
}
const type = types[token];
if (type == undefined) {
console.error(
`ERROR: Unexpected token ${token} in .type, expected `
+ "result type");
this.type = undefined;
this.state = State.TOP;
return;
}
this.type.results.push(type);
}
mem_action() {
const action = {
type: Action.MEM,
@@ -730,6 +801,7 @@ export class Assembler {
[Action.ENTER]: (action) => this.action_enter(action),
[Action.EXIT]: (action) => this.action_exit(action),
[Action.ELSE]: (action) => this.action_else(action),
[Action.TYPE]: (action) => this.action_type(action),
};
this.exports = [];
@@ -742,6 +814,7 @@ export class Assembler {
this.defs = {};
this.blocks = [];
this.types = [];
this.type_bindings = {};
}
action_append(action) {
@@ -874,6 +947,12 @@ export class Assembler {
this.blocks.push(undefined);
}
action_type(action) {
const type = this.func_type(action.the_type);
const index = this.ensure_type(type);
this.type_bindings[action.the_type.name] = index;
}
push(chunk) {
const text = this.decoder.decode(chunk, { stream: true });
for (const action of this.parser.handle(text))
@@ -1066,7 +1145,9 @@ export class Assembler {
}
func_type({ params, results }) {
const param_types = Object.values(params);
const param_types = params.length == undefined
? Object.values(params)
: params;
return [
types["func"],
param_types.length,