C3言語を触ってみた時のメモ (1) 2024/10
(注)このページは調べながら書いているのでどんどん追加修正されていきます
C3言語とは
ぶっちゃけな言い方をすると
C言語があまりにもアレなので (-:
言語仕様を現代的に進化させました
という言語
C2言語[1]からインスパイアされたらしい
C3言語ホーム: https://c3-lang.org/
Github ページ: https://github.com/c3lang/c3c
Discord グループ C3
C3言語の概要
- ネイティブコードコンパイラで高速実行、バックエンドはLLVM
- 静的型付き言語
- C言語好きな人に一定の支持が得られることが期待できる
- C言語の雰囲気を残した近縁種な感じ??
- C言語コードを外部関数・ライブラリとして使う(使われる)のは簡単にできる(ABIが同じ)
特徴の一部(全部は無理)
-
言語の名前は
C3
-
コンパイラの実行名は
c3c
-
ソースコードの拡張子は
*.c3
-
ファイルを一つコンパイルするだけなら
c3c compile ./hello.c3
-
コンパイラにビルドツールが統合されている
./project.json
ファイルにビルドオプションを書く -
C言語を起点として進化した別言語
部分的に見るとC言語と100%互換があるコードが*.c3c
ソース内に存在可能 (後述) -
- C言語の
typedef
はdef
に置き換わった - すべてのユーザー定義型の1文字目は大文字で始める
- C言語の
-
演算子の優先順位の一部はC言語と非互換
-
foreach文で配列に対してイテレータ(インデックス可)が使える
-
独自文法のマクロ構文を導入 (#if #ifdef #define ... マクロは廃止)
-
Moduleベースのネームスペースを導入(#include は廃止)
-
defer: 遅延実行ディレクティブあり
-
エラー処理は
例外処理
ではなくOptionalを使ってハンドリングする
unrwap 付き if文, orelse, catch 等が使える -
SIMDを使った高速実行を意図したVector型
-
C++言語のVector型(std::vector)と類似の物は標準ライブラリのList型
-
関数の前方参照宣言は不要
関数の本体を書く前にその関数を呼び出せる -
ジェネリクスあり
-
RAIIはない
-
配列に対するスライス(Slice)型の導入
-
文字列型は3種類
-
◎ 関数にデフォルト引数が使える \(^o^)/
-
関数のオーバロードはない
-
極一部で演算子のオーバロードが使える
-
インターフェース型が使える
-
リフレクションあり(コンパイル時と実行時)
-
構造体にメソッドがバインドできる
-
◎ 標準ライブラリを使う時にメモリアロケータを明示使用する必要はない(明示しても良い)
-
elif
,elsif
に相当する予約語がない様だ -
- 明示的な初期化が無くても警告やエラーは出ない
int y @noinit;
の様に0初期化動作を避けることも可能
-
構造体のポインタを使ってフィールド参照する時の
->
は.
に置き換えられた -
バックエンドがLLVMなのでLLVMが対応できるCPUアーキテクチャには対応可能(c3c v1.0目標)
C3言語の状況: 開発ロードマップ
- 現在のバージョンはv0.6.3でv1.0.0に向けて開発中
ライブラリは未成熟だけどコンパイラは現状の版でもプロダクションに使えるという記述がある
v1.0リリースは 2028/04 (今は2024/10)
- v1.0に向けて足りないものとして
- C言語からC3言語へのコンバーターアプリ
- Regex(正規表現)ライブラリなど
気づいた点
- ドキュメントがわかりにくい気がする
項目数は妥当だけど内容の詳細度が足りなくて理解できない部分が多い感じ - 競合?する言語は多分Zig言語
- 標準ライブラリでアロケータを明示しなくて良いのでZig言語よりもスッキリ書ける
- 型推論について
ChatGPTやCoPilotに聞いてみるとC3言語には型推論機能があると出るんだけど
公式文書では探せなかった
DiscordのC3言語グループ内を検索すると
型推論の乱用を避けるためマクロ内限定でvar = ..
としてだけ使えるみたいだった
C3言語コンパイラのインストール
Download Windows ZIPファイル
インストール方法 Windows
-
上記zipファイルを漢字やスペースを含まないフォルダに解凍するのが無難
例えばc:\User\username\c3
に解凍したとするc3 │ c3c.exe │ msvc_build_libraries.py │ ├─c3c_rt/ │ └─lib/
-
Visual Studio 2022 をインストールしていない人はランタイムライブラリが必要なので
上記c3フォルダ内のmsvc_build_libraries.py
をコマンドラインで実行する
Pythonは導入済みとするとコマンドラインでcd c:\User\username\c3 python msvc_build_libraries.py
とする
-
Windowsの環境変数PATHに
c:\User\username\c3
を追加
C3言語 テストプロジェクトを作る
コマンドラインで
c3c init myapp
myappフォルダにプロジェクトファイル群が生成される
tree myapp
.
|-- build # ビルド後に生成された内容
| |-- myapp.exe
| |-- myapp.lib
| |-- myapp.pdb
| `-- tmp
|-- docs
|-- lib
|-- LICENSE
|-- Makefile
|-- project.json
|-- README.md
|-- resources
|-- scripts
|-- src
| `-- main.c3 # myappのソースコード
`-- test
Hello worldプログラムが src/main.c3
に生成される
cd myapp
cat src/main.c3
src/main.c3の中身
module myapp;
import std::io;
fn int main(String[] args)
{
io::printn("Hello, World!");
return 0;
}
pwd
myapp
c3c run
で実行できる
c3c build
で ビルドのみ
コマンドラインオプションは
c3c -O2 -g0 run
c3c -Os -g0 build
-g0
はデバッグ情報なし、デバッグランタイムなしの指定(リリース用ランタイムを使う)
コンパイル時最適化オプション
これは多分Clang/LLVM と同じはず(未調査)
ベンチマークを取るときは少なくとも -g0
を付けないとオプションによっては
デバッグ用のランタイム(恐らく低速)が使われる可能性がある
実際にビルドした実行ファイルを調べたところ
-g0
-O0 -O1 -O2 -O3
[ VCRUNTIME140.dll ]
[ dbghelp.dll ]
-O4 -O5 -Os -Oz
[ VCRUNTIME140.dll ]
-O0 -O1 -O2 -O3
については-g0
指定がないと低速のデバッグランタイムが使われる-O4 -O5 -Os -Oz
については-g0
なしでもリリース用のランタイムが使われる
C言語の様に書けるが...
- このコードはC3言語用のソースードだけど
- 先頭の
fn
をカットすればC言語でもコンパイル可能で - forループの書式はC99に準拠
- 下記のwhileループはC言語と同じ
fn int total(int a){
int sum = 0;
int k = a << 2;
for(int i = 0, int n = k; i < a; i+=2){
sum += i + n;
n++;
}
while(a-- > 0){
sum += a;
}
return sum;
}
c3cコマンドライン・オプション
$ c3c
Usage: c3c [<options>] <command> [<args>]
Commands:
compile <file1> [<file2> ...] Compile files without a project into an executable.
init <project name> Initialize a new project structure.
init-lib <library name> Initialize a new library structure.
build [<target>] Build the target in the current project.
benchmark Run the benchmarks in the current project.
test Run the unit tests in the current project.
clean Clean all build files.
run [<target>] [-- [<arg1> ...]] Run (and build if needed) the target in the current project.
dist [<target>] Clean and build a target for distribution.
directives [<target>] Generate documentation for the target.
bench [<target>] Benchmark a target.
clean-run [<target>] [-- [<arg1> ...]] Clean, then run the target.
compile-run <file1> [<file2> ...] [-- [<arg1> ...]] Compile files then immediately run the result.
compile-only <file1> [<file2> ...] Compile files but do not perform linking.
compile-benchmark <file1> [<file2> ...] Compile files into an executable and run benchmarks.
compile-test <file1> [<file2> ...] Compile files into an executable and run unit tests.
static-lib <file1> [<file2> ...] Compile files without a project into a static library.
dynamic-lib <file1> [<file2> ...] Compile files without a project into a dynamic library.
headers <file1> [<file2> ...] Analyse files and generate C headers for public methods.
vendor-fetch <library> ... Fetches one or more libraries from the vendor collection.
project <subcommand> ... Manipulate or view project files.
Options:
--stdlib <dir> - Use this directory as the C3 standard library path.
--no-entry - Do not generate (or require) a main function.
--libdir <dir> - Add this directory to the C3 library search paths.
--lib <name> - Add this library to the compilation.
--path <dir> - Use this as the base directory for the current command.
--template <template> - Select template for 'init': "exe", "static-lib", "dynamic-lib" or a path.
--about - Prints a short description of C3.
--symtab <value> - Sets the preferred symtab size.
--max-mem <value> - Sets the preferred max memory size.
--run-once - After running the output file, delete it immediately.
-V --version - Print version information.
-E - Lex only.
-P - Only parse and output the AST as JSON.
-C - Only lex, parse and check.
- - Read code from standard in.
-o <file> - Write output to <file>.
-O0 - Safe, no optimizations, emit debug info.
-O1 - Safe, high optimization, emit debug info.
-O2 - Unsafe, high optimization, emit debug info.
-O3 - Unsafe, high optimization, single module, emit debug info.
-O4 - Unsafe, highest optimization, relaxed maths, single module, emit debug info, no panic messages.
-O5 - Unsafe, highest optimization, fast maths, single module, emit debug info, no panic messages, no backtrace.
-Os - Unsafe, high optimization, small code, single module, no debug info, no panic messages.
-Oz - Unsafe, high optimization, tiny code, single module, no debug info, no panic messages, no backtrace.
-D <name> - Add feature flag <name>.
-U <name> - Remove feature flag <name>.
--trust=<option> - Trust level: none (default), include ($include allowed), full ($exec / exec allowed).
--output-dir <dir> - Override general output directory.
--build-dir <dir> - Override build output directory.
--obj-out <dir> - Override object file output directory.
--script-dir <dir> - Override the base directory for $exec.
--llvm-out <dir> - Override llvm output directory for '--emit-llvm'.
--emit-llvm - Emit LLVM IR as a .ll file per module.
--asm-out <dir> - Override asm output directory for '--emit-asm'.
--emit-asm - Emit asm as a .s file per module.
--obj - Emit object files. (Enabled by default)
--no-obj - Do not output object files, this is only valid for `compile-only`.
--no-headers - Do not generate C headers when building a library.
--target <target> - Compile for a particular architecture + OS target.
--threads <number> - Set the number of threads to use for compilation.
--safe=<yes|no> - Turn safety (contracts, runtime bounds checking, null pointer checks etc) on or off.
--panic-msg=<yes|no> - Turn panic message output on or off.
--optlevel=<option> - Code optimization level: none, less, more, max.
--optsize=<option> - Code size optimization: none, small, tiny.
--single-module=<yes|no> - Compile all modules together, enables more inlining.
--show-backtrace=<yes|no> - Show detailed backtrace on segfaults.
-g - Emit debug info.
-g0 - Emit no debug info.
-l <library> - Link with the library provided.
-L <library dir> - Append the directory to the linker search paths.
-z <argument> - Send the <argument> as a parameter to the linker.
--cc <path> - Set C compiler (for C files in projects and use as system linker).
--linker=<option> [<path>] - Linker: builtin, cc, custom (default is 'cc'), 'custom' requires a path.
--use-stdlib=<yes|no> - Include the standard library (default: yes).
--link-libc=<yes|no> - Link libc other default libraries (default: yes).
--emit-stdlib=<yes|no> - Output files for the standard library. (default: yes)
--panicfn <name> - Override the panic function name.
--testfn <name> - Override the test runner function name.
--benchfn <name> - Override the benchmark runner function name.
--reloc=<option> - Relocation model: none, pic, PIC, pie, PIE.
--x86cpu=<option> - Set general level of x64 cpu: baseline, ssse3, sse4, avx1, avx2-v1, avx2-v2 (Skylake/Zen1+), avx512 (Icelake/Zen4+), native.
--x86vec=<option> - Set max type of vector use: none, mmx, sse, avx, avx512, default.
--riscvfloat=<option> - Set type of RISC-V float support: none, float, double
--memory-env=<option> - Set the memory environment: normal, small, tiny, none.
--strip-unused=<yes|no> - Strip unused code and globals from the output. (default: yes)
--fp-math=<option> - FP math behaviour: strict, relaxed, fast.
--win64-simd=<option> - Win64 SIMD ABI: array, full.
--debug-stats - Print debug statistics.
--print-linking - Print linker arguments.
--benchmarking - Run built-in benchmarks.
--testing - Run built-in tests.
--list-attributes - List all attributes.
--list-builtins - List all builtins.
--list-keywords - List all keywords.
--list-operators - List all operators.
--list-precedence - List operator precedence order.
--list-project-properties - List all available keys used in project.json files.
--list-manifest-properties - List all available keys used in manifest.json files.
--list-targets - List all architectures the compiler supports.
--list-type-properties - List all type properties.
--print-output - Print the object files created to stdout.
--print-input - Print inputted C3 files to stdout.
--winsdk <dir> - Set the directory for Windows system library files for cross compilation.
--wincrt=<option> - Windows CRT linking: none, static-debug, static, dynamic-debug (default if debug info enabled), dynamic (default).
--windef <file> - Use Windows 'def' file for function exports instead of 'dllexport'.
--macossdk <dir> - Set the directory for the MacOS SDK for cross compilation.
--macos-min-version <ver> - Set the minimum MacOS version to compile for.
--macos-sdk-version <ver> - Set the MacOS SDK compiled for.
--linux-crt <dir> - Set the directory to use for finding crt1.o and related files.
--linux-crtbegin <dir> - Set the directory to use for finding crtbegin.o and related files.
--vector-conv=<option> - Set vector conversion behaviour: default, old.
--sanitize=<option> - Enable sanitizer: address, memory, thread.
ChatGPT に聞いてみた
GPT-4o モデル: スクリプト: C3言語のC言語との違いについて超絶詳しく教えて
出力は省略 😃
詳細は省略 http://c2lang.org/ ,https://github.com/c2lang/c2compiler ↩︎
内容について間違いや勘違いがあれば後日修正します ↩︎
恐らくグローバル変数も(C言語流れなので) ↩︎