- C3はC言語をベースとしており、モジュール、演算子オーバーロード、ジェネリクス、コンパイル時実行などの高度な機能を提供する
- 馴染みあるCの文法を維持しつつ、エラー処理、defer、foreachなど生産性と安全性を強化する構文が搭載されている
- 宣言的コントラクト(contracts)、オプショナル型とエラー処理方式の導入により、安全性と明確さが向上している
- 標準ライブラリとビルドシステムの統合、一時メモリ割り当てなど実用的な開発環境がサポートされている
- ビルド、プロジェクト生成、コード構造などでZig言語との類似性があり、新しい言語設計の実験がうかがえる
C3の概要と特徴
C3とは何か?
- C3は既存のC言語の上に構築された言語で、馴染みある文法の維持と同時に、Cでは難しかったモジュールシステム、演算子オーバーロード、ジェネリクス、コンパイル時実行、エラー処理、defer、value methods、段階的コントラクト(contracts)、スライス、foreach、ダイナミック型サポートなどの機能を提供する
- 名前空間を活用したモジュール構造により名前の衝突を防ぐ(
abc::Contextのような命令的な名前空間を使用)
- 主な目標は、生産性を高め、現代的なシステムプログラミング機能を安全に提供すること
言語の特徴
Hello Worldの例
- Cと文法的に類似している
- 関数宣言では
fn キーワードを明示的に使う必要がある
- 入出力などの標準ライブラリ関数が強力で、さまざまな型もそのまま出力できる
foreachループ
- Cと異なりforeach構文を標準でサポートする
- 参照による反復では変数名の前に
& を付ける(高度な機能)
- break、continueをサポートし、他言語のforeachに近い
whileループ
- C99以前ではwhile条件式の内部で宣言を使えなかったが、C3では内部宣言が可能
enumとswitch文
- switch文で暗黙のbreakをサポートする(暗黙/明示breakの混在は好みが分かれる)
nextcase キーワードで明確なケース移動(ジャンプテーブルの実装を簡単にする)をサポートする
- ZigやCなど既存言語で複雑だったswitch-caseの流れを簡潔に制御できる
deferキーワード
- スコープ終了時にdeferで予約した文を逆順に実行し、リソースの後始末を安全に保証する
catch、try と組み合わせたdefer活用(エラー処理フローの制御)
structとunion
- struct内部に名前付き/無名形式のサブstruct/unionを許可し、tagged unionパターンの設計がしやすい
- 無名(同名フィールド重複)と名前衝突の区別を厳密に明示する
エラー処理方式
? 記号でオプショナル型をサポートし、エラーと値オプションを統合して利便性を高めている
catch キーワードで空の状態(Optionalなし)/エラー分岐が可能
- Rust、Zigと異なりエラーとオプション値の区別が弱い(長所: 単純さ、短所: 意図の明確さが下がる)
! 演算子(rethrow)で例外伝播が可能
コントラクト(Contracts)
- 関数の事前/事後条件(Require/Ensure)を
<* .. *> の間に記述する(コンパイル時に条件確認)
- コンパイル時fold解析までサポートする(静的解析は未実装)
structメソッド
- 型指定 + ドット記法(
Foo.next)で関連メソッドを構成でき、名前空間もある(プリミティブ型を含む)
- 構造体/ユニオン/enumなどすべての型にメソッドを許可する
マクロ
- コンパイル時評価ベースのマクロ(
macro キーワード)
$ でコンパイル時パラメータ、# で評価前に渡す仕組みを実装する
- Cスタイル(絡み合ったマクロ問題を最小化し、ASTの安定性を重視し、
@ 接頭辞チェックなど)
- 型リフレクションおよびコンパイル時実行をマクロで処理する
型プロパティ
alignof, kindof, extnameof, sizeof, typeid, methodsof, has_tagof, tagof, is_eq, is_ordered, is_substruct など
- メタプログラミング、リフレクションに適している
Base64/Hexリテラル
b64"..." x"..." 形式でバイト列を直接宣言できる
- 組み込みマクロ
$embed に置き換える必要性もある(実際には使用頻度は低い)
プリミティブ型
- int、uint、char(常にunsigned)、bool、float、int128/uint128など多様な基本型
- iptr、uptr、isz、uszなどポインタ/サイズ系の別型がある(やや直感性に欠ける)
- Cと異なりbit-sizeが保証される
その他
- 演算子オーバーロード、構造体サブタイピング、ジェネリクス、ランタイムディスパッチ、any型、**ビットフィールド構造体(bitstructs)**など幅広い機能セットを備える
実習: C3体験記
C3のインストール
- 公式サイトのプリビルドバイナリ、直接ソースからのビルドの2方式をサポート
- LLVM、LLDのインストールが必要(リンク問題が発生する場合は
-DLLVM_DIR、-DLLD_DIR のCMakeフラグを活用)
- 一部ディストリビューションではLLDライブラリが含まれない問題があり、バイナリの直接ダウンロードが推奨される
- C3コンパイラはlibtinfo依存性が必要
プロジェクト作成
c3c init コマンドで標準フォルダ構造を生成する(LICENSE/README.md/project.json/src など)
- Bluild、ビルドターゲット、ソース設定など、基盤となるプロジェクト構成を提供する(Zig、Cargoに類似)
- 基本のmain.c3ファイルは非常に簡潔(意見: 新しいユーザーに適している)
電卓を作る
設計と目的
- 再帰下降パーサー(Recursive Descent Parser)および電卓の中核ロジックを実装しながら、C3の関数、入出力、メモリ管理、ループなど多様な構文を実習する
- 文法の直感性、実践での生産性など、優れている点/不便な点を直接把握することが目的
入力処理
@pool で**一時アロケータ(tmem)**を使用し、スコープ終了時に自動でメモリ解放する(arena allocator)
- 標準的なメモリ管理方式としてtmem(一時)、mem(一般)をサポートし、関数単位でアロケータを渡すパターンを採用している(ZigとCの長所を組み合わせた形)
- main関数は戻り値の明示が必須(コンパイラで強制)
- 戻り値を無視してもよい関数には
@maydiscard 属性を付ける(悪意ある無視を防止)
トークナイザー実装
- ユーザー入力をトークンリストに分解する
- C3標準ライブラリのList、foreach構文、switch-case(nextcase、暗黙/明示breakの組み合わせ)など多様な制御文を活用する
- スライス構文(両端インデックスをどちらも含む)と長さ0のスライスに関して混乱がありうる(別途長さ指定構文が存在)
- 一時/一般アロケータを混在して使えるなど、メモリ管理の透明性と柔軟性があり、Rustなど他言語と比べても優れている
パーサー実装
結論および総合評価
- C3は伝統的なシステム言語と現代的設計の接点を目指している
- Zig、Rust、Cを研究しつつ、生産性とコードの安定性を両立する言語として設計されている
- モジュール性、安全なメモリ/エラー/コントラクト処理、強力なメタプログラミング、直感的なビルドシステムなど多様な機能が際立つ
- 学習曲線は、C経験者であれば段階的に入っていきやすい
- 言語サーバー、IDEなどエコシステムの未成熟や一部構文の好みが分かれる点は改善が必要
- 実務のローレベル/システム開発で次世代の代替言語として注目に値する
まだコメントはありません。