Show HN: Nimic – Pure Python as a systems language with AOT compilation

Hacker News Top Tools

Summary

Nimic is a pure Python module that enables writing AOT-compilable code using a Python DSL that transpiles to Nim, achieving C-level performance while remaining valid Python.

No content available
Original Article
View Cached Full Text

Cached at: 06/25/26, 08:09 AM

dima-quant/nimic

Source: https://github.com/dima-quant/nimic

Nimic

Nimic is a pure Python module that facilitates writing AOT compilable code with a subset of Python (domain specific language), aiming to get C-level performance without leaving Python. Based on ctypes built-in module, it includes emulation of native types, pointers and operations on them, implementing dispatch, operator overloading, and templates. Nimic closely follows Nim programming language, to which nimic code transpiles.

Key principle: nimic code is valid Python that runs natively and transpiles to equivalent Nim code.

Module Architecture

nimic/
├── ntypes.py       — Public API: re-exports type system + Nim keyword/builtin shims
├── ntypesystem.py  — Core type system (Object, NScalar, seq, dispatch, distinct, converter)
├── transpiler.py   — AST-based Python → Nim source code transpiler
├── inliner.py      — Template function inlining (@template, @template_expand)
├── ncode/          — Nim definitions (pydefs.nim, pystd/)
├── nimpy/          — API for generating Python libraries
├── std/            — Python shims for Nim stdlib (math, options, os, paths, strformat, ...)
└── system/         — Python shims for Nim system modules (ansi_c)

ntypesystem.py — Core Type System

Organized in layers from low-level memory to high-level abstractions:

LayerClassesPurpose
MemoryNtype, NTypeRegistryctypes-backed buffers with value semantics
ScalarsNScalarNInteger / NFloatFixed-width types (int8..int64, uint8..uint64, float16..float64) with arithmetic promotion
StructsObjectNim “object” — fields via annotations, backed by ctypes.Structure
EnumsNIntEnumNim integer enums with auto-registration
VariantsObject + match kind:Nim “case object” — discriminated unions
Containersseq[T], UncheckedArray[T]Growable sequence and pointer-indexed array
Dispatch@dispatch, DispDict, NMetaClassNim-style multi-dispatch via type annotations
Modifiers@distinct, @converterType distinctness and trivial type conversions
Stringsstringstr subclass with Nim-compatible &, %, isEmpty

ntypes.py — Public API & Keywords

Re-exports all of ntypesystem and adds Nim keyword/builtin emulation:

  • Compiler hintsconst, let, var, block, export, alias (no-ops in Python, scoping in Nim)
  • Reference typesref, ptr, mut@ (@ operator returns identity)
  • Enum utilitiesNStrEnum with succ/pred/ord/nrange/low/high
  • Cast & memorycast[T](x), sizeof(x), addr(x), unsafe_addr(x)
  • Type aliasesSomeInteger, SomeFloat, untyped, char, u64, i64, f64
  • Iterationfields(obj), fields(a, b), countdown(a, b)
  • Compile-timecomptime(x), defined(varname), static
  • Templates@template, @template_expand (re-exported from inliner)

transpiler.py — Python → Nim Transpiler

A modified CPython ast.py where _Unparser is extended to emit Nim syntax. Implements 30+ transformation rules for indentation, type definitions, function signatures, operators, imports, and control flow.

inliner.py — Template Inlining

@template + @template_expand decorators perform AST-level function inlining for untyped templates, substituting parameter names with call arguments.

DSL Conventions

Nimic uses Python syntax with specific conventions that have dual meaning — runtime behavior in Python and transpilation semantics for Nim:

ConventionExamplePurpose
with let/var/const:with let: x = vec3(1,2,3)Variable declaration scope qualifier
mut @ annotationdef f(x: mut @ Vec3):Mutable argument (var in Nim)
{.pragma.} docstring"""{.inline.}"""Nim pragma (inline, borrow, noSideEffect)
@dispatch@dispatch
def f(x: float64):
Multi-dispatch by argument types
@distinct@distinct
class Color(Vec3):
Distinct type (no implicit conversion)
@template@template
def toUV(v):
Template (inlined at call site)
@converter@converter
def toVec3(uv):
Implicit type converter
<<=dst <<= -srcValue assignment to mutable variable
match kind:match kind:
  case K.a: ...
Variant type definition (case object)
comptime(expr)if comptime(cond):Compile-time evaluation (when in Nim)
fields(obj)for f in fields(obj):Iterate over object fields
with export:with export: mod1, mod2Re-export modules

Projects built with nimic

Quick Example

from __future__ import annotations
from nimic.ntypes import *

# Struct definition (Nim object)
class Vec3(Object):
    x: float64
    y: float64
    z: float64

    def __add__(self: Vec3, v: Vec3) -> Vec3:
        """{.inline.}"""
        result = Vec3()
        result.x = self.x + v.x
        result.y = self.y + v.y
        result.z = self.z + v.z
        return result

# Distinct type
@distinct
class Point3(Vec3):
    """{.borrow: `.`.}"""

# Multi-dispatch
@dispatch
def point3(x: float64, y: float64, z: float64) -> Point3:
    result = Point3(Vec3())
    result.x = x; result.y = y; result.z = z
    return result

# Usage
with let:
    a = point3(1.0, 2.0, 3.0)
    b = point3(4.0, 5.0, 6.0)
    c = Vec3(a) + Vec3(b)

Similar Articles

Show HN: Nibble

Hacker News Top

Nibble is a C-like systems programming language implemented in 3000 lines of C that generates LLVM IR without external dependencies or heap allocations. It supports defer, recursion, various types, structs, pointers, and includes graphical demos.

Performance of the Wren programming language

Lobsters Hottest

The Wren language site posts micro-benchmarks showing it outruns standard Python/Ruby/Lua interpreters while staying a simple bytecode VM, crediting NaN-tagging and fixed object layout.

Mojo 1.0 Beta

Hacker News Top

Modular announces the Mojo 1.0 Beta, a high-performance programming language that combines Python's ease of use with the speed of compiled languages for AI and systems programming.