オフィスアワーがそろそろ始まるよ!()

組込み関数

@から始まる関数は、Zenのコンパイラに組み込まれている関数です。これを組込み関数と呼びます。Zenの組込み関数の役割は主に3つです。

  1. 言語仕様上の特殊な機能を提供する
  2. コンパイラが持つメタ情報にアクセスする
  3. LLVM intrinsicを直接使えるようにする

Zenの組込み関数の多くはLLVMのintrinsicを直接呼び出します。この特徴はZenの移植性を飛躍的に高めています。従来では、ターゲットのプロセッサアーキテクチャごとにアセンブリを書かなければならないようなアトミックなメモリ操作関数の戻り先アドレスを移植性のある形で記述できます。

組込み関数は、コンパイラの最適化に委ねずに、プログラマが直接ターゲットとする機械語を生成するのに役立ちます。LLVMバックエンドが、プロセッサアーキテクチャごとに最小の命令になるように最適化されたコードを出力します。ある時は1つの機械語命令に、またある時は最適化された複数の機械語命令の組み合わせになります。

例えば、レジスタの最上位ビットから0のビットが何個続いているかを取得する@clz関数がありますが、このような命令は多くの場合プロセッサが専用命令を用意しており、1命令で実行できます。@clz関数は、専用命令を持っているプロセッサがターゲットの場合には、1命令の機械語を出力し、もし専用の命令がない場合は、LLVMバックエンドが最適化されたコードを出力します。

LLVM intrinsicに興味がある場合、LLVM intrinsic functionsをご覧下さい。

各組込み関数の詳細は、アルファベット順で掲載します。まず、カテゴリごとにどのような関数があるのか、一覧をお見せします。

カテゴリ別の一覧

オーバーフロー検出整数演算

演算

型変換

アトミック

浮動小数点演算

ビット演算

その他LLVM intrinsics

メモリ配置

メタ関数

async

デバッグ

C言語

その他

各組込み関数の詳細

アルファベット順に掲載しています。

@addWithOverflow

@addWithOverflow(comptime T: type, a: T, b: T, result: *T) bool

result.* = a + bを実行します。オーバーフローが起これば、 result にオーバーフローした結果のビットを格納して true を返します。オーバーフローが起こらなければ、resultに結果を格納し、false を返します。

Tは整数型であるかどうか、言語レベルでチェックされます。

@alignCast

@alignCast(comptime alignment: u29, ptr: var) var

ptr は単一オブジェクトへのポインタ (*T / ?*T)、関数ポインタ (fn() / ?fn())、スライス ([]T) のいずれかです。 alignment が新しい値になっていない限り、 ptr と同じ型を返します。ポインタが正しくアライメントされていることを保証するために、誤ったアライメントを持つポインタへの変換が行われていないかチェックされます。詳しくは、11.1.未定義動作の誤ったアライメントを持つポインタへの変換を参照して下さい。

@alignOf

@alignOf(comptime T: type) comptime_int

現在のビルドターゲットにおいて、C ABIを満たすために型Tが持たなければならないアライメントを返します。ポインタはalignmentフィールドを持っており、このalignmentフィールドの値と、ポインタが指す型のサイズが一致している場合、型情報からアライメントの情報は取り除かれます。

下の例で、x86_64ターゲットでは@alignOf(u32)4になります。u32のサイズは4バイトであるため、*u32*align(4) u32とは同じ型になります (すなわち、align(4)は省略可能です) 。

comptime {
    ok(*u32 == *align(@alignOf(u32)) u32);
}

結果はビルドターゲットアーキテクチャ固有のコンパイル時定数です。@sizeOf(T)以下になることが保証されています。

@asyncCall

@asyncCall(frame_buffer: []align(@alignOf(@Frame(anyAsyncFunction))) u8, result_ptr, function_ptr, args: ...) anyframe->T

この関数は、function_ptrで与える関数ポインタを非同期呼び出しします。ここで、function_ptrがasyncかどうかは関係ありません。

frame_buffer は関数フレーム全体を格納する十分なサイズを有していなければなりません。関数フレームのサイズは @frameSize で計算できます。frame_bufferが十分な大きさでない場合、安全性保護付き未定義動作を引き起こします。

result_ptr はオプションの引数で、nullを渡すこともできます。null以外が渡された場合、呼び出された関数は result_ptr に関数の結果を直接書き込みます。このポインタは await が完了した後で、読みとることができます。 awaitに提供する結果を受け取るためのメモリ領域は、 result_ptr から結果をコピーします。

@atomicLoad

@atomicLoad(comptime T: type, ptr: *const T, comptime ordering: builtin.AtomicOrder) T

アトミックにポインタをデリファレンス (値をメモリからロードして) して値を返します。T はビット幅が次の条件を満たすポインタ型、整数型のいずれかである必要があります:

  • 8ビット以上
  • usize以下
  • 2の累乗

ノート: usizeのビット幅はターゲットアーキテクチャに依存することに注意して下さい。

@atomicRmw

@atomicRmw(comptime T: type, ptr: *T, comptime op: builtin.AtomicRmwOp, operand: T, comptime ordering: builtin.AtomicOrder) T

この関数は、アトミックにメモリを修正して修正前の値を返します。RmwRead modify writeの省略です。

T はビット幅が次の条件を満たすポインタ型、整数型のいずれかである必要があります:

  • 8ビット以上
  • usize以下
  • 2の累乗

ノート: usizeのビット幅はターゲットアーキテクチャに依存することに注意して下さい。

メモリに書き込む前の操作として、以下の操作をサポートしています。これらは、builtin.AtomicRmwOp列挙型のヴァリアントとして定義されています。

  • .Xchg - operand を変更せずメモリにストアします。
  • .Add - 整数型の場合、2の補数のラップアラウンドな加算です。浮動小数点型もサポートします。
  • .Sub - 整数型の場合、2の補数のラップアラウンドな減算です。浮動小数点型もサポートします。
  • .And - ビット単位の and です。
  • .Nand - ビット単位の nand です。
  • .Or - ビット単位の or です。
  • .Xor - ビット単位のxor です。
  • .Max - operand が大きければ保存します。整数型と浮動小数点型をサポートします。
  • .Min - operand が小さければ保存します。整数型と浮動小数点型をサポートします。

@bitCast

@bitCast(comptime DestType: type, value: var) DestType

value の型を他の型に変更します。変換前と変換後とで、ビット表現は変わりません。

変換前と変換後の型のビット幅は同じでなければなりません。すなわち、@sizeOf(@typeOf(value)) == @sizeOf(DestType) が満たされる必要があります。

ターゲットとする型 (DestType) にポインタ型を指定することはできません。これが必要ならば、 @ptrCast@intToPtr を使います。

例えば次のような時に使います。

  • f32u32 に変更
  • i32u32 に変更

value がコンパイル時計算可能であれば、コンパイル時に動作します。structのメモリ配置は定義されていないため、同じサイズのスカラ型にビットキャストするとエラーが発生します。ただしpacked structであれば、エラーになりません。

@bitOffsetOf

@bitOffsetOf(comptime T: type, comptime field_name: []const u8) comptime_int

構造体のメンバフィールドに対して、構造体の先頭からのビットオフセットを返します。

packed struct以外は、常に8で割り切れる値になります。packed structの場合、複数のフィールドが同じバイトオフセットを持つ場合 (1バイト内に複数のフィールドがある場合) がありますが、ビットオフセットは異なる値を持ちます。

@boolToInt

@boolToInt(value: bool) u1

trueu1(1) に、 falseu1(0) に変換します。

value がコンパイル時計算可能ならば、型は u1 ではなく comptime_int になります。

@breakpoint

@breakpoint()

この関数は、デバッガがブレイクを起こす、プラットフォーム固有のデバッグトラップ命令を挿入します。関数スコープ内でのみ有効です。

@mulAdd

@mulAdd(comptime T: type, a: T, b: T, c: T) T

(a * b) + cのような融合積和演算 (fused multiply-add; FMA/FMAD) を実行します。丸め回数が1回だけなので、計算精度が高くなります。

@byteSwap

@byteSwap(comptime T: type, integer: T) T

integer のバイト順を入れ替えます。ビッグエンディアンの整数をリトルエンディアンの整数に、リトルエンディアンの整数をビッグエンディアンの整数に変換します。T は8で割り切れるビット数の整数型でなければなりません。

@bitReverse

@bitReverse(comptime T: type, integer: T) T

integer のビットパターンを反転します。該当する場合は記号ビットも含まれます。 T はあらゆる整数型を受け付けます。

例えば、 0b10110110 (u8 = 182, i8 = -74) は 0b01101101 (u8 = 109, i8 = 109)になります。

@byteOffsetOf

@byteOffsetOf(comptime T: type, comptime field_name: []const u8) comptime_int

構造体のメンバフィールドに対して、構造体の先頭からのバイトオフセットを返します。

@bytesToSlice

@bytesToSlice(comptime Element: type, bytes: []u8) []Element

バイト (u8) のスライスやバイトの配列を、 Element を要素型に持つスライスに変換します。結果のスライスが持つポインタは、変換前のスライスが持つポインタと同じです。

Element 型のスライスに余りなく分割できないバイト長を変換しようとすると、安全性保護付き未定義動作になります。

@cDefine

@cDefine(comptime name: []u8, value)

C言語のプリプロセッサマクロを定義します。@cImport の一時バッファに #define $name $valueを追加します。この関数は @cImport 内でのみ使えます。

値なしでマクロ定義するには、次のようにします。

@cDefine("_GNU_SOURCE", "")

次も参照してください。

@cImport

@cImport(expression) type

この関数は Cソースコードをパースして、関数、型、変数、そして互換性のあるマクロ定義を、Zenの構造体にインポートして、その型を返します。

expression はコンパイル時に解釈されます。組込み関数 @cInclude@cDefine 、そして @cUndef はこの expression の中でのみ動作します。

通常アプリケーションの全体の中で @cImport は1回だけ使用するべきです。これはコンパイラが clang を複数回呼び出すことを防ぎ、またインライン関数が重複することを防ぐためです。

@cImport式を複数回使用しなければならない理由としては、以下のことが考えられます。

  • シンボルの衝突を避ける。例えば foo.hbar.h が両方とも #define CONNECTION_COUNT を持つ場合。

次も参照してください。

@cInclude

@cInclude(comptime path: []u8)

これは #include <$path>\ncImport の一時バッファに追加します。この関数は @cImport 内でのみ使えます。

次も参照してください:

@clz

@clz(comptime T: type, integer: T)

この関数は integer の最上位ビットから0が何個続いているかを数えます。

integer がコンパイル時計算可能な場合、戻り値型は comptime_int となります。そうでない場合、戻り値型はT 型のビット数を表すことができる最小ビット幅の符号なし整数となります。

integer が0の場合、 @clzT 型のビット幅を返します。

次も参照してください:

@cmpxchgStrong

@cmpxchgStrong(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T

この関数は強いアトミックな比較交換 (compare and swap; CAS) を実行します。操作がアトミックであることを除いて、これは次のコードと同等です。

fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_value: T) ?T {
    const old_value = ptr.*;
    if (old_value == expected_value) {
        ptr.* = new_value;
        return null;
    } else {
        return old_value;
    }
}

ループ内で cmpxchg を使用する場合、@cmpxchgWeak を使うことを推奨します。@cmpxchgWeakの方が効率の良い機械語命令が実装されているためです。

AtomicOrderbuiltin.AtomicOrder 列挙型として定義されています。

pub const AtomicOrder = enum {
    Unordered,
    Monotonic,
    Acquire,
    Release,
    AcqRel,
    SeqCst,
};

@typeOf(ptr).alignment@sizeOf(T) 以上でなければいけません。

次も参照してください。

@cmpxchgWeak

@cmpxchgWeak(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T

この関数は弱いアトミックな比較交換 (compare and swap; CAS) を実行します。操作がアトミックであることを除いて、これは次のコードと同等です。

fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_value: T) ?T {
    const old_value = ptr.*;
    if (old_value == expected_value and usuallyTrueButSometimesFalse()) {
        ptr.* = new_value;
        return null;
    } else {
        return old_value;
    }
}

ループ内で cmpxchg を使用する場合、時々発生するアトミック操作の失敗は問題にならないこともあり、より効率的な機械語になる cmpxchgWeak がお勧めです。ただし、 @cmpxchgStrong のほうが、動作の保証は強いです。

AtomicOrderbuiltin.AtomicOrder 列挙型として定義されています。

@typeOf(ptr).alignment@sizeOf(T) 以上でなければなりません。

次も参照してください。

@compileError

@compileError(comptime msg: []u8)

この関数は、コンパイラの意味解析のフェーズで検出されると、メッセージ msg を出力するコンパイルエラーを起こします。

意味解析での検出を回避する方法もあります。例えばコンパイル時定数や comptime 関数で ifswitch を使い、この関数が解析対象外になるようにします。

@compileLog

@compileLog(args: ...)

この関数はコンパイル時に渡された引数を表示します。

誤ってコンパイルログ文をコードベースに残さないようにするため、コンパイルログ文を指摘するコンパイルエラーが出力されます。このエラーはコードが生成されるのを防ぎますが、一方で分析を妨害することはありません。

この関数はコンパイル時に実行されるコードで printfデバッグ するために使用されます。

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

const num1 = blk: {
    var val1: i32 = 99;
    @compileLog("comptime val1 = ", val1);
    val1 = val1 + 1;
    break :blk val1;
};

test "main" {
    @compileLog("comptime in main");

    warn("Runtime in main, num1 = {}.\n", num1);
}
$ zen test test.zen
| "comptime in main"
| "comptime val1 = ", 99
/deps/zen/docgen_tmp/test.zen:11:5: error: found compile log statement
    @compileLog("comptime in main");
    ^
/deps/zen/docgen_tmp/test.zen:5:5: error: found compile log statement
    @compileLog("comptime val1 = ", val1);
    ^

上記のように出力されます。

分析によって全ての @compileLog 呼び出しが除かれたり実行されなければ、プログラムは正常にコンパイルされ、生成された実行可能ファイルが表示されます。

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

const num1 = blk: {
    var val1: i32 = 99;
    val1 = val1 + 1;
    break :blk val1;
};

test "main" {
    warn("Runtime in main, num1 = {}.\n", num1);
}
$ zen test test.zen
1/1 test "main"...Runtime in main, num1 = 100.
OK
All tests passed.

@ctz

@ctz(comptime T: type, integer: T)

この関数は integer の最下位ビットから連続している0の個数を数えます。

integer がコンパイル時計算可能な場合、戻り型は comptime_int となります。そうでない場合、戻り型はTのビット数を表すことができる最小ビット幅を持つ符号無し整数となります。

integer が0の場合、@ctz は整数型 T のビット幅を返します。

次も参照してください。

@cUndef

@cUndef(comptime name: []u8)

これは #undef $name@cImport の一時バッファに追加します。この関数は @cImport 内でのみ使えます。

次も参照してください。

@divExact

@divExact(numerator: T, denominator: T) T

この関数は割り切れる除算を行います。この関数を使用するには denominator != 0 であることと、 @divTrunc(numerator, denominator) * denominator == numerator であることを呼び出し側で保証しなければなりません。

  • @divExact(6, 3) == 2
  • @divExact(a, b) * b == a

上記2つの条件を満たさない場合にエラーコードを返すには、 @import("std").math.divExact を使用してください。

次も参照してください。

@divFloor

@divFloor(numerator: T, denominator: T) T

負の無限大へ向かって丸める、フロア除算を行います。符号無し整数の場合 numerator / denominator と同じです。この関数を使用するには denominator != 0 であることと、 !(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1) であることを呼び出し側で保証する必要があります。

  • @divFloor(-5, 3) == -2
  • @divFloor(a, b) + @mod(a, b) == a

上記2つの条件を満たさない場合にエラーコードを返すには、 @import("std").math.divFloor を使用してください。

次も参照してください。

@divTrunc

@divTrunc(numerator: T, denominator: T) T

0の方向に丸める切り捨て除算を行います。符号無し整数の場合 numerator / denominator と同じです。この関数を使用するには denominator != 0 であることと、 !(@typeId(T) == builtin.TypeId.Int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1) であることを呼び出し側で保証する必要があります。

  • @divTrunc(-5, 3) == -1
  • @divTrunc(a, b) + @rem(a, b) == a

上記2つの条件を満たさない場合にエラーコードを返すには、 @import("std").math.divTrunc を使用してください。

次も参照してください。

@embedFile

@embedFile(comptime path: []const u8) [X]u8

この関数は、 path で与えられたファイルのバイト数に等しい長さのコンパイル時配列を返します。配列の内容はファイルの内容となります。

@import と同じように、 path は絶対パスまたは現在のファイルからの相対パスです。

次も参照してください。

@enumToInt

@enumToInt(enum_or_tagged_union: var) var

列挙型の値をその整数タグ型の値に変換します。タグ付き共用体が渡されると、タグの値が列挙型の値として使用されます。

可能性のある列挙型の値が1つだけの場合、結果はコンパイル時計算可能であり、 その型はcomptime_int となります。

次も参照してください。

@errorName

@errorName(err: anyerror) []const u8

この関数はエラーの文字列表現を返します。error.OutOfMem の文字列表現は "OutOfMem" です。

アプリケーション内で @errorName の呼び出しが全くない場合や、全ての呼び出しのerrがコンパイル時計算可能な場合、エラー名テーブルは生成されません。

@errorReturnTrace

@errorReturnTrace() ?*builtin.StackTrace

バイナリがエラーリターントレースを使用してビルドされており、エラーまたはエラー共用体を戻り値型として持つ関数を呼び出す関数内でこの関数が呼び出された場合は、スタックトレースオブジェクトを返します。そうでなければ null を返します。

@errorToInt

@errorToInt(err: var) @IntType(false, @sizeOf(anyerror) * 8)

エラー型をエラー型の整数表現へ変換します。

次の型をサポートします。

  • グローバルエラー型
  • エラー型
  • エラー共用体

ソースコードを変更すると、エラーの整数表現も変更される可能性があるため、この型変換は通常は使用しないことをお勧めします。

次も参照してくだい。

@errSetCast

@errSetCast(comptime T: DestType, value: var) DestType

エラー種別を、あるエラー型から別のエラー型に変換します。変換先のエラー型にないエラー種別を変換しようとすると、安全性保護付き未定義動作が発生します。

@export

@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) void

出力オブジェクトファイルにシンボルをつくります。

この関数は、条件付きでシンボルをエクスポートするために、 comptime ブロックから呼び出すことができます。 target が C ABIを使用した関数で、 linkageStrong ならば、関数宣言をexport fnで行うのと等価です。

const builtin = @import("builtin");

comptime {
    @export("foo", internalName, builtin.GlobalLinkage.Strong);
}

extern fn internalName() void {}
$ zen build-obj test.zen

これは次に相当します。

export fn foo() void {}
$ zen build-obj test.zen

exportを使用する時でも、 シンボル名に文字列を指定するために @"foo" の構文を使用できます。

export fn @"A function name that is a complete sentence."() void {}

ノート: シンボルは任意の文字列を使用することができます。上記のようにスペースが入っていても問題ありません。

$ zen build-obj test.zen

結果のオブジェクトを見ると、シンボル名に文字列がそのまま使用されているのがわかります。

00000000000001f0 T A function name that is a complete sentence.

@fence

@fence(order: AtomicOrder)

この関数は操作の順序を保証するためのものです。

AtomicOrder@import("builtin").AtomicOrder 列挙型として定義されています。

@field

@field(lhs: var, comptime field_name: []const u8) (field)

フィールドを文字列 ("field_name") で指定することで、 lhs.field_name に相当するフィールドアクセスを行います。

@fieldParentPtr

@fieldParentPtr(comptime ParentType: type, comptime field_name: []const u8,
field_ptr: *T) *ParentType

フィールドのポインタが与えられた時、構造体のベースポインタを返します。

@floatCast

@floatCast(comptime DestType: type, value: var) DestType

浮動小数点型同士の型変換を行います。この型変換は安全ですが、数値の精度が失われる可能性があります。

@floatToInt

@floatToInt(comptime DestType: type, float: var) DestType

浮動小数点型の値の整数部分をターゲットの整数型に変換します。

整数部分が変換先の型で表現できない場合、安全性保護付き未定義動作を引き起こします。

次も参照してください。

@frame

@frame() *@Frame(func)

この関数は、与えられた関数フレームへのポインタを返します。 この型は、 anyframe->T および anyframe に暗黙の型変換ができます。ここで T はスコープ内関数の戻り値の型です。

この関数は中断ポイントを含みませんが、スコープ内の関数を 非同期関数 にします。

@Frame

@Frame(func: var) type

この関数は、関数のフレームタイプを返します。 非同期関数 や呼び出し規約が特定されていない関数で機能します。

このタイプは、例えば非同期関数フレームのヒープ割り当てを可能にするような、 async の戻り型として使われるのに適しています。

const std = @import("std");

test "heap allocated frame" {
    const frame = try std.heap.direct_allocator.create(@Frame(func));
    frame.* = async func();
}

fn func() void {
    suspend;
}
$ zen test test.zen
1/1 test "heap allocated frame"...OK
All tests passed.

@frameAddress

@frameAddress() usize

この関数は現在のスタックフレームのベースポインタを返します。

実装はターゲットアーキテクチャに依存しており、全てのプラットフォームに対して一貫するものではありません。強力な最適化により、フレームアドレスはリリースモードで使用できないことがあります。

この関数は関数のスコープ内でのみ有効です。

@frameSize

@frameSize() usize

@sizeOf(@Frame(func))と同じです。ここでfuncは実行時計算可能であってもかまいません。

この関数は通常、@asyncCallと一緒に使います。

@handle

@handle()

この関数は promise->T 型を返します。ここで T はスコープ内非同期関数の戻り値型です。

この関数は非同期関数のスコープ内でのみ有効です。

@hasDecl

@hasDecl(comptime container: type, comptime name: []const u8) bool

構造体や列挙型や共用体が name と一致する宣言を持つかどうかを返します。

const std = @import("std");
const ok = std.testing.ok;

const Foo = struct {
    nope: i32,

    pub var blah = "xxx";
    const hi = 1;
};

test "@hasDecl" {
    ok(@hasDecl(Foo, "blah"));

    // `hi` は privateですが、このテストは Foo として同じファイルの
    // スコープ内にあるため @hasDecl は true を返します。別ファイル
    // 内で Foo が宣言されると false を返します。

    ok(@hasDecl(Foo, "hi"));

    // @hasDecl はフィールドではなく宣言に対して作用します。
    ok(!@hasDecl(Foo, "nope"));
    ok(!@hasDecl(Foo, "nope1234"));
}
$ zen test test.zen
1/1 test "@hasDecl"...OK
All tests passed.

次も参照してください。

@hasField

@hasField(comptime T: type, comptime name: []const u8) bool

構造体、共用体、列挙型にnameのフィールドが存在するかどうかを返します。

結果はコンパイル時定数です。

関数、変数、定数は対象外です。

次も参照してください。

@import

@import(comptime path: []u8) type

この関数は、 path に対応する Zen ファイルを見つけて、まだ追加されていない場合はそのファイルをビルドに追加します。

Zenのソースファイルは、暗黙の構造体です。拡張子を除いたファイル名が名前のベースになります。

pubキーワードが付いた宣言は、異なるソースファイルから参照することができます。

path は相対パスでも絶対パスでもよく、さらにパッケージ名を指定することも可能です。相対パスで指定する場合、 @import 関数呼び出しを含むファイルに対する相対パスとなります。

次のパッケージは常に利用可能です。

  • @import("std") - Zen の標準ライブラリ。
  • @import("builtin") - コンパイラが提供する型と変数。 zen builtinコマンドは標準出力にソースを出力します。

次も参照してください。

@inlineCall

@inlineCall(function: X, args: ...) Y

function を呼び出します。通常の関数呼び出しと異なる点は、@inlineCallはインライン展開されることが保証される点です。もしインライン展開できなかった場合、コンパイルエラーになります。

const ok = @import("std").testing.ok;

test "inline function call" {
    ok(@inlineCall(add, 3, 9) == 12);
}

fn add(a: i32, b: i32) i32 { return a + b; }
$ zen test test.zen
1/1 test "inline function call"...OK
All tests passed.

次も参照してください。

@intCast

@intCast(comptime DestType: type, int: var) DestType

同じ数値を維持しながら整数型の値を別の整数型に変換します。変換先の整数型で表現できる範囲外の数値を変換しようとすると、安全性保護付き未定義動作が発生します。

@intToEnum

@intToEnum(comptime DestType: type, int_value: @TagType(DestType)) DestType

整数を列挙型の値に変換します。

変換先の列挙型において、変換しようとする整数値をに対応するヴァリアントがない場合、安全性保護付き未定義動作を引き起こします。

次も参照してください。

@intToError

@intToError(value: @IntType(false, @sizeOf(anyerror) * 8)) anyerror

エラーの整数表現からグローバルエラー型に変換します。

ソースコードを変更すると、エラーの整数表現も変更される可能性があるため、この型変換は通常は使用しないことをお勧めします。

いかなるエラー種別にも対応していない整数を変換しようとすると、安全性保護付き未定義動作が発生します。

次も参照してください。

@intToFloat

@intToFloat(comptime DestType: type, int: var) DestType

整数を最も近い浮動小数点表現に変換します。逆方向に変換するには、@floatToInt を使用します。この型変換は常に安全です。

@intToPtr

@intToPtr(comptime DestType: type, address: usize) DestType

整数値をポインタに変換します。逆方向に変換するには、@ptrToInt を使います。

変換先のポインタ型が0番地を許容する/しないに関わらず、アドレスが0番地の場合、安全性保護付き未定義動作を引き起こします。

@IntType

@IntType(comptime is_signed: bool, comptime bit_count: u16) type

この関数は、与えられた符号とビット数を持つ整数型を返します。整数型の最大ビット数は 65535 です。

@memberCount

@memberCount(comptime T: type) comptime_int

この関数は構造体型、列挙型、共用型のメンバー数を返します。

結果はコンパイル時定数となります。

関数、変数、および定数は対象外です。

@memberName

@memberName(comptime T: type, comptime index: usize) [N]u8

構造体、共用型、列挙型のフィールド名を返します。

結果はコンパイル時定数となります。

関数、変数、および定数は対象外です。

@memberType

@memberType(comptime T: type, comptime index: usize) type

構造体と共用体のフィールド型を返します。

@memcpy

@memcpy(noalias dest: [*]u8, noalias source: [*]const u8, byte_count: usize)

この関数は、あるメモリ領域から別のメモリ領域へバイト列をコピーします。destsource はどちらもポインタです。双方のメモリ領域は重なっていてはいけません。

この関数は低レベルの組込み関数で、安全機構はありません。大抵の場合、この関数より次のようなコピー方法を用いるべきです。

for (source[0..byte_count]) |b, i| dest[i] = b;

コンパイラの最適化は上記コードを memcpy に変換します。

これの標準ライブラリ関数もあります。

const mem = @import("std").mem;
mem.copy(u8, dest[0..byte_count], source[0..byte_count]);

@memset

@memset(dest: [*]u8, c: u8, byte_count: usize)

この関数はメモリ領域を c に設定します。 dest はポインタです。

この関数は低レベルの組込み関数で、安全機構はありません。大抵の場合、この関数より次のようなメモリ初期化を使うべきです。

for (dest[0..byte_count]) |*b| b.* = c;

コンパイラの最適化は上記コードを memset に変換します。

これの標準ライブラリ関数もあります。

const mem = @import("std").mem;
mem.set(u8, dest, c);

@mod

@mod(numerator: T, denominator: T) T

剰余演算を行います。符号無し整数の場合 numerator % denominator と同じです。この関数を使用するには denominator > 0 である必要があります。

  • @mod(-5, 3) == 1
  • @divFloor(a, b) + @mod(a, b) == a

エラーを返す同様の関数は、標準ライブラリにあります。std.math.mod です。

次も参照してください。

@mulWithOverflow

@mulWithOverflow(comptime T: type, a: T, b: T, result: *T) bool

result.* = a * b を実行します。オーバーフローが起これば、 result にオーバーフローした結果のビットを格納して true を返します。オーバーフローが起こらなければ、resultに結果を格納し、false を返します。

Tは整数型であるかどうか、言語レベルでチェックされます。

@newStackCall

@newStackCall(new_stack: []align(target_stack_align) u8, function: var, args: ...) var

function を呼び出します。ただし function は、呼び出し元と同じスタックではなく、 new_stack パラメータで提供されたスタックを使用します。

新しいスタックは target_stack_align のアライメントを満たす必要があります。これはターゲットアーキテクチャ固有の値です。全てのターゲットで動作する安全な値は 16 です。Async Functions の @Frame 型で @sizeOf を使うことで、この値を得ることもできます。

const std = @import("std");
const ok = std.testing.ok;

var new_stack_bytes: [1024]u8 = undefined;

test "calling a function with a new stack" {
    const arg = 1234;

    const a = @newStackCall(new_stack_bytes[0..512], targetFunction, arg);
    const b = @newStackCall(new_stack_bytes[512..], targetFunction, arg);
    _ = targetFunction(arg);

    ok(arg == 1234);
    ok(a < b);
}

fn targetFunction(x: i32) usize {
    ok(x == 1234);

    var local_variable: i32 = 42;
    const ptr = &local_variable;
    ptr.* += 1;

    ok(local_variable == 43);
    return @ptrToInt(ptr);
}
$ zen test test.zen
1/1 test "calling a function with a new stack"...OK
All tests passed.

@noInlineCall

@noInlineCall(function: var, args: ...) var

function を呼び出します。

しかしながら、通常の関数呼び出しとは異なり、@noInlineCall では呼び出しがインライン化されないことが保証されます。呼び出しをインライン化する必要がある場合、コンパイルエラーが発生します。

const ok = @import("std").testing.ok;

test "noinline function call" {
    ok(@noInlineCall(add, 3, 9) == 12);
}

fn add(a: i32, b: i32) i32 {
    return a + b;
}
$ zen test test.zen
1/1 test "noinline function call"...OK
All tests passed.

次も参照してください。

@OpaqueType

@OpaqueType() type

サイズ不明(ただしゼロ以外)の新しい型を作成します。

通常、構造体の詳細を公開しないCコードとやり取りする時に、型安全性を保証するために使われます。

const Derp = @OpaqueType();
const Wat = @OpaqueType();

extern fn bar(d: *Derp) void;
export fn foo(w: *Wat) void {
    bar(w);
}

test "call foo" {
    foo(undefined);
}
$en test test.zen
/deps/zen/docgen_tmp/test.zen:6:9: error: expected type '*Derp', found '*Wat'
    bar(w);
        ^
/deps/zen/docgen_tmp/test.zen:6:9: note: pointer type child 'Wat' cannot cast into pointer type child 'Derp'
    bar(w);
        ^

@panic

@panic(message: []const u8) noreturn

パニックハンドラ関数を呼び出します。デフォルトでは、パニックハンドラ関数はルートソースファイルで公開されているパブリックなパニック関数を呼び出し、指定されていない場合は std/special/panic.zen で提供されているものを呼び出します。

通常、 @import("std").debug.panic を使う方が好ましいです。しかし、@panic が便利なケースが2つあります 。

  • ライブラリコードから、プログラマが公開しているルートソースファイルのパニック関数を呼び出す場合。
  • CコードとZenコードとを混在していて、複数の .o ファイルにまたがって正規のパニック実装を呼び出す時。

@popCount

@popCount(comptime T: type, integer: T)

integer1が立っているビット数を数えます。

もし integer がコンパイル時計算可能であれば、戻り値型は comptime_int となります。そうでない場合、戻り値型はTのビット数を表現できる最小ビット数を持つ符号無し整数です。

次も参照してください。

@ptrCast

@ptrCast(comptime DestType: type, value: var) DestType

ポインタ型を別のポインタ型に変換します。

オプション型で包まれたポインタにも対応します。nullが格納されているオプション型で包まれたポインタをポインタ型に型変換すると、安全性保護付き未定義動作が発生します。

@ptrToInt

@ptrToInt(value: var) usize

value をポインタのアドレスである usize に変換します。 value は以下の型のうちのどれかです:

  • *T
  • ?*T
  • fn()
  • ?fn()

その他の変換方法としては、@intToPtr を使います。

@rem

@rem(numerator: T, denominator: T) T

剰余を計算します。符号無し整数の場合、 numerator % denominator と同じです。この関数を使用するには denominator > 0 である必要があります。

  • @rem(-5, 3) == -2
  • @divTrunc(a, b) + @rem(a, b) == a

エラーを返す関数については、@import("std").math.mod を参照してください。

次も参照してください。

@returnAddress

@returnAddress() usize

この関数は、現在の関数が戻った時に実行される次の機械語命令のアドレスを返します。

この実装はターゲットアーキテクチャ固有で、全てのプラットフォームで一貫性があるわけではありません。

この関数は関数スコープの中でのみ有効です。関数が呼び出し元の関数にインライン展開された場合、この関数の呼び出しは、呼び出し元関数に適用されます。

@setAlignStack

@setAlignStack(comptime alignment: u29)

関数が少なくとも alignment バイトの静的な割り当てを持つことを保証します。

@setCold

@setCold(is_cold: bool)

関数がほとんど呼び出されないことをコンパイラに伝えます。この情報は最適化に使用されます。

@setEvalBranchQuota

@setEvalBranchQuota(new_quota: usize)

コンパイル時のコード実行で使うことができる分岐の最大数を変更します。コンパイル時のコード実行で分岐が最大数に到達すると、コンパイル時実行を断念してコンパイルエラーを起こします。

new_quota がデフォルトの割り当て(1000)よりも小さい、または、以前に明示的に設定された割り当てよりも小さい場合、無視されます。

test "foo" {
    comptime {
        var i = 0;
        while (i < 1001) : (i += 1) {}
    }
}
$ zen test test.zen
/deps/zen/docgen_tmp/test.zen:4:9: error: evaluation exceeded 1000 backwards branches
        while (i < 1001) : (i += 1) {}
        ^

今度は @setEvalBranchQuota を使います。

test "foo" {
    comptime {
        @setEvalBranchQuota(1001);
        var i = 0;
        while (i < 1001) : (i += 1) {}
    }
}
$ zen test test.zen
1/1 test "foo"...OK
All tests passed.

@setFloatMode

@setFloatMode(mode: @import("builtin").FloatMode)

現在のスコープの浮動小数点モードを設定します。可能な値はbuiltin.FloatMode列挙型に定義されています。

pub const FloatMode = enum {
    Strict,
    Optimized,
};
  • Strict(デフォルト)- 浮動小数点演算は厳密な IEEE 準拠に従います。
  • Optimized - 浮動小数点演算は以下を全て行うことがあります:
    • 引数と結果が、 NaN ではないと仮定します。NaN に対する定義された動作を維持するには最適化が必要ですが、結果の値は未定義です。
    • 引数と結果が、無限大あるいはマイナス無限大ではないと仮定します。+/- 無限大に対する定義された動作を維持するには最適化が必要ですが、結果の値は未定義です。
    • 引数や結果のゼロの符号を意味のないものとして処理します。
    • 除算を実行するのではなく、引数の逆数を使用します。
    • 浮動小数点数縮小を実行します(例えば、積和演算における、加算の前にある乗算を融合します)。
    • 浮動小数点の結果を変化させうる代数的に等価な変換を実行します(例えば、再結合)。 これは GCC における -ffast-math に相当します。

浮動小数点モードは子スコープによって継承され、どんなスコープにおいても上書き可能です。コンパイル時ブロックを使用することで、浮動小数点モードを構造体またはモジュールスコープで設定可能です。

@setRuntimeSafety

@setRuntimeSafety(safety_on: bool)

ランタイム安全性確認が関数呼び出しを含むスコープに対して有効かどうか設定します。

test "@setRuntimeSafety" {
    // この組込み関数はスコープに適用されます。ここで、整数オーバーフローは
    // ReleaseFastとReleaseSmallモードでも捕捉されません。
    // var x: u8 = 255;
    // x += 1; // ReleaseFast/ReleaseSmallモードでは未定義動作
    {
        // しかし、このブロックは安全性チェックが有効化されているので、
        // ReleaseFast/ReleaseSmallモードでも安全性チェックが行われます。
        @setRuntimeSafety(true);
        var x: u8 = 255;
        x += 1;

        {
            // 設定値は別のスコープでは上書き可能です。ここでは整数オーバーフローは
            // どのビルドモードでも捕捉されません。
            @setRuntimeSafety(false);
            // var x: u8 = 255;
            // x += 1; // 全てのビルドモードで未定義動作
        }
    }
}
$ zen test test.zen --release-fast
1/1 test "@setRuntimeSafety"...integer overflow

Tests failed. Use the following command to reproduce the failure:
/deps/zen/docgen_tmp/test

@shlExact

@shlExact(value: T, shift_amt: Log2T) T

左シフト操作(<<)を実行します。呼び出し元は1ビットもシフトアウトしないことを保証しなければなりません。

shift_amt の型は log2(T.bit_count) ビットの符号無し整数です。これは、shift_amt >= T.bit_count が未定義動作であるからです。

次も参照してください。

@shlWithOverflow

@shlWithOverflow(comptime T: type, a: T, shift_amt: Log2T, result: *T) bool

result.* = a << b を実行します。オーバーフローが起これば、 result にオーバーフローした結果のビットを格納して true を返します。オーバーフローが起こらなければ、resultに結果を格納し、false を返します。

shift_amt の型は log2(T.bit_count) ビットの符号無し整数です。これは、shift_amt >= T.bit_count が未定義動作であるからです。

次も参照してください。

@shrExact

@shrExact(value: T, shift_amt: Log2T) T

右シフト操作(>>)を実行します。呼び出し元は1ビットもシフトアウトしないことを保証しなければなりません。

shift_amt の型は log2(T.bit_count) ビットの符号無し整数です。これは、shift_amt >= T.bit_count が未定義動作であるからです。

次も参照してください。

@sizeOf

@sizeOf(comptime T: type) comptime_int

この関数は T をメモリに格納する際のバイト数を返します。結果はターゲットアーキテクチャ固有のコンパイル時定数です。

このサイズはパディングを含みます。メモリ内に2つの連続したTがある場合、これはインデックス 0 の要素とインデックス 1 の要素の間のバイト単位のオフセットになります。整数型については、@sizeOf(T)@typeInfo(T).Int.bits か、どちらを使用したいか考えて下さい。

この関数はランタイム時にサイズを測定します。 comptime_inttypeのように、実行時に許可されていない型の場合、結果は 0 になります。

次も参照してください。

@sliceToBytes

@sliceToBytes(value: var) []u8

スライスまたは配列を u8 のスライスに変換します。変換後のスライスは、変換前と同じアドレスを指すptrフィールドを持ちます。

@sqrt

@sqrt(comptime T: type, value: T) T

浮動小数点数の平方根を計算します。利用可能な場合は専用のハードウェア命令を使用します。ベクトルと同様に、 f16f32f64 、そして f128 をサポートします。

@sin

@sin(comptime T: type, value: T) T

浮動小数点数のsin (正弦) 関数です。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@cos

@cos(comptime T: type, value: T) T

浮動小数点数のcos (余弦) 関数です。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@exp

@exp(comptime T: type, value: T) T

浮動小数点数に対する基底 e の指数関数です。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@exp2

@exp2(comptime T: type, value: T) T

浮動小数点数に対する基底 2 の指数関数です。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@ln

@ln(comptime T: type, value: T) T

浮動小数点の自然対数を返します。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@log2

@log2(comptime T: type, value: T) T

2を底とする浮動小数点数の対数を返します。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@log10

@log10comptime T: type, value: T) T

10を低とする浮動小数点の対数を返します。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@fabs

@fabs(comptime T: type, value: T) T

浮動小数点の絶対値を返します。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@floor

@floor(comptime T: type, value: T) T

与えられた浮動小数点以下で、最大の整数値を返します。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@ceil

@ceil(comptime T: type, value: T) T

与えられた浮動小数点数以上で、最小の整数値を返します。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@trunc

@trunc(comptime T: type, value: T) T

与えられた浮動小数点数を0の方向の整数へ丸めます。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@round

@round(comptime T: type, value: T) T

与えられた浮動小数点数を0とは逆方向の整数へ丸めます。利用可能な場合は専用のハードウェア命令を使用します。現在は f32f64 をサポートしています。

@subWithOverflow

@subWithOverflow(comptime T: type, a: T, b: T, result: *T) bool

result.* = a - b を実行します。オーバーフローが起これば、 result にオーバーフローした結果のビットを格納して true を返します。オーバーフローが起こらなければ、resultに結果を格納し、false を返します。

Tは整数型であるかどうか、言語レベルでチェックされます。

@tagName

@tagName(value: var) []const u8

列挙型の値や共用体の値を、タグ名を表す文字列 (u8のスライス) に変換します。

@TagType

@TagType(T: type) type

列挙型の場合、値を格納するために使われる整数型を返します。

共用体の場合、タグの値を格納するために使われる列挙型を返します。

@This

@This() type

この関数呼び出しが含まれる最も内側の構造体や共用体の型を返します。自身を参照する必要がある無名構造体を使う時に便利です。

const std = @import("std");
const ok = std.testing.ok;

test "@This()" {
    var items = [_]i32{ 1, 2, 3, 4 };
    const list = List(i32){ .items = items[0..] };
    ok(list.length() == 4);
}

fn List(comptime T: type) type {
    return struct {
        const Self = @This();

        items: []T,

        fn length(self: Self) usize {
            return self.items.len;
        }
    };
}
$ zen test test.zen
1/1 test "@This()"...OK
All tests passed.

@This() をグローバルスコープで使うと、現在のインポートへの参照を返します。

@Trap

@Trap() noreturn

ターゲットアーキテクチャ固有のトラップ命令を生成します。

@truncate

@truncate(comptime T: type, integer: var) T

この関数は integer から上位ビットを切り捨て、元のサイズ以下の整数型の値を返します。

次のコードは、安全性保護付き未定義動作を引き起こします。

test "integer cast panic" {
    var a: u16 = 0xabcd;
    var b: u8 = @intCast(u8, a);
}
$ zen test test.zen
1/1 test "integer cast panic"...integer cast truncated bits
/deps/zen/docgen_tmp/test.zen:3:17: 0x204608 in test "integer cast panic" (test)
    var b: u8 = @intCast(u8, a);
                ^
/deps/install/lib/zen/std/special/test_runner.zen:13:25: 0x22555d in std.special.main (test)
        if (test_fn.func()) |_| {
                        ^
/deps/install/lib/zen/std/special/start.zen:139:37: 0x2243c6 in std.special.posixCallMainAndExit (test)
            const result = root.main() catch |err| {
                                    ^
/deps/install/lib/zen/std/special/start.zen:56:5: 0x22424f in std.special._start (test)
    @noInlineCall(posixCallMainAndExit);
    ^

Tests failed. Use the following command to reproduce the failure:
/deps/zen/docgen_tmp/test

しかしこれは明確に定義された実用的なコードです。

const std = @import("std");
const ok = std.testing.ok;

test "integer truncation" {
    var a: u16 = 0xabcd;
    var b: u8 = @truncate(u8, a);
    ok(b == 0xcd);
}
$ zen test truncate.zen
1/1 test "integer truncation"...OK
All tests passed.

ターゲットプラットフォーム上のエンディアンに関係なく、この関数は常に integer の上位ビットを切り捨てます。

Tcomptime_int なら、意味的には暗黙の型変換と同じです。

@typeId

@typeId(comptime T: type) @import("builtin").TypeId

型の種類を返します。返ってくる型の種類はbuiltin.TypeId列挙型に定義されています。

pub const TypeId = enum {
    Type,
    Void,
    Bool,
    NoReturn,
    Int,
    Float,
    Pointer,
    Array,
    Struct,
    ComptimeFloat,
    ComptimeInt,
    Undefined,
    Null,
    Optional,
    ErrorUnion,
    Error,
    Enum,
    Union,
    Fn,
    Block,
    BoundFn,
    ArgTuple,
    Opaque,
};

@typeInfo

@typeInfo(comptime T: type) @import("builtin").TypeInfo

型の情報を返します。(builtin.TypeInfo) 共用体の値を返します。詳しくは、zen builtinで出力されるメッセージを参照して下さい。

構造体、共用体、列挙型およびエラー型の場合、フィールドは宣言と同じ順序であることが保証されています。宣言の場合は順序の指定はありません。

@typeName

@typeName(T: type) [N]u8

この関数は型の文字列表現を、文字列 (u8のスライス) として返します。型名の文字列リテラルと同じものです。

@typeOf

@typeOf(expression) type

この関数は、引数の expression の型である、コンパイル時定数を返します。expression は評価されます。

@unionInit

@unionInit(comptime Union: type, comptime active_field_name: []const u8, init_expr) Union

この関数は共用体の初期化構文と同じですが、フィールド名が識別子トークンではなく コンパイル時計算可能な文字列であることが異なります。

@unionInitinit_expr に結果の位置を転送します。

@Vector

@Vector(comptime len: u32, comptime ElemType: type) type

この関数は SIMD のベクトル型を返します。

ElemType は整数型か浮動小数点型かポインタ型である必要があります。

ノート: 本節の内容は、Zig言語の組込み関数に関するドキュメントを和訳したものをベースとしています。

☰ 人の生きた証は永遠に残るよう ☰
Copyright © 2018-2019 connectFree Corporation. All rights reserved.
Zen, the Zen three-circles logo and The Zen Programming Language are trademarks of connectFree corporation in Japan and other countries.