🛡️ Tratamento de Erros

Proteja seu programa contra falhas inesperadas!

🛡️

Por que tratar erros?

Erros acontecem: arquivos não existem, divisões por zero, valores inválidos... Em vez de deixar seu programa quebrar, você pode capturar e tratar esses erros!

Tabela de Referência

FunçãoDescriçãoUso
lance_erro(mensagem) Lança um erro Interromper execução quando algo está errado
afirme(condição, mensagem) Verifica uma condição Validar pré-condições
chame_protegido(função, ...) Chama função capturando erros Executar código que pode falhar
chame_protegido_estendido(função, tratador, ...) Como acima, com tratador de erro Capturar erros com stack trace

Lançando Erros

lance_erro(mensagem [, nível])

Interrompe a execução e lança um erro com a mensagem especificada:

função divida(a, b)
    se b == 0 então
        lance_erro("Divisão por zero não é permitida!")
    fim
    retorne a / b
fim

divida(10, 0)  -- Erro: Divisão por zero não é permitida!
💡 O parâmetro nível (opcional) indica onde reportar o erro:
  • 1 (padrão): Reporta na linha que chamou lance_erro
  • 2: Reporta na função que chamou a função atual
  • 0: Não adiciona informação de posição

Validando Condições

afirme(condição [, mensagem])

Verifica se uma condição é verdadeira. Se for falsa, lança um erro:

função calcule_raiz(n)
    afirme(n >= 0, "Número deve ser não-negativo!")
    retorne matemática.obtenha_raiz_quadrada(n)
fim

calcule_raiz(-5)  -- Erro: Número deve ser não-negativo!

Se a condição for verdadeira, afirme retorna todos os argumentos:

local arquivo = afirme(terminal.abra("dados.txt"), "Arquivo não encontrado!")
-- Se abrir com sucesso, 'arquivo' recebe o manipulador
-- Se falhar, lança erro com a mensagem

Capturando Erros

chame_protegido(função, ...)

Executa uma função em modo protegido. Se ocorrer um erro, ele é capturado em vez de parar o programa:

função funcao_perigosa()
    lance_erro("Algo deu errado!")
fim

local sucesso, erro = chame_protegido(funcao_perigosa)

se sucesso então
    exiba("Tudo certo!")
fim

se não sucesso então
    exiba("Erro capturado: " .. erro)
fim

Retorno de chame_protegido

SituaçãoPrimeiro retornoDemais retornos
SucessoverdadeiroValores retornados pela função
ErrofalsoMensagem de erro

Passando argumentos

função divida(a, b)
    se b == 0 então
        lance_erro("Divisão por zero!")
    fim
    retorne a / b
fim

-- Passando argumentos para a função
local ok, resultado = chame_protegido(divida, 10, 2)
se ok então
    exiba("Resultado: " .. resultado)  -- 5
fim

local ok, erro = chame_protegido(divida, 10, 0)
se não ok então
    exiba("Erro: " .. erro)  -- Divisão por zero!
fim

Tratamento Avançado

chame_protegido_estendido(função, tratador, ...)

Como chame_protegido, mas permite especificar uma função para tratar o erro (útil para obter stack trace):

função meu_tratador(erro)
    retorne "ERRO TRATADO: " .. erro
fim

função funcao_problematica()
    lance_erro("Falha crítica!")
fim

local ok, msg = chame_protegido_estendido(funcao_problematica, meu_tratador)
exiba(msg)  -- ERRO TRATADO: Falha crítica!

Obtendo informações de depuração

função tratador_com_rastreamento(erro)
    retorne depuração.obtenha_rastreamento(erro, 2)
fim

local ok, erro = chame_protegido_estendido(funcao_perigosa, tratador_com_rastreamento)
se não ok então
    exiba("Stack trace:")
    exiba(erro)
fim

Padrões Comuns

Função que retorna erro como valor

função abra_arquivo_seguro(nome)
    local ok, resultado = chame_protegido(função()
        retorne afirme(terminal.abra(nome))
    fim)

    se ok então
        retorne resultado, nulo
    fim

    se não ok então
        retorne nulo, resultado
    fim
fim

local arquivo, erro = abra_arquivo_seguro("dados.txt")
se erro então
    exiba("Não foi possível abrir: " .. erro)
fim

Validação de parâmetros

função processe_usuario(dados)
    afirme(obtenha_tipo(dados) == "tabela", "dados deve ser uma tabela")
    afirme(dados.nome, "dados.nome é obrigatório")
    afirme(dados.idade, "dados.idade é obrigatório")
    afirme(dados.idade > 0, "dados.idade deve ser positivo")

    -- Prosseguir com processamento...
    exiba("Processando: " .. dados.nome)
fim

Try-finally (limpeza garantida)

função processe_arquivo(nome)
    local arquivo = afirme(terminal.abra(nome))

    local ok, resultado = chame_protegido(função()
        -- Código que pode falhar
        local conteudo = arquivo:leia("*tudo")
        retorne conteudo
    fim)

    -- Sempre fecha o arquivo (como finally)
    arquivo:feche()

    se não ok então
        lance_erro(resultado)  -- Re-lança o erro
    fim

    retorne resultado
fim

Erros Comuns

❌ Problema✅ Solução
Esquecer de verificar retorno de chame_protegido Sempre verifique o primeiro valor retornado
Usar afirme para controle de fluxo normal Use se para lógica normal, afirme para validações
Engolir erros sem tratar Log ou trate adequadamente todos os erros capturados
🎉 Agora você sabe proteger seu código contra falhas! Use chame_protegido para código crítico e afirme para validações.
```