{"id":49127542,"url":"https://github.com/rphle/numerobis","last_synced_at":"2026-04-21T16:12:10.112Z","repository":{"id":334971367,"uuid":"1068581974","full_name":"rphle/numerobis","owner":"rphle","description":"A statically typed programming language with automatic handling of arbitrary physical units and compile-time dimensional safety.","archived":false,"fork":false,"pushed_at":"2026-04-16T14:48:24.000Z","size":17603,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-16T16:33:34.090Z","etag":null,"topics":["c","compiled-language","compiler","measurement","numerobis","physics","programming-language","programming-languages","python","python3","static-typing","units","units-converter","units-measures-converter","units-of-measure","units-of-measurement","unitsofmeasurement"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rphle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-02T15:44:58.000Z","updated_at":"2026-04-16T14:48:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rphle/numerobis","commit_stats":null,"previous_names":["rphle/numerobis"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rphle/numerobis","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rphle%2Fnumerobis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rphle%2Fnumerobis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rphle%2Fnumerobis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rphle%2Fnumerobis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rphle","download_url":"https://codeload.github.com/rphle/numerobis/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rphle%2Fnumerobis/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32099323,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-21T11:25:29.218Z","status":"ssl_error","status_checked_at":"2026-04-21T11:25:28.499Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","compiled-language","compiler","measurement","numerobis","physics","programming-language","programming-languages","python","python3","static-typing","units","units-converter","units-measures-converter","units-of-measure","units-of-measurement","unitsofmeasurement"],"created_at":"2026-04-21T16:12:09.380Z","updated_at":"2026-04-21T16:12:10.104Z","avatar_url":"https://github.com/rphle.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Numerobis\n\nA modern, compiled, statically-typed programming language that treats physical units and dimensions as first-class citizens of the type system. Dimension and unit errors are caught **before execution** — and unit conversions happen **automatically**.\n\n\u003e [!WARNING]\n\u003e The language and its documentation are unfinished. While usable, Numerobis is not recommended for production code yet.\n\n-----\n\n## Why?\n\nIn most programming languages, physical quantities are plain numbers. Units exist only as informal convention, and there is no way to automatically detect unit inconsistencies — the kind of mistake that caused the [loss of the Mars Climate Orbiter](https://en.wikipedia.org/wiki/Mars_Climate_Orbiter) in 1999.\n\nNumerobis integrates units and dimensions directly into its type system:\n\n- **Dimension errors are caught at compile time** — adding a length to a mass is a type error.\n- **Unit conversions are automatic** — you never write conversion factors by hand.\n- **Non-multiplicative units are supported natively** — including affine units like °C and °F, and logarithmic units like dBm and pH.\n\nNumerobis compiles to C99, giving it a significant performance advantage over interpreted languages.\n\n-----\n\n## Installation\n\n### Python\n\nMake sure to have Python ≥ 3.12 installed.\nYou can override the Python executable used by the build system by setting the `NBIS_PYTHON` environment variable or passing it directly to make: `make build PYTHON=python3.12`.\n\n### Linux\n\n1.  **Install Dependencies** — Ensure your system has the core build utilities installed:\n    ```bash\n    sudo apt update \u0026\u0026 sudo apt install -y \\\n      cmake pkg-config build-essential \\\n      automake autoconf libtool\n    ```\n\n2.  **Build \u0026 Install** — Run the following command to build the runtime library and the compiler:\n    ```bash\n    make build\n    ```\n    Once finished, the `nbis` CLI will be available.\n\n### Windows (Experimental)\n\nWindows support currently utilizes Anaconda/Conda to manage the build environment. \n\n1.  **Environment Setup** — Open an Anaconda PowerShell Prompt and create a dedicated environment:\n    ```powershell\n    conda create -n numerobis\n    conda activate numerobis\n    ```\n\n2.  **Install Build Tools** — Install the necessary toolchain from the Conda repositories:\n    ```powershell\n    conda install m2w64-gcc cmake msys2-make ninja pkg-config\n    ```\n\n3.  **Build** \n    ```powershell\n    make build\n    ```\n\n-----\n\n### Graphics Support (Optional)\n\nIf you plan to use the `graphics` module, you must install the **SDL2** development libraries. The build system will automatically detect these and enable graphics support.\n\n#### Linux \n```bash\nsudo apt install libsdl2-dev libsdl2-ttf-dev\n```\n#### Windows\n```powershell\nconda install sdl2 sdl2_ttf\n```\n\n-----\n\n#### CCache (optional)\n\nTo speed up repeated builds, install `ccache`:\n\n```bash\nsudo apt install ccache\n```\n\nYou can then enable compiler caching via:\n\n```bash\n--cache\n```\n\n#### Benchmarks\n\nTo run benchmarks, install `hyperfine` for statistically robust timing:\n\n```bash\nsudo apt install hyperfine\n```\n\n-----\n\n### Editor Support\n\nNumerobis provides syntax highlighting for VSCode. You can install the extension locally into your editor by running:\n\n```bash\nmake highlight\n```\n\nThis copies the syntax configuration directly into your `~/.vscode/extensions` directory\n\n-----\n\n## CLI Reference\n\n### `nbis build`\n\n**Usage:** `nbis build SOURCE [OPTIONS]`\n\n| Flag | Default | Description |\n| :--- | :--- | :--- |\n| `-o`, `--output` | `src_name` | Output binary path. |\n| `--run` / `--no-run` | `--no-run` | Execute the binary immediately after building. |\n| `--quiet` | Off | Suppress non-essential compiler output. |\n| `--debug` / `--no-debug` | `--debug` | Emit debug information (`-g`). |\n| `-O {0,1,2,3,s}` | `0` | Optimization level passed to the C compiler. |\n| `--cc` | `gcc` | C compiler to use (e.g., `clang`). |\n| `--linker` | `None` | Set a specific C linker to use. |\n| `--cmake` / `--no-cmake` | `--cmake` | Use CMake for build configuration. |\n| `--ccache` / `--no-ccache`| `--no-ccache`| Use `ccache` to speed up recompilation. |\n\n### `nbis view`\n\n**Usage:** `nbis view SOURCE [OPTIONS]`\n\n| Flag | Default | Description |\n| :--- | :--- | :--- |\n| `-o`, `--output` | *(stdout)* | Write generated C code to a file instead of printing. |\n| `--theme` | `monokai` | Rich syntax highlighting theme. |\n| `--line-numbers` / `--no-line-numbers` | On | Toggle line numbers in terminal output. |\n\n-----\n\n## Running Tests\n\nTests are executed via `run.py` (or `make test`). The runner parses `.nbis` files, checks for expected error codes, and measures performance.\nThe test suite currently contains 1,333 unit tests (all of which maintain a 100% pass rate).\n\n**Usage:** `python3 run.py [TEST_NAMES...] [OPTIONS]` or `make test -- [TEST_NAMES...] [OPTIONS]`\n\n### Output Options\n\n- `-v`, `--verbose`: Show output for failed tests (default mode).\n- `-f`, `--full`: Show output for **all** tests (passed and failed).\n- `-p`, `--print`: Print the generated C code during the test run.\n- `-F`, `--format`: Print C code with formatting applied.\n\n### Execution Options\n\n| Flag | Default | Description |\n| :--- | :--- | :--- |\n| `-j`, `--jobs` | `CPU Count` | Number of parallel jobs for test execution. |\n| `--cc` | `gcc` | C compiler used for test binaries. |\n| `--linker` | `None` | C linker used for test binaries. |\n| `--no-cmake` | Off | Skip CMake and use direct GCC bindings (unstable). |\n| `--no-lib` | Off | Skip re-building the static runtime libraries before testing. |\n| `--ccache` | Off | Enable `ccache` for test compilation. |\n\n### Targeted Testing\n\nYou can run specific test files by providing their names without the `.nbis` extension:\n\n```bash\n# Run only the echo and logic tests\nmake test -- echo logic\n```\n\n-----\n\n## Language Reference\n\n\u003e For concise examples, browse the `tests/` directory (canonical examples) and `examples/`.\n\n### Comments\n\n```nim\n# single-line comment\n\n#[ multi-line\n   comment ]#\n```\n\n### Variables \u0026 Type Annotations\n\nType and dimension annotations are optional — the compiler infers them bidirectionally.\n\n```python\nx: Type = expr\nx: Mass = 1000       # dimension annotation\n\ni: Int   = 10\nf: Num   = 3.14\nm: Int[Length] = 10 m\ns: Str  = \"hello\"\nb: Bool = true\nn: Num = 42          # 'Int' is a subtype of 'Num'!\nl0: List        = [1, 2, 3]\nl1: List[Int]   = [1, 2, 3]\nl2: List[Mass]  = [1 kg, 2 kg, 3 kg]\nfn: ![[s: Str, n: Int], Str] = !(s: Str, n: Int): Str = s * n\n```\n\n### Functions\n\nFunctions support default arguments. The body can be a single expression or a block.\n\n```python\ngreet!(name: Str, times: Int = 1): Str = name * times\n\nfibonacci!(n: Int): Int = {\n    if n \u003c= 1 then\n        return n\n    return fibonacci(n - 1) + fibonacci(n - 2)\n}\n\necho(fibonacci(20))\n```\n\n### Global Variables\n\nYou can reference and modify variables in the outer scope from within functions using the `global` keyword.\n\n```python\nx = 5\n\nf!() = {\n    global x\n    x = x * 2\n}\n\nf()\necho(x) # 10\n```\n\n\n### Control Flow\n\n```python\n# if / else\nif a \u003c b then echo(\"small\")\nelse {\n    if a \u003e 15 then echo(\"large\") else echo(\"medium\")\n}\n\n# else if chains\nif a \u003c b then echo(\"small\")\nelse if a == b then echo(\"equal\")\nelse echo(\"large\")\n\n# for over a range\nfor i in 0..10 do echo(i)\n\n# for over a list\nfor item in [1, 2, 3] do echo(item)\n\n# while\ni = 0\nwhile i \u003c 10 do {\n    echo(i)\n    i = i + 1\n}\n\n# loops with break and continue\nwhile true do {\n    i = i + 1\n    if i \u003e= 11 then {break}\n    if i % 2 == 0 then {continue}\n    echo(i)\n}\n```\n\n### Lists \u0026 Indexing\n\nLists are ordered and homogeneous. Indexing is zero-based and follows Python conventions (negative indices, slices).\n\n```python\nlst = [10, 20, 30]\nlst[0]   # 10\nlst[-1]  # 30\nlst[1:]  # [20, 30]\n\n# Built-in list methods\nlst.append(40)\nlst.pop(0)\nlst.insert(0, 42)\nlst.extend([50, 60])\n```\n\n### Structs\n\nNumerobis supports custom data structures. You can define fields, provide default values, and instantiate them using keyword arguments.\n\n```python\nstruct Fruit {\n    name: Str,\n    size: Length = 10cm,\n    edible: Bool = false\n}\n\napple = Fruit(\"Apple\", 10cm, true)\nananas = Fruit(\"Ananas\", 30cm)\n\necho(apple.name)\necho(apple.size -\u003e m)\n```\n\n### Methods\n\nYou can bind functions as methods directly to types via dot-syntax.\n\n```python\nStr.length!(self: Str) = 42\necho(\"test\".length())\n\nlst = [\"test\".len, [\"t\", \"e\", \"s\", \"t\"].len]\nfor fn in lst do\n    echo(fn())\n```\n\n### Generics\n\nFunctions can accept generic type variables using the `?` prefix, allowing you to write flexible operations that enforce input-output relationships. Generics work for normal types and variables dimensions.\n\n```python\nid!(x: ?T): ?T = x\nid(1) + 2\nid(\"hello\") + \"!\"\n\n# Generic dimension enforcement\ndimid!(x: Num[?D]): Num[?D] = x\n```\n\n-----\n\n## Units \u0026 Dimensions\n\n### Defining Dimensions and Units\n\n```python\ndimension Length             # base dimension\ndimension Volume = Length^3  # derived dimension\n\nunit m: Length               # base unit for Length\nunit km = 1000 m             # derived unit (dimension inferred)\nunit L  = (0.1 m)^3          # volume in litres\n\nunit taco;                   # shorthand: creates dimension \"Taco\" and base unit \"taco\"\n```\n\n### Unit Suffixes on Literals\n\nUnits are **suffixes on number literals**, not standalone values. This avoids naming conflicts (e.g. `m` can still be used as a variable name).\n\n```python\nm = 410 kg         # 'm' is a variable, 'kg' is a unit suffix — no conflict\n```\n\nA unit suffix extends up to one space from the number, or arbitrarily far inside parentheses:\n\n```python\n# \"5 metres divided by variable s\"\n5 m / s\n5m / s\n\n# \"5 metres per second\"\n5m/s\n5 m/s\n5(m / s)\n```\n\nAllowed operators **inside suffixes**: `*`, `/`, `^`\n\n### Affine Units (e.g. Temperature)\n\n```python\nunit °C: Temperature = _ K + 273.15\nunit °F = (5/9) * (_ K + 459.67)\n\necho(0°C -\u003e K)    # 273.15 K\necho(0°C -\u003e °F)   # 32 °F\n```\n\nThe underscore `_` is the placeholder for the input value. Every unit definition is a function that maps a value to its base unit.\n\n### Logarithmic Units (e.g. Decibels)\n\n```python\nunit mW  = 0.001 W\nunit dBm = 10^(_ mW / 10mW)\n\necho(2 * 60dBm)          # 63.0103 dBm\necho(60dBm |+| 60dBm)    # 120 dBm      (raw number addition, ignores unit)\n```\n\n### The Delta Operator\n\nFor affine and logarithmic units, plain `+` and `-` are semantically restricted. The delta operators `|+|` and `|-|` operate on raw values and reattach the unit afterwards:\n\n```python\n0°C |-| 32°F    # 0 °C\n10dB |+| 5dB    # 15 dB\n```\n\n### Unit Conversions\n\nUse `-\u003e` to convert between compatible units or between types:\n\n```python\n500 m -\u003e km          # 0.5 km\n1 gallon -\u003e L        # 3.78541 L\n\"1234\" -\u003e Int        # 1234 (type conversion)\n(\"1234\" -\u003e Int) + 1  # 1235\n```\n\nConversions between incompatible dimensions are caught at compile time.\n\n### Imports\n\nImport with the `@` prefix to distinguish units/dimensions from regular names. You can also import native standard library modules using standard dot-syntax.\n\n```python\nfrom mymodule import name, @myunit, @MyDimension\nfrom imperial import @gallon\n\n# grouped import shorthand\nfrom si import @(kg, m, km, s, K, J, kJ, kW, h, rad)\n\n# dot-syntax module imports\nimport math\nimport random\n\necho(math.sin(1 rad))\n```\n\n-----\n\n## Type System\n\n`Int` is a subtype of `Num`. Values of type `Int` can be assigned to variables of type `Num` and are automatically promoted. The inverse assignment requires an explicit conversion.\n\n### Dimension Annotations\n\n```python\nx: Length = 42 m\ny: Num[Mass] = 3.14 kg\nl: List[Length] = [x, 6 m, 7 km]\n```\n\n### Compile-Time Errors\n\n```\n'm' declared as [Mass] but has dimension [Length]\nm: Mass = 2m\n```\n\n```\nIncompatible dimensions in addition: [Mass·Length²·Time⁻³] vs [Mass·Length²·Time⁻²]\n42 watt + 3.14 joule\n```\n\n### Interop with C\n\nExternal C functions can be declared and called from Numerobis using the `extern` keyword:\n\n```python\nextern echo!(value, end: Str = \"\\n\"): None;\n```\n\n-----\n\n## Examples\n\n### Energy to Boil a Gallon of Water\n\n```python\nfrom si       import @(kg, L, g, K, kJ, kW, h, J)\nfrom imperial import @gallon\n\nunit °F  = (5/9) * (_ K + 459.67)\nunit cal = 4.184 J\nunit kWh = kW * h\n\ndensity_water = 1 (kg / L)\nmass_water    = 1 gallon * density_water\nc_water       = 1 (cal / (g * K))\nΔT            = (212°F -\u003e K) - (70°F -\u003e K)\nheat          = mass_water * c_water * ΔT\n\necho(heat -\u003e kJ)    # 1249.45 kJ\necho(heat -\u003e kWh)   # 0.347071 kWh\n```\n\n### Logarithmic Unit Addition\n\n```python\nunit mW  = 0.001 W\nunit dBm = 10^(_ mW / 10mW)\n\necho(2 * 60dBm)         # 63.0103 dBm\necho(60dBm |+| 60dBm)   # 120 dBm\n```\n\n### Affine Temperature Conversions\n\n```python\nunit °C: Temperature = _ K + 273.15\nunit °F = (5/9) * (_ K + 459.67)\n\necho(5°C)           # 5 °C\necho(0°C -\u003e K)      # 273.15 K\necho(0°C -\u003e °F)     # 32 °F\necho(0°C |-| 32°F)  # 0 °C\n```\n\n---\n\n### Graphics and Simulations\n\nThe standard library provides a `graphics` module for creating windows, drawing shapes, and handling user input. It is well suited for interactive visualizations, small games, and physics simulations.\n\nA good starting point is the example collection, especially [ball.nbis](examples/ball.nbis) and [scaling.nbis](examples/scaling.nbis), which demonstrate animation, coordinate transformations, and real-time rendering.\n\n---\n\n## Standard Library\n\nThe standard library is still evolving and does not yet have complete reference documentation. For now, the best overview of available functionality is the source itself: [src/numerobis/stdlib/](src/numerobis/stdlib/).\n\n### Modules\n\n- `builtins` – core functions and methods available in every program\n- `constants` – physical and mathematical constants (planned to grow)\n- `graphics` – SDL2-based rendering and input handling, similar in spirit to pygame\n- `imperial` – imperial units of measurement\n- `information` – units for digital information (bit, byte, etc.)\n- `math` – mathematical functions\n- `random` – random number generators and probability distributions\n- `si` – SI units and dimensions\n- `time` – timing utilities\n\n\n-----\n\n## Project Layout\n\n```\nsrc/numerobis/\n  analysis/      — dimension checker, unit simplifier, inversion\n  cli/           — nbis command-line entry point\n  compiler/      — codegen, linker, scoping, C emission\n  lexer/         — tokeniser\n  nodes/         — AST node definitions\n  parser/        — recursive-descent parser + unit expression parser\n  typechecker/   — type inference, dimension algebra, operator rules\n  stdlib/        — built-in modules\nruntime/         — C runtime sources, built into libruntime.a\ntests/           — language tests, benchmarking\nexamples/        — small example programs\nhighlighting/    – VS Code syntax highlighting extension\nscripts/         — build helpers\nassets/          — generated diagrams\n```\n\n\n![Package diagram](assets/packages.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frphle%2Fnumerobis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frphle%2Fnumerobis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frphle%2Fnumerobis/lists"}