Skip to content

エラーハンドリング強化#55

Merged
shadowlink0122 merged 15 commits intomainfrom
feature/v0.13.1
Nov 16, 2025
Merged

エラーハンドリング強化#55
shadowlink0122 merged 15 commits intomainfrom
feature/v0.13.1

Conversation

@shadowlink0122
Copy link
Owner

@shadowlink0122 shadowlink0122 commented Nov 15, 2025

Cb言語 v0.13.1 統合リリースノート

リリース日: 2025年11月16日
ステータス: ✅ Released
Git Tag: v0.13.1


🎯 概要

v0.13.1は、v0.13.0で導入されたAsync/Awaitとジェネリクス機能を大幅に強化し、実用的な言語として成熟させる重要なリリースです。このリリースでは、4つの段階的な改善(v0.13.1~v0.13.4)を統合し、以下の主要な機能を提供します:

  • ジェネリック構造体配列の完全サポート - 構造体内の配列、配列の構造体、ジェネリック関数との連携が完全に動作
  • Async Implメソッドの完全サポート - Interface/Impl内でasyncメソッドが完全に動作
  • 文字列配列とVector - 文字列を配列やベクターで扱えるように
  • ネストしたmatch式 - 複雑なenum型のパターンマッチングをサポート
  • Generic配列の修正 - すべての型でGeneric配列が正しく動作
  • try/checked式の実装 - Result型ベースのエラーハンドリング
  • 包括的テストスイート - 4373テスト全合格、672行の新規テストコード

🆕 主要新機能

1. ジェネリック構造体配列の包括的サポート 🔥

ジェネリック構造体内の配列、ジェネリック構造体の配列、そしてジェネリック関数との連携が完全に動作するようになりました。

構造体内の配列:

struct Container<T> {
    T[5] items;
    int count;
};

Container<int> int_container;
int_container.items[0] = 10;
int_container.items[1] = 20;

Container<string> str_container;
str_container.items[0] = "Hello";
str_container.items[1] = "World";

配列の構造体:

struct Box<T> {
    T value;
};

Box<int>[3] boxes;
boxes[0].value = 10;
boxes[1].value = 20;
boxes[2].value = 30;

ジェネリック関数との連携:

Box<T> make_box<T>(T value) {
    Box<T> result;
    result.value = value;
    return result;
}

T max<T>(T a, T b) {
    if (a > b) return a;
    return b;
}

Container<int> c;
c.items[0] = 10;
c.items[1] = 50;
int max_val = max<int>(c.items[0], c.items[1]);  // 50

実装内容:

  • 構造体内の配列(T[N])の完全サポート
  • 配列の構造体(S<T>[N])の完全サポート
  • ネストされたジェネリック構造体のサポート
  • 複数型パラメータ(Pair<T, U>)のサポート
  • ループ、コピー、更新、検索などの操作

包括的テスト:

  • 672行のテストコード
  • 30のテストセクション
  • 75以上のアサーション
  • int, long, string型のサポート確認

2. Async Implメソッドと自動self同期

2. Async Implメソッドと自動self同期

Interface/Impl内でasyncメソッドを定義し、selfを通じた状態管理が自動的に行われるようになりました。

interface Counter {
    async int increment(int amount);
}

struct MyCounter {
    int count;
}

impl Counter for MyCounter {
    async int increment(int amount) {
        self.count = self.count + amount;  // selfへの書き込み
        yield;  // 処理を中断
        return self.count;  // 自動的に元の構造体に反映される
    }
}

技術的詳細:

  • SimpleEventLoopがタスク完了時に自動的にselfを同期
  • yieldを含む複雑な非同期処理でも状態が保証される
  • __self_receiver__メタ変数でレシーバー名を追跡

修正されたバグ:

  • ASYNC-172: async implメソッドでselfを書き換えてもawait後に値が戻らない
  • ASYNC-173: yieldを含むasync implメソッドでselfメンバーが破棄される
  • ASYNC-174: selfメンバー代入時に元のレシーバーを特定できない
  • ASYNC-176: ASanビルドで累積値が0に戻る問題

3. 文字列配列のサポート

string[N]型の配列が完全に動作するようになりました。

void main() {
    // 宣言と代入
    string[3] fruits;
    fruits[0] = "Apple";
    fruits[1] = "Banana";
    fruits[2] = "Cherry";
    
    // リテラルからの初期化
    string[5] days = ["Mon", "Tue", "Wed", "Thu", "Fri"];
    
    // const配列
    const string[2] greetings = ["Hello", "World"];
    
    // アクセス
    println("First fruit: '{fruits[0]}'");  // First fruit: 'Apple'
}

実装内容:

  • 配列要素への代入時に基底型(TYPE_STRING)をチェック
  • array_stringsベクターへの直接代入をサポート
  • const修飾子のチェックを追加

4. Vectorのサポート

文字列をVectorで扱えるようになり、動的な文字列配列が可能になりました。

import stdlib.std.vector;

void main() {
    Vector<string> names;
    
    // 要素の追加
    names.push_back("Alice");
    names.push_back("Bob");
    names.push_front("Charlie");
    
    // アクセス
    string first = names.at(0);  // "Charlie"
    println("First: '{first}'");
    
    // 長さ
    long len = names.get_length();  // 3
    
    // 削除
    names.pop_back();  // "Bob"を削除
}

技術的詳細:

  • 文字列の自動deep copy: malloc()で新しいメモリを確保
  • 既存文字列の自動解放: 上書き時に古い文字列をfree()
  • メモリレイアウト: char*ポインタの配列

5. ネストしたmatch式

Option<Result<T, E>>のような複雑な型でパターンマッチングができるようになりました。

void main() {
    Result<int, string> inner = Result<int, string>::Ok(42);
    Option<Result<int, string> > outer = Option<Result<int, string> >::Some(inner);
    
    match (outer) {
        Some(result) => {
            println("Outer: Some");
            match (result) {  // ネストしたmatch
                Ok(value) => {
                    println("Inner: Ok({value})");  // Inner: Ok(42)
                }
                Err(error) => {
                    println("Inner: Err({error})");
                }
            }
        }
        None => {
            println("Outer: None");
        }
    }
}

実装内容:

  • Variableにassociated_valueフィールドを追加(生ポインタとして実装)
  • enum変数の評価を拡張(関連値の有無で処理を分岐)
  • matchのバインディング処理を拡張
  • 古いスタイルのenum(関連値なし)との互換性を維持

重要な技術的決定:

  • std::shared_ptr<Variable>ではなく生ポインタ(Variable*)を使用
  • deep copyでメモリ破壊問題を回避

6. try/checked式の実装

trychecked式でエラーハンドリングが可能になりました。

void main() {
    // try式: 例外をResult型に変換
    Result<int, RuntimeError> result = try {
        int value = risky_operation();
        value * 2
    };
    
    match (result) {
        Ok(value) => println("Success: {value}"),
        Err(error) => println("Error occurred")
    }
    
    // checked式: 境界チェックなどを強制
    Result<int, RuntimeError> safe_result = checked {
        arr[10]  // 範囲外アクセスをエラーとして返す
    };
}

実装内容:

  • AST_TRY_EXPR/AST_CHECKED_EXPRノードを追加
  • ReturnException/RuntimeExceptionを捕捉してResult<T, RuntimeError>へ変換
  • 配列境界・ポインタ参照・算術演算などを安全モードで実行

7. Generic配列の文字列型バグ修正

Container<string>のようなGeneric構造体の配列メンバーで、文字列が正しく表示されるようになりました。

修正前:

struct Container<T> {
    T[5] items;
};

Container<string> cs;
cs.items[0] = "Hello";
println("{cs.items[0]}");  // "0"が表示される(バグ)

修正後:

Container<string> cs;
cs.items[0] = "Hello";
println("{cs.items[0]}");  // "Hello"が正しく表示される ✅

実装内容:

  • 構造体メンバー配列アクセスの型判定を改善
  • 型推論に頼らず、実際のVariableの状態を確認
  • 文字列配列の判定を2段階で実装

🐛 修正されたバグ

カテゴリ ID 内容 詳細
Async ASYNC-172 async implメソッドでselfを書き換えてもawait後に値が戻らない イベントループがselfの書き戻しを行っていなかった問題を修正
Async ASYNC-173 yieldを含むasync implメソッドでselfメンバーが破棄される タスクスコープにselfself.*を丸ごと保持
Async ASYNC-174 selfメンバー代入時に元のレシーバーを特定できない __self_receiver__メタ変数を導入
Async ASYNC-176 ASanビルドのみ累積値が0に戻る forループがyield後に誤って同じ代入をやり直さないよう修正
Generic GEN-201 Generic配列で文字列型を使用すると"0"が表示される 型判定を改善し、実際のデータを確認するようになった
String STR-301 文字列配列への代入でセグメンテーションフォールト 文字列配列への代入処理を実装
String STR-302 Vectorでセグメンテーションフォールト 文字列のdeep copy実装を追加
Enum ENUM-401 古いスタイルのenumが"(struct)"と表示される 関連値の有無で処理を分岐
Memory MEM-501 std::shared_ptrによるメモリ破壊 生ポインタとdeep copyを使用するよう変更
Test TEST-601 Integration testのタイミング測定の単位不一致 ミリ秒と秒の混在を修正、パフォーマンステストが正しく動作するように

📊 テスト結果

最終テスト統計

═══════════════════════════════════════════════════════════
=== Final Test Summary ===
═══════════════════════════════════════════════════════════
✅ [1/4] Integration tests: PASSED (4373 tests)
✅ [2/4] Unit tests: PASSED (30 tests)
✅ [3/4] Stdlib C++ tests: PASSED (29 tests)
✅ [4/4] Stdlib Cb tests: PASSED (33 tests, 5 suites)
═══════════════════════════════════════════════════════════
Test suites: 4/4 passed, 0/4 failed
Total time: 23s
═══════════════════════════════════════════════════════════

🎉 All 4 Test Suites Passed Successfully! 🎉

Integration Test詳細:
  Total:  4373 tests
  Passed: 4373 tests
  Failed: 0 tests
  
  Tests with timing: 344
  Total time: 17.8秒
  Average time: 51.8ms
  Min time: 10.2ms
  Max time: 2.7秒

新規テストケース

Async/Await:

  • tests/cases/async/test_impl_async_method.cb - Async implメソッド
  • tests/cases/async/test_impl_async_yield.cb - Async impl + yield
  • tests/cases/async/test_struct_async_method_basic.cb - 構造体asyncメソッド

ジェネリック構造体配列:

  • tests/cases/generics/test_generic_struct_array_comprehensive.cb - 構造体内の配列(251行、10セクション)
  • tests/cases/generics/test_array_of_generic_structs.cb - 構造体の配列(213行、10セクション)
  • tests/cases/generics/test_generic_functions_with_arrays.cb - ジェネリック関数と配列(208行、10セクション)
  • tests/integration/generics/test_generics.hpp - Integration testに3テスト追加(24→27テスト)

エラーハンドリング:

  • tests/cases/error_handling/test_try_checked.cb - try/checked式

その他:

  • tests/cases/v0.13.2/test_comprehensive.cb - Generic配列テスト
  • tests/cases/v0.13.3/test_simple_string_array.cb - 文字列配列
  • ✅ テスト用のVector<string>ケース複数

📈 パフォーマンス

  • ビルド時間: 標準ビルド ~15秒(8コアCPU)
  • テスト時間: 全テスト実行 ~23秒
  • Integration test時間: 17.8秒(4373テスト)
  • 平均テスト時間: 51.8ms/test
  • 最小テスト時間: 10.2ms
  • 最大テスト時間: 2.7秒
  • メモリ使用量: 文字列deep copyによる若干の増加(許容範囲内)

🔄 後方互換性

v0.13.0からv0.13.1へのアップグレードは完全に後方互換性があります:

  1. ✅ 既存のコードはすべて動作します
  2. ✅ 新機能を使用しない限りコード変更は不要
  3. ✅ ビルドやテストの変更は不要

アップグレード手順:

# 最新のソースコードを取得
git checkout v0.13.1
git pull

# クリーンビルド
make clean && make

# テスト実行(オプション)
make test

⚠️ 既知の制限事項

v0.13.1では以下の機能が完全にサポートされています:

✅ 完全サポート機能

  1. ジェネリック構造体配列

    • 構造体内の配列(struct S<T> { T[N] items; }
    • 配列の構造体(S<T>[N]
    • ネストされたジェネリック構造体
    • 複数型パラメータ(Pair<T, U>
    • ジェネリック関数との連携
  2. Async/Await

    • Interface/Impl内のasyncメソッド
    • selfの自動同期
    • yieldを含む複雑な非同期処理
  3. 文字列配列とVector

    • string[N]配列
    • Vector<string>
    • deep copyによるメモリ管理
  4. パターンマッチング

    • ネストしたmatch式
    • Option<Result<T, E>>のような複雑な型

📋 今後の拡張予定(v0.14.x以降)

以下の機能は現在調査中または計画段階です:

  1. Future配列の完全サポート

    Future<int>[3] futures;  // 将来的にサポート予定
    
  2. より高度なAsync/Generic統合

    • async Generic関数
    • Generic Future型
  3. パフォーマンス最適化

    • 文字列コピーの削減
    • メモリ使用量の最適化

📁 変更されたファイル

コア実装(9ファイル)

  1. src/backend/interpreter/core/interpreter.h

    • Variable構造体にassociated_valueフィールドを追加
    • コピーコンストラクタと代入演算子を更新
  2. src/backend/interpreter/evaluator/literals/eval.cpp

    • enum変数の評価を拡張
    • 関連値の有無で処理を分岐
  3. src/backend/interpreter/executors/control_flow_executor.cpp

    • matchのバインディング処理を拡張
    • associated_valueのサポート
  4. src/backend/interpreter/executors/declarations/variable_declaration.cpp

    • enum関連値の設定処理を追加
  5. src/backend/interpreter/managers/variables/declaration.cpp

    • enum関連値の設定処理を追加
  6. src/backend/interpreter/executors/assignments/simple_assignment.cpp

    • 文字列配列への代入処理を追加
  7. src/backend/interpreter/evaluator/functions/call_impl.cpp

    • array_get<T>()/array_set<T>()に文字列型のサポート追加
  8. src/backend/interpreter/event_loop/simple_event_loop.cpp

    • self同期処理を追加
  9. src/backend/interpreter/evaluator/core/evaluator.cpp

    • Generic配列の型判定を改善

テストファイル(7ファイル)

  1. tests/cases/generics/test_generic_struct_array_comprehensive.cb

    • 構造体内の配列の包括的テスト(251行)
  2. tests/cases/generics/test_array_of_generic_structs.cb

    • 構造体の配列の包括的テスト(213行)
  3. tests/cases/generics/test_generic_functions_with_arrays.cb

    • ジェネリック関数と配列の連携テスト(208行)
  4. tests/integration/generics/test_generics.hpp

    • 3つの新しいIntegration testを追加(Test 25-27)
  5. tests/integration/struct/basic_struct_tests.hpp

    • タイミング測定の単位を修正(ミリ秒→秒変換)
  6. tests/cases/generics/README_GENERIC_ARRAY_TESTS.md

    • ジェネリック配列テストの包括的ドキュメント

ドキュメント(4ファイル)

  • docs/spec.md - v0.13.1の仕様を更新
  • docs/todo/v0.13.1_implementation_plan.md - 実装計画(完了)
  • docs/todo/v0.13.4_implementation_plan.md - 実装計画(完了)
  • release_notes/v0.13.1.md - この統合リリースノート

📚 使用例

Async Impl + 文字列配列 + Vector

import stdlib.std.vector;

interface Logger {
    async void log(string message);
}

struct FileLogger {
    Vector<string> logs;
    int count;
}

impl Logger for FileLogger {
    async void log(string message) {
        self.logs.push_back(message);
        self.count = self.count + 1;
        yield;  // I/O待機をシミュレート
        println("[{self.count}] {message}");
    }
}

void main() {
    FileLogger logger;
    
    Future<void> f1 = logger.log("First message");
    Future<void> f2 = logger.log("Second message");
    
    await f1;
    await f2;
    
    println("Total logs: {logger.count}");  // Total logs: 2
    println("First log: '{logger.logs.at(0)}'");  // First log: 'First message'
}

ネストしたmatch + try式

async Result<int, string> divide_async(int a, int b) {
    if (b == 0) {
        return Result<int, string>::Err("Division by zero");
    }
    yield;
    return Result<int, string>::Ok(a / b);
}

void main() {
    Future<Result<int, string>> f1 = divide_async(10, 2);
    Future<Result<int, string>> f2 = divide_async(10, 0);
    
    Option<Result<int, string> > opt1 = Option<Result<int, string> >::Some(await f1);
    Option<Result<int, string> > opt2 = Option<Result<int, string> >::Some(await f2);
    
    // ネストしたmatch
    match (opt1) {
        Some(result) => {
            match (result) {
                Ok(value) => println("Result 1: {value}"),  // Result 1: 5
                Err(error) => println("Error 1: {error}")
            }
        }
        None => println("No result 1")
    }
    
    match (opt2) {
        Some(result) => {
            match (result) {
                Ok(value) => println("Result 2: {value}"),
                Err(error) => println("Error 2: {error}")  // Error 2: Division by zero
            }
        }
        None => println("No result 2")
    }
}

🎯 開発統計

  • 開発期間: 2025年11月15日~16日(2日間)
  • コミット数: 統合前の4つのバージョン + ジェネリック配列テスト + バグ修正
  • 追加コード: ~1,200行(テストコード672行を含む)
  • 削除/修正コード: ~120行
  • 影響を受けたファイル: 20ファイル
  • 修正されたバグ: 10件
  • 追加されたテスト: 13個以上(30テストセクション)
  • 最終テスト数: 4373テスト(全合格)

- Add comprehensive documentation for known issues
- Create v0.13.3 test cases for future implementation
- Update version to v0.13.3
- Update IMPLEMENTATION_STATUS.md
- All existing tests (33 tests, 5 suites) pass

Known Issues (to be fixed in v0.13.4):
- String array initialization
- Vector<string> support
- Generic struct arrays
- Nested match expressions

See release_notes/v0.13.3.md for details
- Add comprehensive generic struct array support as main feature #1
- Update test statistics: 4373 tests (all passing)
- Add new test files documentation (672 lines of test code)
- Fix test timing bug (TEST-601) in bug fixes list
- Update known limitations section (removed generic array limitations)
- Update development statistics and performance metrics
- Document all new test cases and integration tests
@shadowlink0122 shadowlink0122 merged commit dc8ec7b into main Nov 16, 2025
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant