Created
October 13, 2018 08:42
-
-
Save sfpgmr/07ff44fba6b0b5243736eca7c8b463de to your computer and use it in GitHub Desktop.
オレオレ言語のコルーチンをハンド・コンパイルしてみた。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import binaryen_ from '../binaryen-wasm'; | |
import fs from 'fs'; | |
export function getInstance(obj,imports = {}) { | |
const bin = new WebAssembly.Module(obj); | |
const inst = new WebAssembly.Instance(bin, imports); | |
return inst; | |
} | |
(async ()=>{ | |
let binaryen; | |
await new Promise((resolve, reject) => { | |
binaryen = binaryen_({ | |
onRuntimeInitialized: m => { | |
resolve(); | |
} | |
}); | |
}); | |
try { | |
const lib = getInstance(binaryen.parseText(await fs.promises.readFile('./tests/co-test.wat','utf8')).emitBinary()).exports; | |
lib.initCo(); | |
let v; | |
while(v = lib.doCo()){ | |
console.log(v); | |
} | |
} catch (e){ | |
console.log(e); | |
} | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; // コルーチン定義 | |
;; coroutine i32 Co(){ | |
;; i32 a = 32; | |
;; yield a; | |
;; while(a){ | |
;; a -= 1; | |
;; yield a; | |
;; } | |
;; return a; | |
;; } | |
;; // コルーチンの初期化 | |
;; export void initCo(){ | |
;; Co* co = new(0) Co(); | |
;; } | |
;; // コルーチンの実行 | |
;; export i32 doCo(){ | |
;; Co* co = 0;// メモリオフセットをセット(なんという仕様。。) | |
;; return co(); | |
;; } | |
;; コンパイル後のイメージ(ハンドでコンパイルしてみた) | |
(module | |
(type $initCo (func)) | |
(type $doCo (func (result i32))) | |
(memory $0 1 1) | |
(export "initCo" (func $initCo)) | |
(export "doCo" (func $doCo)) | |
;; coroutineの初期化 | |
(func $initCo (type $initCo) | |
;; Co* co = new(0) Co(); | |
;; コルーチン状態管理用のメモリの初期化 | |
;; 0 ... 終了 | |
;; 1 ... 初期化 | |
;; 2 ... 1つ目のyield | |
;; 3 ... 2つ目のyield | |
(i32.store (i32.const 0) (i32.const 1)) | |
;; ローカル変数 a用のメモリの初期化 | |
(i32.store (i32.const 4) (i32.const 0)) | |
) | |
;; coroutineの実行 | |
(func $doCo (; 0 ;) (type $doCo) (result i32) | |
(block $end | |
(block $loopend | |
(loop $loopstart | |
(block $yield_resume | |
(block $start | |
(block $doCoInit | |
(br_table $end $doCoInit $start $yield_resume (i32.load (i32.const 0))) | |
) | |
;; 状態が1(初期化済み)の場合は先頭から実行 | |
;; i32 a = 32; | |
(i32.store (i32.const 4) (i32.const 32)) | |
;; yield a; | |
;; 1つ目のyieldの処理 | |
;; yieldの次にジャンプするように状態をセット | |
(i32.store (i32.const 0) (i32.const 2)) | |
(return (i32.load (i32.const 4))) | |
) | |
;; while(a) | |
(br_if $loopend (i32.eqz (i32.load (i32.const 4)))) | |
;; a -= 1; | |
(i32.store (i32.const 4) | |
(i32.sub | |
(i32.load (i32.const 4) ) | |
(i32.const 1) | |
) | |
) | |
;; yield a; | |
;; 2つ目のyieldの処理 | |
;; 状態を3に設定 | |
(i32.store (i32.const 0) (i32.const 3)) | |
(return (i32.load (i32.const 4))) | |
) | |
;; 状態を2に戻す | |
(i32.store (i32.const 0) (i32.const 2)) | |
(br $loopstart) | |
) | |
) | |
;;状態の終了をセット | |
(i32.store (i32.const 0) (i32.const 0)) | |
) | |
;; 値を戻す | |
;; return a; | |
(i32.load (i32.const 4)) | |
) | |
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 | |
31 | |
30 | |
29 | |
28 | |
27 | |
26 | |
25 | |
24 | |
23 | |
22 | |
21 | |
20 | |
19 | |
18 | |
17 | |
16 | |
15 | |
14 | |
13 | |
12 | |
11 | |
10 | |
9 | |
8 | |
7 | |
6 | |
5 | |
4 | |
3 | |
2 | |
1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment