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

組込み関数

@から始まる関数は、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: *mut T) bool

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

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

@alignCast

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

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

@alignedSizeOf

@alignedSizeOf(comptime T: type) comptime_int

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

例えば、x86_x64 アーキテクチャでは @sizeOf(u24) の結果は 3 となりますが、@alignedSizeOf(u24) の結果は 4 になります。

次も参照してください。

@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)以下になることが保証されています。

@alignTo

@alignTo(value: usize, alignment: usize) usize

value 以上で最小の alignment の倍数を返します。

例えば、アドレス addr を4バイト境界に合わせたい場合は、新たなアドレスを @alignTo(addr, 4) として求めます。

@atomicLoad

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

アトミックにポインタをデリファレンス (値をメモリからロードして) して値を返します。

T は次のいずれかの型である必要があります。

  • ポインタ型
  • ビット幅が次の条件を満たす整数型、有効な整数タグを持つ列挙型
    • 8ビット以上
    • usize以下
    • 2の累乗
  • 浮動小数点型

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

@atomicRmw

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

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

T は次のいずれかの型である必要があります。

  • ポインタ型
  • ビット幅が次の条件を満たす整数型、有効な整数タグを持つ列挙型
    • 8ビット以上
    • usize以下
    • 2の累乗
  • 浮動小数点型

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

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

.AtomicRmwOp 操作内容 対応する型
.Xchg operand を変更せずメモリにストア ポインタ型、整数型、列挙型、浮動小数点型、ブール型
.Add 加算 ポインタ型、整数型、浮動小数点型
.Sub 減算 ポインタ型、整数型、浮動小数点型
.And ビット単位の and ポインタ型、整数型
.Nand ビット単位の nand ポインタ型、整数型
.Or ビット単位の or ポインタ型、整数型
.Xor ビット単位の xor ポインタ型、整数型
.Max operand が大きければストア ポインタ型、整数型
.Min operand が小さければストア ポインタ型、整数型

.Add, .Sub は整数型の場合は2の補数でラップアラウンドします。

@atomicStore

@atomicStore(comptime T: type, ptr: *mut T, value: T, comptime ordering: builtin.AtomicOrder) void

アトミックに値をメモリに格納します。

T は次のいずれかの型である必要があります。

  • ポインタ型
  • ビット幅が次の条件を満たす整数型、有効な整数タグを持つ列挙型
    • 8ビット以上
    • usize以下
    • 2の累乗
  • 浮動小数点型

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

@bitCast

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

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

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

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

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

  • f32u32 に変更
  • i32u32 に変更

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

@bitOffsetOf

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

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

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

@boolToInt

@boolToInt(value: bool) u1

trueu11 に、 falseu10 に変換します。

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

@breakpoint

@breakpoint()

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

@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)になります。

@bitSizeOf

@bitSizeOf(comptime T: type) comptime_int

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

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

@byteOffsetOf

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

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

@bytesToSlice

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

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

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

@call

@call(modifier: std.builtin.CallModifier, stack: ?std.builtin.StackSlice, function: anytype, args: anytype) anytype

function を呼び出します。modifier を指定することで、通常の関数呼び出しの他、さまざまな方法で呼び出しができます。これらは CallModifier 列挙型として定義されています。

modifierCallModifier.async_kw を指定する場合は stack にスタックフレームとして使用する領域を指定する必要があります。指定する領域は std.Target.stack_align のアライメントで配置されている必要があります。フレームサイズは @Frame@sizeOf を使用して計算できます。サイズが十分でない場合は安全保護付き未定義動作を引き起こします。 CallModifier.async_kw 以外の場合は stack には null を指定します。

CallModifier 説明
auto 通常の関数呼び出しです。
async_kw asyncキーワードをつけた関数呼び出しと同様になります。
no_async 呼び出す関数が suspend しないことを確認するアサーションに用います。
always_tail 末尾呼出し最適化されることが保証されます。もし末尾呼出し最適化できなかった場合、コンパイルエラーになります。
never_tail 末尾呼出し最適化されないことが保証されます。もし末尾呼出し最適化する必要がある場合、コンパイルエラーになります。
always_inline インライン展開されることが保証されます。もしインライン展開できなかった場合、コンパイルエラーになります。
never_inline インライン展開されないことが保証されます。もしインライン展開する必要がある場合、コンパイルエラーになります。
compile_time コンパイル時に関数呼び出しを評価します。もし評価に失敗した場合、コンパイルエラーになります。

次の例のように、第一引数に auto を渡して呼び出すと、通常の関数呼び出しと同じになります。 第三引数は呼び出す関数、第四引数は関数の引数リストを無名構造体リテラルでまとめたものです。

examples/ch07-builtins/src/builtin_functions.zen:6:14

fn add(a: i32, b: i32) i32 {
    return a + b;
}

test "basic add functionality" {
    // 次の2つは同じ意味です
    ok(@call(.auto, null, add, .{ 3, 7 }) == 10);
    ok(add(3, 7) == 10);
}

次の例では、always_inlineを指定し、常にインライン展開します。

examples/ch07-builtins/src/builtin_functions.zen:16:18

test "basic add functionality" {
    ok(@call(.always_inline, null, add, .{ 3, 7 }) == 10);
}

次の例では async_kw を指定し、asyncAdd を非同期呼び出ししています。第二引数には @sizeOf@Frame を使用して asyncAdd のフレームサイズを求めて、std.Target.stack_align のアライメントで配置したバッファをスタックフレームとして指定しています。

fn asyncAdd(a: i32, b: i32) i32 {
    suspend;
    return a + b;
}

test "@call - async" {
    var stack: [@sizeOf(@Frame(asyncAdd))]u8 align(std.Target.stack_align) = undefined;

    const frame = @call(.async_kw, &mut stack, asyncAdd, .{ 3, 7 });

    resume frame;

    const result = await frame;
    ok(result == 10);
}

次も参照してください。

@cDefine

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

C言語のプリプロセッサマクロを定義します。@cImport の一時バッファに #define $name $value\nを追加します。この関数は @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: *mut T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T

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

fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *mut 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: *mut T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T

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

fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *mut 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デバッグ するために使用されます。

examples/ch07-builtins/src/builtin_functions.zen:20:36

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

test "main" {
    if (enable_compilelog) {
        @compileLog("comptime in main");
    }

    warn("Runtime in main, num1 = {}.\n", .{num1});
}
| *"comptime in main"
| *"comptime val1 = ", 99
Semantic Analysis [███████▒░░ 901/1227] src/builtin_functions.zen:32:9: error[E02026]: found compile log statement
        @compileLog("comptime in main");
        ~
...
src/builtin_functions.zen:24:9: error[E02026]: found compile log statement
        @compileLog("comptime val1 = ", val1);
        ~
...

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

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

次のコードのように comptime に解決する条件で @compileLog が呼び出されないようにするとコンパイルはエラーとなりません。

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

test "main" {
    if (enable_compilelog) {
        @compileLog("comptime in main");
    }

    warn("Runtime in main, num1 = {}.\n", .{num1});
}
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\n@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 であることと、 !(@typeInfo(T) == .Int and T.is_signed and numerator == std.math.minInt(T) and denominator == -1) であることを呼び出し側で保証する必要があります。

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

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

次も参照してください。

@divTrunc

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

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

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

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

次も参照してください。

@embedFile

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

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

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

次も参照してください。

@enumToInt

@enumToInt(enum_or_tagged_union: anytype) anytype

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

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

次も参照してください。

@errorName

@errorName(err: anyerror) []u8

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

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

@errorReturnTrace

@errorReturnTrace() ?*builtin.StackTrace

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

@errorToInt

@errorToInt(err: anytype) std.math.Int(false, @sizeOf(anyerror) * 8)

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

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

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

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

次も参照してくだい。

@errSetCast

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

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

@export

@export(target: anytype, comptime options: std.builtin.ExportOptions) void

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

この関数は、条件付きでシンボルをエクスポートするために、 comptime ブロックから呼び出すことができます。 ExportOptions では シンボル名, リンケージ, セクションを指定することができます。

pub const ExportOptions = struct {
    name: []u8,
    linkage: GlobalLinkage = .Strong,
    section: ?[]u8 = null,
};

シンボル名のnameは必須です。 リンケージとセクションはデフォルト値を設定しており、デフォルトでは、リンケージはStrong、セクションは指定なし、となります。

GlobalLinkagebuiltin.zen 内に列挙型として定義されています。

pub const GlobalLinkage = enum {
    Internal,
    Strong,
    Weak,
    LinkOnce,
};

target が C ABIを使用した関数で、 linkageStrong ならば、関数宣言をexport fnで行うのと等価です。

const builtin = @import("builtin");

comptime {
    const options = std.builtin.ExportOptions {
        .name = "foo",
    };
    @export(internalName, options);
}

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: anytype, comptime field_name: []u8) (field)

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

@fieldParentPtr

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

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

@floatCast

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

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

@floatToInt

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

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

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

次も参照してください。

@frame

@frame() *mut @Frame(func)

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

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

@Frame

@Frame(func: anytype) type

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

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

examples/ch07-builtins/src/builtin_functions.zen:38:45

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

fn func() void {
    suspend;
}

@frameAddress

@frameAddress() usize

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

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

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

@frameSize

@frameSize(func: anytype) usize

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

@hasDecl

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

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

examples/ch07-builtins/src/builtin_functions.zen:47:66

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"));
}

次も参照してください。

@hasField

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

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

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

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

次も参照してください。

@import

@import(comptime path: []u8) type

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

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

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

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

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

  • @import("std") - Zen の標準ライブラリ。
  • @import("builtin") - コンパイラが提供する型と変数。

次も参照してください。

@intCast

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

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

@intToEnum

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

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

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

次も参照してください。

@intToError

@intToError(value: std.math.Int(false, @sizeOf(anyerror) * 8)) anyerror

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

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

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

次も参照してください。

@intToFloat

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

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

@intToPtr

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

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

型変換は、addressがコンパイル時計算可能な場合、コンパイル時に実行します。 それ以外の場合、実行時に型変換を行います。

examples/ch07-builtins/src/builtin_functions.zen:68:75

test "type conversion from int to pointer" {
    // コンパイル時型変換
    const comptime_ptr = @intToPtr(*u32, 0xff00);

    // 実行時型変換
    var addr: usize = 0xff00;
    const runtime_ptr = @intToPtr(*u32, addr);
}

変換先のポインタ型が allowzero、オプション型ポインタの場合を除いて、address0 を指定すると、コンパイルエラーまたは安全性保護付き未定義動作になります。

型変換実行時、アドレスのアライメントがチェックされます。 addressDestType型のアライメントに従わなければなりません。 アライメントに沿っていない場合、コンパイルエラーまたは安全性保護付き未定義動作になります。

次のコードはアライメントに沿っていないアドレスへの変換を試みています。 *u32は4バイトのアライメントを持っているため、4バイトアライメントに沿っていないアドレス0xffff*u32に変換できません。

test "compiler error: type conversion from int to pointer" {
    const comptime_ptr = @intToPtr(*u32, 0xffff);
}

test "runtime error: type conversion from int to pointer" {
    var addr: usize = 0xffff;
    const runtime_ptr = @intToPtr(*u32, addr);
}

@is

@is(comptime DestType: type, value: anytype) ?DestType

value を型 DestType に安全に型変換します。

@to との違いは戻り値として変換後の値そのものではなくオプション型を返すことです。変換が可能な場合は変換後の値が格納され、変換できない場合は null となります。これにより、例えばインタフェースへの変換チェックを行ってインタフェース制約を満たさない場合の処理を実装する、というようなことができます。

整数型の値を別の整数型に変換する場合はコンパイル時に安全に型変換可能である値のみ変換が行われます。 実行時に値が確定する場合は変換可能かどうかに関わらず null を返します。

examples/ch07-builtins/src/builtin_functions.zen:77:92

test "@is for const integer" {
    const can_express_with_u8: u32 = 10;
    ok(@is(u8, can_express_with_u8).? == 10);

    const larger_than_u8: u32 = 300;
    ok(@is(u8, larger_than_u8) == null);
}

// 実行時の値が変換可能かどうかに関わらず、 `null` が返ります
test "@is for var integer" {
    var can_express_with_u8: u32 = 10;
    ok(@is(u8, can_express_with_u8) == null);

    var larger_than_u8: u32 = 300;
    ok(@is(u8, larger_than_u8) == null);
}

詳しくは、11.4 暗黙の型変換と明示的な型変換の 安全な型変換 を参照して下さい。

次も参照してください。

@mulAdd

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

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

@memcpy

@memcpy(noalias dest: [*]mut u8, noalias source: [*]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: [*]mut 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) * b + @mod(a, b) == a

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

次も参照してください。

@mulWithOverflow

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

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

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

@OpaqueType

@OpaqueType() type

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

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

examples/ch07-builtins/src/builtin_functions.zen:94:104

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);
}
src/builtin_functions.zen:94:9: error[E02046]: expected '*src.builtin_functions.Derp', found '*src.built
in_functions.Wat'
    bar(w);
        ~
src/builtin_functions.zen:94:9: note[E00019]: pointer type child 'src.builtin_functions.Wat' cannot cast into pointer type child 'src.builtin_fun
ctions.Derp'
    bar(w);
        ~

@overlay

@overlay(parent: type, child: type) type

構造体parentの関数やフィールドに対し、childの関数やフィールドを上書きした新しい構造体を返します。

examples/ch07-builtins/src/builtin_functions.zen:107:136

test "overlay" {
    const parent = struct {
        const n: u32 = 20;
        const m: u32 = 30;

        fn foo() []u8 {
            return "foo_parent";
        }
        fn bar() []u8 {
            return "bar_parent";
        }
    };

    const child = @overlay(parent, struct {
        const n: i16 = 60;

        fn foo() []u8 {
            return "foo_child";
        }
        fn fiz() []u8 {
            return "fiz_child";
        }
    });

    ok(child.n == 60);
    ok(child.m == 30);
    equalSlices(u8, child.foo(), "foo_child");
    equalSlices(u8, child.bar(), "bar_parent");
    equalSlices(u8, child.fiz(), "fiz_child");
}

@panic

@panic(message: []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: anytype) DestType

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

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

@ptrToInt

@ptrToInt(value: anytype) 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) * 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)よりも小さい、または、以前に明示的に設定された割り当てよりも小さい場合、無視されます。

examples/ch07-builtins/src/builtin_functions.zen:138:143

test "exceeded 1000 backwards branches" {
    comptime {
        var i = 0;
        while (i < 1001) : (i += 1) {}
    }
}
src/builtin_functions.zen:136:9: error[E04008]: evaluation exceeded 1000 backwards branches
        while (i < 1001) : (i += 1) {}
        ~

このような場合、次のコードのように @setEvalBranchQuota でより大きい値を指定することでコンパイルが通るようになります。

examples/ch07-builtins/src/builtin_functions.zen:145:151

test "@setEvalBranchQuota" {
    comptime {
        @setEvalBranchQuota(1001);
        var i = 0;
        while (i < 1001) : (i += 1) {}
    }
}

@setFloatMode

@setFloatMode(mode: builtin.FloatMode)

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

pub const FloatMode = enum {
    Strict,
    Optimized,
};
  • Strict(デフォルト)- 浮動小数点演算は厳密な IEEE 準拠に従います。

  • Optimized - 浮動小数点演算は以下を全て行うことがあります:

    • 引数と結果が NaN や正負の無限大ではないと仮定した最適化を行います。
    • 引数や結果のゼロの符号を意味のないものとして処理します。
    • 除算を実行するのではなく、引数の逆数を使用します。
    • 浮動小数点数縮小を実行します(例えば、積和演算における、加算の前にある乗算を融合します)。
    • 浮動小数点の結果を変化させうる代数的に等価な変換を実行します(例えば、再結合)。

    これらは GCC における -ffast-math に相当します。

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

@setRuntimeSafety

@setRuntimeSafety(safety_on: bool)

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

examples/ch07-builtins/src/builtin_functions.zen:182:202

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: *mut 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 が未定義動作であるからです。

次も参照してください。

@shuffle

@shuffle(comptime E: type, a: @Vector(a_len, E), b: @Vector(b_len, E), comptime mask: @Vector(mask_len, i32)) @Vector(mask_len, E)

2つのベクトル型データ ab から要素を選び出し、新しいベクトル型データを生成して返します。 生成するベクトル型データは、長さを mask_len で、ab からどの要素を選び出すかを mask の要素で指定します。

要素の選択は次の疑似コードのように行われます。

var result: @Vector(mask_len, E) = undefined;

for (mask) |index, i| {
    result[i] = if (index >= 0) a[index] else b[-(index + 1)];
}

mask の要素が正数の場合はその値をインデックスとして a の要素を選択し、負数の場合はその値の1の補数をインデックスとして b の要素を選択します。つまり、b の要素を選択する場合は mask の要素としてインデックスの1の補数を指定します。

mask または ab の選択された要素が undefined の場合は、生成されるベクトル型データの要素は undefined になります。

a または bundefined を指定した場合は他方と同じ要素数で全要素が undefined のベクトル型データとして扱われます。ab の両方に undefined を指定した場合は全要素 undefined のベクトル型データが生成されます。

maskab の範囲外のインデックスを指定した場合はコンパイルエラーになります。

要素の型 E として指定できるのは整数型、浮動小数点型、ポインタ型、ブール型です。

次のコードでは要素数4の2つのベクトル型データから要素数6の新しいベクトル型データを生成しています。

examples/ch07-builtins/src/builtin_functions.zen:204:212

test "@shuffle" {
    var a: @Vector(4, u32) = [4]u32{ 1, 2, 3, 4 };
    var b: @Vector(4, u32) = [4]u32{ 5, 6, 7, 8 };
    const mask: @Vector(6, i32) = [6]i32{ 0, -(0 + 1), -(3 + 1), 3, 1, -(2 + 1) };
    const expected = [6]u32{ 1, 5, 8, 4, 2, 7 };

    var res = @shuffle(u32, a, b, mask);
    equalSlices(u32, &expected, &@to([6]u32, res));
}

次も参照してください。

@sizeOf

@sizeOf(comptime T: type) comptime_int

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

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

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

次も参照してください。

@sliceToBytes

@sliceToBytes(value: anytype) []u8

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

@splat

@splat(comptime len: u32, scalar: anytype) @Vector(len, @TypeOf(scalar))

scalar で指定した値を len で指定した要素数分格納したベクトル型データを生成します。

scalar に指定できるのは整数型、浮動小数点型、ポインタ型、ブール型の値です。

次も参照してください。

@sqrt

@sqrt(value: anytype) @TypeOf(value)

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

@sin

@sin(value: anytype) @TypeOf(value)

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

@cos

@cos(value: anytype) @TypeOf(value)

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

@exp

@exp(value: anytype) @TypeOf(value)

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

@exp2

@exp2(value: anytype) @TypeOf(value)

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

@log

@log(value: anytype) @TypeOf(value)

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

@log2

@log2(value: anytype) @TypeOf(value)

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

@log10

@log10(value: anytype) @TypeOf(value)

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

@fabs

@fabs(value: anytype) @TypeOf(value)

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

@floor

@floor(value: anytype) @TypeOf(value)

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

@ceil

@ceil(value: anytype) @TypeOf(value)

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

@trunc

@trunc(value: anytype) @TypeOf(value)

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

@round

@round(value: anytype) @TypeOf(value)

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

@subWithOverflow

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

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

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

@tagName

@tagName(value: anytype) []u8

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

@TagType

@TagType(T: type) type

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

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

@This

@This() type

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

examples/ch07-builtins/src/builtin_functions.zen:153:169

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: []mut T,

        fn length(self: Self) usize {
            return self.items.len;
        }
    };
}

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

@to

@to(comptime DestType: type, value: anytype) DestType

value を型 DestType に安全に型変換します。

詳しくは、11.4 暗黙の型変換と明示的な型変換の 安全な型変換 を参照して下さい。 可能な限り他の型変換より@toによる安全な型変換を利用するべきです。

次も参照してください。

@trap

@trap() noreturn

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

@truncate

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

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

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

examples/ch07-builtins/src/builtin_functions.zen:171:174

test "integer cast panic" {
    var a: u16 = 0xabcd;
    var b: u8 = @intCast(u8, a);
}
src/builtin_functions.zen:168:17: 0x204535 in test "integer cast panic" (test)
    var b: u8 = @intCast(u8, a);
                ^
/lib/zen/std/special/test_runner.zen:50:28: 0x20a14b in std.special.main (test)
        } else test_fn.func();
                           ^
/lib/zen/std/start.zen:259:37: 0x204fcb in std.start.posixCallMainAndExit (test)
            const result = root.main() catch |err| {
                                    ^
/lib/zen/std/start.zen:121:5: 0x204dff in std.start._start (test)
    @call(.{ .modifier = .never_inline }, posixCallMainAndExit, .{});
    ^

Tests failed. Use the following command to reproduce the failure:

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

examples/ch07-builtins/src/builtin_functions.zen:176:180

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

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

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

@Type

@Type(comptime info: builtin.TypeInfo) type

型情報のタグ付き共用体(builtin.TypeInfo)の値から定義される型を返します。つまり、@typeInfo と逆の動作をします。

次も参照してください。

@typeInfo

@typeInfo(comptime T: type) builtin.TypeInfo

型の情報を返します。(builtin.TypeInfo) タグ付き共用体の値を返します。詳しくは、std/builtin.zen内のTypeInfoの定義を参照して下さい。

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

次も参照してください。

@typeName

@typeName(T: type) [N]u8

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

@TypeOf

@TypeOf(expression) type

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

@unionInit

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

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

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

@Vector

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

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

要素の型 ElemType として指定できるのは整数型、浮動小数点型、ポインタ型、ブール型です。

次も参照してください。

Chapter 1

Chapter 2

Chapter 3

Chapter 4

Chapter 5

Chapter 6

Chapter 7

Chapter 8

Chapter 9

Chapter 10

Chapter 11

Chapter 12

Chapter 13

Chapter 14

Chapter 15

Appendix

Error Explanation

☰ 人の生きた証は永遠に残るよう ☰
Copyright © 2018-2020 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.