# coffee-ahk

[English](./README.md) | [中文](./README.zh.md) | [日本語](./README.ja.md)

`coffeescript` を `ahk` に変換します。

[Documentation](./docs/documentation.md) | [中国語ドキュメント](./docs/cn/documentation.md) | [AI Agent 使用ガイド](./USAGE.md)

> **AI エージェント向け**: [USAGE.md](./USAGE.md) に、AHK 変換向けの CoffeeScript 作法をまとめています。文書は中国語ですが、AI エージェントは問題なく理解できます。

## 特長

- CoffeeScript を AutoHotkey v1 スクリプトに変換
- クラス構文、継承、メソッドバインディングをサポート
- モジュールの import/export 構文（`.coffee`、`.ahk`、`.json`、`.yaml` を含む）
  - `import './module'`（副作用）、`import m from './module'`（デフォルト）、`import { a, b } from './module'`（名前付き）、`import m, { a } from './module'`（混在）
  - `export default`（単一式、複数行ブロック、またはオブジェクトリテラル）
  - `export { named, exports }`（名前付きエクスポート、任意のキー/値ペア）
  - 再帰的な import 解決と名前空間の分離
- `node_modules` を部分的にサポート：裸の import は `package.json` の `main` フィールド経由で `./node_modules/<pkg>` を解決
- 関数型プログラミングに対応。関数は第一級市民
- アロー関数（`->`, `=>`）と `this` バインディング
- 引数バインディング、デフォルト値、可変長引数
- 配列/オブジェクトの分割代入
- 分割代入、スプラット、連鎖比較、負のインデックス、if-then-else 式などのシンタックスシュガー
- try/catch/finally によるエラー処理
- 連鎖呼び出しと暗黙の関数呼び出し
- 匿名関数と高階関数
- バッククォートでのネイティブ AHK コード埋め込み
- 変数/予約語の厳密チェック

## 使い方

```shell
pnpm i coffee-ahk
```

```typescript
import c2a from "coffee-ahk";

await c2a("./script/toolkit/index.coffee", {
  salt: "toolkit",
  save: true,
  verbose: false,
});
```

## オプション

| オプション | 型      | デフォルト | 説明                                                                       |
| ---------- | ------- | ---------- | -------------------------------------------------------------------------- |
| `salt`     | string  | auto       | 生成関数の識別子プレフィックス。既定はソースパス/内容の決定的ハッシュ（`s`+base36）|
| `save`     | boolean | true       | `.ahk` ファイルに書き込み                                                  |
| `string`   | boolean | false      | 入力をソース文字列として扱い、コンパイル結果を返す                          |
| `comments` | boolean | false      | 出力コメントを保持                                                         |
| `metadata` | boolean | true       | 出力にタイムスタンプコメントを含める                                       |
| `ast`      | boolean | false      | `<name>.ast.json` も出力（`save` が必要）                                  |
| `coffeeAst`| boolean | false      | CoffeeScript AST を表示（`verbose` が必要）                                |
| `verbose`  | boolean | false      | デバッグログを有効化                                                       |

## 制限

- AutoHotkey は大文字/小文字を区別しません。変数名・関数名も同様です。
  **クラス名は大文字/小文字を区別するように擬似的に扱います：**
  - クラス名は大文字で始める必要があります。
  - AHK v1 での大文字/小文字の疑似表現のため、クラス識別子内の大文字は全角 Unicode に置き換えます（例: `Animal` → `Ａnimal`）。
- getter/setter は未対応
- **1 文字クラス名は禁止**：AHK v1 では 1 文字のクラス名に問題があります。クラス名は 2 文字以上が必要です。
- **暗黙の return は単一文の関数本体のみ有効**：
  - 本体が 1 つの文/式の関数は自動で return
  - 複数文の本体は明示的な `return` が必要
  - 例外: 関数本体の最後の文が `if`/`else if`/`else` チェーンの場合、実行された分岐の最後の式を返す——複数文本体でも有効で、分岐末尾のネストした `if` は再帰処理される
  - `for`/`while`/`try`/native 本体は暗黙 return されない
  - 波括弧なしの複数行オブジェクトリテラルは壊れた出力になる——`return { ... }` で括弧を付けること
- AHK に真の boolean 型はなく、`true`、`false`、`on`、`off` はシンタックスシュガー
- AHK では文字と数字の区別が曖昧で、`'0'` は偽扱い
- `NaN`、`null`、`undefined` は空文字列 `''` に変換
- オプショナルチェーン (`?`) は未対応（コンパイルエラー）
- 符号なし右シフト (`>>>`) は未対応（コンパイルエラー）
- `async`/`await` とジェネレーター（`yield`）は未対応（コンパイルエラー）
- for ループ分割代入（`for [a, b] in arr`）は未対応（コンパイルエラー）。回避: `for item in arr` の後に `[a, b] = item`
- ネストした配列分割代入（`[a, [b, c]] = x`）は未対応（コンパイルエラー）。回避: 手動で平坦化
- if-then-else 式は `=` 右辺、`return`/`throw` の後、括弧内で使用可能。`else` 省略時は `""`、`else if` チェーンは右結合の三項演算にコンパイル。呼び出し引数・配列・インデックス括弧・オブジェクトリテラル内は未対応（コンパイルエラー）——先に変数へ代入すること
- ネストした if-then-else 式（`if a then (if b then c else d) else e`）は未対応（コンパイルエラー）。回避: 一時変数または分割した文
- 後置形（`return x if y`、`x++ while c`、`x++ for x in xs`）、ループ内包表記、`for` 修飾子（`when`/`by`/`own`）は未対応（コンパイルエラー）
- `export` はファイルベースのコンパイルのみ対応——文字列入力中の `export` はコンパイルエラー。`export {}` は合法な no-op
- `||`/`&&` は `=` 右辺でチェーン末尾が非ブールリテラルの場合のみ値を保持する三項演算に変換（`x = a || "d"` は `x := a ? a : "d"` 相当）。それ以外では AHK の 0/1 ブール意味のまま
- スプレッド呼び出し `f(...args)` は `args*` にコンパイル。メンバー/インデックス式のスプレッド（`f(...a.b)`）は未対応（コンパイルエラー）——先に変数へ代入すること
- `arguments` と `eval` は未対応（コンパイルエラー）——rest パラメータ（`args...`）または事前計算を使用
- 式位置の `try`/`switch`、regex リテラル（`///...///`）、`debugger` は未対応（コンパイルエラー）
- 切り捨て除算（`//`）と剰余（`%`、`%%`）は AHK 構文と衝突（コンパイルエラー）。代わりに `Mod(a, b)` を使用
- クラス外で `=>` を使わないでください。AHK の純関数には `this` がありません
- `.coffee` は UTF-8、`.ahk` は BOM 付き UTF-8 が必須
- import/export と `node_modules` 解決は不完全
- **クラス + Export の衝突**：AHK v1 のクラスはトップレベルに定義する必要があります（関数/クロージャ内不可）。エクスポート対象モジュールはスコープ分離のため `do ->` で包まれるため、クラスを直接 export できません。回避: クラスを別ファイルに定義し `export` せず、`import './myclass'` の副作用 import でトップレベルに読み込む。
- **配列/オブジェクト索引の制限**：AHK v1 では `[]` は `{}` のシンタックスシュガー（`[a,b]` は `{1:a, 2:b}`）で、配列とオブジェクトをネイティブに区別できません。インデックス変換器（`ℓci`）は配列を数値インデックス、オブジェクトを文字列キーとして扱います。オブジェクトで数値キー（例: `obj[0]`）を使うと `obj[1]` に誤変換されます。注意: AHK v1 では `obj[0]` と `obj["0"]` は**別キー**です（数値 vs 文字列）。変数は例外で、`i := "0"; obj[i]` は数値キーにアクセスします（純数字文字列は自動変換）。回避: 文字列キーは `obj["0"]` を使うか、Native 埋め込みで直接 AHK にアクセスしてください。
- **Native 変数参照**：関数内の Native コードは、一時変数（`λ_var`）でクロージャ変数を橋渡しします。Native ブロック前: `λ_var := λ.var`、ブロック後: `λ.var := λ_var`。これにより `Sort` や `StringUpper` などの AHK コマンドが単純変数を扱えます。

---

## 言語機能の互換性

| 機能 / 構文                               | CoffeeScript |   AutoHotkey v1    | coffee-ahk |
| ---------------------------------------- | :----------: | :----------------: | :--------: |
| **coffee-ahk の利点**（AHK ❌ → ✅）       |
| アロー関数（`->`, `=>`）                  |      ✅      |         ❌         |     ✅     |
| 匿名関数                                  |      ✅      | ⚠️（Func オブジェクトのみ） |     ✅     |
| `=>` による `this` バインディング         |      ✅      |         ❌         |     ✅     |
| 配列の分割代入                            |      ✅      |         ❌         |     ✅     |
| オブジェクトの分割代入                    |      ✅      |         ❌         |     🟡     |
| 文字列補間（`"#{}"`）                     |      ✅      | ⚠️（`%var%` のみ） |     ✅     |
| 複数行文字列（`"""`）                     |      ✅      |   ⚠️（継続行）     |     ✅     |
| `unless`（否定 if）                       |      ✅      |         ❌         |     ✅     |
| `until`（否定 while）                     |      ✅      |         ❌         |     ✅     |
| 暗黙の return                             |      ✅      |         ❌         |     🟡     |
| `do`（IIFE）                              |      ✅      |         ❌         |     ✅     |
| 暗黙の関数呼び出し                         |      ✅      |   ⚠️（コマンドのみ）|     ✅     |
| `import`/`export`                         |      ✅      |   ⚠️（`#Include`） |     🟡     |
| **完全対応**                              |
| クラス宣言と継承                          |      ✅      |         ✅         |     ✅     |
| コンストラクタ（`__New`）                 |      ✅      |         ✅         |     ✅     |
| `super` / `base`                          |      ✅      |         ✅         |     ✅     |
| 静的メソッド/プロパティ                   |      ✅      |         ✅         |     ✅     |
| 関数のデフォルト引数                      |      ✅      |  ✅（リテラルのみ） |     ✅     |
| `if`/`else`, `switch`/`case`              |      ✅      |         ✅         |     ✅     |
| `for key, value in obj`                   |      ✅      |         ✅         |     ✅     |
| `while`/`loop`                            |      ✅      |         ✅         |     ✅     |
| `break`/`continue`                        |      ✅      |         ✅         |     ✅     |
| `try`/`catch`/`finally`/`throw`            |      ✅      |         ✅         |     ✅     |
| 配列/オブジェクトリテラル                 |      ✅      |         ✅         |     ✅     |
| 真偽値、比較、論理演算                    |      ✅      |         ✅         |     ✅     |
| ビット演算（`&\|^~<<>>`）                 |      ✅      |         ✅         |     ✅     |
| `new` 演算子                              |      ✅      |         ✅         |     ✅     |
| 連鎖メソッド呼び出し                      |      ✅      |         ✅         |     ✅     |
| ネイティブ AHK 埋め込み（バッククォート） |      ❌      |         ✅         |     ✅     |
| **部分対応**                              |
| 可変長引数（`...args`）                   |      ✅      |   ⚠️（可変引数）   |     🟡     |
| 関数呼び出しでのスプレッド                |      ✅      |   ⚠️（可変引数）   |     🟡     |
| `typeof`                                  |      ✅      |         ❌         |     ✅     |
| `instanceof`                              |      ✅      |         ❌         |     ✅     |
| 連鎖比較（`1<y<10`）                      |      ✅      |         ❌         |     ✅     |
| 負のインデックス（`arr[-1]`）             |      ✅      |         ❌         |     ✅     |
| If-then-else 式（`if a then b else c`）    |      ✅      |         ❌         |     ✅     |
| **非対応**                                |
| オプショナルチェーン（`?.`）              |      ✅      |         ❌         |     ❌     |
| Null 合体（`??`）                         |      ✅      |         ❌         |     ❌     |
| Getter/Setter                             |      ✅      |    ⚠️（メタ関数）  |     ❌     |
| `async`/`await`                           |      ✅      |         ❌         |     ❌     |
| ジェネレーター/`yield`                    |      ✅      |         ❌         |     ❌     |
| `Map`/`Set`/`Symbol`                      |      ✅      |         ❌         |     ❌     |

注: coffee-ahk 列が ❌ の機能は **コンパイルエラー** になります（説明付き）。

凡例:
✅ サポート・同等  🟡 部分対応/制限あり  ⚠️ 注意事項あり  ❌ 非対応
