Aprenda Fazendo

25 Exemplos Progressivos

Do Hello World a Microkernels — cada exemplo ensina um conceito novo.

00 Hello World Básico

O ponto de partida. Em Artcode, println é uma função builtin que aceita qualquer valor e imprime com quebra de linha. Não há boilerplate — nenhuma função main obrigatória para scripts simples.

00_hello.art
// Exemplo 00 - Olá Mundo
println("Hello, Artcode!");
$ art run examples/00_hello.art
01 Valores e Variáveis Básico

Artcode usa let para bindings imutáveis e var para mutáveis. A inferência de tipos é automática — Int, Float, String e Bool são detectados pelo compilador sem anotação.

01_values_and_variables.art
// Exemplo 01 - Valores e Variáveis
let inteiro  = 42;
let flutuante = 3.14;
let texto    = "Artcode";
let booleano = true;
println(inteiro);
println(flutuante);
println(texto);
println(booleano);
let soma = inteiro + 8;
println(soma);
$ art run examples/01_values_and_variables.art
02 Arrays & Options Básico

Arrays em Artcode são dinâmicos e heterogêneos por padrão. O tipo Optional é expresso com none — um literal especial que garante ausência de valor sem recorrer a null ou ponteiros nulos.

02_arrays_options.art
// Exemplo 02 - Arrays e Option (None)
let nums  = [1, 2, 3];
let vazio = [];
let opt   = none; // literal option vazio
println(nums);
println(vazio);
println(opt);
$ art run examples/02_arrays_options.art
03 Controle de Fluxo Básico

Artcode usa if/else clássico, mas os operadores lógicos são palavras-chave: and, or, !. Escopos aninhados com { } criam novos namespaces — variáveis locais não "vazam" para o escopo externo (shadowing controlado).

03_control_flow.art
// Exemplo 03 - Controle de Fluxo
let a = 10; let b = 20;
if (a < b) { println("a < b"); } else { println("a >= b"); }
if (a < b and b > 15) { println("duas condições"); }
let sol = true;
if (sol) { println("Praia!"); }
if (!sol or a == 10) { println("Uma condição verdadeira"); }
// Escopo aninhado
let nivel = "global";
{ let nivel = "local"; println(nivel); }
println(nivel); // "global" — não foi afetado
$ art run examples/03_control_flow.art
04 Funções & Closures Básico

Funções são declaradas com func e suportam anotações de tipo opcionais nos parâmetros e retorno. Closures capturam o ambiente léxico automaticamente — variáveis do escopo externo ficam acessíveis sem nenhuma sintaxe especial.

04_functions_closures.art
// Exemplo 04 - Funções e Captura de Escopo
func soma(a: Int, b: Int) -> Int { return a + b }
println(soma(2, 3));

let x = 5;
func inc(n) { return n + x } // captura `x` do escopo externo
println(inc(10)); // 15
$ art run examples/04_functions_closures.art
05 Structs, Enums & Match Tipos & Estruturas

struct define tipos produto com campos nomeados. enum define tipos soma com variantes que podem carregar dados. match faz pattern matching exaustivo — casos com .Variant desestrutura os dados da variante automaticamente.

05_structs_enums_match.art
// Exemplo 05 - Structs, Enums e Match
struct Pessoa { nome: String, idade: Int }
enum Status { Ok, Erro(String) }

let p = Pessoa { nome: "Ada", idade: 42 };
println(p.nome); println(p.idade);

let falha = Status.Erro("Falhou");
match falha {
    case .Ok:          println("Tudo certo")
    case .Erro(msg):   println(msg)
}
$ art run examples/05_structs_enums_match.art
06 Enum Shorthand Tipos & Estruturas

Variantes de enum podem ser referenciadas sem o prefixo do tipo quando o compilador consegue inferir o contexto — use .Variant em vez de Tipo.Variant. Para evitar ambiguidade, a forma qualificada (Resultado.Ok(10)) é sempre válida.

06_enum_shorthand_inference.art
// Exemplo 06 - Enum Shorthand & Inferência
enum Resultado { Ok(Int), Err(String) }

let r1 = Resultado.Ok(10);
let r2 = Resultado.Err("Falha");

match r1 { case .Ok(v):  println(v)  case .Err(e): println(e) }
match r2 { case .Ok(v):  println(v)  case .Err(e): println(e) }
$ art run examples/06_enum_shorthand_inference.art
07 Pattern Matching + Guards Tipos & Estruturas

Cases de match aceitam um guard opcional com if para adicionar predicados extras sobre o valor desestruturado. Permite lógica condicional precisa sem aninhamento de ifs dentro dos arms.

07_pattern_matching_guards.art
// Exemplo 07 - Pattern Matching com Guards
enum E { V(Int), W(Int) }
let x = E.V(10);
let y = E.V(5);
let z = E.W(8);

match x {
    case .V(v) if v > 8: println(f"v>8: {v}")
    case .V(v):           println(f"v: {v}")
    case .W(w):           println(f"w: {w}")
}
$ art run examples/07_pattern_matching_guards.art
08 f-Strings & Format Specs Tipos & Estruturas

f-strings em Artcode suportam especificadores de formato embutidos com : — como {n:hex}, {s:upper}, {s:trim}, {s:pad10}. Chaves literais são escapadas com {{ }}.

08_fstrings_format_specs.art
// Exemplo 08 - f-Strings e Especificadores de Formato
let n = 255;
let s = "  AbC  ";
println(f"hex={n:hex} trim={s:trim} upper={s:upper}");
println(f"lower={s:lower} pad={s:pad10}");
println(f"chave literal: {{ {n} }}");
$ art run examples/08_fstrings_format_specs.art
09 Métodos em Struct & Enum Tipos & Estruturas

Métodos são funções declaradas com func Tipo.nome(self). O self é auto-bound ao receiver na chamada. Enums têm acesso a variant e values intrinsecamente para inspeção em runtime.

09_methods_struct_enum.art
// Exemplo 09 - Métodos em Structs e Enums
struct Pessoa { nome: String }
func Pessoa.greet(self) { println(f"Olá, {self.nome}!"); }

let p = Pessoa { nome: "Ada" };
p.greet(); // → Olá, Ada!

enum Status { Ok, Err(String) }
func Status.describe(self) {
    println(f"variant={variant} values={len(values)}");
}
let s1 = Status.Ok;
let s2 = Status.Err("x");
s1.describe(); s2.describe();
$ art run examples/09_methods_struct_enum.art
10 Result & Propagação Tratamento de Erros

O enum Result (Ok, Err) está no prelude e é usado para propagação explícita de erros. Sem exceções implícitas — cada falha é um valor que o caller deve tratar com match.

10_result_like_pattern_try.art
// Exemplo 10 - Propagação explícita de Result
func divide(a: Int, b: Int) -> Result {
    if b == 0 { return Result.Err("/0") }
    return Result.Ok(a / b)
}
func quarter(n: Int) -> Result {
    let r = divide(n, 2);
    match r {
        case .Ok(h): {
            let r2 = divide(h, 2);
            match r2 {
                case .Ok(q):  return Result.Ok(q)
                case .Err(e): return Result.Err(e)
            }
        }
        case .Err(e): return Result.Err(e)
    }
}
let r = quarter(40);
match r { case .Ok(v): println(f"q={v}")  case .Err(e): println(e) }
$ art run examples/10_result_like_pattern_try.art
11 Arrays Builtin Methods Coleções

Arrays têm métodos nativos como .sum(), .count(), .map(fn) e .filter(fn). O type-checker emite diagnósticos se você chamar sum() em um array heterogêneo.

11_arrays_builtin_methods.art
// Exemplo 11 - Métodos builtin de Array
let nums = [1, 2, 3, 4];
println(nums.sum());   // 10
println(nums.count()); // 4

let mixed = [1, 2, "a"];
println(mixed.count()); // 3 (ok — heterogêneo)
// mixed.sum() → erro de tipo (array misto)
$ art run examples/11_arrays_builtin_methods.art
12 Métricas de Execução Memória & GC

O runtime Artcode emite métricas de execução no stderr ao finalizar: contagem de erros tratados, crash_free%, chamadas de função etc. Este exemplo mostra como evitar divisão por zero e ainda observar as métricas.

12_metrics_demo.art
// Exemplo 12 - Métricas de Execução (ver stderr)
println("A"); println("B");
let denom = 0;
if denom == 0 {
    println("denom is zero, skipping division")
} else {
    println(10 / denom)
}
println("C");
// → stderr: handled_errors=0  crash_free=100%
$ art run examples/12_metrics_demo.art
13 Weak Cycle Demo Memória & GC

weak cria uma referência fraca — ela não impede o GC(ARC) de liberar o objeto. O operador w? é o upgrade opcional: retorna o valor se o dono ainda existir, ou None se já foi dropado.

13_weak_cycle_demo.art
// weak cria referência fraca para `a`
let a = 1;
let w = weak a;
// w? — upgrade opcional: retorna o valor se `a` existir
let opt = w?;
$ art run examples/13_weak_cycle_demo.art
14 Cycle Stub Memória & GC

Stub mínimo usado pelo linter de dependências para detectar ciclos de referência potenciais. Cria uma referência weak "morta" — útil para verificar que o linter identifica o padrão sem precisar de um ciclo real.

14_cycle_stub.art
// Nenhum ciclo real — weak "morta" simulada
let a = 1;
let w = weak a;
// sem API para drop programático ainda
$ art run examples/14_cycle_stub.art
15 Finalizers Memória & GC

on_finalize(obj, fn) registra uma função que será chamada quando o GC(ARC) liberar obj. Finalizers rodam de forma assíncrona e podem promover handles externos. Blocos performant usam a arena interna.

15_finalizer_examples.art
let outside = [99];

func fin_promote() {
    let _promoted = outside;
}

// Registra finalizer dentro de um bloco performant
performant {
    let _target = [1, 2, 3];
    on_finalize(_target, fin_promote);
}
// Ao sair do bloco, _target é finalizado e fin_promote é chamado
$ art run examples/15_finalizer_examples.art
16 Weak & Unowned Memória & GC

weak(obj) retorna um handle que não mantém o objeto vivo. unowned(obj) é um ponteiro direto sem ownership — válido enquanto o dono existir. weak_get(w) e unowned_get(u) são as APIs de depuração para obter o valor.

16_weak_unowned_demo.art
// Exemplo 1: weak — upgrade falha após drop do strong
{
    let owner = [99];
    let w = weak(owner);
    println("inside:", weak_get(w));
}
println("after block: owner foi dropado");

// Exemplo 2: unowned — válido enquanto dono existir
{
    let owner2 = [7];
    let u = unowned(owner2);
    println("inside:", unowned_get(u));
}
println("after block: owner2 foi dropado");
$ art run examples/16_weak_unowned_demo.art
17 Métricas de Arena Memória & GC

Blocos performant alocam objetos em uma arena de curta duração — o GC processa tudo de uma vez ao sair do bloco. Combinando com on_finalize, é possível observar e reagir ao ciclo de vida de objetos de curta duração com precisão.

17_metrics_arena_demo.art
let outside = [99];
let promoted = none;

func fin_promote() { let promoted = outside; }

performant {
    let _a = [1, 2, 3];
    on_finalize(_a, fin_promote);
}
// após блок: _a finalizado, fin_promote chamado
$ art run examples/17_metrics_arena_demo.art
18 Standard Library Standard Library

A stdlib embutida inclui: Map (map_new, map_set, map_get), Set, funções matemáticas (math_abs, math_pow, math_clamp), time_now, rand_next e I/O de arquivos (io_write_text, io_read_text).

18_stdlib_features.art
// Map
let m = map_new();
map_set(m, "hello", 42);
println(map_get(m, "hello"));  // 42
println(len(m));               // 1

// Set
let s = set_new();
set_add(s, 10); set_add(s, 10); // duplicata ignorada
println(len(s)); // 1

// Math
println(math_pow(2, 3));    // 8
println(math_clamp(15, 1, 10)); // 10

// IO
io_write_text("out.txt", "Hello IO!");
println(io_read_text("out.txt"));
$ art run examples/18_stdlib_features.art
19 Performant Arena Standard Library

Blocos performant { } são uma funcionalidade experimental que contorna o GC padrão usando uma arena de memória. Objectos alocados dentro não podem vazar para fora — o type-checker rejeita return de valores da arena.

19_performant_arena.art
performant {
    let x = [1, 2, 3];
    // return x; ← rejeitado pelo TypeInfer (não pode vazar arena)
}
$ art run examples/19_performant_arena.art
20 Atores Simples Concorrência

Artcode tem um modelo de atores baseado em mensagens. spawn actor { } cria um ator e retorna seu ID. actor_send(id, envelope(...)) envia mensagens. run_actors() aciona o scheduler cooperativo para processar a fila.

20_actors_simple.art
// Spawn do ator como expressão — retorna actor id
let a = spawn actor {
    let msg = actor_receive();
    if msg { println(msg); }
};

// Enviar envelopes para o ator `a`
let ok1 = actor_send(a, envelope(none, 7, 1));
let ok2 = actor_send(a, make_envelope(42, 5));

// Drive the scheduler — ator processa as mensagens
run_actors();
$ art run examples/20_actors_simple.art
21 Microkernel Concorrência

Demonstra uma carga CPU-bound com recursão para gerar chamadas quentes de função — útil para benchmarks de JIT/interpretador. A função sum_work usa tail-recursion e é chamada repetidamente para simular um microkernel de cálculo.

21_microkernel.art
func sum_work(n) {
    func sum_down(i, acc) {
        if i <= 0 { return acc; }
        return sum_down(i - 1, acc + i);
    }
    return sum_down(n, 0);
}

func main() {
    // 200 chamadas de sum_work(20) para gerar hot calls
    sum_work(20); sum_work(20); sum_work(20);
    // ... (200 total)
    return 0;
}
main();
$ art run examples/21_microkernel.art
22 Fmt Test Ferramentas

Código intencionalmente mal-formatado para testar o auto-formatter art fmt. Espaçamento inconsistente, chaves sem espaço — o formatter deve normalizar tudo enquanto preserva comentários e lógica.

22_fmt_test.art
// This file has terrible formatting!
let x= 10;
if x >5{
    println("Bigger!");
    // I want to keep this comment intact!
    if x>20 {
        println("Huge!");
    } else { println("Moderate"); }
}
// art fmt → normaliza espaçamento automaticamente
$ art fmt examples/22_fmt_test.art
23 Linter Tests Ferramentas

Demonstra dois padrões que o linter art lint detecta: shadowing suspeito (reuso de nome de variável em escopo aninhado) e arms mortos em match (case após wildcard _ nunca será executado).

23_linter_tests.art
func test_shadowing() {
    let x = 10;
    if x > 5 {
        let x = 20; // ← linter: suspicious shadow
        println(x);
    }
}
func test_dead_arms() {
    let value = 5;
    match value {
        case _:  println("Caught all!");
        case 10: println("unreachable"); // ← dead code
    }
}
test_shadowing(); test_dead_arms();
$ art lint examples/23_linter_tests.art
24 Result & Option Sugar Tratamento de Erros

Açúcar sintático avançado para monads nativas: if let Ok(v) = expr desestrutura inline; .is_ok(), .is_err(), .unwrap() e .unwrap_or(default) são métodos builtin de Result e Option.

24_result_option_sugar.art
func test_result_sugar() {
    let success = Result.Ok(42);
    let failure  = Result.Err("Went wrong");

    println(success.is_ok());        // true
    println(success.unwrap());       // 42
    println(failure.unwrap_or(-1)); // -1

    if let Ok(value) = success {
        println("Success:", value)
    }
    if let Err(msg) = failure {
        println("Failure:", msg)
    }
}

func test_option_sugar() {
    let some_val = Option.Some("Hello");
    let none_val = Option.None;

    println(some_val.is_some());              // true
    println(none_val.unwrap_or("Default"));  // "Default"

    if let Some(text) = some_val { println(text) }
}

test_result_sugar();
test_option_sugar();
$ art run examples/24_result_option_sugar.art