Open12

MoonBitを触ってみる回

適温適温

豆知識:linguistにMoonBitのコードハイライトはまだない(moon=MoonScriptなので別物)

適温適温

とりあえずmainをいちばんシンプルにする

fn main {

}

buildからのwabt

moon build
wasm2wat target/wasm/release/build/main/main.wasm

何も入っていない 無

(module
  (type (;0;) (func))
  (func (;0;) (type 0))
  (table (;0;) 0 0 funcref)
  (memory (;0;) 1)
  (export "moonbit.memory" (memory 0))
  (export "_start" (func 0))
  (elem (;0;) (i32.const 0) func))
適温適温

今度はハロワだけしてみる

fn main {
  println("Hello, world!")
}

Denoのスクリプトで実行してみる

const wasm = "target/wasm/release/build/main/main.wasm";

// spectest
let output = "";
const importModule = {
  spectest: {
    print_char: (char: number) => {
      output += String.fromCharCode(char);
    },
  },
};

// Load wasm
const wasmCode = await Deno.readFile(wasm);
const wasmModule = new WebAssembly.Module(wasmCode);
const wasmInstance = new WebAssembly.Instance(wasmModule, importModule);

// Run
const main = wasmInstance.exports["_start"] as CallableFunction;
main();
console.log(output);
$ moon build
$ deno run -A test.ts

Hello, world!

適温適温

ドキュメントにはまだ記載がないっぽいが、lib単体でビルドして関数を公開する方法はすでにあるらしい。現時点ではこれが参考になります👇
https://discuss.moonbitlang.com/t/the-moonbit-update-0401/197

こう書き換えておく

lib/hello.mbt
pub fn hello() -> String {
  "Hello, world!"
}
lib/moon.pkg.json
{
  "link": {
    "wasm": {
      "exports": ["hello"]
    }
  }
}
適温適温

wasm全然わからないがこうすると動く 👊 これもdeno

これを実施することで「wasmから吐き出された文字列を受け取る」まで実行できました。あとはこれを素直にworkerに乗せてやれば終わり…

const wasm = "target/wasm/release/build/lib/lib.wasm";

// Load wasm
const wasmCode = await Deno.readFile(wasm);
const wasmModule = new WebAssembly.Module(wasmCode);
const wasmInstance = new WebAssembly.Instance(wasmModule);

// Run
const hello = wasmInstance.exports["hello"] as CallableFunction;
const memory = wasmInstance.exports["moonbit.memory"] as WebAssembly.Memory;
const memoryBuffer = new Uint8Array(memory.buffer);
const result = hello();

// Print
const encoder = new TextDecoder("utf-8");
const length = memoryBuffer[result];
const str = encoder.decode(new Uint8Array(memory.buffer, result + 1, length));
console.log(str);
適温適温

終わりではあるのですが、jsラッパーなしのwasm単体で実行してくれるとカッコイイのでちょっと調べています

適温適温

wasiの話が出てくるスレッド
https://discuss.moonbitlang.com/t/moonbit-on-the-server/88

要約が欲しい人向けのAI要約

この議論は、wasmtime、wasmedge、またはwazeroなどのサーバーサイドのWASMランタイムで、Moonbitコードを実行する可能性について話し合っています。主な要点は次のとおりです。

  1. 現在、MoonbitからホストのFunctionを呼び出す唯一の方法は、wazeroとwasmtimeの例のように関数を渡すことです。
  2. 将来的にMoonbitはWASI標準をサポートする可能性があり、MoonbitCLIを必要とせずにWASI準拠のランタイムで実行できるようになります。
  3. WASIとWASM-GC(WASMのためのガベージコレクション提案)はまだプレビュー/実験段階にあり、現時点でMoonbitをWASIランタイムで実行するのが難しくなっています。
  4. DenoはWASIとWASM-GCの両方をサポートしている唯一のランタイムですが、面倒な回避策が必要です。
  5. ユーザーはMoonbitCLIや追加のツーリングを必要とせずに、任意のWASIランタイムで実行できる単一のデプロイ可能なWASMファイルを希望しています。
  6. WASIとWASM-GCが成熟すれば、WASMのポータビリティ目標に沿って、サーバーサイドのWASMランタイムでMoonbitコードをデプロイして実行するのが容易になると期待されています。

要約すると、この議論ではサーバーサイドのWASMランタイムでMoonbitを実行する際の現在の制限と、ポータブルでシンプルな方法での将来の期待について話し合われています。

適温適温

自分の知識だとどうにもならない感を察したので、方向性を変えて遊んでいきます

適温適温

説明をめちゃくちゃ省くと、このリポジトリを参考にしてwasi準拠な振る舞いをするwasmをビルドしてやれば、
npx wrangler@wasm dev target/wasm-gc/release/build/main/main.wasm でレスポンス返せるところまでは来ました
https://github.com/peter-jerry-ye/wasi/tree/main

ただこの実装をそのまま使うと、UTF-8ではなくてUTF-16 LEになってしまう。たぶんfd_writeの書き込みが固定長になってるせいだと思うけどまだちゃんと見れてないです

適温適温

𝕐𝕆𝕌 𝕎𝕀ℕ

pub fn utf8_bytes(str : String) -> Bytes {
  let mut length = 0
  let chars : Array[Char] = Array::make(str.length(), ' ')
  for i = 0; i < str.length(); i = i + 1 {
    let char : Char = str[i]
    let code : Int = char.to_int()
    chars[i] = char
    if code < 0x80 {
      length = length + 1
    } else if code < 0x0800 {
      length = length + 2
    } else if code < 0x010000 {
      length = length + 3
    } else if code < 0x110000 {
      length = length + 4
    }
  }
  let result = Bytes::make(length, 0)
  let mut j : Int = 0
  for i = 0; i < str.length(); i = i + 1 {
    let c = chars[i]
    j = j + result.set_utf8_char(j, c)
  }
  result
}
fn main {
  let bs = @lib.utf8_bytes("<body>Hello, MoonBit!</body>")
  @wasi.stdout.write(bs).unwrap() |> ignore
}
$ npx wrangler@wasm dev target/wasm-gc/release/build/main/main.wasm
$ curl http://localhost:8787

<body>Hello, MoonBit!</body>