Skip to content

Commit 009b20c

Browse files
authored
Merge pull request #11 from thomscoder/expandOperations
Expand operations
2 parents 2d0c3b9 + 95c4a4c commit 009b20c

17 files changed

Lines changed: 160 additions & 30 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Luna is a reeeaaally tiny, yet expanding, compiler for WebAssembly Text Format,
66

77
<img src="https://i.ibb.co/hdcV1h0/Screenshot-2022-11-01-alle-17-47-06.png" alt="luna" />
88

9-
It is so tiny that can only make additions lol.
9+
It is so tiny that can only make the four operations (addition, subtraction, multiplication and division) with `i32` type numbers.
1010

1111
# Why ❓
1212

compiler/compiler.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,19 @@ func Compile(ast []types.AstNode) Module {
268268
functionBody = append(functionBody, sectionData{0x01})
269269
functionBody = append(functionBody, encodeVector(functionBodyData)...)
270270

271+
// Internal instructions (e.g. i32.const)
272+
case texts.InternalInstruction:
273+
var localIndex uint
274+
value, ok := node.Expression.Value.(string)
275+
if !ok {
276+
log.Fatal("Not string")
277+
}
278+
279+
v, _ := strconv.Atoi(value)
280+
localIndex = uint(v)
281+
282+
code = append(code, sectionData{node.MapTo}...)
283+
code = append(code, omologateEncoded(localIndex)...)
271284
}
272285

273286
}

compiler/parser.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,6 @@ func parseStatement(currentToken *iteratorEmulatorStruct, eatToken func(val stri
135135
Expression: parseExpression(currentToken, eatToken, index),
136136
MapTo: defaults.Opcodes["get_local"],
137137
}
138-
}
139-
switch currentToken.token.Value {
140138
case "i32.add":
141139
eatToken("i32.add")
142140
return types.AstNode{
@@ -151,6 +149,27 @@ func parseStatement(currentToken *iteratorEmulatorStruct, eatToken func(val stri
151149
Expression: types.ExpressionNode{},
152150
MapTo: defaults.Opcodes["i32_sub"],
153151
}
152+
case "i32.mul":
153+
eatToken("i32.mul")
154+
return types.AstNode{
155+
Type: texts.FuncInstruction,
156+
Expression: types.ExpressionNode{},
157+
MapTo: defaults.Opcodes["i32_mul"],
158+
}
159+
case "i32.div":
160+
eatToken("i32.div")
161+
return types.AstNode{
162+
Type: texts.FuncInstruction,
163+
Expression: types.ExpressionNode{},
164+
MapTo: defaults.Opcodes["i32_div"],
165+
}
166+
case "i32.const":
167+
eatToken("i32.const")
168+
return types.AstNode{
169+
Type: texts.InternalInstruction,
170+
Expression: parseExpression(currentToken, eatToken, index),
171+
MapTo: defaults.Opcodes["i32_const"],
172+
}
154173
}
155174
}
156175

compiler/tokenizer.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ var tokens = []string{
3131
// A better and more robust regex could be implemented
3232
var instructions = []string{
3333
"local\\.get",
34-
"i32\\.(add|sub)",
34+
"i32\\.(add|sub|mul|div|const)",
3535
}
3636

3737
var numTypes = []string{

defaults/defaults.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ var (
3030
i32_and = 0x71
3131
i32_add = 0x6a
3232
i32_sub = 0x6b
33+
i32_mul = 0x6c
34+
i32_div = 0x6d
3335
f32_add = 0x92
3436
f32_sub = 0x93
3537
f32_mul = 0x94
@@ -51,6 +53,8 @@ var Opcodes = map[string]interface{}{
5153
"i32_eqz": i32_eqz,
5254
"i32_add": i32_add,
5355
"i32_sub": i32_sub,
56+
"i32_mul": i32_mul,
57+
"i32_div": i32_div,
5458
"i32_eq": i32_eq,
5559
"f32_eq": f32_eq,
5660
"f32_lt": f32_lt,

example/dist/bundle.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ var Opcodes = {
4343
i32_and: 113,
4444
i32_add: 106,
4545
i32_sub: 107,
46+
i32_mul: 108,
47+
i32_div: 109,
4648
f32_add: 146,
4749
f32_sub: 147,
4850
f32_mul: 148,
@@ -190,14 +192,18 @@ function parseCodeSection(wasm) {
190192
let numberOfLocals = wasm.readByte();
191193
let instructions = [];
192194
let locals = [];
195+
let internals = [];
193196
while (wasm.pos < wasm.data.length) {
194197
const instruction = wasm.readByte();
195198
instructions.push(instruction);
196199
if (instruction == Opcodes.get_local) {
197200
locals.push(wasm.readByte());
198201
}
202+
if (instruction == Opcodes.i32_const) {
203+
internals.push(wasm.readByte());
204+
}
199205
}
200-
code.push([locals, instructions]);
206+
code.push({ locals, internals, instructions });
201207
}
202208
return code;
203209
}
@@ -227,10 +233,11 @@ var Processor = class {
227233
this.stack = [];
228234
}
229235
executeFunc() {
230-
for (const instruction of this.func[1]) {
231-
if (instruction == Opcodes.get_local) {
232-
this.stack.push(this.params[this.func[0].shift()]);
233-
}
236+
for (const instruction of this.func.instructions) {
237+
if (instruction == Opcodes.get_local)
238+
this.stack.push(this.params[this.func.locals.shift()]);
239+
if (instruction == Opcodes.i32_const)
240+
this.stack.push(this.func.internals.shift());
234241
this.#parseInstruction(instruction);
235242
}
236243
}
@@ -243,6 +250,12 @@ var Processor = class {
243250
case Opcodes.i32_sub:
244251
result = this.stack.reduce((prev, current) => prev - current);
245252
return this.stack.push(result);
253+
case Opcodes.i32_mul:
254+
result = this.stack.reduce((prev, current) => prev * current, 1);
255+
return this.stack.push(result);
256+
case Opcodes.i32_div:
257+
result = this.stack.reduce((prev, current) => prev / current);
258+
return this.stack.push(result);
246259
}
247260
}
248261
getResult() {

example/editor/editor.js

Whitespace-only changes.

example/index.html

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,17 @@ <h1>Luna</h1>
1515
A sample compiler for WebAssembly Text Format.<br/>
1616
Check the <a href="http://github.com/thomscoder/luna" target="_blank">github repository</a>
1717
</p>
18+
<small>Try to change the name of the export (e.g. "addNumbers" to "lunaAddition")</small>
1819
<div class="container">
1920
<div class="inner-container">
20-
<small>Try to change the name of the export (e.g. "addNumbers" to "lunaAddition")</small>
2121
<div id="code"></div>
22+
<select id="instruction">
23+
<option value="addition">Addition</option>
24+
<option value="subtraction">Subtraction</option>
25+
<option value="division">Division</option>
26+
<option value="multiplication">Multiplication</option>
27+
<option value="const">Const</option>
28+
</select>
2229
<button id="compile">Compile</button>
2330
</div>
2431
<div class="inner-container">
@@ -29,11 +36,11 @@ <h1>Luna</h1>
2936
<div class="inner-container">
3037
Calculate (add or subtract):
3138
<div>
32-
<label for="t-input-1">Num 1</label>
39+
<label id="label-1" for="t-input-1">Num 1</label>
3340
<input name="t-input-1" id="input-1" type="text" />
3441
</div>
3542
<div>
36-
<label for="t-input-2">Num 2</label>
43+
<label id="label-2" for="t-input-2">Num 2</label>
3744
<input name="t-input-2" id="input-2" type="text" />
3845
</div>
3946
<div id="btn-result-container"><button id="btn">Result</button></div>
@@ -46,7 +53,8 @@ <h1>Luna</h1>
4653
as it defines some global objects
4754
-->
4855
<script src="./js/wasm_exec.js"></script>
49-
<script src="./editor/editor.js"></script>
5056
<script type="module" src="./js/index.js"></script>
57+
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.9/addon/mode/simple.min.js" integrity="sha512-CGM6DWPHs250F/m90YZ9NEiEUhd9a4+u8wAzeKC6uHzZbYyt9/e2dLC5BGGB6Y0HtEdZQdSDYjDsoTyNGdMrMA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
58+
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.9/mode/wast/wast.min.js" integrity="sha512-jROitIYzp4fmQniVqF+eAnO5xKsZbKhI9Mue2XHaUtyC6rFxvcS/utxK+e1tMdlN/JP20A1qPEPPHwts42A4JQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
5159
</body>
5260
</html>

example/js/index.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import startAeonRuntime from '../dist/bundle.js';
2+
import { defaultText } from './inputDefaultText.js';
3+
import { CONST_MODE } from './texts/texts.js';
24

35
const go = new Go(); // Defined in wasm_exec.js. Don't forget to add this in your index.html.
46

@@ -43,8 +45,10 @@ const runLunaAddition = async () => {
4345
// Set the result onto the doc
4446
const input1 = document.getElementById('input-1');
4547
const input2 = document.getElementById('input-2');
48+
const label2 = document.getElementById('label-2')
4649
const codeContainer = document.getElementById('code');
4750
const moduleContainer = document.getElementById('module');
51+
const selectInstruction = document.getElementById('instruction');
4852

4953
const compile = document.getElementById('compile');
5054
const btn = document.getElementById('btn')
@@ -54,21 +58,23 @@ const runLunaAddition = async () => {
5458

5559

5660
btn.setAttribute('disabled', true)
57-
const input = `(module
58-
(func (export "addNumbers") (param i32 i32) (result i32)
59-
local.get 0
60-
local.get 1
61-
i32.add)
62-
)
63-
`
6461

65-
66-
const editor = CodeMirror(codeContainer, {
67-
value: input,
62+
let editor = CodeMirror(codeContainer, {
63+
value: defaultText(selectInstruction),
6864
mode: "wast",
6965
lineNumbers: true,
7066
});
7167

68+
// Change editor content based on selected mode
69+
selectInstruction.onchange = (e) => {
70+
editor.setValue(defaultText(selectInstruction));
71+
// Hide second input on const
72+
if (e.target.value === CONST_MODE) {
73+
input2.style.display = 'none';
74+
label2.style.display = 'none';
75+
}
76+
}
77+
7278
compile.addEventListener('click', async () => {
7379
moduleContainer.innerHTML = ""
7480
const textContent = editor.getValue()

example/js/inputDefaultText.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { ADDITION_MODE, CONST_MODE, DIVISION_MODE, MULTIPLICATION_MODE, SUBTRACTION_MODE } from "./texts/texts.js"
2+
3+
export const defaultText = (select) => {
4+
const instruction = select.value
5+
switch (instruction) {
6+
case ADDITION_MODE:
7+
return `(module
8+
(func (export "addNumbers") (param i32 i32) (result i32)
9+
local.get 0
10+
local.get 1
11+
i32.add)
12+
)
13+
`
14+
case SUBTRACTION_MODE:
15+
return `(module
16+
(func (export "subtractNumbers") (param i32 i32) (result i32)
17+
local.get 0
18+
local.get 1
19+
i32.sub)
20+
)
21+
`
22+
case MULTIPLICATION_MODE:
23+
return `(module
24+
(func (export "multiplyNumbers") (param i32 i32) (result i32)
25+
local.get 0
26+
local.get 1
27+
i32.mul)
28+
)
29+
`
30+
case DIVISION_MODE:
31+
return `(module
32+
(func (export "divideNumbers") (param i32 i32) (result i32)
33+
local.get 0
34+
local.get 1
35+
i32.div)
36+
)
37+
`
38+
case CONST_MODE:
39+
return `(module
40+
(func (export "operationWithInternalVariable") (param i32 i32) (result i32)
41+
local.get 0
42+
i32.const 10
43+
i32.add)
44+
)
45+
`
46+
}
47+
}

0 commit comments

Comments
 (0)