Assemble kernel on the client #1
83
asm.js
83
asm.js
@@ -97,6 +97,9 @@ const State = Object.freeze({
|
|||||||
DEF_VALUE: 25,
|
DEF_VALUE: 25,
|
||||||
BLOCK_NAME: 26,
|
BLOCK_NAME: 26,
|
||||||
BLOCK_TYPE: 27,
|
BLOCK_TYPE: 27,
|
||||||
|
TYPE_NAME: 28,
|
||||||
|
TYPE_PARAM: 29,
|
||||||
|
TYPE_RESULT: 30,
|
||||||
});
|
});
|
||||||
|
|
||||||
const Action = Object.freeze({
|
const Action = Object.freeze({
|
||||||
@@ -118,11 +121,13 @@ const Action = Object.freeze({
|
|||||||
ENTER: 16,
|
ENTER: 16,
|
||||||
EXIT: 17,
|
EXIT: 17,
|
||||||
ELSE: 18,
|
ELSE: 18,
|
||||||
|
TYPE: 19,
|
||||||
});
|
});
|
||||||
|
|
||||||
const types = {
|
const types = {
|
||||||
"void": 0x40,
|
"void": 0x40,
|
||||||
"func": 0x60,
|
"func": 0x60,
|
||||||
|
"funcref": 0x70,
|
||||||
"i32": 0x7f,
|
"i32": 0x7f,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -208,6 +213,7 @@ class Parser {
|
|||||||
".utf8": State.UTF8,
|
".utf8": State.UTF8,
|
||||||
".align": State.ALIGN,
|
".align": State.ALIGN,
|
||||||
".def": State.DEF_NAME,
|
".def": State.DEF_NAME,
|
||||||
|
".type": State.TYPE_NAME,
|
||||||
};
|
};
|
||||||
this.blocks = new Set(["block", "loop", "if"]);
|
this.blocks = new Set(["block", "loop", "if"]);
|
||||||
this.handlers = {
|
this.handlers = {
|
||||||
@@ -239,6 +245,9 @@ class Parser {
|
|||||||
[State.DEF_VALUE]: (token) => this.token_def_value(token),
|
[State.DEF_VALUE]: (token) => this.token_def_value(token),
|
||||||
[State.BLOCK_NAME]: (token) => this.token_block_name(token),
|
[State.BLOCK_NAME]: (token) => this.token_block_name(token),
|
||||||
[State.BLOCK_TYPE]: (token) => this.token_block_type(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 = [];
|
this.results = [];
|
||||||
@@ -669,6 +678,68 @@ class Parser {
|
|||||||
return action;
|
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() {
|
mem_action() {
|
||||||
const action = {
|
const action = {
|
||||||
type: Action.MEM,
|
type: Action.MEM,
|
||||||
@@ -730,6 +801,7 @@ export class Assembler {
|
|||||||
[Action.ENTER]: (action) => this.action_enter(action),
|
[Action.ENTER]: (action) => this.action_enter(action),
|
||||||
[Action.EXIT]: (action) => this.action_exit(action),
|
[Action.EXIT]: (action) => this.action_exit(action),
|
||||||
[Action.ELSE]: (action) => this.action_else(action),
|
[Action.ELSE]: (action) => this.action_else(action),
|
||||||
|
[Action.TYPE]: (action) => this.action_type(action),
|
||||||
};
|
};
|
||||||
|
|
||||||
this.exports = [];
|
this.exports = [];
|
||||||
@@ -742,6 +814,7 @@ export class Assembler {
|
|||||||
this.defs = {};
|
this.defs = {};
|
||||||
this.blocks = [];
|
this.blocks = [];
|
||||||
this.types = [];
|
this.types = [];
|
||||||
|
this.type_bindings = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
action_append(action) {
|
action_append(action) {
|
||||||
@@ -874,6 +947,12 @@ export class Assembler {
|
|||||||
this.blocks.push(undefined);
|
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) {
|
push(chunk) {
|
||||||
const text = this.decoder.decode(chunk, { stream: true });
|
const text = this.decoder.decode(chunk, { stream: true });
|
||||||
for (const action of this.parser.handle(text))
|
for (const action of this.parser.handle(text))
|
||||||
@@ -1066,7 +1145,9 @@ export class Assembler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func_type({ params, results }) {
|
func_type({ params, results }) {
|
||||||
const param_types = Object.values(params);
|
const param_types = params.length == undefined
|
||||||
|
? Object.values(params)
|
||||||
|
: params;
|
||||||
return [
|
return [
|
||||||
types["func"],
|
types["func"],
|
||||||
param_types.length,
|
param_types.length,
|
||||||
|
|||||||
Reference in New Issue
Block a user