Panoramica della lingua Nim

Nim 2.2 — linguaggio di sistema | Sintassi simile a Python | Backend C/JS/LLVM | GC opzionale | metaprogrammazione tramite macro

Paradigma

Multi-paradigma: imperativo, funzionale, orientato agli oggetti (tramite la sintassi della chiamata al metodo), metaprogrammazione. Tipizzazione statica con inferenza completa (tipo Hindley-Milner), equivalenza di tipo strutturale. Compilazione tramite C, C++, JavaScript o LLVM. Le macro basate su AST vengono eseguite in fase di compilazione.

Tipi

Categoria Tipi
Firmato int int8 int16 int32 int64 int (a seconda della piattaforma)
Intero non firmato uint8 uint16 uint32 uint64 uint
Galleggiante float32 float64
Bool bool
Car char (1 byte)
Stringa string (mutabile, con prefisso di lunghezza)
Stringa di C cstring (con terminazione null)
Matrice array[N, T] array[T]
Sequenza seq[T] (array dinamico, gestito da GC)
Tupla (T1, T2) / tuple[a: T1, b: T2]
Oggetto object / ref object (heap + GC per impostazione predefinita)
Enum enum { variant, variant2 }
Gamma range[0..100] (sottointervallo)
Impostato set[T] (bitfield, fino a 256 elementi)
Puntatore ptr T
Riferimento ref T (tracciato GC)
Facoltativo Option[T] (da std)
Risultato Result[T, E]
Distinto distinct T (involucro nuovo tipo)
Digitare la classe Concept/generic vincolo
Vuoto void (tipo di ritorno)
Mai never (divergente)

Dichiarazioni

Costruisci Sintassi Note
Funzione proc name(params): Ret = body
Metodo proc name(self: T; params): Ret = body
Modello template name(params): untyped = body Sostituzione dell'AST
Macro macro name(params): untyped = body Manipolazione dell'AST
Variabile let x = expr Immutabile
Mutevole var x = expr
Costante const NAME = expr In fase di compilazione
Lascia (runtime) let x: T = expr
Oggetto type Name = object Tipo di valore
Oggetto rif type Name = ref object Allocato nell'heap
Tupla type Name = tuple[a: T, b: U]
Enum type Name = enum { a, b, c }
Unione type Name = object { case tag: T of ... } Variant/SUM tipo
Digita l'alias type Name = T
Importa import module / from module import name
Includi include "file.nim" Inclusione testuale
Tipo di processo type Handler = proc(params): Ret

Flusso di controllo

Costruisci Sintassi Note
Se if cond: ... else: ...
Se (espressione) let x = if cond: a else: b
Caso case expr: of val: ... else: ... Esauriente
Mentre while cond: ...
Per for x in iterable: ...
Per (intervallo) for i in 0..<n: ...
Per (contato) for i, x in enumerate(arr): ...
Per (coppie) for k, v in pairs(table): ...
Blocca block label: ... Blocco denominato
Pausa break label
Continua continue
Ritorno return expr
Rendimento yield expr Negli iteratori
Prova try: ... except E: ... finally: ...
Differire defer: expr Esegui all'uscita dall'ambito
Scartare discard expr Ignora il risultato

Caratteristiche del caso (corrispondenza).

Operatori

Categoria Operatori
Aritmetica + - * / div mod ^ (xor)
Confronto == != < > <= >=
Logico and or not xor
Bit per bit and or not xor shl shr asr
Impostato + - * (intersezione) < <= (sottoinsieme)
Identità is (controllo tipo) of (controllo sottotipo)
Varie .. (intervallo) ..< $ (stringificazione) @ (prefisso seq) & (stringa concat)
Indirizzo addr x
Deref p[]
Freccia => (ramo scatola, lambda)

Sovraccarico degli operatori

È possibile eseguire l'overload di qualsiasi operatore: `+`, `*`, `in`, ecc. Gli operatori personalizzati possono essere definiti con la notazione backtick.

Sintassi della chiamata al metodo

# Object-oriented style
echo "hello".len()
x.addr().repr()

# Uniform Function Call Syntax (UFCS)
# Any proc can be called as method:
proc greet(s: string): string = "Hello " & s
"world".greet()  # "Hello world"

Generici

proc id[T](x: T): T = x

type
  Pair[T, U] = object
    first: T
    second: U

# Concepts (type constraints)
proc sort[T: SomeOrdinal](arr: var seq[T]) = ...

proc hash[T: Hashable](x: T): int =
  # T must implement Hashable concept

Memoria e GC

Categoria Comportamento
Pila Tipi di valore (object, tuple, array)
Mucchio (GC) ref object, seq, string, pointer to ref
Heap (manuale) ptr T tramite alloc/dealloc
GC Opzionale: --gc:arc, --gc:orc, --gc:markandsweep, --gc:boehm, --gc:none

ARC/ORC (da Nim 2.0)

Memoria manuale

var p = alloc(sizeof(int))
p[] = 42
dealloc(p)

Macro e metaprogrammazione

import macros

macro assert(cond: untyped): untyped =
  # AST manipulation at compile time
  result = quote do:
    if not `cond`:
      echo "assertion failed: ", astToStr(`cond`)
      quit(1)

# Usage
assert(1 + 1 == 3)

# Template (simpler than macro)
template repeat(n: int, body: untyped): untyped =
  for i in 0..<n:
    body

repeat(3, echo "hello")

Funzionalità in fase di compilazione

Libreria standard (selezionata)

Modulo Contenuto
system Procedure, operatori e tipi integrati
strutils divisione di stringhe, unione, ricerca, sostituzione, rimozione, formato, parseInt, toUpper
sequtils mappa, filtra, piega, zip, tutto, qualsiasi, concatena, deduplica
tables Table OrderedTable CountTable TableRef
sets HashSet OrderedSet BitSet
math sqrt, sin, cos, log, pow, casuale, Pi, Tau, Eulero
os fileExists, dirExists, createDir, deleteFile, getEnv, sleep, commandLineParams
osproc execCmd, execProcess, startProcess
net Socket, connetti, invia, ricevi, ascolta, accetta
asyncnet / asyncdispatch Asincrono I/O con async/await
json parseJson, %* (costruttore), [] accesso, carino
xmltree / parsexml Analisi e costruzione XML
parseopt Analisi delle opzioni della riga di comando
critbits Alberi critici
sha1 / md5 / base64 Primitive crittografiche
times DateTime, TimeInterval, ora, formato, analisi
streams StringStream, FileStream, MemoryStream
logging Registratore con livelli e gestori
macros Tipi AST, quoteDo, newStmtList, genSym
pegs / re Corrispondenza PEG e Regex
distros --os:, --cpu: rilevamento
endians Big-endian/little-endian conversione

Gestione degli errori

# Exceptions (runtime)
try:
  let f = open("file.txt")
  defer: f.close()
  echo f.readAll()
except IOError as e:
  echo "IO error: ", e.msg
finally:
  echo "done"

# Result type (no exception, Nim 2.0+)
from std/result import Result, Ok, Err

func div(a, b: int): Result[int, string] =
  if b == 0:
    return Err("division by zero")
  return Ok(a div b)

# Raise exceptions
raise newException(ValueError, "invalid input")

# Option type
import std/options
let x: Option[int] = some(42)
let y: Option[int] = none(int)

Compilazione

nim c file.nim             # compile with C backend
nim cpp file.nim           # compile with C++ backend
nim js file.nim            # compile to JavaScript
nim r file.nim             # compile + run
nim build                  # compile project (newer)
nimble build               # compile with Nimble package
nim check file.nim         # type-check only
nim doc file.nim           # generate documentation
nim pretty file.nim        # format code

Flag di compilazione

--opt:speed --opt:size --opt:none -d:release --gc:orc --gc:arc --gc:markandsweep --cc:clang --cc:gcc --mm:arc --threads:on --stackTrace:on --lineTrace:on --checks:on

Gestore di pacchetti agile

nimble init                 # create package
nimble install <pkg>       # install dependency
nimble build                # build project
nimble test                 # run tests
nimble publish              # publish to nimble registry

nimble.cfg configura i metadati del pacchetto, le dipendenze e le regole di creazione.

Interoperabilità C

# Declare C function
proc printf(fmt: cstring): cint {.importc, varargs.}

# Import C library
proc sqrt(x: float64): float64 {.importc: "sqrt", header: "math.h".}

# Export to C
proc myFunc(a: cint): cint {.exportc.} = a * 2

# Inline C code
{.emit: """
static int add(int a, int b) { return a + b; }
""".}

proc add(a, b: cint): cint {.importc: "add".}

# C type mappings
# int → cint, char → cchar, void → pointer
# char* → cstring, struct → object {.pure, inheritable.}
# size_t → csize, size_t → csize_t

Funzionalità dell'interfaccia delle funzioni estranee