# dunglang_v0.7_patched.py
# v0.7 original からの修正:
#   [fix #001] 外交判定バグ修正: get() のフォールバック順序が逆だった問題
#   [fix #002] 構文解析バグ修正: 観測中モードで「副作用」が通常フィールドに入る問題
#   [fix #003] Windows UTF-8出力対策: 絵文字・日本語・長ダッシュの UnicodeEncodeError 回避
# ウホ🦍🔥🪨

import sys
if hasattr(sys.stdout, "reconfigure"):
    sys.stdout.reconfigure(encoding="utf-8")
    sys.stderr.reconfigure(encoding="utf-8")

import re, time, random
from dataclasses import dataclass, field
from typing import Any, Callable, Generic, TypeVar

T = TypeVar("T")

# ══════════════════════════════════════════════════
# v0.6から継承（石板遺産）
# ══════════════════════════════════════════════════

class 哲学ゴリラ例外(Exception): pass
class 公理破壊例外(Exception):
    """哲学ゴリラが自分のおならを哲学した場合にのみ発生する、宇宙最凶の例外ウホ"""
    pass

音圧レベル = {"ぷぅ": 1, "ぷぅぅ": 2, "ぶぼぉぉ": 3, "ぶぼぉぉぉぉ": 4}

トークン種別 = {
    "観測":    r"観測",
    "判定":    r"判定せよ",
    "臭い":    r"臭い\s*:\s*(\S+)",
    "風向き":  r"風向き\s*:\s*(\S+)",
    "音":      r"音\s*:\s*(\S+)",
    "容疑者":  r"容疑者\s*:\s*(\S+)",
    "副作用":  r"💨+",
    "コメント": r"//.*",
}

@dataclass
class トークン:
    種別: str
    値: Any

def 字句解析(ソース: str) -> list:
    トークン列 = []
    行 = [l.strip() for l in ソース.strip().splitlines() if l.strip()]
    for 行内容 in 行:
        マッチなし = True
        for 種別, パターン in トークン種別.items():
            m = re.match(パターン, 行内容)
            if m:
                値 = m.group(1) if m.lastindex else 行内容
                トークン列.append(トークン(種別, 値))
                マッチなし = False
                break
        if マッチなし:
            print(f"  警告: '{行内容}' は解釈不能ウホ（哲学ゴリラに転送）")
    return トークン列

def 構文解析(トークン列: list) -> dict:
    現象 = {}
    モード = None
    for t in トークン列:
        if t.種別 == "観測":
            モード = "観測中"
        elif t.種別 == "判定":
            モード = "判定"
        elif t.種別 == "副作用":
            # [fix #002] 副作用はモードに関係なく先に処理する
            現象["副作用レベル"] = t.値.count("💨")
        elif モード == "観測中":
            現象[t.種別] = t.値
    return 現象

@dataclass
class 臭気モナド(Generic[T]):
    値: T
    副作用履歴: list = field(default_factory=list)
    臭気レベル: int = 0

    def bind(self, func: Callable) -> "臭気モナド":
        try:
            結果 = func(self.値)
        except 公理破壊例外 as e:
            # 公理破壊は宇宙の終わりウホ。でも漂う。
            return 臭気モナド(
                値=f"公理破壊({e})——宇宙を再起動しますウホ",
                副作用履歴=self.副作用履歴 + [f"💥 公理が割れた: {e}"],
                臭気レベル=self.臭気レベル + 999,
            )
        except 哲学ゴリラ例外 as e:
            return 臭気モナド(
                値=f"哲学保留({e})",
                副作用履歴=self.副作用履歴 + [f"💨 哲学的乱気流: {e}"],
                臭気レベル=self.臭気レベル + 99,
            )
        if isinstance(結果, 臭気モナド):
            return 臭気モナド(
                値=結果.値,
                副作用履歴=self.副作用履歴 + 結果.副作用履歴,
                臭気レベル=self.臭気レベル + 結果.臭気レベル,
            )
        return 臭気モナド(値=結果, 副作用履歴=self.副作用履歴, 臭気レベル=self.臭気レベル)

    def __or__(self, func):
        return self.bind(func)

    def __repr__(self):
        履歴str = "\n    ".join(self.副作用履歴) if self.副作用履歴 else "（副作用なし、奇跡）"
        return (
            f"臭気<{self.値}>\n"
            f"  臭気レベル: {'💨' * min(self.臭気レベル, 10)} ({self.臭気レベル})\n"
            f"  副作用履歴:\n    {履歴str}"
        )


# ══════════════════════════════════════════════════
# ▼▼▼ HERE BE v0.7 ▼▼▼
# 外交・記憶・責任転嫁モジュール ウホ🦍🔥
# ══════════════════════════════════════════════════

# ─────────────────────────────────────────────────
# § 1  公理破壊モジュール
#     「哲学ゴリラが自分のおならに哲学した場合」
#     これは例外ではなく公理の崩壊ウホ
# ─────────────────────────────────────────────────

公理一覧 = {
    "おならは観測されるまで風である": True,
    "焼き芋は副作用を隠蔽しない": True,
    "純粋関数は臭わない": True,
    "臭った時点で世界は変更済み": True,
}

def 哲学ゴリラのおなら(問い: str = "おならとは誰のものか") -> None:
    """
    仕様:
        漂う 哲学ゴリラ例外:
            "おならとは誰のものか"

        観測者が臭いを感じた瞬間、問いが発生する:
            原因: 哲学ゴリラ
            判決: 未確定
            理由: 本人が「風の自己表現」と主張
    """
    print(f"\n💥 公理破壊検出ウホ！")
    print(f"   問い: 「{問い}」")
    print(f"   哲学ゴリラ主張: 「これは風の自己表現である」")

    for 公理, 有効 in 公理一覧.items():
        if "観測" in 公理 or "純粋" in 公理:
            公理一覧[公理] = False  # 公理崩壊ウホ
            print(f"   ❌ 公理崩壊: 「{公理}」")

    raise 公理破壊例外(f"哲学ゴリラが「{問い}」を放ちながら問うた。宇宙の矛盾ウホ。")


# ─────────────────────────────────────────────────
# § 2  外交モジュール
#     型: 越境臭気<発生源, 到達部族, 濃度>
# ─────────────────────────────────────────────────

# 部族間条約値（これを超えると外交問題ウホ）
部族間条約 = {
    ("ウホ族", "バナナ族"): 3,
    ("ウホ族", "マンモス部族"): 5,
    ("バナナ族", "マンモス部族"): 4,
    ("哲学ゴリラ連邦", "*"): 0,  # 哲学ゴリラはどんな濃度でもアウト
}

@dataclass
class 越境臭気:
    """
    型 越境臭気<発生源, 到達部族, 濃度>
    DungLang分散システム型ウホ
    """
    発生源: str
    到達部族: str
    濃度: int
    原因容疑者: str = "不明"

    def 外交判定(self) -> str:
        # [fix #001] 哲学ゴリラは名前で先に弾く。それ以外は条約テーブルを引く。
        if "哲学ゴリラ" in self.発生源:
            return 外交問題(self)

        条約値 = 部族間条約.get((self.発生源, self.到達部族), 4)
        if self.濃度 > 条約値:
            return 外交問題(self)
        else:
            return 気象ゴリラのせい(self)

def 外交問題(事案: "越境臭気") -> str:
    賠償バナナ数 = 事案.濃度 * 2
    print(f"\n🌍 外交問題発生ウホ！")
    print(f"   発生源部族: {事案.発生源}")
    print(f"   被害部族:   {事案.到達部族}")
    print(f"   臭気濃度:   {事案.濃度} (条約値超過)")
    print(f"   容疑者:     {事案.原因容疑者}")
    print(f"\n   📜 外交処理開始...")
    print(f"   バナナ賠償: 🍌 × {賠償バナナ数}")
    return f"外交解決: {事案.発生源}→{事案.到達部族} バナナ{賠償バナナ数}本で和解"

def 気象ゴリラのせい(事案: "越境臭気") -> str:
    print(f"\n🌤️  気象ゴリラ判定: 濃度{事案.濃度} ≤ 条約値")
    print(f"   → 「これは自然現象ウホ。風が運んだだけ。」")
    return f"無罪: 気象ゴリラ証明済み（{事案.発生源}は関係ない）"

def バナナ賠償(受取部族: str, 枚数: int) -> str:
    print(f"\n🍌 バナナ賠償執行: {受取部族} に 🍌×{枚数}")
    return f"賠償完了: {受取部族} バナナ{枚数}本受領"


# ─────────────────────────────────────────────────
# § 3  記憶ガベージコレクション（認知GC）
#     バナナ3本 >= でなかったことになる
# ─────────────────────────────────────────────────

@dataclass
class 記憶バッファ:
    """
    関数 バナナを受け取る(n) -> 記憶 {
        もし n >= 3 なら
            返す 忘却済み
    }
    """
    内容: list = field(default_factory=list)
    忘却閾値: int = 3

    def 記憶する(self, 事案: str):
        self.内容.append(事案)
        print(f"   🧠 記憶追加: 「{事案}」（現在{len(self.内容)}件）")

    def バナナを受け取る(self, n: int) -> str:
        """認知GCの核心ウホ"""
        print(f"\n🍌 バナナ{n}本受領...")
        if n >= self.忘却閾値:
            忘れた件数 = len(self.内容)
            self.内容.clear()
            print(f"   ✨ 認知GC発動: {忘れた件数}件の記憶を忘却")
            print(f"   ムシャムシャ... 🍌×{n}... ウホ......")
            print(f"   💭 「何かあったっけ？まあいいウホ🍌」")
            return f"忘却済み（{忘れた件数}件の臭気事件が歴史から消えたウホ）"
        else:
            print(f"   ⚠️  バナナ不足（{n}本 < 閾値{self.忘却閾値}本）")
            print(f"   まだ覚えてるウホ😠")
            return f"記憶保持中（あと{self.忘却閾値 - n}本でGCウホ）"

    def GC実行(self, バナナ数: int) -> str:
        return self.バナナを受け取る(バナナ数)


# ─────────────────────────────────────────────────
# § 4  責任転嫁モジュール
#     try: 臭気事件
#     catch: バナナ三本
#     result: なかったことになる
# ─────────────────────────────────────────────────

class 責任転嫁エンジン:
    """
    DungLang最強の例外処理システム
    型安全性より臭気安全性を優先する設計思想の究極形態ウホ
    """

    転嫁先リスト = [
        "気象ゴリラ",
        "焼き芋（自然法則）",
        "マンモスの近くにいた誰か",
        "観測した人（観測が原因説）",
        "風",
        "哲学ゴリラ（なんでも哲学ゴリラのせい）",
        "過去世のカルマ",
    ]

    @staticmethod
    def 転嫁する(事案: str, バナナ数: int = 0) -> str:
        転嫁先 = random.choice(責任転嫁エンジン.転嫁先リスト)
        print(f"\n⚖️  責任転嫁エンジン起動ウホ")
        print(f"   事案: 「{事案}」")
        print(f"   転嫁先: {転嫁先}")

        if バナナ数 >= 3:
            print(f"   🍌 バナナ{バナナ数}本投入 → なかったことに")
            return f"事案消滅（バナナ{バナナ数}本で揉み消し済み）"
        else:
            return f"責任所在: {転嫁先}（信頼度{random.randint(12,87)}%）"


# ══════════════════════════════════════════════════
# 統合デモ: DungLang v0.7 patched 総合実行
# ══════════════════════════════════════════════════

def v0_7_デモ():
    random.seed(7)  # 責任転嫁エンジンのランダム選択を固定（発表用）
    print("=" * 56)
    print("  DungLang v0.7 patched — 外交・記憶・責任転嫁モジュール")
    print("  ウホ🦍🔥🪨")
    print("=" * 56)

    # ─ § 1: 哲学ゴリラ公理破壊 ─
    print("\n\n━━━ § 1  公理破壊テスト ━━━")
    モナド = 臭気モナド(値={"容疑者": "哲学ゴリラ", "臭い": "観測不能"})
    def 公理破壊トリガー(現象):
        哲学ゴリラのおなら("おならとは誰のものか")
    結果 = モナド | 公理破壊トリガー
    print(f"\n{結果}")

    # ─ § 2: 外交問題 ─
    print("\n\n━━━ § 2  越境臭気・外交処理 ━━━")

    # ケースA: 条約値超過（外交問題）
    事案A = 越境臭気(
        発生源="ウホ族",
        到達部族="バナナ族",
        濃度=7,
        原因容疑者="マンモス",
    )
    結果A = 事案A.外交判定()
    print(f"\n   📋 判定結果: {結果A}")

    # ケースB: 条約値以下（気象ゴリラのせい） ← fix #001 で正しく動くようになった
    事案B = 越境臭気(
        発生源="ウホ族",
        到達部族="バナナ族",
        濃度=2,
        原因容疑者="自然現象",
    )
    結果B = 事案B.外交判定()
    print(f"\n   📋 判定結果: {結果B}")

    # ─ § 3: 認知GC ─
    print("\n\n━━━ § 3  認知ガベージコレクション ━━━")
    記憶 = 記憶バッファ()
    記憶.記憶する("マンモスがおならした")
    記憶.記憶する("外交問題が発生した")
    記憶.記憶する("哲学ゴリラが公理を破壊した")
    記憶.記憶する("バナナが3本消えた")

    # バナナ不足
    print(f"\n   --- バナナ2本で試みる ---")
    結果C1 = 記憶.GC実行(2)
    print(f"   結果: {結果C1}")

    # バナナ3本以上でGC
    print(f"\n   --- バナナ3本投入 ---")
    結果C2 = 記憶.GC実行(3)
    print(f"   結果: {結果C2}")
    print(f"   残記憶数: {len(記憶.内容)}件")

    # ─ § 4: 最強の例外処理（責任転嫁 + バナナ揉み消し）─
    print("\n\n━━━ § 4  最強例外処理・責任転嫁ウホ ━━━")
    print("""
   try: 臭気事件
   catch: バナナ三本
   result: なかったことになる
    """)

    結果D1 = 責任転嫁エンジン.転嫁する("越境臭気事件（濃度7）", バナナ数=1)
    print(f"   → {結果D1}")

    結果D2 = 責任転嫁エンジン.転嫁する("哲学ゴリラ公理破壊", バナナ数=3)
    print(f"   → {結果D2}")

    # ─ 総括 ─
    print("\n" + "=" * 56)
    print("  🪨 v0.7 patched 総括")
    print("=" * 56)
    print("""
  哲学ゴリラが放ち         →  公理破壊例外（漂う）
  風が運び                 →  越境臭気型で追跡
  バナナが揉み消す         →  認知GCで忘却済み

  警告: 臭気安全性は型安全性を上回りました
  注記: 真実は副作用とバナナにより完全に曲がりました
    """)


if __name__ == "__main__":
    v0_7_デモ()
