Macro-style helpers that let UNNCLang pseudo code run through the Python interpreter
Project description
UNNCLang Interpreter Helpers
为 UNNC CELEN086 课程准备的一个 Python 包,利用“宏”式占位符让 UNNCLang 伪代码可以直接由 Python 解释器处理。核心思路是把 endif 等语句定义成特殊对象,它们在运行时什么也不做,但可以出现在源代码中,从而保留课堂上的书写风格。
快速开始
- 安装依赖(建议使用虚拟环境):
pip install -e .
- 在你的脚本中导入并暴露宏:
from unnclang import load_macros load_macros(globals()) # 或者 from unnclang import endif 逐个导入
现在就可以在 Python 文件里写出 UNNCLang 风格的结构:
from unnclang import load_macros
load_macros(globals())
value = 5
if value > 0:
print("positive")
endif # 这行在运行时什么也不做,但可以保留 UNNCLang 的语感
测试代码示例
项目自带 tests/test_macros.py,包含一个最小脚本验证 endif 能够作为裸语句出现:
pytest tests/test_macros.py
测试里会 exec 以下脚本片段并断言 message == "positive":
from unnclang import load_macros
load_macros(globals())
value = 5
if value > 0:
message = "positive"
endif
你可以在此基础上增添更多断言,或把 exec 内容替换成真实的 UNNCLang 练习题。
endif 示例
仓库已经内置了 endif 语句,定义位于 src/unnclang/macros/core.py:
@statement_macro(doc="Marks the end of a conditional block in UNNCLang-style code.")
def endif():
return None
由于它被注册成 StatementMacro 对象,Python 解释器会把 endif 当作一个普通名字处理,因此你可以直接写 endif(不要加括号),而不会触发任何函数调用。
为了课堂更方便,包在导入时会把所有注册的 statement macros 注入到 Python 的 builtins,这意味着在导入 unnclang 之后,脚本全局就可以直接出现 endif 这样裸的名字而无需显式调用 load_macros(globals())。
如果你不想要这种全局注入(例如避免污染全局命名空间),可以在导入后调用:
import unnclang
unnclang.disable_builtin_macros()
去哪里添加更多宏?
- 打开
src/unnclang/macros/core.py(或者在src/unnclang/macros/新建模块)。 - 使用
@statement_macro装饰器声明一个新的 UNNCLang 语句:from unnclang import statement_macro @statement_macro() def endwhile(): """结束 while 循环。""" return None
- 确保模块被
unnclang/macros/__init__.py导入,这样一import unnclang就会注册到全局表里。 - 在用户代码里
load_macros(globals())或from unnclang import endwhile即可直接使用。
🎯 小贴士:
statement_macro会保留你的 Python 函数作为handler字段,未来如果要做真正的源码重写或静态检查,可以利用这些处理器实现更加复杂的行为。
项目结构
pyproject.toml # 包配置
src/unnclang/ # 包源码
├── __init__.py # 对外 API(load_macros、statement_macro 等)
├── registry.py # 宏注册与导出逻辑
└── macros/ # 内置的 UNNCLang 语句定义
└── core.py # 已存在的 endif 定义
README.md # 本说明文档
docs/ # 开发与扩展文档(如何添加宏与预处理规则)
tests/ # pytest 用例与示例脚本
└── test_macros.py
UNNCLang — 教学伪代码到 Python 的轻量工具
UNNCLang 是为教学(例如 UNNC CELEN086)准备的一个轻量 Python 包,目标是让课堂上书写的伪代码(例如带 endif、then:、otherwise 的风格)能更方便地在 Python 环境里测试与运行。
本项目采用两条策略:
- 语句宏(statement macros):把像
endif这样的裸名字注册为占位符(不会改变运行时语义,只是避免 NameError)。 - 预处理(preprocessor):把不可被 Python 直接解析的语法糖(例如
if a>1 then:)转换成合法的 Python 源再执行。
这个仓库已包含示例实现、一个 CLI(uncl),以及扩展指南,适合拿来做课堂演示或二次开发。
快速开始
建议使用虚拟环境:
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
安装后你将获得:
- Python 包
unnclang可用于脚本导入; - 命令行工具
uncl,用于运行 UNNCLang 风格的源文件。
示例:
在仓库根有一个最小示例 demo.uncl(四行):
import unnclang
if a>1 then:
print("1")
endif
直接运行:
# 方式 A:已安装为脚本
uncl demo.uncl
# 或者(不安装)
python -m unnclang.cli demo.uncl
如果未定义 a,程序会抛出标准的 Python NameError;如需在运行时传入变量:
uncl demo.uncl -s a=2
包内 API(快速参考)
unnclang.run_uncl(path, set_vars=None):读取并预处理 UNNCLang 源文件,再以 Python 执行。set_vars为可选字典,预置执行命名空间。unnclang.statement_macro:装饰器,用于注册 statement-style 宏(占位的裸名字)。unnclang.disable_builtin_macros():如果你不想让宏被注入到全局builtins,可以调用此函数移除注入的名字。
注意:包导入时默认会把注册的 statement macros 注入到 builtins(为了教学方便)。如果你要避免污染全局命名空间,请在导入后调用 disable_builtin_macros()。
CLI:uncl
安装后会有 uncl 命令,其基本用法:
uncl FILE [--set-var name=value]...
示例:
uncl demo.uncl -s a=2
uncl 只是把 UNNCLang 源预处理为合法 Python 并执行;若源引用未定义的变量(如 a),会抛出 Python 的 NameError。
如何添加新的语法支持(概览)
详见 docs/EXTENDING.md。简要步骤:
- 若只是要让某个裸名字存在(例如
endwhile),在src/unnclang/macros/中用@statement_macro注册一个占位函数;导入包时会自动注册并注入到builtins(可用disable_builtin_macros()取消)。 - 若要支持无法被 Python 直接解析的语法糖(例如
then:、otherwise、repeat/until),修改src/unnclang/runner.py中的_preprocess(text),在执行前把教学语法转换成合法 Python。对于更复杂的语法建议使用tokenize或写小型解析器以避免误替换注释/字符串。 - 为新语法添加测试(
tests/),并在 CI 中运行pytest。
发布到 PyPI(简要)
仓库已包含一个 GitHub Actions workflow(.github/workflows/publish.yml),当你把 tag 推到仓库(例如 v0.1.0)时会自动构建并发布到 PyPI。发布前需要在仓库 Secrets 中配置 PYPI_API_TOKEN。
本地发布流程示例:
# 更新版本号(pyproject.toml)并提交
git tag v0.1.0
git push origin v0.1.0
Actions 将在检测到 tag 时触发构建并上传到 PyPI(需要配置好 secrets)。
开发
- 源码位于
src/unnclang/;内置宏在src/unnclang/macros/。 - 运行测试:
pip install -e .[dev] pytest
如果你想把更多课堂语法(例如 repeat..until、endfor)直接支持成语义等价的 Python,我可以帮你把 _preprocess 改成基于 tokenize 的更健壮实现并添加对应测试。欢迎继续告诉我你想要的关键字列表。
许可证:MIT
Project details
Release history Release notifications | RSS feed
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 unnclang-0.1.0.tar.gz.
File metadata
- Download URL: unnclang-0.1.0.tar.gz
- Upload date:
- Size: 12.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
488b1476bbb0b5b9255ec6dc7bac61c3745fb9cc33ac4769b4c3345991fa001b
|
|
| MD5 |
8eecb1fa9af12284da8526996a488d81
|
|
| BLAKE2b-256 |
41ac54a0358a487866540d4c9711362778f60456f9e089c3d81a2c3829be6d0a
|
File details
Details for the file unnclang-0.1.0-py3-none-any.whl.
File metadata
- Download URL: unnclang-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5fa16149d8d486699a98094611da6154aaf3f1069ab5ecd2bd0c74492e1d60fa
|
|
| MD5 |
6d58bf989ce0361ab191713685d833ee
|
|
| BLAKE2b-256 |
2daed1602fe719f5f16203c2753c44cbfba9bf32c9f3db1cd31d8644b59f053a
|