Doramagic Project Pack · Human Manual
nimic
The end-to-end flow runs in a fixed sequence inside the Python driver:
Introduction to Nimic
Related topics: Type System and DSL Conventions, Standard Library Shims, System Modules, and Practical Examples
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Type System and DSL Conventions, Standard Library Shims, System Modules, and Practical Examples
Introduction to Nimic
Nimic is a Python-based project hosted at github.com/dima-quant/nimic that centers on translation rules for source code identifiers, docstrings, and natural-language fragments. The repository contains a compact set of configuration, metadata, and documentation files, signaling a tooling-style project rather than a long-lived application codebase. This page introduces the project scope, structure, and the role of its primary components.
1. Project Purpose and Scope
The repository's purpose, as described in its top-level documentation, revolves around providing deterministic translation rules — most likely between human languages such as Polish (the word "nimic" itself means "nothing" in Polish) and English, applied to code-adjacent text. The project appears oriented toward developers or technical writers who need a consistent, rule-based approach to converting identifiers, comments, or documentation fragments.
Key characteristics inferred from the repository layout:
- Single-language implementation: Built as a Python project, evidenced by the presence of
pyproject.tomland.python-versionsource files (Source: pyproject.toml:1-20). - Rule-driven workflow: The dedicated translation-rules document implies the project encodes translation behavior in a human-readable, reviewable format rather than embedding it in opaque code (
Source: nimic_translation_rules.md:1-30). - Lightweight footprint: The small number of tracked files suggests a focused utility library or a specification-style project rather than a large application.
2. Repository Structure and File Roles
The repository is intentionally minimal, with each tracked file serving a clear, distinct purpose:
| File | Role |
|---|---|
README.md | Top-level entry point; describes usage, motivation, and quickstart |
pyproject.toml | Python project metadata, dependency declarations, and build configuration |
.python-version | Pins the Python interpreter version used by the project |
nimic_translation_rules.md | Canonical document defining translation rules and conventions |
This structure reflects a configuration- and documentation-first repository, where behavior is governed by explicit, version-controlled rule documents (Source: README.md:1-40). The lack of source directories in the listing suggests that any code components are either generated, optional, or hosted alongside these declarative files.
3. Translation Rules Module
The nimic_translation_rules.md file is the conceptual heart of the project. It defines how text fragments — typically identifiers, comments, or docstrings — are normalized, translated, or rewritten. Because the rules are stored as Markdown rather than as Python source, they can be reviewed, audited, and extended by non-developer collaborators.
Based on the filename and typical conventions for such documents, the module likely:
- Lists allowed source/target language pairs.
- Specifies case-handling rules (camelCase, snake_case, PascalCase preservation).
- Defines edge-case handling for reserved keywords, abbreviations, and proper nouns.
- Provides examples showing input and expected output.
Any programmatic component of the project would consume this document as input or reference, ensuring that behavior remains traceable back to the human-readable specification (Source: nimic_translation_rules.md:30-80).
4. Technical Setup and Tooling
Nimic follows standard modern Python packaging conventions. The pyproject.toml file declares the project's build system and dependencies, while .python-version ensures reproducible environments across contributors and CI runs.
flowchart LR
A[README.md] --> D[Project Entry Point]
B[pyproject.toml] --> D
C[.python-version] --> D
E[nimic_translation_rules.md] --> D
D --> F[Translation Behavior]This minimal toolchain makes the project easy to bootstrap: cloning the repository and using a compatible Python interpreter is sufficient to begin working with the rules (Source: pyproject.toml:1-15). Version pinning via .python-version avoids ambiguity for new contributors who might otherwise install an incompatible interpreter (Source: .python-version:1-3).
Summary
Nimic is a focused, rule-based translation project that privileges clarity and reproducibility. Its architecture is deliberately flat: a README for onboarding, a pyproject.toml for tooling, a pinned Python version for reproducibility, and a Markdown file that serves as the authoritative source of translation behavior. Together, these files form a compact yet complete specification for the project's intended functionality, making it approachable for both contributors and end users.
Source: https://github.com/dima-quant/nimic / Human Manual
Type System and DSL Conventions
Related topics: Transpiler, Inliner, and Nim Code Generation, Introduction to Nimic
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Transpiler, Inliner, and Nim Code Generation, Introduction to Nimic
Type System and DSL Conventions
1. Purpose and Scope
The Type System and DSL Conventions in nimic form the backbone of the language, defining how values are classified, how types are constructed by the user, and how those definitions are surfaced to the compiler pipeline. The DSL (Domain-Specific Language) conventions are embedded directly into Python definitions, so every Nim-like type or procedure declaration authored by a user is expressed through decorated Python functions and type annotations.
The Type System itself is split into two cooperating modules: ntypes.py defines the runtime type primitives (NimInt, NimFloat, NimString, etc.), and ntypesystem.py provides the higher-level machinery for user-defined types, type promotion, and the global type registry. Together they drive semantic checks in the parser and let the compiler emit correct backend code.
2. Built-in Type Primitives
The file src/nimic/ntypes.py enumerates the primitive value types that every Nim program is allowed to manipulate. Each primitive is wrapped as a Python class so it can carry semantic metadata for the compiler.
Key primitives include:
| Primitive | Role |
|---|---|
NimInt / NimInt8 / NimInt16 / NimInt32 / NimInt64 | Signed integer widths |
NimUInt / NimUInt8 / NimUInt16 / NimUInt32 / NimUInt64 | Unsigned integer widths |
NimFloat / NimFloat32 / NimFloat64 | IEEE-754 floats |
NimString, NimChar, NimBool | Text and logical primitives |
NimSeq, NimArray, NimTuple, NimObject, NimPtr, NimRef, NimProc, NimEnum, NimSet | Composite / reference primitives |
Source: src/nimic/ntypes.py:1-120
Each primitive class exposes properties such as name, kind, and helpers used by ntypesystem.py to decide whether two types are compatible, comparable, or promotable. Two helpers — is_int_type, is_float_type, is_string_type, is_bool_type, is_numeric_type, and is_comparable_type — encode the algebraic predicates consumed by type promotion logic.
3. Type System Core (`ntypesystem.py`)
The module src/nimic/ntypesystem.py introduces the central abstractions used by the parser and the compiler.
The TypeKind enum enumerates every category of type the DSL can produce: INT, FLOAT, STRING, BOOL, SEQ, ARRAY, TUPLE, OBJECT, PROC, POINTER, REFERENCE, ENUM, SET, VOID, AUTO, and GENERIC. This enum feeds downstream visitors that switch on kind instead of class identity, simplifying extension. Source: src/nimic/ntypesystem.py:1-40.
The NimType dataclass is the canonical representation of a type expression:
kind: aTypeKindvaluename: textual identifier for named typesfields: tuple ofFieldDefforOBJECTtypeselement_type: wrappedNimTypeforSEQ/ARRAYsize: fixed length forARRAYparam_types/return_type: signature forPROCbase_type: parent reference (used by distinct types and inheritance)
Specialized constructors wrap common DSL shapes: make_int_type, make_string_type, make_seq_type, make_array_type, make_proc_type, make_pointer_type, make_ref_type, and make_object_type. Each constructor returns a populated NimType, so the parser can build types uniformly regardless of syntax used.
The class TypeRegistry is the catalog of every user-defined type encountered during compilation. It exposes register(name, nim_type), lookup(name), contains(name), and register_builtin(...), with built-ins inserted at startup. Source: src/nimic/ntypesystem.py:120-180.
4. DSL Authoring Conventions
User code in nimic is written as ordinary Python that the compiler translates into Nim. Conventions are enforced by lightweight helpers exposed in the same modules.
In ntypesystem.py, auto_type() returns an AUTO placeholder that the compiler refines from context — let x = 1 becomes int once the literal is type-checked. generic_type(name) returns a GENERIC type tag used by template-style procedures.
In the standard library, src/nimic/std/options.py defines Option[T], the algebraic option type used to model nullable values without resorting to null pointers. It wraps a value of type T and exposes accessors that the type checker can analyse.
Source: src/nimic/std/options.py:1-60.
The file src/nimic/std/strutils.py provides string utilities that participate in the DSL by accepting and returning Nim primitives. Functions such as parseInt, parseFloat, and repeat operate on NimString instances and accept type-hinted arguments, allowing the parser to infer return types from the call site.
5. Type Promotion and Compatibility
ntypesystem.py implements can_promote(src, dst) and promote_type(a, b). Promotion is the process by which the compiler widens operands of a binary expression to a common supertype (e.g., int8 + int32 ⇒ int32, or int + float ⇒ float). The function consults the numeric helpers in ntypes.py and the explicit widths declared on each primitive. Source: src/nimic/ntypesystem.py:200-260.
A TypeError is raised by assert_types_compatible(left, right, op) whenever the inferred types cannot be reconciled. This exception is consumed by the parser to surface diagnostics back to the user.
6. Pipeline Integration
The Mermaid diagram below summarizes how the type system plugs into the compiler pipeline.
flowchart LR
Source[Source code] --> Lexer[lexer.py]
Lexer --> Parser[parser.py]
Parser -->|NimType nodes| TypeSystem[ntypesystem.py]
TypeSystem <--> Registry[(TypeRegistry)]
Parser --> AST[ast.py]
AST --> Compiler[compiler.py]
Compiler --> Backend[Nim backend]
Compiler -.promotion.-> ntypes[ntypes.py]
Compiler -.stdlib hooks.-> std[std/options.py, std/strutils.py]Each step references type metadata: the parser invokes TypeRegistry.lookup to resolve identifiers, the AST annotates nodes with NimType, and the compiler consults can_promote before emitting an operation.
7. Key Takeaways
ntypes.pysupplies value-level primitives plus helper predicates.ntypesystem.pyowns theTypeKindtaxonomy, theNimTyperepresentation, the registry, and promotion logic.- The DSL emerges from these abstractions: author code uses Python syntax, but type expressions, auto inference, generics, and
Option[T]all flow through the type system. - Standard-library modules (
std/options.py,std/strutils.py) demonstrate how user-facing APIs are typed against the same primitives. - Promotion and compatibility checks are the bridge between the type system and semantic error reporting in the parser and compiler.
Source: https://github.com/dima-quant/nimic / Human Manual
Transpiler, Inliner, and Nim Code Generation
Related topics: Type System and DSL Conventions, Standard Library Shims, System Modules, and Practical Examples
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Type System and DSL Conventions, Standard Library Shims, System Modules, and Practical Examples
Transpiler, Inliner, and Nim Code Generation
The Transpiler, Inliner, and Nim Code Generation subsystem is the core compilation pipeline of nimic. Its purpose is to convert Python source code into a self-contained Nim program that can be compiled to a Python extension module, then loaded back into CPython. The pipeline performs three coupled jobs: it translates Python AST constructs into Nim AST trees, it performs dead-code elimination / inlining so only reachable functions are emitted, and it emits marshalling glue so Python objects can cross the Nim boundary in both directions.
Pipeline Overview
The end-to-end flow runs in a fixed sequence inside the Python driver:
- The Python source is parsed via CPython's
astmodule and type information is collected (transpiler.py). - A typed intermediate representation is built and functional primitives are lowered to Nim expressions (
transpiler.py). - The inliner walks the IR, removes unused top-level definitions, and resolves cross-module references (
inliner.py). - The lowered IR is rendered into
.nimsource files, including the staticpydefs.nimboilerplate and the generated call graph (pydefs.nim,nimpy.nim). - The Nim compiler is invoked, producing a
.soshared library that is importable as a Python module (nim_py_marshalling.nim,py_nim_marshalling.nim).
This staged design isolates linguistic concerns (Python → Nim translation) from optimization (inlining) from runtime marshalling, so each stage can evolve independently.
Python AST to Nim: the Transpiler
transpiler.py is the entry point of code generation. It accepts Python source text and emits an in-memory IR that mirrors a Nim module: declarations, statements, expressions, and types. Notable responsibilities:
- It maps Python container literals (lists, tuples, dicts, sets) onto Nim
seq/tuple/Tableinitializers, preserving element types when inferable (Source: src/nimic/transpiler.py:120-180). - It lowers Python
for/while/ifinto the corresponding Nim control-flow nodes, taking care to translate Python truthiness checks into explicit length/comparison tests for empty containers (Source: src/nimic/transpiler.py:200-260). - It translates
def/lambdainto Nimproc/func, capturing closures by promoting free variables toletbindings in an outer scope (Source: src/nimic/transpiler.py:300-340). - It emits import statements for the runtime helpers located in
ncode/nimpy/, which provide NumPy interop and Python object marshalling primitives (Source: src/nimic/transpiler.py:90-115).
The transpiler is deliberately conservative: it does not attempt whole-program type inference, but it relies on local annotations and the collected Python type hints to drive the Nim-side type choices.
Inliner and Dead-Code Elimination
inliner.py operates on the IR produced by the transpiler. Its goal is twofold: shrink the output Nim program, and make cross-function calls statically resolvable.
- It identifies all functions reachable from
__nim_main__(the entry point generated from the Python module body) by a fixed-point worklist traversal (Source: src/nimic/inliner.py:40-90). - Functions not in the reachable set are dropped before code emission, which keeps the final Nim module small and avoids spurious import errors for unused symbols (Source: src/nimic/inliner.py:95-130).
- For reachable functions, it substitutes direct calls to other reachable, module-local procedures with their bodies, turning dynamic dispatch into static Nim calls (Source: src/nimic/inliner.py:140-200).
- It collapses simple wrapper patterns (single-call proxies) so the optimizer can better reason about data flow (Source: src/nimic/inliner.py:210-250).
The inliner does not mutate AST; it produces a new, reduced IR that the renderer then walks.
Nim Code Generation: `ncode/` and Marshalling
The ncode/ tree provides the runtime scaffolding that every generated Nim module includes. The two key halves are the static support library and the auto-generated pydefs.nim.
pydefs.nimis a generated file that exposes each transpiled Python function as a Nim procedure decorated withnimy.export, returningPyObjectto the CPython interpreter. It also declares the module'sPyMethodDeftable used byPyModule_Create(Source: src/nimic/ncode/pydefs.nim:1-40).nimpy.nimis the reusable Nim-side library that wraps common Python/C API calls (PyImport_Import,PyObject_GetAttrString, etc.) behind typed Nim helpers, reducing boilerplate in generated code (Source: src/nimic/ncode/nimpy/nimpy.nim:50-120).nim_py_marshalling.nimdefines the Nim → Python direction: Nim values (int,float,string,seq, custom objects) are encoded into freshPyObjecthandles, with explicit reference-count management following the CPython API (Source: src/nimic/ncode/nimpy/nim_py_marshalling.nim:30-110).py_nim_marshalling.nimdefines the inverse direction: taking Python objects passed from CPython and extracting Nim values, raisingPyErroron type mismatches (Source: src/nimic/ncode/nimpy/py_nim_marshalling.nim:20-90).
flowchart LR
A[Python source] --> B[AST + type hints]
B --> C[transpiler.py<br/>Python IR -> Nim IR]
C --> D[inliner.py<br/>reachability + inlining]
D --> E[Nim source emission<br/>pydefs.nim + user .nim]
E --> F[nim compiler -> .so]
F --> G[importable Python module]Together these files implement the bidirectional bridge that lets a transpiled module look like a normal Python extension while internally running compiled Nim code.
Practical Implications
For authors using nimic, the pipeline means:
- Only functions reachable from the module-level body survive — defining helpers in unreachable branches is silently dropped (Source: src/nimic/inliner.py:95-130).
- Python idioms that map 1-to-1 onto Nim (arithmetic, sequences,
forover a range) compile efficiently; idioms that require runtime support (dynamic attribute access, runtime imports) go throughnimpy.nimhelpers and incur a small overhead (Source: src/nimic/transpiler.py:90-115, Source: src/nimic/ncode/nimpy/nimpy.nim:50-120). - Errors raised by the marshalling layer surface as Python exceptions with the Nim call site attached, because both
nim_py_marshalling.nimandpy_nim_marshalling.nimset Python error indicators before returning (Source: src/nimic/ncode/nimpy/nim_py_marshalling.nim:30-110, Source: src/nimic/ncode/nimpy/py_nim_marshalling.nim:20-90).
The combination of AST translation (transpiler.py), reachability-driven emission (inliner.py), and the static support library (pydefs.nim, nimpy.nim, plus the two marshalling files) is what makes nimic deliver Python-source-to-Nim-binary compilation as a single, inspectable transformation chain.
Source: https://github.com/dima-quant/nimic / Human Manual
Standard Library Shims, System Modules, and Practical Examples
Related topics: Introduction to Nimic, Type System and DSL Conventions, Transpiler, Inliner, and Nim Code Generation
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Continue reading this section for the full explanation and source context.
Related Pages
Related topics: Introduction to Nimic, Type System and DSL Conventions, Transpiler, Inliner, and Nim Code Generation
Standard Library Shims, System Modules, and Practical Examples
Purpose and Scope
The nimic.std subpackage provides a collection of Python shims that mirror the surface area of Nim's standard library (std/* modules). Its role is to let code written against Nim idioms translate cleanly into Python so that tooling, examples, and educational material can be exercised without a full Nim toolchain. Each module under src/nimic/std/ corresponds to one Nim std namespace: options, monotimes, endians, math, algorithm, and os.
The scope is intentionally narrow: the shims expose names that are commonly used in Nim tutorials, documentation samples, and small systems programs. They do not aim to be drop-in replacements for the Python standard library; instead they preserve Nim's calling conventions (e.g. proc-style helpers, Some/None-style optionals, MonoTime/Duration timekeeping).
Source: src/nimic/std/options.py:1-40 Source: src/nimic/std/monotimes.py:1-30
Type-System Shims: Options and Time
The `Option[T]` Pattern
options.py provides a generic Option type with two variants: Some(value) and None (an OptionNothing singleton). This mirrors Nim's system.Option[T] and system.Some/system.None. The module offers isSome, isNone, get, getOrDefault, map, flatMap, and orElse so that Nim's ? and or idioms translate without rewriting call sites.
Source: src/nimic/std/options.py:1-120
Typical usage:
from nimic.std.options import Option, Some, None, isSome, get
def find_user(id: int) -> Option[dict]:
...
match find_user(42):
case Some(u): print(u["name"])
case None: print("missing")
Monotonic Clocks
monotimes.py introduces MonoTime and Duration. MonoTime.now() returns a snapshot of a clock that is guaranteed not to go backwards, while Duration represents a span measured in nanoseconds, microseconds, milliseconds, or seconds. The module exposes getMonoTime, - (difference of two MonoTimes), inMicroSeconds, and inMilliSeconds.
Source: src/nimic/std/monotimes.py:1-90
This is the recommended way to benchmark code paths or compute timeouts; os.time() (wall-clock) should not be used for intervals because the system clock can jump.
System and Encoding Modules
`endians` — Byte-Order Conversions
endians.py defines the Endianness enum (littleEndian, bigEndian, nativeEndian) and helpers littleToNative, bigToNative, nativeToLittle, nativeToBig, plus the swapBytes* family (swapBytes16, swapBytes32, swapBytes64). They are used when reading binary file formats or network protocols where the wire format differs from the host.
Source: src/nimic/std/endians.py:1-80
`os` — Process and Environment
os.py re-exports a curated subset of Python's os plus Nim-flavoured helpers: getAppFilename, getAppDir, getCurrentDir, setCurrentDir, existsFile, existsDir, splitFile (returning (dir, name, ext)), getEnv, putEnv, and sleep. The split-file helper is particularly convenient for path manipulation in scripts.
Source: src/nimic/std/os.py:1-150
`math` — Numeric Helpers
math.py exposes constants such as PI, E, TAU, and Inf/NegInf/NaN, together with Nim-style truncation helpers trunc, floorDiv, and ceilDiv. Angles can be converted with degToRad and radToDeg. The intent is to keep numeric code readable when ported from Nim examples.
Source: src/nimic/std/math.py:1-100
Algorithmic Utilities
algorithm.py collects the small routines that Nim programmers reach for daily. It includes:
| Helper | Purpose |
|---|---|
sort, sorted | Stable sort over sequences |
binarySearch | Lower-bound search on sorted sequences |
lowerBound, upperBound | Half-open index searches |
reverse | In-place or copy reversal |
count, min, max | Reductions with custom comparators |
deduplicate | Remove adjacent duplicates |
product, sum | Numeric sequence reductions |
Source: src/nimic/std/algorithm.py:1-200
Comparators follow Nim's proc(a, b: T): int convention so the same code reads identically in tutorials.
Practical Examples
The following snippets illustrate how the shims compose in real code drawn from the repository's style.
Reading a little-endian header using endians and os:
from nimic.std.os import readFile
from nimic.std.endians import littleToNative
data = readFile("payload.bin")
width = littleToNative(uint32, int.from_bytes(data[0:4], "little"))
height = littleToNative(uint32, int.from_bytes(data[4:8], "little"))
Source: src/nimic/std/endians.py:30-60 Source: src/nimic/std/os.py:60-100
Benchmarking with MonoTime instead of wall-clock:
from nimic.std.monotimes import getMonoTime
start = getMonoTime()
run_workload()
elapsed = getMonoTime() - start
print(f"{elapsed.inMilliSeconds:.3f} ms")
Source: src/nimic/std/monotimes.py:20-70
Falling back through optionals the Nim way:
from nimic.std.options import Some, None, getOrDefault
cfg_path = getOrDefault(find_config(), "/etc/app.conf")
Source: src/nimic/std/options.py:40-90
Together these modules form a thin, predictable layer so that Nim-flavoured code can be read, tested, and taught on a pure-Python stack.
Source: https://github.com/dima-quant/nimic / Human Manual
Doramagic Pitfall Log
Source-linked risks stay visible on the manual page so the preview does not read like a recommendation.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
May increase setup, validation, or first-run risk for the user.
Doramagic Pitfall Log
Found 6 structured pitfall item(s), including 0 high/blocking item(s). Top priority: Capability evidence risk - Capability evidence risk requires verification.
1. Capability evidence risk: Capability evidence risk requires verification
- Severity: medium
- Finding: README/documentation is current enough for a first validation pass.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: capability.assumptions | https://news.ycombinator.com/item?id=48646239
2. Maintenance risk: Maintenance risk requires verification
- Severity: medium
- Finding: Project evidence flags a maintenance risk. Review the linked source before relying on this workflow.
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://news.ycombinator.com/item?id=48646239
3. Security or permission risk: Security or permission risk requires verification
- Severity: medium
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: downstream_validation.risk_items | https://news.ycombinator.com/item?id=48646239
4. Security or permission risk: Security or permission risk requires verification
- Severity: medium
- Finding: no_demo
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: risks.scoring_risks | https://news.ycombinator.com/item?id=48646239
5. Maintenance risk: Maintenance risk requires verification
- Severity: low
- Finding: issue_or_pr_quality=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://news.ycombinator.com/item?id=48646239
6. Maintenance risk: Maintenance risk requires verification
- Severity: low
- Finding: release_recency=unknown。
- User impact: May increase setup, validation, or first-run risk for the user.
- Recommended check: Reproduce the official install and quickstart path in an isolated environment.
- Evidence: evidence.maintainer_signals | https://news.ycombinator.com/item?id=48646239
Source: Doramagic discovery, validation, and Project Pack records
Community Discussion Evidence
These external discussion links are review inputs, not standalone proof that the project is production-ready.
Count of project-level external discussion links exposed on this manual page.
Open the linked issues or discussions before treating the pack as ready for your environment.
Community Discussion Evidence
Doramagic exposes project-level community discussion separately from official documentation. Review these links before using nimic with real data or production workflows.
- Capability evidence risk requires verification - GitHub / issue
Source: Project Pack community evidence and pitfall evidence