Visão geral da linguagem Nim

Nim 2.2 — linguagem de sistemas | Sintaxe semelhante ao Python | Back-ends C/JS/LLVM | GC opcional | metaprogramação via macros

Paradigma

Multiparadigma: imperativo, funcional, orientado a objetos (via sintaxe de chamada de método), metaprogramação. Tipagem estática com inferência completa (tipo Hindley-Milner), equivalência de tipo estrutural. Compilação via C, C++, JavaScript ou LLVM. Macros baseadas em AST são executadas em tempo de compilação.

Tipos

Categoria Tipos
Assinado int8 int16 int32 int64 int (dependente da plataforma)
Int não assinado uint8 uint16 uint32 uint64 uint
Flutuar float32 float64
Bool bool
Caráter char (1 byte)
Corda string (mutável, prefixado por comprimento)
Cadeia C cstring (terminação nula)
Matriz array[N, T] array[T]
Sequência seq[T] (matriz dinâmica, gerenciada por GC)
Tupla (T1, T2) / tuple[a: T1, b: T2]
Objeto object / ref object (pilha + GC por padrão)
Enum enum { variant, variant2 }
Alcance range[0..100] (subfaixa)
Definir set[T] (campo de bits, até 256 elementos)
Ponteiro ptr T
Referência ref T (rastreado por GC)
Opcional Option[T] (de padrão)
Resultado Result[T, E]
Distinto distinct T (invólucro de novo tipo)
Classe de tipo Concept/generic restrição
Vazio void (tipo de retorno)
Nunca never (divergente)

Declarações

Construir Sintaxe Notas
Função proc name(params): Ret = body
Método proc name(self: T; params): Ret = body
Modelo template name(params): untyped = body Substituição AST
macro macro name(params): untyped = body Manipulação AST
Variável let x = expr Imutável
Mutável var x = expr
Constante const NAME = expr Tempo de compilação
Deixe (tempo de execução) let x: T = expr
Objeto type Name = object Tipo de valor
Objeto de referência type Name = ref object Alocado em heap
Tupla type Name = tuple[a: T, b: U]
Enum type Name = enum { a, b, c }
União type Name = object { case tag: T of ... } Variant/SUM tipo
Digite o alias type Name = T
Importar import module / from module import name
Incluir include "file.nim" Inclusão textual
Tipo de processo type Handler = proc(params): Ret

Fluxo de controle

Construir Sintaxe Notas
Se if cond: ... else: ...
Se (expressão) let x = if cond: a else: b
Caso case expr: of val: ... else: ... Exaustivo
Enquanto while cond: ...
Para for x in iterable: ...
Para (intervalo) for i in 0..<n: ...
Para (contado) for i, x in enumerate(arr): ...
Para (pares) for k, v in pairs(table): ...
Bloquear block label: ... Bloco nomeado
Pausa break label
Continuar continue
Retorno return expr
Rendimento yield expr Em iteradores
Experimente try: ... except E: ... finally: ...
Adiar defer: expr Executar na saída do escopo
Descartar discard expr Ignorar resultado

Recursos de caso (correspondência)

Operadores

Categoria Operadores
Aritmética + - * / div mod ^ (xor)
Comparação == != < > <= >=
Lógico and or not xor
Bit a bit and or not xor shl shr asr
Definir + - * (interseção) < <= (subconjunto)
Identidade is (verificação de tipo) of (verificação de subtipo)
Diversos .. (intervalo) ..< $ (stringify) @ (prefixo seq) & (string concat)
Endereço addr x
Deref p[]
Flecha => (ramificação de caso, lambda)

Sobrecarga do Operador

Qualquer operador pode ser sobrecarregado: `+`, `*`, `in`, etc. Operadores personalizados podem ser definidos com notação de crase.

Sintaxe de chamada de método

# 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"

Genéricos

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

Memória e GC

Categoria Comportamento
Pilha Tipos de valor (object, tuple, array)
Pilha (GC) ref object, seq, string, pointer to ref
Pilha (manual) ptr T através de alloc/dealloc
CG Opcional: --gc:arc, --gc:orc, --gc:markandsweep, --gc:boehm, --gc:none

ARC/ORC (desde Nim 2.0)

Memória manual

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

Macros e metaprogramação

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")

Recursos de tempo de compilação

Biblioteca Padrão (selecionada)

Módulo Conteúdo
system Procs, operadores e tipos integrados
strutils divisão de string, junção, localização, substituição, remoção, formato, parseInt, toUpper
sequtils mapear, filtrar, dobrar, compactar, todos, qualquer, concat, desduplicar
tables Table OrderedTable CountTable TableRef
sets HashSet OrderedSet BitSet
math sqrt, sin, cos, log, pow, aleatório, Pi, Tau, Euler
os fileExists, dirExists, createDir, removeFile, getEnv, sleep, commandLineParams
osproc execCmd, execProcess, startProcess
net Soquete, conectar, enviar, receber, ouvir, aceitar
asyncnet / asyncdispatch Assíncrono I/O com async/await
json parseJson,%* (construtor), [] acesso, bonito
xmltree / parsexml Análise e construção de XML
parseopt Análise de opção de linha de comando
critbits Árvores de bits críticos
sha1 / md5 / base64 Primitivos criptográficos
times DateTime, TimeInterval, agora, formatar, analisar
streams StringStream, FileStream, MemoryStream
logging Logger com níveis e manipuladores
macros Tipos AST, quoteDo, newStmtList, genSym
pegs / re Correspondência de PEG e Regex
distros --os:, --cpu: detecção
endians Big-endian/little-endian conversão

Tratamento de erros

# 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)

Compilação

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

Sinalizadores de compilação

--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

Gerenciador de pacotes ágil

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 metadados de pacote, dependências e regras de construção.

Interoperabilidade 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

Recursos de interface de função externa