# https://github.com/dima-quant/nimic 项目说明书

生成时间：2026-06-25 08:01:10 UTC

## 目录

- [Project Overview and Module Architecture](#page-1)
- [Core Type System and DSL Conventions](#page-2)
- [Transpiler Engine and Template Inlining](#page-3)
- [Standard Library Shims, nimpy API, and Examples](#page-4)

<a id='page-1'></a>

## Project Overview and Module Architecture

### 相关页面

相关主题：[Core Type System and DSL Conventions](#page-2), [Transpiler Engine and Template Inlining](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/dima-quant/nimic/blob/main/README.md)
- [src/nimic/__init__.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/__init__.py)
- [src/nimic/ntypes.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/ntypes.py)
- [src/nimic/ntypesystem.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/ntypesystem.py)
- [src/nimic/transpiler.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/transpiler.py)
- [src/nimic/inliner.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/inliner.py)
- [examples/preprocess.py](https://github.com/dima-quant/nimic/blob/main/examples/preprocess.py)

</details>

# Project Overview and Module Architecture

## 项目目标与设计理念

Nimic 是一个纯 Python 模块，提供一套受限的 Python 子集（DSL）：写出来的代码既能直接在 CPython 解释器中运行，又能通过转译得到等价的 Nim 源码，进而借助 Nim 编译器获得接近 C 的性能。整个运行时建立在标准库 `ctypes` 之上，无需任何 C 扩展或外部二进制。

核心设计原则是"一份源码，两套语义"——每一个 DSL 约定都同时承担两层含义：解释执行时的 Python 行为 + 转译为 Nim 后的语义。例如 `with let:` 在 Python 中只是一个无操作的上下文标记，转译后却成为真正的 `let` 作用域限定符；而 `mut @` 注解在运行时被忽略，转译时则变成 Nim 的 `var` 参数。资料来源：[README.md:31-58]()、[README.md:65-78]()。

## 模块架构总览

仓库被组织成"用户代码 → 公共 API → 核心实现 → 支撑资源"四层。`ntypes.py` 把类型系统的全部符号连同 Nim 关键字/内建（`const`/`let`/`var`、`sizeof`、`cast[T]`、`@`、`ref`、`ptr` 等）合并成单一对外 API；`__init__.py` 中的 `nimp()` 则是脚本式入口，负责从源码中提取 `# /// nimic` 块并触发转译。资料来源：[src/nimic/ntypes.py:36-56]()、[src/nimic/__init__.py:22-37]()。

```mermaid
flowchart TB
    subgraph User["用户代码层"]
        EX["examples/*.py<br/>使用 nimic DSL 的脚本"]
    end
    subgraph Public["公共 API 层"]
        NT["src/nimic/ntypes.py<br/>关键字、别名、re-export"]
        INIT["src/nimic/__init__.py<br/>nimp() 入口"]
    end
    subgraph Core["核心实现层"]
        NTS["src/nimic/ntypesystem.py<br/>ctypes 类型系统"]
        TR["src/nimic/transpiler.py<br/>AST → Nim 源码"]
        IN["src/nimic/inliner.py<br/>模板内联"]
    end
    subgraph Support["支撑资源"]
        STD["std/ & system/<br/>Nim 标准库 Python 垫片"]
        NIM["ncode/ & nimpy/<br/>Nim 端绑定"]
    end
    EX --> NT
    EX --> INIT
    NT --> NTS
    INIT --> TR
    INIT --> NTS
    TR --> NTS
    EX --> IN
    TR --> Support
    NT --> Support
```

## 核心子模块职责

- **`ntypesystem.py`** — 核心类型系统，自底向上分四层：内存层（`Ntype`、`NTypeRegistry`、`BufferRegistry`）→ 标量层（`NScalar` → `NInteger`/`NFloat`，含 `int8`..`int64`、`uint8`..`uint64`、`float16`/`32`/`64`，以及算术提升 `determine_common_type`）→ 结构层（`Object`/`NTuple`/`NIntEnum`/变体）→ 容器与修饰层（`seq[T]`、`UncheckedArray[T]`、`@distinct`、`@converter`、多分派）。注册时通过 `NMetaClass` 读取 `__annotations__`，并把泛型特化缓存到 `_Object._n_specializations`。资料来源：[src/nimic/ntypesystem.py:7-40]()、[src/nimic/ntypesystem.py:115-150]()。
- **`ntypes.py`** — 公共 API 与关键字层。重新导出 `ntypesystem` 全部符号；把 `const`、`let`、`var`、`block`、`export`、`alias`、`static` 实现为 `contextlib.nullcontext()`，使 DSL 既不破坏 Python 语法，又能在 Nim 端保留语义。同时提供 `untyped`、`SomeInteger`、`SomeFloat`、`cast[T]`、`comptime()`、`defined()`、`fields()`、`countdown()` 等运行/编译期工具。资料来源：[src/nimic/ntypes.py:36-56]()、[src/nimic/ntypes.py:65-100]()。
- **`transpiler.py`** — Python → Nim 转译器。本质是 CPython `ast.py` 的修改版，`_Unparser` 被扩展为输出 Nim 语法；文件头注释中显式列出 30+ 条规则（缩进双空格、引号统一为双引号、`slice [a:b]` 映射为 `[a..<b]`、`_` 替换为 `discard`、`class` 转 `type`、`{.pragma.}` 文档字符串转 Nim pragma、`&`/`|`/`<</` 等运算符重命名为 Nim 关键字）。`unparse()` 还会接收 `_n_registry`，以解析用户自定义类型。资料来源：[src/nimic/transpiler.py:27-58]()、[src/nimic/transpiler.py:80-140]()。
- **`inliner.py`** — 模板内联器。`@template` 装饰器在返回类型为 `untyped` 或文档字符串含 `{.dirty.}` 时把函数体 AST 注册到 `_n_templates`；`@template_expand` 通过 `_ParameterReplacer` + `_TemplateInliner` 把调用点处的形参名替换为实参 AST 节点。资料来源：[src/nimic/inliner.py:14-31]()、[src/nimic/inliner.py:38-72]()。
- **`__init__.py`** — 入口模块。`stream()` 用正则 `(?m)^# /// (?P<type>[a-zA-Z0-9-]+)$...` 抽取文件中所有元数据块；`nimp(obj, srcs, wdir)` 仅处理标记为 `nimic` 的块，调用 `inspect.getsource` → `transpiler.parse` → `transpiler.unparse` 后把生成的 Nim 源码写入 `srcs`。资料来源：[src/nimic/__init__.py:15-37]()。

## 数据流：从 DSL 源码到 Nim 代码

完整的转译流程由 `nimp()` 串联：

1. `stream()` 扫描源码，按正则匹配出所有以 `# /// <type>` 起、`# ///` 止的元数据块；非 `nimic` 的块（如 `pyproject` 风格的元数据）会被忽略。资料来源：[src/nimic/__init__.py:15-20]()]。
2. 对类型为 `nimic` 的块，`nimp()` 通过 `inspect.getsource(obj)` 获取完整源码，交给 `transpiler.parse()` 构造 AST。资料来源：[src/nimic/__init__.py:22-30]()]。
3. `transpiler.unparse(aast, _n_registry)` 借助 `_n_registry` 中的 ctypes 类型映射，按文档化规则逐层改写：缩进 → 字符串/切片 → 类型声明 → 运算符重命名 → 控制流 → 多分派/泛型特化。资料来源：[src/nimic/transpiler.py:36-58]()]。
4. 模板与多分派在解释期由 `ntypesystem` 处理：注册时遍历 `__annotations__`，按 `T_map` 把泛型参数替换为具体类型，并把特化类缓存到 `_Object._n_specializations`。资料来源：[src/nimic/ntypesystem.py:115-150]()。

实际样例 `examples/preprocess.py` 演示了完整链路：文件先 `from nimic.ntypes import *` 引入 DSL 类型，再用 `# /// nimic` 包裹待转译函数体；`nimp()` 收集生成的 Nim 源码到 `srcs` 字典，供后续 Nim 编译步骤消费。资料来源：[examples/preprocess.py:1-30]()。

## 失败模式与注意事项

- `ptr[T]` 字段未赋值时由 `NilPtr("ptr[T]")` 占位以保留类型信息；业务代码若把字段写成普通 `None`，`_n_view` 仍为 `None`，但 `__eq__` 会把它视作 nil，可能与 `autorename()` 的预期分支不一致。资料来源：[src/nimic/ntypesystem.py:24-44]()。
- 转译器依赖 `inspect.getsource(cls)` 读取类源码以识别 Nim `case object`（通过检测类体中是否存在 `match` 语句）；来自 REPL、`exec()` 或被深度装饰的类会触发 `OSError`，需保证类定义在独立 `.py` 文件中。资料来源：[src/nimic/ntypesystem.py:71-90]()。
- `@template` 仅在返回类型注解为 `untyped` 或文档字符串含 `{.dirty.}` 时才注册到 `_n_templates`；普通函数即使加了装饰器也不会被内联。资料来源：[src/nimic/inliner.py:26-37]()。

## See Also

- Core Type System（`ntypesystem.py`）
- Public API & Keywords（`ntypes.py`）
- AST Transpiler Rules（`transpiler.py`）
- Template Inlining（`inliner.py`）

---

<a id='page-2'></a>

## Core Type System and DSL Conventions

### 相关页面

相关主题：[Project Overview and Module Architecture](#page-1), [Transpiler Engine and Template Inlining](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/nimic/ntypesystem.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/ntypesystem.py)
- [src/nimic/ntypes.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/ntypes.py)
- [src/nimic/transpiler.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/transpiler.py)
- [src/nimic/inliner.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/inliner.py)
- [src/nimic/nsystem.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/nsystem.py)
- [src/nimic/nimpy/py_types.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/nimpy/py_types.py)
- [examples/preprocess.py](https://github.com/dima-quant/nimic/blob/main/examples/preprocess.py)
- [README.md](https://github.com/dima-quant/nimic/blob/main/README.md)
</details>

# Core Type System and DSL Conventions

## 概述

nimic 是一个用纯 Python 实现的 Nim 风格 DSL，核心理念是"代码既是合法的 Python，又能转译为等价的 Nim 源码"，借助 ctypes 模块获得 C 级别的内存布局与算术语义。核心类型系统与 DSL 约定是这一理念的两大支柱：前者用 Python 类与元类模拟 Nim 的类型语义、内存布局与多分派；后者用特殊装饰器、注解、上下文管理器与 docstring 内的 Nim pragma 语法，让 Python 语法同时承担"运行时行为"与"转译语义"双重角色。资料来源：[README.md:1-15]()

## 类型系统分层架构

`ntypesystem.py` 中的类型系统按从底层到高层组织为多个层次。`Ntype` 是基类，封装 ctypes 缓冲区与视图，提供值语义；`NTypeRegistry` 统一管理类型、ctypes 类型、变体与最大变体数；`BufferRegistry` 管理共享内存的 ctypes 缓冲区注册与释放。`NScalar` 派生出 `NInteger` 与 `NFloat`，覆盖定宽整数 `int8`..`int64`、`uint8`..`uint64`、`nint` 与 IEEE-754 浮点 `float16`/`float32`/`float64`，并通过 `determine_common_type()` 实现算术提升，同时为每种类型重载算术、比较、位运算与原地运算符。`Object` 借助类体内的 Python 类型注解生成 `ctypes.Structure` 字段，对应 Nim 的 `object`；`NTuple` 在此基础上通过 `__iter__` 支持元组式解包；`NIntEnum` 自动注册到 `DICT_OF_TYPES`；当类体中存在 `match/case` 块时，`Object` 自动识别为 Nim 的 `case object`（辨别联合），通过解析源码 AST 构建变体布局。容器层包括 `seq[T]`（基于 ctypes 数组加缓存实现的可增长序列）与 `UncheckedArray[T]`（指针索引数组）。`string` 继承自 `str`，通过 ctypes 缓冲区提供 `addr()` 支持，并实现 `&`（拼接）、`%`（模板格式化）与 `isEmpty`。`NilPtr` 是保留类型信息的空指针哨兵，用于 `autorename()` 在分派解析时恢复类型名。资料来源：[src/nimic/ntypesystem.py:1-50]()、[README.md:17-32]()

| 层级 | 关键类 / 机制 | 用途 |
|------|--------------|------|
| 内存层 | `Ntype`、`NTypeRegistry`、`BufferRegistry` | 基于 ctypes 的缓冲区值语义与统一注册 |
| 标量层 | `NScalar` → `NInteger` / `NFloat` | 定宽整数与 IEEE-754 浮点，含算术提升 |
| 结构层 | `Object`、`NTuple`、`NIntEnum` | Nim `object` / `tuple` / 整型枚举 |
| 变体层 | `Object` + `match kind:` | Nim `case object`（辨别联合） |
| 容器层 | `seq[T]`、`UncheckedArray[T]` | 可增长序列与指针索引数组 |
| 分派层 | `@dispatch`、`DispDict`、`NMetaClass` | Nim 风格基于类型注解的多分派 |
| 修饰层 | `@distinct`、`@converter` | 类型区分与隐式类型转换 |
| 字符串层 | `string` | 兼容 Nim `&`、`%`、`isEmpty` 的 `str` 子类 |

## DSL 约定与公共 API

`ntypes.py` 作为公共 API 重新导出 `ntypesystem` 中的全部类型与装饰器，并补充 Nim 关键字与内建函数的 Python 替身。`const`/`let`/`var`/`block`/`export`/`alias` 实现为 `contextlib.nullcontext()`——在 Python 中是无操作上下文，转译为 Nim 作用域限定符。`ref`/`ptr`/`mut@` 提供引用类型语义；`@` 运算符返回对象身份，转译为 Nim 的 `ref`/`ptr`/`var` 注解。`NStrEnum` 提供 `succ`/`pred`/`ord`/`nrange`/`low`/`high` 等枚举工具。`cast[T](x)`、`sizeof(x)`、`addr(x)`、`unsafe_addr(x)` 来自 `nsystem` 模块，对应 Nim 的类型转换与内存地址操作；`fields(obj)` 与 `fields(a, b)` 支持字段迭代，`countdown(a, b)` 实现反向迭代；`comptime(x)`、`defined(varname)`、`static` 用于编译时计算。`@template` 与 `@template_expand` 装饰器从 `inliner.py` 重新导出，负责模板内联。`SomeInteger`/`SomeFloat`/`BiggestInt`/`BiggestFloat` 等类型别名对应 Nim 的同名概念。资料来源：[src/nimic/ntypes.py:1-60]()、[src/nimic/nsystem.py]()（经由 `ntypes.py` 导入）、[README.md:33-42]()

DSL 约定层面，Python 语法被赋予双重含义：`with let/var/const:` 是变量声明的作用域限定符；`mut @` 注解标记可变参数（对应 Nim 的 `var`）；`"""{.inline.}"""` 这种 `{.pragma.}` docstring 用于透传 Nim 编译期 pragma（`inline`/`borrow`/`noSideEffect`）；`@dispatch` 实现多分派；`@distinct` 创建无隐式转换的区分类型；`@template` 注册可在调用点内联的模板；`@converter` 定义隐式类型转换器。资料来源：[README.md:51-66]()

## 转译与模板内联机制

`transpiler.py` 是修改自 CPython `ast.py` 的 AST→Nim 源码转译器，扩展了 `_Unparser` 访问者以输出 Nim 语法。它实现了 30 余条转换规则，涵盖缩进、类型定义、函数签名、运算符、导入与控制流，典型规则包括 `rule:dropwith`（去掉 `const`/`let`/`var`/`export`/`block` 前的 `with` 关键字）、`rule:slice`（将 Python 切片 `[a:]`/`[a:b]` 转为 Nim 的 `[a..^1]`/`[a..<b]`）、`rule:classdef`（将 `class` 解释为 Nim 类型定义）、`rule:typealias` 与 `rule:typedistinct`（处理类型别名与 `distinct` 类型）以及 `rule:discard`/`rule:pass`（将 `_ =` 与 `pass` 替换为 Nim 的 `discard`）。资料来源：[src/nimic/transpiler.py:1-40]()

`inliner.py` 提供 `@template` 与 `@template_expand` 装饰器，在 AST 层级对无类型模板做函数内联：当被装饰函数的返回类型注解为 `untyped`（或 docstring 含 `{.dirty.}`）时，它把函数体解析为 AST 片段存入 `_n_templates`；`_ParameterReplacer` 把形参 `Name` 节点替换为实参节点，`_TemplateInliner` 在调用点把变换后的模板体拼接进去。`nimpy/py_types.py` 中的 `Py_ssize_t` 直接继承 `NInteger` 并手动注册到 `DICT_OF_TYPES` 与 `DICT_OF_C_TYPES`（映射到 `ctypes.c_int64`），同时定义 `PyBUF_SIMPLE`/`PyBUF_WRITABLE`/`PyBUF_ND` 等缓冲区协议标志常量。`examples/preprocess.py` 演示了完整用法：从 `from nimic.ntypes import *` 引入类型系统，使用 `ptr[uint8]`、`ptr[float32]`、`array[3, float32]`、`nint` 与 `with let:` 等约定编写可同时在 Python 运行并转译为 Nim 的图像预处理代码，调用了 `nearest_neighbour_compute_source_index` 等带类型注解的函数。资料来源：[src/nimic/inliner.py:1-30]()、[src/nimic/nimpy/py_types.py:1-16]()、[examples/preprocess.py:1-20]()

## 参见

- [README.md](https://github.com/dima-quant/nimic/blob/main/README.md) — 项目概览与模块地图
- [src/nimic/transpiler.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/transpiler.py) — Python → Nim 转译规则完整列表
- [src/nimic/inliner.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/inliner.py) — 模板内联实现细节
- [src/nimic/nimpy/](https://github.com/dima-quant/nimic/tree/main/src/nimic/nimpy) — 生成 Python 扩展库的 API

---

<a id='page-3'></a>

## Transpiler Engine and Template Inlining

### 相关页面

相关主题：[Core Type System and DSL Conventions](#page-2), [Standard Library Shims, nimpy API, and Examples](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/nimic/transpiler.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/transpiler.py)
- [src/nimic/inliner.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/inliner.py)
- [nimic_translation_rules.md](https://github.com/dima-quant/nimic/blob/main/nimic_translation_rules.md)
- [src/nimic/__init__.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/__init__.py)
- [src/nimic/ntypesystem.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/ntypesystem.py)
- [src/nimic/ntypes.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/ntypes.py)
- [README.md](https://github.com/dima-quant/nimic/blob/main/README.md)
- [examples/preprocess.py](https://github.com/dima-quant/nimic/blob/main/examples/preprocess.py)
</details>

# Transpiler Engine and Template Inlining

## 1. 概述与定位

nimic 项目的核心目标是用 Python 的一个受限子集（DSL）编写可 AOT 编译、达到 C 级性能的代码。该 DSL 既是合法的 Python（可直接在解释器中运行），又可被转译为等价的 Nim 源码。承担这一双重性转换的正是 **转译引擎（Transpiler Engine）** 与 **模板内联机制（Template Inlining）**。

资料来源：[README.md]()

- **转译引擎**：基于 CPython `ast.py` 修改而来，将 `_Unparser` 访问器扩展为输出 Nim 语法，实现 30 余条变换规则。资料来源：[src/nimic/transpiler.py]()
- **模板内联**：通过 `@template` / `@template_expand` 装饰器，在抽象语法树（AST）层完成未类型化模板的函数内联，把形参名替换为调用实参。资料来源：[src/nimic/inliner.py]()

两者协同工作：`inliner.py` 先在 Python 端完成"源代码到源代码"的 AST 重写，`transpiler.py` 再把最终 AST 展开为 Nim 文本。

## 2. 转译引擎（transpiler.py）

### 2.1 核心结构

`transpiler.py` 并非从零实现的解析器，而是对 CPython 标准库 `ast.py` 的修改版。模块顶部保留 `parse()`、`literal_eval()` 等公共函数，主体逻辑放在扩展后的 `_Unparser` 访问器中。

资料来源：[src/nimic/transpiler.py]()

### 2.2 变换规则分类

`transpiler.py` 内嵌的 docstring 列出了完整的规则族。下列为最关键的几类：

| 类别 | 规则示例 | 作用 |
|------|----------|------|
| 格式化 | `rule:doublespace`、`rule:quote`、`rule:slice`、`rule:discard`、`rule:pass` | 缩进、字符串、切片、`_ = …` → `discard`、`pass` → `discard` |
| 作用域 | `rule:dropwith`、`rule:writeexport` | 去掉 `with let/var/const:` 中的 `with`，让 `export` 不带括号 |
| 类型系统 | `rule:classdef`、`rule:classdefseq`、`rule:typealias`、`rule:typedistinct` | `class` → `type`，`class X(Y)` → `type X* = Y`，`@distinct class X(Y)` → `type X* = distinct Y` |
| 控制流 | `rule:match`、`rule:case`、`rule:block` | Python 的 `match/case` 与 `_block()` 翻译为 Nim 的 `case` 与 `block:` |
| 编译期 | `rule:comptime`、`rule:templateinline` | `if comptime(...)` → `when ...`，`with template_inline:` → 模板内联点 |

资料来源：[src/nimic/transpiler.py]()、[nimic_translation_rules.md]()

### 2.3 入口与调度

`src/nimic/__init__.py` 中的 `ntranspile(args)` 是面向用户的入口函数。它接受一个模块或文件路径，把该模块作为 AST 源，通过 `transpiler.unparse(aast, _n_registry)` 输出 Nim 源码字符串，并递归地把其 `import` 的 nimic 子模块一并展开。

资料来源：[src/nimic/__init__.py]()

```python
# 伪代码示意
nim_src, modules_names = transpiler.unparse(aast, _n_registry)
srcs[obj.__name__] = nim_src
for module_name in modules_names:
    nimp(sys.modules[module_name], srcs, wdir)
```

资料来源：[src/nimic/__init__.py]()

## 3. 模板内联（inliner.py）

### 3.1 装饰器语义

`@template` 会检测函数是否声明返回 `untyped`，或 docstring 中含 `{.dirty.}` 标记；满足条件则把它以 AST 片段形式登记到模块级字典 `_n_templates` 中。

```python
@template
def toUV(v):
    """{.inline.}"""
    return v.x & v.y
```

`@template_expand` 则装饰 *调用方* 函数，使用 `ast.NodeTransformer` 遍历其函数体，匹配 `_n_templates` 中的已注册模板，并用 `_ParameterReplacer` 把形参节点替换为实参节点。

资料来源：[src/nimic/inliner.py]()

### 3.2 AST 节点替换流程

```mermaid
flowchart LR
    A[被 @template 装饰的函数] --> B[inspect.getsource + ast.parse]
    B --> C[_n_templates 注册表]
    C --> D[被 @template_expand 装饰的调用方]
    D --> E[_TemplateInliner 遍历调用方 AST]
    E --> F[检测到模板调用节点]
    F --> G[_ParameterReplacer 形参→实参]
    G --> H[返回展开后的 AST 片段]
    H --> I[transpiler.unparse 输出 Nim]
```

资料来源：[src/nimic/inliner.py]()、[src/nimic/transpiler.py]()

注意：typed 模板仍需 `return` 语句，仅作为普通 Python 函数参与转译；只有 `untyped` / `{.dirty.}` 模板才进入内联通道。资料来源：[src/nimic/inliner.py]()

## 4. DSL 约定与典型用法

`ntypes.py` 把 `template`、`template_expand` 重新导出，使 DSL 风格统一。下表给出常见转换对照（节选）：

| Nim 写法 | Nimic 写法 | 触发规则 |
|----------|-----------|----------|
| `var x: int` | `with var: x = 0` | `rule:dropwith` |
| `type Vec3 = object` | `class Vec3(Object):` | `rule:classdef` |
| `type Time = distinct float64` | `@distinct`<br>`class Time(float64):` | `rule:typedistinct` |
| `template foo(): untyped` | `@template`<br>`def foo() -> untyped:` | `rule:templateinline` |
| `when x < 5:` | `if comptime(x < 5):` | `rule:comptime` |

资料来源：[src/nimic/ntypes.py]()、[nimic_translation_rules.md]()、[README.md]()

`ntypesystem.py` 还负责在 Python 运行时模拟 Nim 的内存模型、值类型语义和多分派，使 DSL 在解释执行与 Nim 编译执行时表现一致。资料来源：[src/nimic/ntypesystem.py]()

## 5. 常见失败模式

- **未在调用方使用 `@template_expand`**：untyped 模板不会在 Python 端被展开，转译后的 Nim 也找不到对应实现。资料来源：[src/nimic/inliner.py]()
- **类型注解缺失**：`converter`、`dispatch` 等装饰器依赖 `__annotations__` 推断源/目标类型；缺少注解将导致注册失败。资料来源：[src/nimic/ntypesystem.py]()
- **混合 Python 语法**：`@distinct` 必须紧贴 `class` 定义之上，且父类必须是 `ntypesystem` 中的合法类型；非 DSL 兼容语法会被 `_Unparser` 原样输出，引发 Nim 编译错误。资料来源：[src/nimic/transpiler.py]()

## See Also

- 类型系统与多分派：[src/nimic/ntypesystem.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/ntypesystem.py)
- 公共 API 与关键字：[src/nimic/ntypes.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/ntypes.py)
- 完整翻译规则表：[nimic_translation_rules.md](https://github.com/dima-quant/nimic/blob/main/nimic_translation_rules.md)
- 项目入口与转译调度：[src/nimic/__init__.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/__init__.py)
- 预处理示例：[examples/preprocess.py](https://github.com/dima-quant/nimic/blob/main/examples/preprocess.py)

---

<a id='page-4'></a>

## Standard Library Shims, nimpy API, and Examples

### 相关页面

相关主题：[Core Type System and DSL Conventions](#page-2), [Transpiler Engine and Template Inlining](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [src/nimic/nimpy/__init__.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/nimpy/__init__.py)
- [src/nimic/nimpy/py_types.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/nimpy/py_types.py)
- [src/nimic/nimpy/raw_buffers.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/nimpy/raw_buffers.py)
- [examples/preprocess.py](https://github.com/dima-quant/nimic/blob/main/examples/preprocess.py)
- [examples/test_preprocess.py](https://github.com/dima-quant/nimic/blob/main/examples/test_preprocess.py)
- [README.md](https://github.com/dima-quant/nimic/blob/main/README.md)
- [nimic_translation_rules.md](https://github.com/dima-quant/nimic/blob/main/nimic_translation_rules.md)
- [src/nimic/transpiler.py](https://github.com/dima-quant/nimic/blob/main/src/nimic/transpiler.py)
</details>

# Standard Library Shims, nimpy API, and Examples

## 概览

nimic 是一个纯 Python 模块，目标是让用户用 Python 语法的子集（DSL）写出既能在 Python 中直接运行、又能被转译为等价的 Nim 源码、从而获得 C 级性能的程序。为了弥合 Nim 与 Python 之间的生态差异，nimic 在三个层面提供 shim（垫片）：

- `nimpy/`：桥接 CPython C API 的模块，让 nimic 代码可以读取 `numpy.ndarray` 等带缓冲区协议的对象。
- `std/`：Nim 标准库的 Python 兼容实现（`math`、`options`、`os`、`paths`、`strformat` 等）。
- `system/`：Nim `system` 模块的 Python shim（`ansi_c` 等）。

这些 shim 与 `ntypesystem` 中的类型系统共同构成 nimic 的运行基础，transpiler 则在转译阶段把它们还原为对 Nim 原生模块的引用。

资料来源：[README.md:30-50]()

## nimpy API

`nimpy` 是 nimic 中负责 Nim ↔ Python 互操作的薄包装层。模块入口只做再导出，避免命名空间污染：

```python
from nimic.nimpy.py_types import *
from nimic.nimpy.raw_buffers import *
PyObject = object
```

资料来源：[src/nimic/nimpy/__init__.py:1-6]()

### 核心组件

| 组件 | 来源 | 作用 |
|------|------|------|
| `Py_ssize_t` | `py_types.py` | 平台相关的有符号大小类型，继承自 `NInteger`，映射到 `ctypes.c_int64` |
| `PyBUF_SIMPLE` / `PyBUF_WRITABLE` / `PyBUF_ND` | `py_types.py` | CPython 缓冲区协议标志常量（`0x0000` / `0x0001` / `0x0008`） |
| `RawPyBuffer` | `raw_buffers.py` | Nim `RawPyBuffer` 的 Python 替身，包装 `Py_buffer` 结构，含 `buf` 与 `shape` 字段 |
| `getBuffer` | `raw_buffers.py` | 顶层函数，转译后等价于 Nim 的 UFCS `obj.getBuffer(buf, flags)` |

`Py_ssize_t` 手动注册到 `DICT_OF_TYPES` 与 `DICT_OF_C_TYPES` 中，因为 `NInteger` 的直接子类会跳过自动注册：

```python
class Py_ssize_t(NInteger):
    _n_bits, _n_signed, _n_rank = 64, True, 8
DICT_OF_TYPES["Py_ssize_t"] = Py_ssize_t
DICT_OF_C_TYPES["Py_ssize_t"] = ctypes.c_int64
```

资料来源：[src/nimic/nimpy/py_types.py:6-21]()

`RawPyBuffer` 用 nimic 注解语法声明字段：

```python
class RawPyBuffer(Object):
    buf: pointer
    shape: pointer
```

转译后等价于 Nim 中的对象类型，调用方可通过 `cast[ptr[UncheckedArray[Py_ssize_t]]](buf.shape)` 读取维度信息。

资料来源：[src/nimic/nimpy/raw_buffers.py:18-25]()

`getBuffer` 在 Python 端通过 `ctypes` 直接读取 numpy 数组的地址并构造形状数组，在 Nim 端则由 nimpy 自身的 UFCS 实现接管：

```python
def getBuffer(obj, buf, flags=0):
    if hasattr(obj, 'ctypes') and hasattr(obj, 'shape'):
        data_addr = obj.ctypes.data
        ndim = obj.ndim
        ShapeArray = ctypes.c_ssize_t * ndim
        # ...
```

资料来源：[src/nimic/nimpy/raw_buffers.py:31-40]()

## 标准库与 system 模块 Shims

`std/` 与 `system/` 目录的 shim 与 `nimpy/` 同构，但规模更大、覆盖更广。它们的存在保证如下导入模式同时在 Python 与 Nim 端可用：

```python
from nimic.std.math import *
from nimic.std.os import *
from nimic.std.options import *
```

`system/ansi_c` 暴露 C ABI 访问能力（`sizeof`、`cast`、`addr` 等），通过 `ctypes` 实现，被 `ntypes.py` 中的 `cast[T](x)`、`sizeof(x)`、`addr(x)` 等函数复用。transpiler 会将 `from nimic.std.math import *` 翻译为 Nim 的 `import math`，反之亦然。

资料来源：[README.md:42-50]()、`src/nimic/transpiler.py`（rule scope 列表）

## 示例：图像预处理管道

`examples/preprocess.py` 演示了 nimpy 的典型用法：把 HWC 的 `uint8` 图像缩放为 CHW 的 `float32` 张量。该文件以 nimic 元注释开头，并在 transpile 之前由 `import_from_path` 加载：

```python
# /// nimic
#
# ///
from nimic.nimpy import *
from nimic.nimpy.raw_buffers import RawPyBuffer, getBuffer
from nimic.nimpy.py_types import Py_ssize_t, PyBUF_SIMPLE, PyBUF_ND, PyBUF_WRITABLE
```

核心函数 `nearest_neighbour_compute_source_index` 实现最近邻缩放的源坐标映射：

```python
def nearest_neighbour_compute_source_index(scale: float64, out_index: nint, input_size: nint) -> nint:
    result = min(nint(floor(float64(out_index) * scale)), input_size - 1)
    return result
```

`hwc2chw_resize_simple` 则接受原始指针、尺寸与均值/方差数组，把逐像素操作放在 `with let:` 作用域中，并使用 `mut @` 注解标记可变参数。该示例是 [Raman Labs 博文](https://ramanlabs.in/static/blog/Generate_Python_extensions_using_Nim_language.html) 中 Nim 实现的 1:1 移植。

资料来源：[examples/preprocess.py:1-24]()

`examples/test_preprocess.py` 进一步给出端到端用法：构造一个 `4×8×3` 的 `np.uint8` 测试帧，调用 `preprocessPipeline_nim` 验证输出形状与 `reverse_channels` 行为：

```python
frame = np.arange(0, 4 * 8 * 3, dtype=np.uint8).reshape((4, 8, 3))
output = preprocess(frame, output_shape=(2, 4), reverse_channels=False)
```

资料来源：[examples/test_preprocess.py:18-25]()

## See Also

- [类型系统与 Transpiler 规则](transpiler-and-typesystem.md)
- [Nimic 翻译规则速查](translation-rules.md)
- [项目总览](README.md)

---

<!-- evidence_pipeline_checked: true -->

---

## Doramagic 踩坑日志

项目：dima-quant/nimic

摘要：发现 6 个潜在踩坑项，其中 0 个为 high/blocking；最高优先级：能力坑 - 能力判断依赖假设。

## 1. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://news.ycombinator.com/item?id=48646239 | README/documentation is current enough for a first validation pass.

## 2. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://news.ycombinator.com/item?id=48646239 | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://news.ycombinator.com/item?id=48646239 | no_demo; severity=medium

## 4. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://news.ycombinator.com/item?id=48646239 | no_demo; severity=medium

## 5. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://news.ycombinator.com/item?id=48646239 | issue_or_pr_quality=unknown

## 6. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://news.ycombinator.com/item?id=48646239 | release_recency=unknown

<!-- canonical_name: dima-quant/nimic; human_manual_source: deepwiki_human_wiki -->
