Zig (linguagem de programação)

linguagem de programação

Zig é uma linguagem de programação de multiparadigma voltado para sistemas e compilável, embora seja de propósito geral, estaticamente tipada, projetada por Andrew Kelley.[3][4] A linguagem é projetada para "robustez, otimização e facilidade de manutenção",[5][6] suportando genéricos em tempo de compilação e reflexão, compilação cruzada e gerenciamento manual de memória.[7] Um dos principais objetivos da linguagem é competir (e melhorar) a linguagem C,[8][9] ao mesmo tempo que se inspira em Rust,[10][11] entre outros.

Zig
Paradigma Imperativo, Procedural, Concorrente, Funcional, Genérica
Surgido em 8 fevereiro 2016; há 8 anos[1]
Última versão 0.11.0 (3 agosto 2023; há 8 meses[2])
Criado por Andrew Kelley
Estilo de tipagem Forte, Estática, Inferido, Estrutural, Genérico
Principais implementações zig (UNIX like) ou zig.exe (Windows)
Influenciada por C, C++, Go, Jai, JavaScript, LLVM, Rust
Plataforma Etapa 1 & 2:

ARM e AARCH64, MIPS32 LE, RISC-V64, x86, x86_64, Wasm32

Etapa 3:

MIPS32 BE e MIPS64, PowerPC e PPC64, RISC-V32, SPARC, S390x, Wasm64

Etapa 4:

AVR, GPU AMD - GCN, GPU Nvidia, Kalimba, MSP430, XCore (XMOS)

Sistema operacional UEFI, UNIX like, Windows
Licença: MIT
Extensão do arquivo: .zig, .zir, .zon
Página oficial ziglang.org

Zig tem muitos recursos para programação de baixo nível, notavelmente como: packed struct (estrutura de variáveis struct com preenchimento de zero entre os campos), inteiros de largura arbitrária[12] e vários tipos de ponteiro.[13]

O compilador é escrito em Zig, atualmente utiliza LLVM[14] como back-end[15][16] principal além de possuir um back-end próprio ainda em desenvolvimento, suportando muitos de seus alvos nativos.[17] O compilador é um software livre e de código aberto sob a licença MIT.[18] O compilador Zig expõe a capacidade de compilar C e C++, semelhante ao Clang, usando os comandos zig cc e zig c++, respectivamente.[19] A linguagem de programação Nim suporta o uso de zig cc como um compilador C.[20]

O desenvolvimento Zig é financiado pela Zig Software Foundation (ZSF), uma corporação sem fins lucrativos comandado por Andrew Kelley como presidente, que recebe doações e contrata vários empregados a tempo inteiro.

Filosofia editar

Sem estruturas de controle oculta editar

Se o código Zig não parece estar pulando para chamar uma função, então não está. Isso significa que você pode ter certeza de que o código a seguir chama apenas foo()e então bar(), e isso é garantido sem a necessidade de saber os tipos de nada:

var a = b + c.d;
foo ();
bar ();

D tem as funções @property, que são métodos que você chama com o que parece ser acesso de campo, portanto, no exemplo acima, c.d pode chamar uma função. Rust tem sobrecarga do operador, então o operador + pode chamar uma função. D tem exceções throw/catch, portanto, foo() pode lançar uma exceção e evitar que bar() seja chamado. (Claro, até mesmo em Zig foo() poderia travar e impedir bar() de ser chamado, mas isso pode acontecer em qualquer linguagem que seja Turing-Completude). O objetivo desta decisão de design é melhorar a legibilidade.

Sem Alocações ocultas editar

Zig tem uma abordagem de trabalho manual quando se trata de alocação de memória. Não há uma palavra-chave new ou qualquer outro recurso semelhante na linguagem que utilize um alocador de memória (por exemplo, operador de concatenação de strings). Todo o conceito da alocação de memória é gerenciado pela biblioteca e o código da aplicação, não pela linguagem.

Exemplo de alocações ocultas:

  • Go utiliza defer para alocar memória a uma pilha de funções locais. Além de ser uma forma não intuitiva para este fluxo de controle funcionar, ele pode causar falhas como falta de memória se você usar defer dentro de um laço de repetição.
  • Corrotinas em C++ faz uso da alocação de memória para chamar uma outra corrotina.
  • Em Go, uma chamada de função pode causar alocação de memória porque as corrotina em Go (goroutine) alocam pequenas pilhas que são redimensionadas quando a pilha de chamadas fica muito cheia.
  • As principais APIs da biblioteca padrão Rust entram em pânico em condições de falta de memória, e as APIs alternativas que aceitam parâmetros de alocação serão um problema a ser considerado mais tarde

Quase todas as linguagens que possuem coletor de lixo têm alocações ocultas, já que o coletor de lixo esconde as evidências no lado da liberação de memória.

O principal problema com alocações ocultas é que elas impedem a reusabilidade de um pedaço do código, limitando desnecessariamente o número de ambientes aos quais o código seria apropriado para ser implantado. Simplificando, existem casos de uso em que se deve ser capaz de confiar no fluxo de controle e chamadas de função para não ter o efeito colateral da alocação de memória, portanto, uma linguagem de programação só pode servir a estes casos de uso se ela puder fornecer esta garantia de forma realista.

Em Zig, há recursos da biblioteca padrão que fornecem e trabalham com alocadores de memória, mas esses são recursos opcionais da biblioteca padrão, já que não são incorporados a linguagem. Se você nunca inicializar um alocador de memória, você pode ter certeza de que seu programa não irá alocar memória.

Cada recurso da biblioteca padrão que precisa alocar memória aceita um parâmetro Allocator para fazer isso. Isto significa que a biblioteca padrão do Zig suporta dispositivos freestanding. Por exemplo std.ArrayList e std.AutoHashMap podem ser utilizadas para programação em bare-metal!

Alocadores personalizados fazem gerenciamento manual de memória com facilidade. Zig tem um alocador de depuração que mantém a segurança da memória em casos de ponteiro selvagem e liberação dupla. Ela automaticamente detecta e imprime vestígios de vazamentos de memória na pilha. Há um alocador de arena para que você possa agrupar qualquer número de alocações em uma e liberá-las todas de uma só vez, em vez de gerenciar cada alocação independentemente. Alocadores para fins especiais podem ser usados para melhorar o desempenho ou uso de memória para qualquer necessidade específica de aplicação.

Autonomia editar

Zig tem uma biblioteca padrão inteiramente opcional que só é compilada em seu programa se você a utilizar. O mesmo ocorre com a biblioteca C, a utilização dela é opcional, exceto em casos de interoperabilidade com linguagem C. O Zig é amigável ao desenvolvimento de sistemas embarcados e bare-metal.

Uma linguagem portátil para bibliotecas editar

Um dos santo graal da programação é a reutilização de código. Infelizmente, na prática, acabamos reinventando a roda várias vezes. Muitas vezes é justificado.

  • Se um aplicativo tem requisitos de tempo real, qualquer biblioteca que usa coleta de lixo ou qualquer outro comportamento não determinístico é desqualificada como dependência.
  • Se uma linguagem torna muito fácil ignorar erros e, portanto, verificar se uma biblioteca trata corretamente e gera bolhas de erros, pode ser tentador ignorar a biblioteca e implementá-la novamente, sabendo que todos os erros relevantes foram tratados corretamente. O Zig é projetado de forma que a coisa mais preguiçosa que um programador pode fazer é lidar com os erros corretamente e, portanto, pode-se estar razoavelmente confiante de que uma biblioteca irá propagar erros.
  • Atualmente, é pragmaticamente verdade que C é a linguagem mais versátil e portátil. Qualquer linguagem que não tenha a capacidade de interagir com o código C corre o risco de ser obscurecida. O Zig está tentando se tornar a nova linguagem portátil para bibliotecas, tornando-o simultaneamente direto para a conformidade com a C ABI para funções externas e introduzindo segurança e design de linguagem que evita bugs comuns nas implementações.

Simplicidade editar

C++, Rust e D têm um grande número de recursos e podem desviar a atenção do significado real do aplicativo em que você está trabalhando. Alguém se encontra depurando seu conhecimento da linguagem de programação em vez de depurar o próprio aplicativo.

O Zig não possui macros nem metaprogramação, mas ainda assim é poderoso o suficiente para expressar programas complexos de uma forma clara e não repetitiva. Inclusive o Rust que possui casos especiais de macros format!, implementando-o no próprio compilador. Enquanto isso, no Zig, a função equivalente é implementada na biblioteca padrão sem nenhum código de caso especial no compilador.

Quando você olha para o código Zig, tudo é uma expressão simples ou uma chamada de função. Não há sobrecarga de operador, métodos de propriedade, despacho de tempo de execução, macros ou fluxo de controle oculto. Zig busca toda a bela simplicidade de C, exceto as armadilhas.

Etapas do Compilador editar

Recentemente houve mudanças no bootstrap no qual é utilizado uma versão anterior do zig no formato Wasm.[21]

Antes editar

O processo de desenvolvimento do compilador se encontra em 4 etapas, embora apenas 3 sejam aderidos atualmente.

  • Etapa 0: compilado somente em C++ (LLVM)
  • Etapa 1: compilado em C++ (LLVM) e Zig (Etapa 0)
  • Etapa 2: compilado somente em Zig (Etapa 1)
  • Etapa 3: Zig (Etapa 2) compilado por ele mesmo.

Depois editar

Durante essa mudança o compilador deixou de possuir mais de 80,000 linhas de código escritos em C++ e também torna o parâmetro -fstage1 e -fno-stage1 (Etapa 1) obsoleto na versão 0.11 ou posterior, restringindo-se a utilização do compilador auto-hospedado (Etapa 2).

Representação Visual editar

 
Etapas do compilador Zig

As demais etapas posteriores ao 1 (um), apresentam instabilidade com a biblioteca padrão, embora suportem mais plataformas e sistemas, quanto ao 0 (zero) serve apenas como base inicial. O objetivo é tornar-se totalmente independente do LLVM, aderindo a Etapa 2 (dois) como padrão, previsto na versão 1.0.

Software desenvolvido em Zig editar

Banco de Dados
  • Tigerbeetle – É um banco de dados distribuído focado em transações financeiras.[22]
Blockchain
  • Sig – É uma implementação do validador Solana otimizada de forma inteligente e escrita em Zig.[23]
Motor Gráfico
  • Mach – Motor gráfico para desenvolvimento de jogos.[24]
Sistema de construção
Web

Exemplos editar

Olá Mundo - Concatenação de Strings editar

const std = @import("std");

const debug = std.debug;
const heap = std.heap;
const mem = std.mem;

// '!' esta sintaxe antes do tipo void indica ao compilador Zig que a função retornará um erro ou um valor.

pub fn main() !void {
    const ola = "Olá,";
    // Qualquer variavel const ou valor literal é de tempo de compilação

    debug.print("\n{}{}\n", .{ ola, " mundo!" });

    // Método 1: concatenação de arranjo (array)
    // Só funciona se os valores forem de tempo de compilação.
    const ola_mundo_at_comptime = ola ++ " mundo!";

    debug.print("{}\n", .{ola_mundo_at_comptime});

    // Método 2: std.mem.concat - Biblioteca padrão
    var buf: [128]u8 = undefined;

    // Alocando um tamanho fixo de memória, equivalente ao tamanho do buf
    const allocator = &heap.FixedBufferAllocator.init(&buf).allocator;

    const ola_mundo_concatenated = try mem.concat(allocator, u8, &[_][]const u8{ ola, " mundo!" });

    debug.print("{}\n", .{ola_mundo_concatenated});

    // Método 3: std.mem.join - Biblioteca padrão
    const ola_mundo_joined = try mem.join(allocator, " ", &[_][]const u8{ ola, "mundo!" });

    debug.print("{}\n", .{ola_mundo_joined});
}

Interoperabilidade com C editar

const std = @import("std").c;
const c = @cImport({
    // Veja em: https://github.com/ziglang/zig/issues/515
    // @cDefine("_NO_CRT_STDIO_INLINE", "1");
    @cInclude("stdio.h");
});

pub fn main() void {
    _ = std.printf("Método 1: Código C em Zig!\n"); // Requer libc (nativo do sistema)
    _ = c.printf("Método 2: Código C em Zig!\n"); // Requer libc (nativo do sistema)
}

// Compilação: zig build-exe ffi.zig -lc

Fibonacci editar

const expect = @import("std").testing.expect;

fn fibonacci(index: u32) u32 {
    if (index < 2) return index;
    return fibonacci(index - 1) + fibonacci(index - 2);
}

test "fibonacci" {
    // testando a função de fibonacci em tempo de execução
    expect(fibonacci(7) == 13);

    // testando a função de fibonacci em tempo de compilação
    comptime {
        expect(fibonacci(7) == 13);
    }
}

// Saída:

// $ zig test test.zig
// 1/1 test "fibonacci"... OK
// All 1 tests passed.

Lista encadeada genérica editar

fn LinkedList(comptime T: type) type {
    return struct {
        pub const Node = struct {
            prev: ?*Node,
            next: ?*Node,
            data: T,
        };

        first: ?*Node,
        last:  ?*Node,
        len:   usize,
    };
}

pub fn main() void {
    var node = LinkedList(i32).Node {
        .prev = null,
        .next = null,
        .data = 1234,
    };

    var list = LinkedList(i32) {
        .first = &node,
        .last = &node,
        .len = 1,
    };
}

Ver também editar

Referências

  1. Kelley, Andrew. «Introduction to the Zig Programming Language». andrewkelley.me. Consultado em 12 de Fevereiro de 2016 
  2. https://github.com/ziglang/zig/releases
  3. «Zig has all the elegant simplicity of C, minus all the ways to shoot yourself in the foot». JAXenter (em inglês). 31 de outubro de 2017. Consultado em 11 de fevereiro de 2020 
  4. «Tired of C? New programming language Zig aims to be more pragmatic and readable» (em inglês). 19 de outubro de 2017. Consultado em 22 de abril de 2020 
  5. Yegulalp, Serdar (29 de agosto de 2016). «New challenger joins Rust to topple C language». InfoWorld (em inglês). Consultado em 11 de fevereiro de 2020 
  6. «Zig language and C». Sina Corp. 12 de julho de 2020. Consultado em 12 de agosto de 2020 
  7. «The Zig Programming Language». ziglang.org. Consultado em 11 de fevereiro de 2020 
  8. «Mozilla's Observatory, the Zig programming language, and uSens' VR/AR SDK—SD Times news digest: Aug. 29, 2016». SD Times (em inglês). 29 de agosto de 2016. Consultado em 11 de fevereiro de 2020 
  9. «The Zig Programming Language». ziglang.org. Consultado em 11 de fevereiro de 2020 
  10. Company, Sudo Null. «Sudo Null - IT News for you». SudoNull (em inglês). Consultado em 11 de fevereiro de 2020 
  11. Kelley, Andrew. «Unsafe Zig is Safer Than Unsafe Rust». andrewkelley.me. Consultado em 11 de fevereiro de 2020 
  12. Tim Anderson 24 Apr 2020 at 09:50. «Keen to go _ExtInt? LLVM Clang compiler adds support for custom width integers». www.theregister.co.uk (em inglês). Consultado em 24 de abril de 2020 
  13. «Documentation - The Zig Programming Language». ziglang.org. Consultado em 24 de abril de 2020 
  14. «SD Times news digest: C++20 concepts in Visual Studio 2010 version 16.3, Bootstrap to drop IE support, and Zig 0.60 released». SD Times (em inglês). 14 de abril de 2020. Consultado em 19 de abril de 2020 
  15. «A Reply to _The Road to Zig 1.0_». www.gingerbill.org (em inglês). 13 de maio de 2019. Consultado em 11 de fevereiro de 2020 
  16. ziglang/zig, Zig Programming Language, 11 de fevereiro de 2020, consultado em 11 de fevereiro de 2020 
  17. «The Zig Programming Language». ziglang.org. Consultado em 11 de fevereiro de 2020 
  18. «ziglang/zig». GitHub (em inglês). Consultado em 11 de fevereiro de 2020 
  19. «0.6.0 Release Notes · The Zig Programming Language». ziglang.org. Consultado em 19 de abril de 2020 
  20. «Add support for 'zig cc' as C compiler. by hessammehr · Pull Request #13757 · nim-lang/Nim». GitHub (em inglês). Consultado em 19 de abril de 2020 
  21. Kelley, Andrew. «Goodbye to the C++ Implementation of Zig». ziglang.org (em inglês). Consultado em 10 de dezembro de 2022 
  22. Greef, Joran (18 de setembro de 2021). «TigerBeetle - A Million Transactions Per Second» (em inglês). Coil. Consultado em 29 de dezembro de 2022 
  23. Ultd, Ahmad (20 de julho de 2023). «Introducing Sig by Syndica» (em inglês). Syndica. Consultado em 15 de agosto de 2023 
  24. Gutekanst, Stephen (3 de maio de 2021). «Mach Engine - game engine & graphics toolkit for the future» (em inglês). Mach. Consultado em 4 de junho de 2022 
  25. «Bootstrapping Uber's Infrastructure on arm64 with Zig» (em inglês). Uber. 3 de maio de 2023. Consultado em 10 de junho de 2023 
  26. Summer, Jarred (29 de outubro de 2021). «Bun - fast all-in-one JavaScript runtime» (em inglês). Oven. Consultado em 14 de dezembro de 2022 

Ligações externas editar