diff --git a/README.md b/README.md index 9be8188..d55a949 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Luna is a reeeaaally tiny, yet expanding, compiler for WebAssembly Text Format, -It is so tiny that can only make additions lol. +It is so tiny that can only make the four operations (addition, subtraction, multiplication and division) with `i32` type numbers. # Why ❓ diff --git a/compiler/compiler.go b/compiler/compiler.go index a598647..94189c5 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -268,6 +268,19 @@ func Compile(ast []types.AstNode) Module { functionBody = append(functionBody, sectionData{0x01}) functionBody = append(functionBody, encodeVector(functionBodyData)...) + // Internal instructions (e.g. i32.const) + case texts.InternalInstruction: + var localIndex uint + value, ok := node.Expression.Value.(string) + if !ok { + log.Fatal("Not string") + } + + v, _ := strconv.Atoi(value) + localIndex = uint(v) + + code = append(code, sectionData{node.MapTo}...) + code = append(code, omologateEncoded(localIndex)...) } } diff --git a/compiler/parser.go b/compiler/parser.go index f1f6cf7..89acc14 100644 --- a/compiler/parser.go +++ b/compiler/parser.go @@ -135,8 +135,6 @@ func parseStatement(currentToken *iteratorEmulatorStruct, eatToken func(val stri Expression: parseExpression(currentToken, eatToken, index), MapTo: defaults.Opcodes["get_local"], } - } - switch currentToken.token.Value { case "i32.add": eatToken("i32.add") return types.AstNode{ @@ -151,6 +149,27 @@ func parseStatement(currentToken *iteratorEmulatorStruct, eatToken func(val stri Expression: types.ExpressionNode{}, MapTo: defaults.Opcodes["i32_sub"], } + case "i32.mul": + eatToken("i32.mul") + return types.AstNode{ + Type: texts.FuncInstruction, + Expression: types.ExpressionNode{}, + MapTo: defaults.Opcodes["i32_mul"], + } + case "i32.div": + eatToken("i32.div") + return types.AstNode{ + Type: texts.FuncInstruction, + Expression: types.ExpressionNode{}, + MapTo: defaults.Opcodes["i32_div"], + } + case "i32.const": + eatToken("i32.const") + return types.AstNode{ + Type: texts.InternalInstruction, + Expression: parseExpression(currentToken, eatToken, index), + MapTo: defaults.Opcodes["i32_const"], + } } } diff --git a/compiler/tokenizer.go b/compiler/tokenizer.go index c6718f2..a12cef1 100644 --- a/compiler/tokenizer.go +++ b/compiler/tokenizer.go @@ -31,7 +31,7 @@ var tokens = []string{ // A better and more robust regex could be implemented var instructions = []string{ "local\\.get", - "i32\\.(add|sub)", + "i32\\.(add|sub|mul|div|const)", } var numTypes = []string{ diff --git a/defaults/defaults.go b/defaults/defaults.go index 9a00056..f3cd6b0 100644 --- a/defaults/defaults.go +++ b/defaults/defaults.go @@ -30,6 +30,8 @@ var ( i32_and = 0x71 i32_add = 0x6a i32_sub = 0x6b + i32_mul = 0x6c + i32_div = 0x6d f32_add = 0x92 f32_sub = 0x93 f32_mul = 0x94 @@ -51,6 +53,8 @@ var Opcodes = map[string]interface{}{ "i32_eqz": i32_eqz, "i32_add": i32_add, "i32_sub": i32_sub, + "i32_mul": i32_mul, + "i32_div": i32_div, "i32_eq": i32_eq, "f32_eq": f32_eq, "f32_lt": f32_lt, diff --git a/example/dist/bundle.js b/example/dist/bundle.js index f5cc15e..c213b0c 100644 --- a/example/dist/bundle.js +++ b/example/dist/bundle.js @@ -43,6 +43,8 @@ var Opcodes = { i32_and: 113, i32_add: 106, i32_sub: 107, + i32_mul: 108, + i32_div: 109, f32_add: 146, f32_sub: 147, f32_mul: 148, @@ -190,14 +192,18 @@ function parseCodeSection(wasm) { let numberOfLocals = wasm.readByte(); let instructions = []; let locals = []; + let internals = []; while (wasm.pos < wasm.data.length) { const instruction = wasm.readByte(); instructions.push(instruction); if (instruction == Opcodes.get_local) { locals.push(wasm.readByte()); } + if (instruction == Opcodes.i32_const) { + internals.push(wasm.readByte()); + } } - code.push([locals, instructions]); + code.push({ locals, internals, instructions }); } return code; } @@ -227,10 +233,11 @@ var Processor = class { this.stack = []; } executeFunc() { - for (const instruction of this.func[1]) { - if (instruction == Opcodes.get_local) { - this.stack.push(this.params[this.func[0].shift()]); - } + for (const instruction of this.func.instructions) { + if (instruction == Opcodes.get_local) + this.stack.push(this.params[this.func.locals.shift()]); + if (instruction == Opcodes.i32_const) + this.stack.push(this.func.internals.shift()); this.#parseInstruction(instruction); } } @@ -243,6 +250,12 @@ var Processor = class { case Opcodes.i32_sub: result = this.stack.reduce((prev, current) => prev - current); return this.stack.push(result); + case Opcodes.i32_mul: + result = this.stack.reduce((prev, current) => prev * current, 1); + return this.stack.push(result); + case Opcodes.i32_div: + result = this.stack.reduce((prev, current) => prev / current); + return this.stack.push(result); } } getResult() { diff --git a/example/editor/editor.js b/example/editor/editor.js deleted file mode 100644 index e69de29..0000000 diff --git a/example/index.html b/example/index.html index 4edc5bd..3b524cb 100644 --- a/example/index.html +++ b/example/index.html @@ -15,10 +15,17 @@