CQL - Chinese Query Language,一套将中文源码转译为 Python 3 / JavaScript 的中文编程语言,含 CQFastAPI/CQPyqt 等中文适配子包
Project description
CQL(Chinese Query Language)
CQL 是一套用 Python 实现的中文编程语言。它将 .cql 中文源码转译为等价的 Python 3 代码,覆盖了除元类、类型注解泛型等极少数高级特性之外的大多数 Python 原生语法(含异步与 match 模式匹配)。
由 CQFISH&喵酱出品。本工具面向中文编程学习者、中文教学场景以及对代码可读性有要求的项目。
开发者请查阅完整使用手册: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(解析器)。
cd cql-lang
pip install .
安装后得到两个命令:cql(编译器/解释器)与 cqlip(包管理器)。
开发模式:
pip install -e .
运行测试:
pip install pytest
pytest tests/ -v
快速开始
# hello.cql
函数 斐波那契(n):
如果 n <= 1:
返回 n
返回 斐波那契(n - 1) + 斐波那契(n - 2)
打印("第 10 项斐波那契数:", 斐波那契(10))
cql run examples/hello.cql
cql build examples/hello.cql # 生成 hello.py
cql repl # 进入交互式解释器
在 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(文本[, 引号])(转义 & < > " '——引号默认转义:" → "、' → ',第二参传 假 时不转义引号,对齐 Python html.escape)、反转义HTML 反转义HTML(文本)(还原命名实体与十进制 / 十六进制数字实体,并兼容无分号 legacy 实体如 &、<,对齐 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 等价;当别名被当作普通值引用(如别名 = 长度)时,由运行时注入的中文命名空间兜底。
类型注解
x: 整数 = 5
名称: 文本 = "CQL"
函数 加(a: 整数, b: 整数) -> 整数:
返回 a + b
支持的中文类型名:整数 int、文本 str、浮点数 float、布尔 bool、列表 list、字典 dict、集合 set、元组 tuple、字节 bytes。
示例片段
# 推导式
平方 = [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(包管理器)
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 中运行:
cql js examples/js_demo.cql --stdout # 查看生成的 JS 源码
cql runjs examples/js_demo.cql # 转译后用 Node.js 执行
# 一份源码,两个目标:
类 计数器:
函数 __init__(自身, 起始 = 0):
自身.值 = 起始
函数 增加(自身, 步 = 1):
自身.值 += 步
返回 自身.值
计数 = 计数器(1)
打印("计数器:", 计数.增加(), 计数.增加(2))
生成的 JS 依赖随包分发的 js_runtime.js(提供打印 / 长度 / 范围等中文内置函数与 12 个中文异常类,浏览器与 Node.js 双兼容)。在浏览器中使用:
<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 两个目标都会自动转译:
数据 = [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 中使用:
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)
# -*- coding: utf-8 -*-
从 CQFastAPI 导入 快速应用, 查询参数, 启动服务
应用 = 快速应用()
@应用.获取("/")
函数 首页():
返回 {"消息": "你好,CQL Web 世界!"}
@应用.获取("/物品/{id}")
函数 获取物品(id: 整数, 名称: 文本 = 查询参数(描述="物品名称")):
返回 {"编号": id, "名称": 名称}
如果 __name__ == "__main__":
启动服务(应用, 端口=8000)
CQPyqt 示例(examples/gui_hello.cql)
# -*- coding: utf-8 -*-
从 CQPyqt 导入 应用程序, 主窗口, 按钮, 标签, 垂直布局, 定时器
应用 = 应用程序([])
窗口 = 主窗口()
窗口.设置窗口标题("CQL 桌面示例")
标签控件 = 标签("点击按钮试试")
按钮控件 = 按钮("点我")
函数 处理点击():
标签控件.设置文本("被点击了!")
按钮控件.被点击.连接(处理点击)
布局 = 垂直布局()
布局.添加控件(标签控件)
布局.添加控件(按钮控件)
窗口.设置布局(布局)
窗口.显示()
应用.执行()
CQSqlite 示例
# -*- 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):
函数 斐波那契(n):
如果 n <= 1:
返回 n
返回 斐波那契(n - 1) + 斐波那契(n - 2)
cql build fib.cql 输出(fib.py):
def 斐波那契(n):
if n <= 1:
return n
return 斐波那契(n - 1) + 斐波那契(n - 2)
转译后的代码与手写 Python 逻辑完全等价,缩进统一为四个空格,字符串字面量与中文标识符原样保留。
当前限制
- 不支持:元类、异步(async/await)、泛型类型注解、f-string 前缀字符串;
#注释在词法阶段被忽略(不会出现在编译产物中),文档字符串("""...""")原样保留;- 关键字(如果 / 循环 等)不能用作标识符;中文内置别名作为标识符时由用户自定义优先。
许可证
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cql_lang-1.4.0.tar.gz.
File metadata
- Download URL: cql_lang-1.4.0.tar.gz
- Upload date:
- Size: 192.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f17dd86a6dd182f0dd1f87924085a5b0e0a0a99b371a50df0c543d8526e74e18
|
|
| MD5 |
a4a22a3f05471ee6571a0bc1dd2ecb1a
|
|
| BLAKE2b-256 |
9bf733039ad21fb0e71d2e432ea3cc7d8b977d50d847adbac35918c4274b8e4f
|
File details
Details for the file cql_lang-1.4.0-py3-none-any.whl.
File metadata
- Download URL: cql_lang-1.4.0-py3-none-any.whl
- Upload date:
- Size: 149.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dc60d8a39d172592026b089ac66d4201d7d3b31511d2f4b4f99ed5442e25c712
|
|
| MD5 |
29a363038c68d9bca1e43980e6381f45
|
|
| BLAKE2b-256 |
a8419d23b031ada3bcc659feda6d2637d6aec96e2fc79d91af7708a9fa9f831d
|