From 6a4877d52cc3941d2658e4e23c2f8757203122ff Mon Sep 17 00:00:00 2001 From: Camden Dixie O'Brien Date: Mon, 9 Mar 2026 23:46:55 +0000 Subject: [PATCH] Implement .param directive --- asm.js | 54 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/asm.js b/asm.js index 3f71387..c687de7 100644 --- a/asm.js +++ b/asm.js @@ -47,10 +47,12 @@ class Tokenizer { } const State = Object.freeze({ - TOP: 0, - EXPORT: 1, - FUNC: 2, - RESULT: 3, + TOP: 0, + EXPORT: 1, + FUNC: 2, + RESULT: 3, + PARAM_NAME: 4, + PARAM_TYPE: 5, }); const Action = Object.freeze({ @@ -58,6 +60,7 @@ const Action = Object.freeze({ EXPORT: 1, FUNC: 2, RESULT: 3, + PARAM: 4, }); const types = { @@ -67,6 +70,7 @@ const types = { const opcodes = { "end": 0x0b, + "local.get": 0x20, "i32.const": 0x41, "i32.mul": 0x6c, }; @@ -80,15 +84,19 @@ class Parser { ".export": State.EXPORT, ".func": State.FUNC, ".result": State.RESULT, + ".param": State.PARAM_NAME, }; this.handlers = { - [State.TOP]: (token) => this.token_top(token), - [State.EXPORT]: (token) => this.token_export(token), - [State.FUNC]: (token) => this.token_func(token), - [State.RESULT]: (token) => this.token_result(token), + [State.TOP]: (token) => this.token_top(token), + [State.EXPORT]: (token) => this.token_export(token), + [State.FUNC]: (token) => this.token_func(token), + [State.RESULT]: (token) => this.token_result(token), + [State.PARAM_NAME]: (token) => this.token_param_name(token), + [State.PARAM_TYPE]: (token) => this.token_param_type(token), }; this.results = []; + this.params = {}; } translate_code(token) { @@ -132,6 +140,31 @@ class Parser { } } + token_param_name(token) { + if (token == LINE_END) { + const action = { type: Action.PARAM, params: this.params }; + this.state = State.TOP; + this.params = {}; + return action; + } else { + this.current_param = token; + this.state = State.PARAM_TYPE; + } + } + + token_param_type(token) { + if (token == LINE_END) { + console.error( + "ERROR: Unexpected newline in .params: expected type"); + this.state = State.TOP; + this.params = {}; + } else { + this.params[this.current_param] = types[token]; + this.current_param = undefined; + this.state = State.PARAM_NAME; + } + } + *handle(src) { let action; for (const token of this.tokenizer.handle(src)) { @@ -158,6 +191,7 @@ export class Assembler { [Action.EXPORT]: (action) => this.action_export(action), [Action.FUNC]: (action) => this.action_func(action), [Action.RESULT]: (action) => this.action_result(action), + [Action.PARAM]: (action) => this.action_param(action), }; this.exports = []; @@ -187,6 +221,10 @@ export class Assembler { this.funcs[this.current_func].results.push(...action.results); } + action_param(action) { + Object.assign(this.funcs[this.current_func].params, action.params); + } + push(chunk) { const text = this.decoder.decode(chunk, { stream: true }); for (const action of this.parser.handle(text))