素朴な自作言語のコンパイラをZigに移植した


移植一覧に戻る


やっつけなので汚いです。ライフゲームコンパイルが通ったのでヨシ、というレベルのものです。

Zig言語(ziglang)を触り始めて1週間くらいの人が雑に書いたものですので、「お手本にできそうな Zig のコード」「かっこいい Zig のコード」を求めている人は参考にならないと思います……。

Zig のバージョンは 0.6.0。 (追記 2021-03-17: 0.7.1 に上げました)

github.com

目次

移植元

memo88.hatenablog.com

ベースになっているバージョン: tag:50 のあたり

(追記 2021-03-17: ステップ56 の修正まで適用しました)

メモ

  • C と Go の中間、GC のない Go みたいな印象
  • sentinel-terminated な配列もなるほど便利そうと思って使ってみたが、通常の配列とは別の型になって煩雑なのと、サイズ固定な配列の出番が実はほとんどなかったので、後から普通の配列+スライスで書き直していった
  • 例外の扱いも Go とは違ったアプローチでおもしろい。最初は試しに使っていたが、お遊びプログラムなのでまじめにやる必要ないかと思い直し、これも後から使わないように(Java でいえば検査例外をその場で RuntimeException に包んで投げ直す感じに)書き変えた。単に煩雑さを避けるのを優先した形なのでほんとはちゃんとハンドリングすべきと思います。
  • 型まわりの理解がまだいまいち(配列や const が絡むあたりとか)
  • あと細かい話がいろいろあった気がするけど、作った後このエントリを書くまでしばらく他のことをしていたら忘れてしまった……思い出したら追記します
    • その間に Zig のバージョンが 0.6 から 0.8 に上がっていた
  • 今回はあんまり余裕なかったので実験的な要素はなし

逆引き的なメモ

標準エラー出力に出力 (v0.6.0)

const std = @import("std");

pub fn main() !void {
    const x = 123;
    const file: std.fs.File = std.io.getStdErr();

    try file.outStream().print("{}\n", .{x});

    // または catch で処理する
    // file.outStream().print("{}", .{x}) catch |err| {
    //     std.debug.panic("error ({})", .{err});
    // };
}

デバッグ用なら std.debug.print が手軽。
https://github.com/ziglang/zig/blob/0.7.1/lib/std/debug.zig#L63

標準入力からの入力をすべて読む

Zig: 1バイトごとに読み書きするだけのcatコマンドを書いてみた

panic (v0.7.1)

https://github.com/ziglang/zig/blob/0.7.1/lib/std/fmt.zig#L1249

const panic = @import("std").debug.panic;

pub fn main() !void {
    panic("PANIC {} {}", .{ -123, "foo" });
}

C の sprintf 相当 (v0.7.1)

https://github.com/ziglang/zig/blob/0.7.1/lib/std/fmt.zig#L1249

const std = @import("std");

pub fn main() !void {
    const s = "foo";
    const n = -123;
    var buf: [16]u8 = undefined;

    const slice: []u8 = try std.fmt.bufPrint(
        &buf,
        "{} bar {}",
        .{ s, n }
    );

    std.debug.print("{}\n", .{ slice });
}

整数 → 文字列 などの変換もこれでできる。

文字列を整数に変換 (v0.7.1)

https://github.com/ziglang/zig/blob/0.7.1/lib/std/fmt.zig#L1072

const std = @import("std");

pub fn main() !void {
    const s = "-123";
    const n = try std.fmt.parseInt(i32, s, 10);
    std.debug.print("{}\n", .{ n });
}

Zig 0.6.0 → 0.7.1 にバージョンアップした際の変更点

(2021-03-17 に追記)