Nim Programming Language
repository·devel·Indexed 12 days ago
https://github.com/nim-lang/nimA programming language that compiles to C, C++, or JavaScript. This documentation covers the Nim compiler, its standard library, development tools like koch and nim-gdb, and detailed changelogs from v0.18.0 through v0.20.0.
What's inside Nim
- Testament is an advanced automatic unittests runner for Nim. It provides process isolation, generates test statistics, supports multiple targets (C, C++, ObjectiveC, JavaScript), and can generate HTML reports. It is designed to handle even complex test scenarios and includes features like dry-runs, logging, and test skipping.
Overview of the Nim Compiler source code
develThe Nim compiler is written in Nim itself. It is important to note that the current codebase was translated from a bootstrapping version originally written in Pascal. As a result, the source code may not represent the highest standards of idiomatic Nim code. For a deep dive into how the compiler is structured, refer to the Internals of the Nim Compiler documentation.Overview of Linenoise
develLinenoise is a minimal, zero-configuration, BSD-licensed replacement for
readline. It is designed to be lightweight and easy to embed in small utilities without the overhead of large libraries likereadline(30k lines) orlibedit(20k lines). It provides essential command-line features including:- Single and multi-line editing mode with standard key bindings.
- History handling (using arrow keys).
- Completion support.
- Minimal footprint: Approximately 1,100 lines of code.
- Broad compatibility: Uses a subset of VT100 escape sequences, making it compatible with ANSI.SYS and most modern terminals.
Generate installers with niminst
develniminst is a tool used to generate installers for Nim programs. It can create Windows installers via Inno Setup and installation/deinstallation scripts for UNIX-like systems.
To use niminst, you must provide a configuration file that describes your project, files, and target operating systems. The tool uses the Nim
parsecfgmodule to parse this configuration.What is the koch maintenance script?
develThekochprogram is Nim's maintenance script, designed as a portable replacement formakeand shell scripting. It is primarily used to build the Nim compiler and perform various maintenance tasks like running tests or generating documentation.Overview of Nim repository structure
develWhen contributing to Nim, familiarize yourself with these core directories:
compiler/: The compiler source code, including plugins incompiler/plugins/.lib/: The standard library.pure/: Modules written in pure Nim.impure/: Modules with dependencies in other languages.wrappers/: Wrappers for non-Nim dependencies.
nimsuggest: Thenimsuggesttool.config/: Configuration for the compiler and documentation generator.doc/: Documentation files (reStructuredText).tests/: Categorized tests for the compiler and standard library. Integration tests belong intests/untestable.tools/: Tools includingniminst(often invoked viakoch).bin/,build/: Empty directories used during the build process.koch.nim: The tool used to bootstrap Nim and manage builds.
What is NimScript and how does it work?
develNimScript is a subset of the Nim language that can be evaluated by Nim's built-in virtual machine (VM). This VM is used for compile-time function evaluation and as a standalone scripting language. While it shares Nim's syntax and metaprogramming capabilities (templates, macros, etc.), it has specific limitations due to the VM implementation.Declare immutable variables with let
develThe
letstatement declares a local or global single-assignment variable. Unlikevar,letvariables are immutable after creation and cannot be used as l-values (you cannot take their address or pass them tovarparameters).Because they are immutable,
letstatements must define a value at declaration, except when usingimportXpragmas (like{.importc.}) where the value is provided by native code (e.g., a Cconst).let x = 10 # x = 20 # Error: cannot assign to let variableHow concept overload resolution works
develWhen matching an operand's type to a concept, the compiler treats the operand as a "potential implementation" and attempts to satisfy every definition in the concept body by substituting
Selfwith that implementation.Specificity Rules (Hierarchical Order Comparison): To avoid impractical complexity during overload resolution, Nim uses simplified rules when comparing concepts:
- A concept is more specific than a type
Torauto. - If comparing two concepts, the result is determined by Concept subset matching.
- In all other cases, the concept is considered less specific than its competitor.
- A concept is more specific than a type
Understanding Procedural Types and Calling Conventions
develA procedural type is internally a pointer to a procedure. The compatibility of two procedural types depends on their calling convention. If the calling conventions differ, they are not compatible.
Key Calling Conventions:
nimcall: The default convention for Nimproc. Equivalent tofastcallon supported C compilers.closure: The default for procedural types without pragmas. It includes a hidden environment pointer (takes two machine words).cdecl: Uses the C compiler's calling convention (e.g.,__cdeclon Windows).stdcall: Microsoft's__stdcallconvention.safecall: Microsoft's__safecallconvention.inline: A hint to the C compiler to inline the procedure.noinline: Prevents the backend compiler from inlining.fastcall: Uses the C compiler's__fastcallimplementation.thiscall: Microsoft's__thiscall(used for C++ class members on x86).syscall: Uses the C__syscall:cconvention (for interrupts).noconv: Uses the C compiler's default convention (no explicit keyword).
Compatibility Note: A
nimcallprocedure can be passed to a parameter expecting aclosureas a special extension.proc printItem(x: int) = ... # This will NOT compile because calling conventions differ (cdecl vs nimcall) proc forEach(c: proc (x: int) {.cdecl.}) = ... forEach(printItem) type OnMouseMove = proc (x, y: int) {.closure.} proc onMouseMove(mouseX, mouseY: int) = echo "x: ", mouseX, " y: ", mouseY proc setOnMouseMove(mouseMoveEvent: OnMouseMove) = discard # This is OK: 'onMouseMove' has the default (nimcall) convention, # which is compatible with 'closure'. setOnMouseMove(onMouseMove)Use pattern operators in term rewriting
develNim's experimental pattern matching allows for special operators in templates and macros to manipulate the AST.
|(Ordered Choice): Creates an ordered choice in a pattern. Note that matching occurs after optimizations like constant folding, soecho 1might not match a pattern expecting a literal if the compiler folded it.{}(Pattern Parameter): Binds a pattern expression to a parameter usingexpr{param}notation.~(Not): Acts as the 'not' operator in patterns.*(Flatten): Flattens a nested binary expression (e.g.,a & b & c) into a single argument list (e.g.,&(a, b, c)). The second operator must be a parameter used to gather arguments.**(Gather with RPN): Similar to*, but also gathers the matched operators in Reverse Polish Notation (RPN).
You can deactivate pattern matching globally using the
--patterns:offcommand line option or locally with thepatternspragma.# The `|` operator creates an ordered choice template t{0|1}(): untyped = 3 let a = 1 echo a # outputs 3 # The `*` operator flattens expressions template optConc{ `&&` * a }(a: string): untyped = &&a let space = " " echo "my" && (space & "awe" && "some " ) && "concat"Understand Nim Memory Management
develFor developers working in real-time settings or requiring specific performance characteristics, the Memory Management documentation describes Nim's various memory management strategies and how to operate them.