2024年10月19日

C3言語を触ってみた時のメモ (1) 2024/10

C3言語を触ってみた時のメモ (1) 2024/10

C3言語を触ってみた時のメモ (1) 2024/10

(注)このページは調べながら書いているのでどんどん追加修正されていきます

C3言語とは


ぶっちゃけな言い方をすると

C言語があまりにもアレなので (-:
言語仕様を現代的に進化させました

という言語
C2言語[1]からインスパイアされたらしい

C3言語ホーム: https://c3-lang.org/
Github ページ: https://github.com/c3lang/c3c
Discord グループ C3

C3言語の概要


  1. ネイティブコードコンパイラで高速実行、バックエンドはLLVM
  2. 静的型付き言語
  3. C言語好きな人に一定の支持が得られることが期待できる
  4. C言語の雰囲気を残した近縁種な感じ??
  5. C言語コードを外部関数・ライブラリとして使う(使われる)のは簡単にできる(ABIが同じ)

特徴の一部(全部は無理)


[2]

  1. 言語の名前はC3

  2. コンパイラの実行名はc3c

  3. ソースコードの拡張子は*.c3

  4. ファイルを一つコンパイルするだけなら

    c3c compile ./hello.c3
    
  5. コンパイラにビルドツールが統合されている
    ./project.jsonファイルにビルドオプションを書く

  6. C言語を起点として進化した別言語
    部分的に見るとC言語と100%互換があるコードが*.c3cソース内に存在可能 (後述)

  7. 型について

    1. C言語のtypedefdefに置き換わった
    2. すべてのユーザー定義型の1文字目は大文字で始める
  8. 演算子の優先順位の一部はC言語と非互換

  9. foreach文で配列に対してイテレータ(インデックス可)が使える

  10. 独自文法のマクロ構文を導入 (#if #ifdef #define ... マクロは廃止)

  11. Moduleベースのネームスペースを導入(#include は廃止)

  12. defer: 遅延実行ディレクティブあり

  13. エラー処理は例外処理ではなくOptionalを使ってハンドリングする
    unrwap 付き if文, orelse, catch 等が使える

  14. SIMDを使った高速実行を意図したVector型

  15. C++言語のVector型(std::vector)と類似の物は標準ライブラリのList型

  16. 関数の前方参照宣言は不要
    関数の本体を書く前にその関数を呼び出せる

  17. ジェネリクスあり

  18. RAIIはない

  19. 契約プログラミングの導入

  20. 配列に対するスライス(Slice)型の導入

  21. 文字列型は3種類

    1. String型: (== char[])[3] 一般的なロカール/グローバル領域に確保される文字列はこれ
    2. DString型: ヒープ領域に確保される文字列
    3. ZString型: (== char*)[3:1] C言語インターフェースで使う型
  22. 関数にデフォルト引数が使える \(^o^)/

  23. 関数のオーバロードはない

  24. 極一部で演算子のオーバロードが使える

  25. インターフェース型が使える

  26. リフレクションあり(コンパイル時と実行時)

  27. 構造体にメソッドがバインドできる

  28. ◎ 標準ライブラリを使う時にメモリアロケータを明示使用する必要はない(明示しても良い)

  29. elif, elsif に相当する予約語がない様だ

  30. ローカル変数はデフォルト値0で初期化済[4]

    1. 明示的な初期化が無くても警告やエラーは出ない
    2. int y @noinit; の様に0初期化動作を避けることも可能
  31. 構造体のポインタを使ってフィールド参照する時の
    ->.に置き換えられた

  32. バックエンドがLLVMなのでLLVMが対応できるCPUアーキテクチャには対応可能(c3c v1.0目標)

C3言語の状況: 開発ロードマップ


開発ロードマップ

  • 現在のバージョンはv0.6.3でv1.0.0に向けて開発中
    ライブラリは未成熟だけどコンパイラは現状の版でもプロダクションに使えるという記述がある
    v1.0リリースは 2028/04 (今は2024/10)

TODOリスト

  • v1.0に向けて足りないものとして
    1. C言語からC3言語へのコンバーターアプリ
    2. Regex(正規表現)ライブラリなど

気づいた点


  1. ドキュメントがわかりにくい気がする
    項目数は妥当だけど内容の詳細度が足りなくて理解できない部分が多い感じ
  2. 競合?する言語は多分Zig言語
  3. 標準ライブラリでアロケータを明示しなくて良いのでZig言語よりもスッキリ書ける
  4. 型推論について
    ChatGPTやCoPilotに聞いてみるとC3言語には型推論機能があると出るんだけど
    公式文書では探せなかった
    DiscordのC3言語グループ内を検索すると
    型推論の乱用を避けるためマクロ内限定でvar = ..としてだけ使えるみたいだった

C3言語コンパイラのインストール


Download Windows ZIPファイル
インストール方法 Windows

  1. 上記zipファイルを漢字やスペースを含まないフォルダに解凍するのが無難
    例えば c:\User\username\c3 に解凍したとする

    c3
    │  c3c.exe
    │  msvc_build_libraries.py
    │  
    ├─c3c_rt/
    │      
    └─lib/
    
  2. Visual Studio 2022 をインストールしていない人はランタイムライブラリが必要なので
    上記c3フォルダ内のmsvc_build_libraries.pyをコマンドラインで実行する
    Pythonは導入済みとするとコマンドラインで

    cd c:\User\username\c3
    python msvc_build_libraries.py
    

    とする

  3. Windowsの環境変数PATHc:\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 ]
  1. -O0 -O1 -O2 -O3 については -g0 指定がないと低速のデバッグランタイムが使われる
  2. -O4 -O5 -Os -Oz については -g0 なしでもリリース用のランタイムが使われる

C言語の様に書けるが...


  1. このコードはC3言語用のソースードだけど
  2. 先頭のfn をカットすればC言語でもコンパイル可能で
  3. forループの書式はC99に準拠
  4. 下記の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言語との違いについて超絶詳しく教えて

出力は省略 😃


  1. 詳細は省略 http://c2lang.org/ ,https://github.com/c2lang/c2compiler ↩︎

  2. 内容について間違いや勘違いがあれば後日修正します ↩︎

  3. distinctされている ↩︎ ↩︎

  4. 恐らくグローバル変数も(C言語流れなので) ↩︎

posted by Copyright (C) audin All Rights Reserved. at 18:39| Comment(0) | C3言語 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は90日以上新しい記事の投稿がないブログに表示されております。