Metadata-Version: 2.4
Name: cql-lang
Version: 1.4.0
Summary: CQL - Chinese Query Language，一套将中文源码转译为 Python 3 / JavaScript 的中文编程语言，含 CQFastAPI/CQPyqt 等中文适配子包
Home-page: https://example.com/cql-lang
Author: CQFISH&喵酱出品
Author-email: cqfish@example.com
License: MIT
Keywords: chinese language compiler cql lark python fastapi pyqt sqlite
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Compilers
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: lark>=1.0
Provides-Extra: web
Requires-Dist: fastapi>=0.100; extra == "web"
Requires-Dist: uvicorn>=0.20; extra == "web"
Provides-Extra: desktop
Requires-Dist: PySide6>=6.4; extra == "desktop"
Provides-Extra: http
Requires-Dist: requests>=2.25; extra == "http"
Requires-Dist: httpx>=0.23; extra == "http"
Provides-Extra: security
Requires-Dist: PyJWT>=2.0; extra == "security"
Requires-Dist: bcrypt>=4.0; extra == "security"
Provides-Extra: config
Requires-Dist: python-dotenv>=0.20; extra == "config"
Provides-Extra: log
Requires-Dist: loguru>=0.6; extra == "log"
Provides-Extra: image
Requires-Dist: Pillow>=9.0; extra == "image"
Provides-Extra: crypto
Requires-Dist: cryptography>=40.0; extra == "crypto"
Provides-Extra: data
Requires-Dist: pydantic>=2.0; extra == "data"
Provides-Extra: office
Requires-Dist: python-docx>=0.8; extra == "office"
Requires-Dist: openpyxl>=3.0; extra == "office"
Provides-Extra: dataframe
Requires-Dist: pandas>=1.3; extra == "dataframe"
Requires-Dist: numpy>=1.21; extra == "dataframe"
Provides-Extra: email
Provides-Extra: schedule
Requires-Dist: APScheduler>=3.9; extra == "schedule"
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Provides-Extra: orm
Requires-Dist: SQLAlchemy>=1.4; extra == "orm"
Provides-Extra: datetime
Requires-Dist: arrow>=1.0; extra == "datetime"
Requires-Dist: python-dateutil>=2.8; extra == "datetime"
Provides-Extra: redis
Requires-Dist: redis>=4.0; extra == "redis"
Provides-Extra: cli
Requires-Dist: typer<0.27,>=0.10; extra == "cli"
Requires-Dist: click<8.4,>=8.0; extra == "cli"
Provides-Extra: all
Requires-Dist: fastapi>=0.100; extra == "all"
Requires-Dist: uvicorn>=0.20; extra == "all"
Requires-Dist: PySide6>=6.4; extra == "all"
Requires-Dist: requests>=2.25; extra == "all"
Requires-Dist: httpx>=0.23; extra == "all"
Requires-Dist: PyJWT>=2.0; extra == "all"
Requires-Dist: bcrypt>=4.0; extra == "all"
Requires-Dist: python-dotenv>=0.20; extra == "all"
Requires-Dist: loguru>=0.6; extra == "all"
Requires-Dist: Pillow>=9.0; extra == "all"
Requires-Dist: cryptography>=40.0; extra == "all"
Requires-Dist: pydantic>=2.0; extra == "all"
Requires-Dist: python-docx>=0.8; extra == "all"
Requires-Dist: openpyxl>=3.0; extra == "all"
Requires-Dist: pandas>=1.3; extra == "all"
Requires-Dist: numpy>=1.21; extra == "all"
Requires-Dist: APScheduler>=3.9; extra == "all"
Requires-Dist: pytest>=7.0; extra == "all"
Requires-Dist: SQLAlchemy>=1.4; extra == "all"
Requires-Dist: arrow>=1.0; extra == "all"
Requires-Dist: python-dateutil>=2.8; extra == "all"
Requires-Dist: redis>=4.0; extra == "all"
Requires-Dist: typer<0.27,>=0.10; extra == "all"
Requires-Dist: click<8.4,>=8.0; extra == "all"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# CQL（Chinese Query Language）

CQL 是一套用 Python 实现的**中文编程语言**。它将 `.cql` 中文源码**转译为等价的 Python 3 代码**，覆盖了除元类、类型注解泛型等极少数高级特性之外的大多数 Python 原生语法（含异步与 match 模式匹配）。

> 由 CQFISH&喵酱出品。本工具面向中文编程学习者、中文教学场景以及对代码可读性有要求的项目。

> 开发者请查阅完整使用手册：[DEVELOPER_GUIDE.md](DEVELOPER_GUIDE.md)，包含 CQL 语言与全部中文适配子包的详细 API 与示例。

## 特性一览

- **全中文关键字**：如果 / 否则如果 / 否则、循环 / 当、中断 / 继续 / 跳过、函数 / 返回 / 类 / 继承、尝试 / 捕获 / 最终 / 抛出、导入 / 从 / 作为、伴随、延迟（lambda）、产量（yield）……
- **中英双运算符**：`+ - * / // % **` 与 `加 / 减 / 乘 / 除 / 整除 / 取余 / 幂` 均可使用；逻辑、比较、位运算同样支持中文词（与 / 或 / 非 / 等于 / 位与 / 左移……）。
- **中文标识符**：变量名、函数名、类名均可使用中文（关键字除外）。
- **中文内置函数别名**：打印 / 输入 / 长度 / 范围 / 类型 / 求和 / 最大值 / 最小值 / 绝对 / 是否是实例…… 编译期自动替换为 Python 内置函数，同时运行时注入命名空间兜底，用户自定义同名标识符优先。
- **中文类型注解**：`x: 整数 = 5`、`函数 加(a: 整数, b: 整数) -> 整数`。
- **完整语法覆盖**：控制流、函数（默认值 / `*args` / `**kwargs` / 返回值）、面向对象（继承 / super / 类与实例方法）、异常处理、导入、容器字面量、切片与解包、四种推导式、装饰器、with、lambda、海象运算符。
- **命令行工具**：`cql run` 运行、`cql build` 编译、`cql repl` 交互式解释器。
- **JavaScript 目标（脱离 Python）**：`cql js` 把 `.cql` 转译为 JavaScript，`cql runjs` 直接用 Node.js 执行，`cql html` 生成自包含 HTML 页面（浏览器双击即运行，连 Node 都不需要），彻底摆脱 Python 运行时。
- **包管理器**：`cqlip install / uninstall / list`，基于 `~/.cql`。
- **中文适配子包**：CQFastAPI（Web 后端）、CQPyqt（桌面 GUI）、CQSqlite（数据库）、CQHttp（网络请求）、CQSecurity（认证加密）、CQConfig（配置管理）、CQLog（日志）、CQPillow（图片处理）、CQCrypto（加密）、CQData（数据校验）、CQOffice（文档处理）、CQDataFrame（数据处理）、CQEmail（邮件收发）、CQSchedule（定时任务）、CQTest（单元测试）、CQORM（数据库 ORM）、CQDateTime（时间日期）、CQRedis（缓存）、CQCLI（命令行工具），均可直接在 `.cql` 源码中使用。

## 安装

要求 Python 3.7+，唯一第三方依赖为 [lark](https://github.com/lark-parser/lark)（解析器）。

```bash
cd cql-lang
pip install .
```

安装后得到两个命令：`cql`（编译器/解释器）与 `cqlip`（包管理器）。

开发模式：

```bash
pip install -e .
```

运行测试：

```bash
pip install pytest
pytest tests/ -v
```

## 快速开始

```cql
# hello.cql
函数 斐波那契(n):
    如果 n <= 1:
        返回 n
    返回 斐波那契(n - 1) + 斐波那契(n - 2)

打印("第 10 项斐波那契数：", 斐波那契(10))
```

```bash
cql run examples/hello.cql
cql build examples/hello.cql        # 生成 hello.py
cql repl                            # 进入交互式解释器
```

在 Python 中以库方式使用：

```python
import cql
code = cql.compile('打印("你好")')
print(code)          # print("你好")
exec(code)
```

## 语法速查

### 关键字映射

| CQL | Python | CQL | Python |
| --- | --- | --- | --- |
| 如果 / 否则如果 / 否则 | if / elif / else | 尝试 / 捕获 / 最终 | try / except / finally |
| 循环 / 当 | for / while | 抛出 / 返回 / 产量 | raise / return / yield |
| 中断 / 继续 / 跳过 | break / continue / pass | 导入 / 从 / 作为 | import / from / as |
| 函数 / 类 / 继承 | def / class / 基类列表 | 全局 / 非局部 | global / nonlocal |
| 异步函数 / 等待 | async def / await | 产量从 | yield from |
| 匹配 / 情况 | match / case（模式匹配） | | |
| 自身 / 超类 | self / super | 伴随 | with |
| 与 / 或 / 非 | and / or / not | 延迟 | lambda |
| 是 / 在 / 不是 / 不在 | is / in / is not / not in | 真 / 假 / 空 | True / False / None |
| 删除 / 断言 | del / assert | 捕获...作为 e | except ... as e |

### 运算符

- 算术：`加 减 乘 除 整除 取余 幂` 或 `+ - * / // % **`
- 比较：`等于 不等于 大于 小于 大于等于 小于等于` 或 `== != > < >= <=`
- 位运算：`位与 位或 异或 取反 左移 右移` 或 `& | ^ ~ << >>`
- 赋值：`= += -= *= /= //= %= **= &= |= ^= <<= >>=` 以及海象 `:=`
- 优先级与 Python 完全一致（由语法规则保证，转译时无需额外加括号）

### 内置函数中文别名

打印 `print`、输入 `input`、长度 `len`、范围 `range`、类型 `type`、是否是实例 `isinstance`、整数 `int`、文本 `str`、浮点数 `float`、布尔 `bool`、列表 `list`、字典 `dict`、集合 `set`、元组 `tuple`、枚举 `enumerate`、压缩 `zip`、排序 `sorted`、求和 `sum`、最大值 `max`、最小值 `min`、绝对 `abs`、地图 `map`、过滤器 `filter`、归约 `reduce`、全部 `all`、任意 `any`、打开 `open`、格式化 `format`……

以及模板格式化函数：格式化 `格式化(模板, ...)`（Python `str.format` 语义，双目标输出逐行一致）。支持位置占位 `{}` / `{0}` / `{1}`（含下标与属性访问 `{0[键]}`）、具名占位 `{名称}`（关键字参数）、转换 `{!r}`（repr）/ `{!s}`（str）、`{{ }}` 转义、嵌套字段（动态宽度，如 `格式化("{:>{}}", "hi", 10)`），以及完整格式说明符 `[[填充]对齐][符号][#][0][宽度][,][.精度][类型]`：对齐 `{:>10}` `{:<10}` `{:^10}` `{:=+10}`、零填充 `{:05d}`、符号 `{:+d}` `{: d}`、进制 `{:x}` `{:X}` `{:o}` `{:b}`（`{:#x}` 带前缀）、千分位 `{:,}`、精度 `{:.2f}` `{:.3}`、类型 `d f e g % c s` 等。Python 目标由运行时兜底调用 `str.format`，JS 目标由 js_runtime.js 完整实现。

以及容器增强函数：去重 `去重(列表)`（保序去重）、打乱 `打乱(列表)`（原地打乱）、扁平 `扁平(嵌套列表)`（展平一层）。这些函数在 Python 目标由运行时兜底（`list(dict.fromkeys(...))`、`random.shuffle`、列表推导），在 JS 目标由 js_runtime.js 提供等价实现。

以及随机数函数（双目标语义对齐 Python `random` 模块，种子可复现）：随机种子 `随机种子(种子)`、随机 `随机()`（[0, 1) 均匀浮点）、随机整数 `随机整数(a, b)`（含两端）、随机范围 `随机范围(a, b[, 步长])`（不含上界，支持步长）、随机均匀 `随机均匀(a, b)`（[a, b] 均匀浮点）、随机选择 `随机选择(序列)`、随机样本 `随机样本(序列, k)`（不放回抽样）。Python 目标由 random 模块兜底（`打乱` 共享同一随机状态，`随机种子` 后 `随机整数` / `打乱` 均可复现）；JS 目标由 js_runtime.js 内置可播种 PRNG（mulberry32）实现，`打乱` 同样受种子控制——浏览器 / Node 中脱离 Python 也能复现随机序列。

以及函数式内置函数：地图 `地图(函数, 可迭代)`（逐元素映射）、过滤器 `过滤器(函数, 可迭代)`（按谓词筛选）、归约 `归约(函数, 可迭代[, 初始值])`（从左到右累加）。这些函数在 Python 目标编译为 `map` / `filter` / `reduce`（`归约` 自动在生成代码中导入 `functools.reduce`），在 JS 目标由 js_runtime.js 提供等价实现（返回数组，`归约` 支持初始值）。

以及 itertools 组合生成函数（双目标语义对齐，均返回「列表的列表」）：乘积 `乘积(...)`（笛卡尔积，支持多个可迭代参数）、排列 `排列(可迭代[, r])`（r 省略时取全排列）、组合 `组合(可迭代, r)`、组合带重复 `组合带重复(可迭代, r)`。Python 目标由运行时兜底包装 `itertools.product` / `permutations` / `combinations` / `combinations_with_replacement`（迭代器元素转成列表），JS 目标由 js_runtime.js 回溯实现；用 `字符串表示` 包裹输出时双目标逐行一致。

以及 JSON 序列化与解析函数（双目标输出逐行一致）：转成JSON `转成JSON(值)`（把字典 / 列表 / 数字 / 布尔等序列化为 compact JSON 字符串——无空格、中文不转义，对齐 Python `json.dumps(ensure_ascii=False, separators=(",", ":"))` 与 JS `JSON.stringify`）、格式化JSON `格式化JSON(值[, 缩进])`（indent 美化输出，缩进默认 2、可自定义如 `格式化JSON(数据, 4)`；对齐 Python `json.dumps(ensure_ascii=False, indent=缩进)` 与 JS `JSON.stringify(x, null, 缩进)`——布尔 `true`/`false`、`None` → `null`、中文键均天然一致，适合在 `cql html` 页面直接展示 JSON 数据）、解析JSON `解析JSON(文本)`（解析 JSON 字符串还原为字典 / 列表，解析后可直接下标取值，如 `解析JSON("{\"a\": 1}")["a"]` → 1；Python 目标为 `json.loads`，JS 目标为 `JSON.parse`）。

以及 CSV 解析与生成函数（双目标输出逐行一致）：解析CSV `解析CSV(文本[, 分隔符])`（把 CSV 文本解析为二维列表，支持自定义分隔符，如 `解析CSV("a;b\n1;2", ";")` → `[['a', 'b'], ['1', '2']]`；空行 → 空列表 `[]`、引号字段按 CSV 规范处理——`""` 转义为 `"`、引号内换行保留、引号后内容拼接 `"a"x` → `ax`、尾部换行不产生空行，对齐 Python `csv.reader`）、转成CSV `转成CSV(二维列表[, 分隔符])`（把二维列表生成为 CSV 文本：行尾 `\r\n`、字段含分隔符 / 引号 / 换行时自动加引号包裹、引号翻倍，对齐 Python `csv.writer`）。Python 目标由标准库 csv 兜底，JS 目标由 js_runtime.js 手写状态机实现——浏览器 / Node 中脱离 Python 也能完整解析与生成 CSV。

以及 Base64 与 URL 编解码函数（双目标输出逐行一致）：编码Base64 `编码Base64(文本)`（按 UTF-8 字节编码，中文安全，如 `编码Base64("喵酱")` → `5Za16YWx`）、解码Base64 `解码Base64(编码)`（还原文本）；URL编码 `URL编码(文本)`（百分号编码，安全字符集与 JS `encodeURIComponent` 完全一致——不编码 `-_.!~*'()` 与字母数字，空格 → `%20`，中文按 UTF-8 十六进制百分号编码，如 `URL编码("你好 世界")` → `%E4%BD%A0%E5%A5%BD%20%E4%B8%96%E7%95%8C`）、URL解码 `URL解码(编码)`（还原，`+` 不转空格）。Python 目标由 base64 / urllib.parse 兜底，JS 目标由 js_runtime.js 实现（Node `Buffer` / 浏览器 `btoa-atob`、`encodeURIComponent` / `decodeURIComponent`）——浏览器 / Node 中脱离 Python 也能完成文本编解码。

以及查询字符串解析与生成函数（双目标输出逐行一致）：解析查询参数 `解析查询参数(文本)`（把查询串解析为 `{键: [值, ...]}`，如 `解析查询参数("a=1&a=2&b=3")` → `{'a': ['1', '2'], 'b': ['3']}`；对齐 Python `parse_qs`——`+` 解码为空格、默认丢弃空值）、转成查询参数 `转成查询参数(字典)`（把字典生成为查询串，如 `转成查询参数({"q": "你好 世界", "tag": "a~b"})` → `q=%E4%BD%A0%E5%A5%BD+%E4%B8%96%E7%95%8C&tag=a~b`；对齐 `urlencode(doseq=True)`——键值对 `&` 连接、空格 → `+`、`~` 保留、`*` 编码为 `%2A`、列表值展开为重复键）。Python 目标由 urllib.parse 兜底，JS 目标由原生 `URLSearchParams` 实现（浏览器 / Node 中脱离 Python 也能解析与生成查询串），适合拼接 / 解析 Web 接口参数。

以及 URL 解析函数（双目标输出逐行一致）：解析URL `解析URL(文本)`（按 RFC 3986 分解，返回 `{协议, 主机, 路径, 查询, 片段}` 中文键字典，如 `解析URL("https://user:pass@a.com:8080/path?q=1#f")` → `{'协议': 'https', '主机': 'user:pass@a.com:8080', '路径': '/path', '查询': 'q=1', '片段': 'f'}`）。Python 目标由 urllib.parse.urlsplit 兜底；JS 目标由 js_runtime.js 用相同 RFC 3986 正则复刻——连默认端口（`a.com:443`）、userinfo、相对 URL（`path?q=1`、`//a.com/path`）、中文域名都逐字段一致，浏览器 / Node 中脱离 Python 也能解析，适合处理链接、抓取重定向、Web 页面开发等场景。

以及文本哈希函数（双目标输出逐行一致，十六进制小写）：哈希MD5 `哈希MD5(文本)`、哈希SHA1 `哈希SHA1(文本)`、哈希SHA256 `哈希SHA256(文本)`、哈希SHA512 `哈希SHA512(文本)`——按 UTF-8 字节计算（中文安全），如 `哈希MD5("喵酱")` → `413cfb2e3be80d5d605452ee47e5d04e`。Python 目标由 hashlib 兜底，JS 目标由 js_runtime.js 调用 Node `crypto` 模块实现（浏览器环境抛出不支持提示）——Node 中脱离 Python 也能计算哈希，可用于校验、签名、缓存键等场景。

以及 HTML 转义与反转义函数（双目标输出逐行一致）：转义HTML `转义HTML(文本[, 引号])`（转义 `& < > " '`——引号默认转义：`"` → `&quot;`、`'` → `&#x27;`，第二参传 `假` 时不转义引号，对齐 Python `html.escape`）、反转义HTML `反转义HTML(文本)`（还原命名实体与十进制 / 十六进制数字实体，并兼容无分号 legacy 实体如 `&amp`、`&lt`，对齐 Python `html.unescape`）。Python 目标由 html 模块兜底，JS 目标由 js_runtime.js 手写实体表 + 数字实体解析实现（浏览器 / Node 中脱离 Python 也能转义），适合在 `cql html` 网页输出或模板渲染时防注入 / 还原内容。

以及类型判断函数（双目标逻辑一致）：是否文本 `是否文本(值)`、是否数字 `是否数字(值)`、是否列表 `是否列表(值)`、是否字典 `是否字典(值)`、是否布尔 `是否布尔(值)`、是否函数 `是否函数(值)`。`是否数字` 排除布尔（`是否数字(真)` → 假，避免 Python `isinstance(True, int)` 为真的差异，与 JS `typeof true !== "number"` 对齐）；`是否字典` 排除数组与空值（`是否字典(空)`、`是否字典([1])` → 假）。Python 目标由 `isinstance` / `callable` 兜底，JS 目标由 js_runtime.js `typeof` / `Array.isArray` 实现（浏览器 / Node 中脱离 Python 也能判断）。布尔结果打印显示沿用既有差异约定（Python `True` / JS `true`），用 `字符串表示` 包裹或转成文本即可统一输出。

以及数学与进制函数：平方根 `平方根(x)`、正弦 `正弦(x)`、余弦 `余弦(x)`、正切 `正切(x)`、对数值 `对数值(x[, 基数])`（不传基数时为自然对数）、对数值基数 `对数值基数(x, 基数)`、指数 `指数(x)`、向上取整 `向上取整(x)`、向下取整 `向下取整(x)`、截断 `截断(x)`、弧度转角度 `弧度转角度(x)`、角度转弧度 `角度转弧度(x)`、平方根近似 `平方根近似(x)`（向下取整的整数平方根）；以及数值与组合计数函数：阶乘 `阶乘(x)`、最大公约数 `最大公约数(a, b, ...)`（支持多参）、最小公倍数 `最小公倍数(a, b, ...)`（支持多参）、组合数 `组合数(n, k)`、排列数 `排列数(n, k)`、反三角 `反正弦(x)` `反余弦(x)` `反正切(x)` `反正切2(y, x)`、双曲正弦 `双曲正弦(x)`；数学常量圆周率 `π`、自然常数 `自然常数`、无穷大 `无穷大`。进制与字符函数：十六进制 `十六进制(x)`、八进制 `八进制(x)`、二进制 `二进制(x)`、字符 `字符(码点)`、序数 `序数(字符)`、可哈希 `可哈希(x)`。Python 目标自动替换为 `math.xxx` 并注入 `import math`（进制/字符函数替换为原生内置 `hex` / `oct` / `bin` / `chr` / `ord` / `hash`），JS 目标由 js_runtime.js 提供等价实现；`整数` 额外支持基数参数（如 `整数("ff", 16)` → 255）。

以及反射与迭代内置函数：是否是子类 `是否是子类(子类, 父类)`、字节 `字节(x)`（数字 → 零值字节数组，可迭代 → 字节数组，字符串 → UTF-8 编码）、帮助 `帮助(对象)`、迭代器 `迭代器(可迭代)`、下一个 `下一个(迭代器[, 默认值])`、索引位置 `索引位置(可迭代, 目标[, 起点])`、切片 `切片(对象, 起始[, 停止[, 步长]])`（与 Python `slice()` 参数语义一致：单参为停止位置）、内存视图 `内存视图(x)`、对象 `对象()`、停止迭代 `停止迭代`（异常）。其中 `索引位置` / `切片` 在 Python 目标由运行时兜底注入（`index` 非内置名、`slice()` 参数语义不符，无法转译期替换），JS 目标由 js_runtime.js 等价实现（含负索引，语义与 Python 完全一致）。

以及日期时间内置函数（双目标输出逐行一致）：现在 `现在()`（当前时间）、时间戳 `时间戳([时间对象])`（秒级，默认当前）、时间 `时间(年, 月, 日[, 时, 分, 秒])`（构造）、格式化时间 `格式化时间(时间对象[, 格式])`（默认 `%Y-%m-%d %H:%M:%S`，支持 `%Y %y %m %d %H %I %M %S %p %A %a %B %b %w %j %%` 等 strftime 格式）、解析时间 `解析时间(文本[, 格式])`（strptime 子集）、从时间戳 `从时间戳(秒)`、取值函数 `年份` / `月份` / `日号` / `小时` / `分钟` / `秒钟`、星期几 `星期几(时间对象)`（周一=0 ... 周日=6）、增加时间 `增加时间(时间对象, 日, 小时, 分钟, 秒)`（位置参数）、相隔天数 `相隔天数(起, 止)`。Python 目标由标准库 datetime 兜底注入，JS 目标由 js_runtime.js 基于 Date 实现（strftime/strptime 翻译器与 Python 语义完全一致）。

以及常见异常：异常 `Exception`、值错误 `ValueError`、类型错误 `TypeError`、键错误 `KeyError`、索引错误 `IndexError`、除零错误 `ZeroDivisionError`、运行时错误 `RuntimeError` 等。

> 说明：中文别名在**函数调用位置**（如 `打印(...)`）会被转译器替换为 Python 内置函数，性能与手写 Python 等价；当别名被当作普通值引用（如 `别名 = 长度`）时，由运行时注入的中文命名空间兜底。

### 类型注解

```cql
x: 整数 = 5
名称: 文本 = "CQL"
函数 加(a: 整数, b: 整数) -> 整数:
    返回 a + b
```

支持的中文类型名：整数 `int`、文本 `str`、浮点数 `float`、布尔 `bool`、列表 `list`、字典 `dict`、集合 `set`、元组 `tuple`、字节 `bytes`。

### 示例片段

```cql
# 推导式
平方 = [x * x 循环 x 在 范围(10) 如果 x % 2 == 0]

# lambda
翻倍 = 延迟 x: x * 2

# 装饰器
@计时器
函数 计算():
    跳过

# 类与继承
类 狗 继承 动物:
    函数 叫(自身):
        返回 "汪汪"

# 异常
尝试:
    抛出 值错误("无效")
捕获 值错误 作为 e:
    打印(e)

# with 文件操作（中文方法名，双目标支持）
伴随 打开("a.txt", "w") 作为 f:
    f.写入("内容")
伴随 打开("a.txt", "r") 作为 f:
    内容 = f.读取()
打印(内容)

# 字典解包合并（双目标支持）
配置 = {"主机": "localhost"}
覆盖 = {"端口": 8080, "主机": "127.0.0.1"}
打印({**配置, **覆盖})   # {'主机': '127.0.0.1', '端口': 8080}
```

## 命令行工具

### cql

```
cql run <file.cql>            # 运行 CQL 程序
cql run <file.cql> -e utf-8   # 指定源文件编码
cql build <file.cql>          # 编译为同名 .py
cql build <file.cql> -o out.py
cql js <file.cql>             # 转译为同名 .js（JavaScript 目标）
cql js <file.cql> -o out.js   # 转译为指定文件
cql js <file.cql> --stdout    # 只打印生成的 JS 源码
cql runjs <file.cql>          # 转译为 JS 并用 Node.js 执行
cql html <file.cql>           # 生成自包含 HTML 页面（浏览器双击即运行，脱离 Python 与 Node）
cql html <file.cql> -o out.html
cql repl                      # 交互式 REPL（支持多行输入，空行提交）
```

### cqlip（包管理器）

```bash
cqlip install 包名               # 从当前目录的「包名.cql」或「包名/」目录安装
cqlip install 包名 --source 路径  # 从指定文件/目录安装
cqlip uninstall 包名
cqlip list
```

- 源码存放于 `~/.cql/packages/包名/`，编译产物存放于 `~/.cql/cache/包名/`（保持相对路径）；
- 安装完成后自动编译全部 `.cql`；
- `cql run` 执行时自动将 `~/.cql/cache` 加入 `sys.path`，可直接 `导入` 已安装的包。

## JavaScript 目标（脱离 Python）

CQL 除了转译为 Python 外，还可以**转译为 JavaScript**，让程序彻底脱离 Python 运行时，直接在浏览器或 Node.js 中运行：

```bash
cql js examples/js_demo.cql --stdout   # 查看生成的 JS 源码
cql runjs examples/js_demo.cql         # 转译后用 Node.js 执行
```

```cql
# 一份源码，两个目标：
类 计数器:
    函数 __init__(自身, 起始 = 0):
        自身.值 = 起始
    函数 增加(自身, 步 = 1):
        自身.值 += 步
        返回 自身.值

计数 = 计数器(1)
打印("计数器：", 计数.增加(), 计数.增加(2))
```

生成的 JS 依赖随包分发的 [js_runtime.js](cql/js_runtime.js)（提供打印 / 长度 / 范围等中文内置函数与 12 个中文异常类，浏览器与 Node.js 双兼容）。在浏览器中使用：

```html
<script src="js_runtime.js"></script>
<script src="your_program.js"></script>
```

JS 目标的语义映射：

| CQL | JavaScript |
| --- | --- |
| 如果 / 否则如果 / 否则 | `if` / `else if` / `else` |
| 循环 x 在 容器 | `for (const x of 容器)` |
| 循环/当 ... 否则 | 标志变量转译（循环未 `中断` 才执行否则块） |
| 函数 / 类 / 继承 | `function` / `class` / `extends` |
| 自身 / 超类 | `this` / `super` |
| 真 / 假 / 空 | `true` / `false` / `null` |
| 与 / 或 / 非 | `&&` / `\|\|` / `!` |
| 等于 / 不等于 / 是 / 不是 | `===` / `!==` / `===` / `!==` |
| 整除 | `Math.floor(a / b)` |
| x 在 容器 / 不在 | `容器.includes(x)` / `!容器.includes(x)` |
| 产量 | `yield`（函数自动变 `function*`） |
| 全局 / 非局部 | 无需映射（JS 闭包天然支持） |
| 捕获 异常 作为 e | `catch(e) { if (e instanceof 异常) {...} }` |
| 三引号字符串 | 模板字符串（反引号） |
| 切片（含步长） | `.slice()` + `.filter()` / `.reverse()` |
| 列表 / 字典推导式 | `.map()` / `.filter()` / `.flatMap()` / `Object.fromEntries()` |
| 字典解包 `{**a, **b}` | 对象展开 `{...a, ...b}`（后写键覆盖先写键） |
| 产量从 | `yield*` |
| 异步函数 / 等待 | `async function` / `await`（顶层等待自动包 async IIFE） |
| 字典方法 `.keys()` / `.get()` / `.items()` 等 | `对象键(d)` / `对象获取(d, 键)` / `对象项目(d)` 等运行时函数 |
| 列表方法 `.append()` / `.sort()` / `.pop()` 等 | `数组追加(a, x)` / `数组排序(a)` / `对象弹出(a)` 等运行时函数 |
| 字符串方法 `.strip()` / `.upper()` / `.join()` 等 | `字符串去空白(s)` / `字符串大写(s)` / `字符串连接(分隔符, 列表)` 等运行时函数 |
| 字符串增强方法 `.center()` / `.ljust()` / `.capitalize()` / `.isdigit()` 等 | `字符串居中(s, 宽)` / `字符串左填充(s, 宽)` / `字符串首字母大写(s)` / `字符串是否数字(s)` 等运行时函数 |
| 集合方法 `.union()` / `.intersection()` / `.issubset()` / `.add()` 等 | `集合并集(a, b)` / `集合交集(a, b)` / `集合子集(a, b)` / `集合添加(s, x)` 等运行时函数 |
| 地图 / 过滤器 / 归约 | js_runtime.js 运行时函数（返回数组，`归约` 支持初始值，等价 Python 的 map / filter / reduce） |
| 数学函数与常量（平方根 / 正弦 / 对数值 / π 等） | js_runtime.js 运行时函数与常量（等价 Python 的 math 模块；`整数` 支持基数参数） |
| 进制与字符（十六进制 / 八进制 / 二进制 / 字符 / 序数 / 可哈希） | js_runtime.js 运行时函数（等价 Python 的 hex / oct / bin / chr / ord / hash） |
| 关键字参数 `f(x, 名=值)` | 关键字实参收集为末尾标记选项对象，运行时与用户函数均按名取值（如 `打印(x, sep="-")`、`打开(路径, "w", encoding="utf-8")`、`时间(年=2026, 月=8)`，与 Python 语义一致） |
| 内置函数增强参数 `排序(x, key=, reverse=)`、`求和(x, start=)`、`幂次(x, y, mod=)`、`字符串表示(x)` | js_runtime.js 运行时函数：`排序` 支持 `key=` 键函数与 `reverse=` 反转（位置第二参兼容）；`最大值` / `最小值` 支持 `key=`；`求和` 支持 `start=` 起始值；`幂次` 支持 `mod=` 模数（Python `pow(x, y, mod)` 语义）；`字符串表示` 对齐 Python `repr`（字符串带引号、容器递归展开、键名带引号、逗号后空格、`null` → `None`），双目标输出逐行一致 |
| 模板格式化 `格式化("{} {}", a, b)` | js_runtime.js 完整实现 Python `str.format` 语义：位置/具名占位、`{0[键]}` 下标、`{!r}` 转换、`{{ }}` 转义、嵌套字段（动态宽度）、格式说明符（对齐 / 填充 / 符号 / 进制 / 千分位 / 精度 / `d f e g % c s` 类型），双目标输出逐行一致 |

> 注意：JS 目标以数组 / 对象语义为准，与 Python 的差异（如 `==` 变为 `===`、整除向下取整）由转译器自动处理，代码无需改动。暂不支持的仅为元类等极少数高级特性。

### 中文方法名别名

除 Python 风格的方法名（`.append()`、`.keys()`、`.strip()`…）外，CQL 同时支持**中文方法名**，Python 与 JavaScript 两个目标都会自动转译：

```cql
数据 = [3, 1, 2]
数据.追加(4)      # 等价于 数据.append(4)
数据.排序()       # 等价于 数据.sort()
学生 = {"小明": 90}
打印(学生.键())   # 等价于 学生.keys()
集合甲 = 集合([1, 2, 3])
集合乙 = 集合([3, 4, 5])
打印(集合甲.并集(集合乙))        # 等价于 集合甲.union(集合乙) -> {1, 2, 3, 4, 5}
打印(集合甲.交集(集合乙))        # 等价于 集合甲.intersection(集合乙) -> {3}
打印(集合甲.差集(集合乙))        # 等价于 集合甲.difference(集合乙) -> {1, 2}
打印(集合丙.子集(集合甲))        # 等价于 集合丙.issubset(集合甲)
集合甲.添加(9)                  # 等价于 集合甲.add(9)
集合甲.丢弃(2)                  # 等价于 集合甲.discard(2)
打印("ab".居中(5, "_"))         # 等价于 "ab".center(5, "_") -> "__ab_"
打印("aBC".首字母大写())         # 等价于 "aBC".capitalize() -> "Abc"
打印("123".是否数字())           # 等价于 "123".isdigit()
打印("pre_x".删除前缀("pre_"))   # 等价于 "pre_x".removeprefix("pre_") -> "x"
打印("Hello World".大小写切换()) # 等价于 "Hello World".swapcase() -> "hELLO wORLD"
打印("42".零填充(5))             # 等价于 "42".zfill(5) -> "00042"
打印("ab-cd".分区("-"))          # 等价于 "ab-cd".partition("-") -> ("ab", "-", "cd")
打印("a\nb".行分割())            # 等价于 "a\nb".splitlines() -> ["a", "b"]
打印("ABC".是否大写())           # 等价于 "ABC".isupper() -> True
```

Python 目标生成 `数据.append(4)`、`集合甲.union(集合乙)` 等原生方法调用；JS 目标改写为 `数组追加(数据, 4)`、`集合并集(集合甲, 集合乙)` 等运行时函数，语义与 Python 完全对齐（如 `.sort()` 数字按数值排序）。

字符串增强方法第一批 12 个（`居中`、`左填充`、`右填充`、`首字母大写`、`每个词大写`、`左去空白`、`右去空白`、`是否数字`、`是否字母`、`是否空白`、`删除前缀`、`删除后缀`）与第二批 10 个（`大小写切换`、`分区`、`右分区`、`行分割`、`零填充`、`出现次数`、`右查找`、`是否数字字母`、`是否大写`、`是否小写`）双目标均自动转译：Python 目标编译为原生方法调用（`.swapcase()`、`.partition()` 等），JS 目标改写为 `字符串大小写切换(s)`、`字符串分区(s, 分隔符)` 等运行时函数。

文件方法同样双目标支持（`伴随 打开(...) 作为 f:` 自动关闭）：`读取`（read 全部）、`写入`（write）、`关闭`（close）、`读行`（readline）、`读全部行`（readlines）、`写行`（writelines）、`刷新`（flush）。Python 目标编译为 `f.read()`、`f.write(...)` 等原生文件方法；JS 目标由 js_runtime.js 的 `打开` 基于 Node.js fs 实现（默认 UTF-8 编码），改写为 `文件读取(f)`、`文件写入(f, ...)` 等运行时函数，`f.closed` 属性同样可用。

## 中文适配子包

cql-lang 附带一系列**全中文 API 的子包**，把热门 Python 库包装成中文类名与方法名，可直接在 `.cql` 源码或普通 Python 中使用：

```bash
pip install .                # 仅核心 cql（依赖 lark）
pip install .[all]           # 安装全部中文适配子包依赖
pip install .[web]           # 仅 Web：fastapi + uvicorn
pip install .[desktop]       # 仅桌面：PySide6
pip install .[image]         # 仅图片：Pillow
pip install .[crypto]        # 仅加密：cryptography
pip install .[data]          # 仅数据校验：pydantic
pip install .[office]        # 仅文档：python-docx + openpyxl
pip install .[dataframe]     # 仅数据处理：pandas + numpy
pip install .[schedule]      # 仅定时任务：APScheduler
pip install .[test]          # 仅测试：pytest
pip install .[orm]           # 仅数据库 ORM：SQLAlchemy
pip install .[datetime]      # 仅时间日期：arrow + python-dateutil
pip install .[redis]         # 仅缓存：redis
pip install .[cli]           # 仅命令行：typer + click
```

| 子包 | 中文 API | 底层库 | 示例 |
| --- | --- | --- | --- |
| `cqfastapi` | 快速应用 / 路由组 / 查询参数 / HTTP异常 / 启动服务 | FastAPI | `应用 = 快速应用()`；`应用.获取("/你好")(函数)` |
| `cqpyqt` | 应用程序 / 主窗口 / 按钮 / 标签 / 垂直布局 / 信号 / 消息框 | PySide6 | `按钮.被点击.连接(槽函数)` |
| `cqsqlite` | 连接 / 执行 / 查询 / 查询字典 / 提交 / 回滚 / 完整性错误 | sqlite3（内置） | `数据库 = 连接("app.db")` |
| `cqhttp` | 获取 / 提交 / 更新 / 删除 / 会话 / 异步会话 / 响应 | requests + httpx | `响应 = 获取("https://...")` |
| `cqsecurity` | 创建令牌 / 验证令牌 / 密码哈希 / 验证密码 | PyJWT + bcrypt | `令牌 = 创建令牌(载荷, 密钥, 过期秒=3600)` |
| `cqconfig` | 环境 / 加载 / 读取 / 设置 | python-dotenv | `加载(".env")`；`读取("数据库地址")` |
| `cqlog` | 调试 / 信息 / 警告 / 错误 / 致命 / 日志器 | loguru（回退 logging） | `信息("服务已启动")` |
| `cqpillow` | 打开 / 新建 / 缩放 / 裁剪 / 旋转 / 滤镜 / 画布 / 颜色 | Pillow | `图片 = 打开("照片.jpg")`；`画布.画圆(...)` |
| `cqcrypto` | 对称加密 / 对称解密 / 哈希 / 生成RSA密钥对 / 公钥加密 | cryptography | `密文 = 对称加密(密钥, 明文)` |
| `cqdata` | 模型 / 字段 / 校验错误 / 验证 | pydantic v2 | `类 用户(模型): 姓名: 文本 = 字段(必填=真)` |
| `cqoffice` | 新建文档 / 添加段落 / 新建工作簿 / 设置单元格 | python-docx + openpyxl | `文档.添加标题("纪要", 1)`；`表.设置单元格(1, 1, "姓名")` |
| `cqdataframe` | 数据表 / 系列 / 读取CSV / 过滤 / 排序 / 分组聚合 / 数组 | pandas + numpy | `表 = 数据表({"姓名": ["小明"], "年龄": [18]})`；`表.过滤(表.列("年龄") > 18)` |
| `cqemail` | 创建邮件 / 发送邮件 / 邮件服务器 / 接收邮件 | smtplib + email + imaplib | `发送邮件("smtp.x.com", 465, "a@b.c", "密码", 邮件对象)` |
| `cqschedule` | 调度器 / 间隔任务 / 定时任务 / 每 / 在 | APScheduler | `调度.间隔任务(函数, 秒=5)`；`@每(5).秒` |
| `cqtest` | 测试 / 断言等于 / 参数化 / 期望异常 / 运行 / 夹具 | pytest | `@测试`；`断言等于(1+1, 2)`；`运行()` |
| `cqorm` | 基类 / 列 / 数据库 / 会话 / 查询结果 / 关系 | SQLAlchemy | `class 用户(基类)`；`会话.查询(用户).过滤(用户.年龄 > 18)` |
| `cqdatetime` | 现在 / 解析 / 时间对象 / 偏移 / 人类化 / 计算年龄 | arrow + dateutil | `现在().格式化("YYYY年MM月DD日")`；`解析("2026-08-01")` |
| `cqredis` | 客户端 / 设置 / 获取 / 哈希设置 / 列表右推 / 发布 / 订阅 | redis-py | `缓存.设置("键", "值", 过期秒=60)`；`缓存.哈希全部("用户:1")` |
| `cqcli` | 命令 / 选项 / 参数 / 运行 / 提示 / 确认 / 进度条 / 表 | typer + click | `@命令(名称="greet")`；`运行()` |

### CQFastAPI 示例（`examples/web_hello.cql`）

```cql
# -*- coding: utf-8 -*-
从 CQFastAPI 导入 快速应用, 查询参数, 启动服务

应用 = 快速应用()

@应用.获取("/")
函数 首页():
    返回 {"消息": "你好，CQL Web 世界！"}

@应用.获取("/物品/{id}")
函数 获取物品(id: 整数, 名称: 文本 = 查询参数(描述="物品名称")):
    返回 {"编号": id, "名称": 名称}

如果 __name__ == "__main__":
    启动服务(应用, 端口=8000)
```

### CQPyqt 示例（`examples/gui_hello.cql`）

```cql
# -*- coding: utf-8 -*-
从 CQPyqt 导入 应用程序, 主窗口, 按钮, 标签, 垂直布局, 定时器

应用 = 应用程序([])
窗口 = 主窗口()
窗口.设置窗口标题("CQL 桌面示例")

标签控件 = 标签("点击按钮试试")
按钮控件 = 按钮("点我")


函数 处理点击():
    标签控件.设置文本("被点击了！")


按钮控件.被点击.连接(处理点击)

布局 = 垂直布局()
布局.添加控件(标签控件)
布局.添加控件(按钮控件)
窗口.设置布局(布局)
窗口.显示()
应用.执行()
```

### CQSqlite 示例

```cql
# -*- coding: utf-8 -*-
从 CQSqlite 导入 连接

数据库 = 连接(":memory:")
数据库.执行("CREATE TABLE 用户(编号 INTEGER PRIMARY KEY, 姓名 TEXT)")
数据库.执行("INSERT INTO 用户(姓名) VALUES(?)", ("小明",))
数据库.提交()
行们 = 数据库.查询("SELECT * FROM 用户")
打印(数据库.查询字典("SELECT * FROM 用户"))
数据库.关闭()
```

> 注意：SQL 语句本身仍使用英文关键字（SQL 并非 Python 语法，CQL 转译器不会改写字符串中的 SQL）。

## 项目结构

```
cql-lang/
├── cql/
│   ├── __init__.py    # 包入口：compile / compile_js / CQLCompileError
│   ├── lexer.py       # Lark EBNF 语法定义 + 缩进处理器
│   ├── parser.py      # Transformer：语法树 -> Python 代码字符串
│   ├── parser_js.py   # Transformer：语法树 -> JavaScript 代码字符串
│   ├── js_runtime.js  # JavaScript 中文运行时（浏览器 / Node.js 双兼容）
│   ├── compiler.py    # 编译主流程：解析 + 转译 + 中文友好错误
│   ├── cli.py         # cql 命令：run / build / js / runjs / repl
│   ├── cqlip.py       # cqlip 命令：install / uninstall / list
│   └── utils.py       # 缩进辅助、关键字/运算符/内置函数/类型映射
├── cqfastapi/         # 中文适配：Web 后端（FastAPI）
├── cqpyqt/            # 中文适配：桌面 GUI（PySide6）
├── cqsqlite/          # 中文适配：数据库（sqlite3）
├── cqhttp/            # 中文适配：网络请求（requests/httpx）
├── cqsecurity/        # 中文适配：认证加密（PyJWT/bcrypt）
├── cqconfig/          # 中文适配：配置管理（python-dotenv）
├── cqlog/             # 中文适配：日志（loguru/logging）
├── cqpillow/          # 中文适配：图片处理（Pillow）
├── cqcrypto/          # 中文适配：加密哈希（cryptography）
├── cqdata/            # 中文适配：数据校验（pydantic）
├── cqoffice/          # 中文适配：文档处理（python-docx/openpyxl）
├── cqdataframe/       # 中文适配：数据处理（pandas/numpy）
├── cqemail/           # 中文适配：邮件收发（smtplib/email）
├── cqschedule/        # 中文适配：定时任务（APScheduler）
├── cqtest/            # 中文适配：单元测试（pytest）
├── cqorm/             # 中文适配：数据库 ORM（SQLAlchemy）
├── cqdatetime/        # 中文适配：时间日期（arrow/dateutil）
├── cqredis/           # 中文适配：缓存（redis-py）
├── cqcli/             # 中文适配：命令行（typer/click）
├── tests/             # pytest 测试用例（覆盖主要语法）
├── examples/          # 示例程序
├── setup.py           # 打包配置（包名 cql-lang，依赖仅 lark）
├── README.md
└── LICENSE
```

## 转译示例

输入（`fib.cql`）：

```cql
函数 斐波那契(n):
    如果 n <= 1:
        返回 n
    返回 斐波那契(n - 1) + 斐波那契(n - 2)
```

`cql build fib.cql` 输出（`fib.py`）：

```python
def 斐波那契(n):
    if n <= 1:
        return n
    return 斐波那契(n - 1) + 斐波那契(n - 2)
```

转译后的代码与手写 Python 逻辑完全等价，缩进统一为四个空格，字符串字面量与中文标识符原样保留。

## 当前限制

- 不支持：元类、异步（async/await）、泛型类型注解、f-string 前缀字符串；
- `#` 注释在词法阶段被忽略（不会出现在编译产物中），文档字符串（`"""..."""`）原样保留；
- 关键字（如果 / 循环 等）不能用作标识符；中文内置别名作为标识符时由用户自定义优先。

## 许可证

[MIT](LICENSE)
