Doramagic 项目包 · 项目说明书

nimic 项目

Nimic 是一个纯 Python 模块,通过使用 Python 的子集(领域特定语言)来编写 AOT 可编译代码,无需离开 Python 即可获得 C 级别的性能,基于内置的 ctypes 模块实现。

Project Overview and Module Architecture

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

章节 相关页面

继续阅读本节完整说明和来源证据。

项目目标与设计理念

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

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

模块架构总览

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

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

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

Core Type System and DSL Conventions

nimic 是一个用纯 Python 实现的 Nim 风格 DSL,核心理念是"代码既是合法的 Python,又能转译为等价的 Nim 源码",借助 ctypes 模块获得 C 级别的内存布局与算术语义。核心类型系统与 DSL 约定是这一理念的两大支柱:前者用 Python 类与元类模拟 Nim 的类型语义、内存布局与多分派;后者用特殊装饰器、注解、上下文管理器与 docs...

章节 相关页面

继续阅读本节完整说明和来源证据。

概述

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 派生出 NIntegerNFloat,覆盖定宽整数 int8..int64uint8..uint64nint 与 IEEE-754 浮点 float16/float32/float64,并通过 determine_common_type() 实现算术提升,同时为每种类型重载算术、比较、位运算与原地运算符。Object 借助类体内的 Python 类型注解生成 ctypes.Structure 字段,对应 Nim 的 objectNTuple 在此基础上通过 __iter__ 支持元组式解包;NIntEnum 自动注册到 DICT_OF_TYPES;当类体中存在 match/case 块时,Object 自动识别为 Nim 的 case object(辨别联合),通过解析源码 AST 构建变体布局。容器层包括 seq[T](基于 ctypes 数组加缓存实现的可增长序列)与 UncheckedArray[T](指针索引数组)。string 继承自 str,通过 ctypes 缓冲区提供 addr() 支持,并实现 &(拼接)、%(模板格式化)与 isEmptyNilPtr 是保留类型信息的空指针哨兵,用于 autorename() 在分派解析时恢复类型名。资料来源:src/nimic/ntypesystem.py:1-50README.md:17-32

层级关键类 / 机制用途
内存层NtypeNTypeRegistryBufferRegistry基于 ctypes 的缓冲区值语义与统一注册
标量层NScalarNInteger / NFloat定宽整数与 IEEE-754 浮点,含算术提升
结构层ObjectNTupleNIntEnumNim object / tuple / 整型枚举
变体层Object + match kind:Nim case object(辨别联合)
容器层seq[T]UncheckedArray[T]可增长序列与指针索引数组
分派层@dispatchDispDictNMetaClassNim 风格基于类型注解的多分派
修饰层@distinct@converter类型区分与隐式类型转换
字符串层string兼容 Nim &%isEmptystr 子类

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 等枚举工具。castTsizeof(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-60src/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:typealiasrule: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_TYPESDICT_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]nintwith let: 等约定编写可同时在 Python 运行并转译为 Nim 的图像预处理代码,调用了 nearest_neighbour_compute_source_index 等带类型注解的函数。资料来源:src/nimic/inliner.py:1-30src/nimic/nimpy/py_types.py:1-16examples/preprocess.py:1-20

参见

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

Transpiler Engine and Template Inlining

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

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 2.1 核心结构

继续阅读本节完整说明和来源证据。

章节 2.2 变换规则分类

继续阅读本节完整说明和来源证据。

章节 2.3 入口与调度

继续阅读本节完整说明和来源证据。

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:doublespacerule:quoterule:slicerule:discardrule:pass缩进、字符串、切片、_ = …discardpassdiscard
作用域rule:dropwithrule:writeexport去掉 with let/var/const: 中的 with,让 export 不带括号
类型系统rule:classdefrule:classdefseqrule:typealiasrule:typedistinctclasstypeclass X(Y)type X* = Y@distinct class X(Y)type X* = distinct Y
控制流rule:matchrule:caserule:blockPython 的 match/case_block() 翻译为 Nim 的 caseblock:
编译期rule:comptimerule:templateinlineif comptime(...)when ...with template_inline: → 模板内联点

资料来源:src/nimic/transpiler.pynimic_translation_rules.md

2.3 入口与调度

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

资料来源:src/nimic/__init__.py

# 伪代码示意
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 中。

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

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

资料来源:src/nimic/inliner.py

3.2 AST 节点替换流程

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.pysrc/nimic/transpiler.py

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

4. DSL 约定与典型用法

ntypes.pytemplatetemplate_expand 重新导出,使 DSL 风格统一。下表给出常见转换对照(节选):

Nim 写法Nimic 写法触发规则
var x: intwith var: x = 0rule:dropwith
type Vec3 = objectclass 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.pynimic_translation_rules.mdREADME.md

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

5. 常见失败模式

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

See Also

资料来源:README.md

Standard Library Shims, nimpy API, and Examples

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

章节 相关页面

继续阅读本节完整说明和来源证据。

章节 核心组件

继续阅读本节完整说明和来源证据。

概览

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

  • nimpy/:桥接 CPython C API 的模块,让 nimic 代码可以读取 numpy.ndarray 等带缓冲区协议的对象。
  • std/:Nim 标准库的 Python 兼容实现(mathoptionsospathsstrformat 等)。
  • system/:Nim system 模块的 Python shim(ansi_c 等)。

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

资料来源:README.md:30-50

nimpy API

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

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

资料来源:src/nimic/nimpy/__init__.py:1-6

核心组件

组件来源作用
Py_ssize_tpy_types.py平台相关的有符号大小类型,继承自 NInteger,映射到 ctypes.c_int64
PyBUF_SIMPLE / PyBUF_WRITABLE / PyBUF_NDpy_types.pyCPython 缓冲区协议标志常量(0x0000 / 0x0001 / 0x0008
RawPyBufferraw_buffers.pyNim RawPyBuffer 的 Python 替身,包装 Py_buffer 结构,含 bufshape 字段
getBufferraw_buffers.py顶层函数,转译后等价于 Nim 的 UFCS obj.getBuffer(buf, flags)

Py_ssize_t 手动注册到 DICT_OF_TYPESDICT_OF_C_TYPES 中,因为 NInteger 的直接子类会跳过自动注册:

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 注解语法声明字段:

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 实现接管:

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 端可用:

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

system/ansi_c 暴露 C ABI 访问能力(sizeofcastaddr 等),通过 ctypes 实现,被 ntypes.py 中的 castTsizeof(x)addr(x) 等函数复用。transpiler 会将 from nimic.std.math import * 翻译为 Nim 的 import math,反之亦然。

资料来源:README.md:42-50src/nimic/transpiler.py(rule scope 列表)

示例:图像预处理管道

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

# /// 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 实现最近邻缩放的源坐标映射:

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 博文 中 Nim 实现的 1:1 移植。

资料来源:examples/preprocess.py:1-24

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

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 规则
  • Nimic 翻译规则速查
  • 项目总览

资料来源:README.md:30-50

失败模式与踩坑日记

保留 Doramagic 在发现、验证和编译中沉淀的项目专属风险,不把社区讨论只当作装饰信息。

medium 能力判断依赖假设

假设不成立时,用户拿不到承诺的能力。

medium 维护活跃度未知

新项目、停更项目和活跃项目会被混在一起,推荐信任度下降。

medium 存在评分风险

风险会影响是否适合普通用户安装。

low issue/PR 响应质量未知

用户无法判断遇到问题后是否有人维护。

Pitfall Log / 踩坑日志

项目: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

来源:Doramagic 发现、验证与编译记录