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)
- Condições da filial:
of val:, of val1, val2:, of 0..10:
- Padrões de intervalo, associação definida, correspondência de tipo
of T(someField): — correspondência de padrão com ligação
- Exaustividade verificada para enums
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)
--gc:arc: contagem de referência determinística (sem coletor de ciclo)
--gc:orc: ARC + coletor de ciclo opcional
{.acyclic.} pragma para tipos sem ciclo
sink parâmetros para semântica de movimento
cursor anotação para semântica semelhante a empréstimo
Memória manual
var p = alloc(sizeof(int))
p[] = 42
dealloc(p)
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
static[T] — forçar avaliação em tempo de compilação
when — condicional em tempo de compilação (como #if em C)
const — constante de tempo de compilação com semântica Nim completa
macro — transformação de código em nível AST
template — substituição em nível de sintaxe
{.pragma.} — pragmas definíveis pelo usuário
compileTime — executa o código em tempo de compilação
import macros — AST construction/manipulation
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
{.importc.} {.exportc.} {.header.} {.link.} {.nodecl.}
{.importcpp.} para interoperabilidade C++
{.importobjc.} para Objetivo-C
{.importjs.} para interoperabilidade JavaScript
{.packed.} para layout de estrutura compatível com ABI
{.union.} para uniões C
{.bitsize.} para campos de bits