Skip to main content

CNSH → C 通用转译器 v2.0

CNSH 是一门中文母语的系统级语言:编译为 C99,再经 gcc/clang 编译为原生可执行文件,内置 DNA 追溯与三色审计。零三方依赖(仅 Python 标准库)。

快速开始

cd packaging/cnsh-v2

# 端到端:CNSH 源码 → C99 → 原生可执行文件 → 运行
python3 -m cnsh_v2 build examples/演示_主程序.cnsh
./examples/演示_主程序

# 只转译
python3 -m cnsh_v2 translate examples/演示_主程序.cnsh

# 只审计 / 查 DNA / 格式化 / 版本
python3 -m cnsh_v2 audit   examples/演示_主程序.cnsh
python3 -m cnsh_v2 dna     examples/演示_主程序.cnsh
python3 -m cnsh_v2 fmt     examples/演示_主程序.cnsh
python3 -m cnsh_v2 version

交互模式(REPL)

python3 -m cnsh_v2 repl              # 启动
python3 -m cnsh_v2 repl --debug      # 显示生成的 CNSH 源与编译报告
python3 -m cnsh_v2 repl --no-color   # 老终端

REPL 里直接输入 CNSH,回车即执行:

龍魂❯ 整数 x = 21
龍魂❯ 打印 x * 2
42
龍魂❯ 函数 加倍(整数 n) 返回类型 整数 {
...     返回 n * 2
... }
✅ 已登记声明
龍魂❯ 打印 加倍(50)
100

内置指令:.帮助 .退出 .清空 .历史 .声明 .载入 <文件> .版本 .重置

执行方式说明(重要):cnsh_v2 是转译器,没有 eval/运行时。 REPL 每段都是「生成 CNSH 源 → Compiler.build() → 跑本机可执行 → 回收 stdout」。 变量与顶层声明跨段保留,旧段输出不会重放(用标记截断)。

性能(Apple M4 Max / clang 21,复算:python3 tools/bench_交互解释器.py):

指标 实测
单段全链路中位 ≈65 ms(编译占 98%)
会话层(生成 20 段源) 0.004 ms(可忽略)
语句 1 → 800 段 74 → 93 ms(1.26×)

结论:瓶颈是每段一次 clang,不是「重放旧语句」——千段以内不需要为它 .重置。

风格检查(lint)

python3 -m cnsh_v2 lint examples/            # 检查
python3 -m cnsh_v2 lint . --fix              # 自动修 L001(行尾空格)
python3 -m cnsh_v2 lint . --json             # 机器可读
python3 -m cnsh_v2 lint . --strict           # CI:W/L 也算失败

规则只管风格与工程卫生,语法/语义由编译器负责(E1xxx/E2xxx),不重复造。

代码 含义 可自动修
L001 行尾空格 ✅ --fix
L002 缩进不是本文件缩进单位的倍数 —
L003 视觉宽度 > 100(中日韩按 2 计) —
L004 文件头 15 行无 DNA 签章 —
L005 有 DNA 但无许可证/归属声明 —
W001 同文件内函数返回类型写法不一致 —
W003 用了英文关键字(if/for/return…) —
E001/E002 控制字符 / 非 UTF-8 —

为什么规则要跟着文件走:仓内 .cnsh 有 v0.1(2 空格缩进)、v1(定义 …:)、 v2(函数 … 返回类型)三种方言。用 v2 的 4 空格去量 v0.1 文件会 100% 误报 (实测 155 个文件里 L002 命中 208 次,全是假的)。所以缩进单位由文件自身推断, 装饰分隔线(# ═════)不算超宽,字符串字面量里的 if 不算英文关键字。

存量基线:155 个文件里 51% 有提示,其中 45% 是行尾空格、38% 缺许可证 —— 都是历史欠账, 不是新代码门槛。E 级为 0,说明没有真错误。

虚拟环境(venv)

python3 -m cnsh_v2 venv create          # 建 .cnsh-env/
eval "$(python3 -m cnsh_v2 venv activate)"   # 激活(导出三个环境变量)
python3 -m cnsh_v2 venv install ./我的库/     # 装本地包(目录里需 cnsh.toml)
python3 -m cnsh_v2 venv list            # 已装包
python3 -m cnsh_v2 venv info            # 环境信息
cnsh_venv_deactivate                    # 停用

CNSH 编译到 C,没有解释器隔离需求。venv 隔离的是三样:stdlib 覆盖、 包搜索路径、构建产物目录。不复制工具链。

三个变量,以及谁真的消费它们(设了没人读就是装饰品,所以逐条列出):

变量 消费点 作用
CNSH_ENV modules.ModuleResolver._搜索根 · cli.build 环境根进搜索路径;build 无 -o 时产物落 $CNSH_ENV/build/
CNSH_STDLIB ModuleResolver._find 仅对 stdlib/... 前缀生效,优先于系统 stdlib
CNSH_PKG_PATH ModuleResolver._搜索根 逐条追加包搜索根

优先级:$CNSH_STDLIB(仅 stdlib/ 前缀)→ $CNSH_ENV → $CNSH_PKG_PATH… → 源文件目录 → 包根。未设变量时行为与旧版完全一致。

不实现:cnsh init 与 cnsh.toml 项目约定 —— 本仓没有这两样,venv 不假装能初始化项目; 包目录里读 cnsh.toml(没有就用目录名/unknown)。也不做远程索引与依赖求解。

顺带修掉一条静默路径:宽容模式下缺失导入会降级成空模块,而 resolver.missing 原先没有任何人读 ⇒ 缺模块完全静默,用户只看到「编译通过 + 运行时报未定义符号」。 现在 Compiler 会输出 W3001: 导入模块缺失,已降级为空模块。

新建项目(init)

python3 -m cnsh_v2 init 我的项目 --venv
cd 我的项目
eval "$(python3 -m cnsh_v2 venv activate)"
python3 -m cnsh_v2 venv install     # 按 cnsh.toml 的 [dependencies]
python3 -m cnsh_v2 build            # 省略源文件 = 用 cnsh.toml 的 entry
./build/主程序

生成的结构:

我的项目/
├── cnsh.toml           项目配置
├── 主程序.cnsh          入口(能编译、能跑)
├── tests/test_主程序.cnsh  自带主函数的测试骨架(能编译、能跑、失败返回非零)
├── stdlib/             项目私有 stdlib 覆盖
├── build/              产物(已 gitignore)
├── .gitignore
└── README.md

cnsh.toml 的每个字段都有人消费:

字段 消费点
project.entry build/translate/audit/dna/fmt 省略源文件时用它
project.target --target,仅 c / c99 / c11
project.name / version 项目标识;venv install 读 name
dependencies venv install 不带参数时按表安装
build.output_dir build 默认输出目录(保留源文件相对路径)

故意不提供 flags 与 dev-dependencies:没有对应实现,写了也不会生效。 不支持 --target python/js/rust:编译器只产出 C,写进配置也编译不出来,所以直接报错。

⚠️ 中文包名必须加引号:"工具库" = "../lib"。 TOML 裸键只允许 ASCII 字母数字与 _/-;写成 工具库 = "..." 会让整份配置解析失败 (不是那一行失效),venv install 会明确报「解析失败」而不是假装「表为空」。

一段 CNSH

导入 "stdlib/字符串.cnsh"

函数 主函数() 返回类型 整数 {
    整数 和 = 0
    对于 (整数 i = 0; i < 10; i++) {
        和 += i
    }
    如果 〖和 > 40〗 {
        打印 字符串_拼接("和是", "四十五")
    } 否则 {
        打印「不大」
    }
    返回 0
}

目录

docs/       语言规范(SPEC/TYPE_SYSTEM/SCOPE_RULES/UNDEFINED_BEHAVIOR/ABI/VERSIONING/CHANGELOG/ROADMAP)
cnsh_v2/    转译器本体(lexer/parser/sema/dna/audit/modules/codegen_c/compiler/cli/...)
stdlib/     标准库 CNSH 侧声明(字符串/数学/文件/时间/输入/内存)
tests/      一致性(JSON 用例)+ 黄金输出 + 回归
tools/      LSP 骨架(当前仅语法诊断)
examples/   端到端示例

测试

python3 tests/run_tests.py                          # 一致性 20 例(纯标准库 runner)
python3 -m pytest tests/test_golden.py tests/regression/   # 黄金输出 + 回归(或各自直接 python3 跑)

治理口径

  • DNA 前缀 #龍芯⚡️,用户 UID9622;旧前缀自动迁移(cnsh_v2/dna.py)。
  • 三色审计 🟢/🟡/🔴,strict 模式 🔴 阻断编译(cnsh_v2/audit.py)。
  • 生成的 C 文件头部自动注入 DNA 注释 + 干支时间戳(08_BIN/lh_输出戳.py,失败降级 ISO,不影响编译)。

断言库(stdlib/断言.cnsh)

导入 "stdlib/断言.cnsh"

函数 主函数() 返回类型 整数 {
    断言相等(2 + 2, 4, "四则运算应成立")
    断言为真(5 > 3, "")
    断言相等文本("龍魂", "龍魂", "")
    打印「✅ 全部通过」
    返回 0
}

失败时立即打印原因到 stderr 并以退出码 1 终止——不是返回一个 0/1 让调用方自己记得检查。

函数 说明
断言(条件, 消息) 条件为假 ⇒ 失败
断言为真 / 断言为假 同上 / 取反
断言相等(期望, 实际, 消息) 整数比较
断言不等(值一, 值二, 消息) 整数比较
断言相等文本(期望, 实际, 消息) 文本比较(C 无重载,故单列)

格式化(fmt)

cnsh fmt 主程序.cnsh            # 打印格式化结果
cnsh fmt 主程序.cnsh -w         # 原地写回
cnsh fmt . --check              # CI:需要格式化的文件存在则退出码 1
cnsh fmt 主程序.cnsh --dry-run  # 打印 diff,不写回

规则:行尾空白、整行注释 #x→# x(装饰行豁免)、连续空行压到 2、末尾恰好 1 个换行。

不做缩进规范化:仓内 v0.1 用 2 空格、v2 用 4 空格,强行统一不该由 fmt 决定。

解析不过的文件一个字节都不动(退出码 2)。原因:现有 formatter.format_source() 实测会删光注释(Token 流重建,注释不进流),用它写回等于数据丢失。 所以 fmt 只做行级处理,并带两条护栏:写回前再解析一次、注释行数不许减少。

调试(debug)

cnsh build --debug 主程序.cnsh   # 只产出带调试符号的产物
cnsh debug 主程序.cnsh           # 编译 + 启动 lldb/gdb
cnsh debug 主程序.cnsh --print-only   # 只打印命令

调试模式下 codegen 在每条语句前发 #line N "源.cnsh",lldb 里变量声明直接显示 decl = 主程序.cnsh:12——不需要 .cnsh.map(没有调试器会读那种文件)。

⚠️ macOS 把 DWARF 放进同名 .dSYM,可执行文件本身不含。 所以「用 file 验证二进制含 DWARF」这条判据在 macOS 上永远假阴性,别用它。

发版(维护者)

python3 tools/发布.py --check      # 本地校验:版本双写 / 构建 / twine check / 关键模块
PYPI_TOKEN=pypi-... python3 tools/发布.py --upload
python3 tools/发布.py --verify --wait 30   # 从 PyPI 拉回来实装实跑

脚本挡四件事:

  1. 版本双写(version.py 与 pyproject.toml 各写一次,漏改就发错版本)
  2. 代理(构建的隔离环境会继承 socks5,报 Missing dependencies for SOCKS support)
  3. 残包(构建成功 ≠ 包里对:逐个检查关键模块与 cli 子命令是否真在 wheel 内)
  4. token 泄漏(只经环境变量传给子进程,不进 argv、不回显)

⚠️ PyPI 同一版本号只能发一次,发错只能换号 —— 所以 --upload 前会把能查的都查一遍。

Metadata

Release files for cnsh-v2 2.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cnsh-v2 2.2.0
File Size Uploaded Provenance
cnsh_v2-2.2.0.tar.gz 133.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for cnsh-v2 2.2.0
File Interpreter ABI Platform
cnsh_v2-2.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 284.4 kB

Release files / cnsh_v2-2.2.0.tar.gz

Download URL cnsh_v2-2.2.0.tar.gz
Size 133.0 kB
Tags Source
SHA-256 checksum
How to use checksums
434b3634c5058b9cf0e87aa63fa3c087223fade51ae564c15d1b3b5f0986752b
BLAKE2b-256 checksum
How to use checksums
989944cb1f7daf51974474b0a410989f613b685ff903b1af750026d29b013e53
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Release files / cnsh_v2-2.2.0-py3-none-any.whl

Download URL cnsh_v2-2.2.0-py3-none-any.whl
Size 151.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6d36dbf03e96db844077fc693df1a8529bf092b263b58eb8b2aacacc8295c361
BLAKE2b-256 checksum
How to use checksums
6fef43d30cff22f346f31757564879d504c932eee1695cee9ce0a83c83e5a8f1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Security for cnsh-v2 2.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

2.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page