Introdução de Algebraic Data Types para C99
(github.com/Hirrolot)Datatype99
Uma biblioteca que oferece tipos de dados algébricos seguros e intuitivos, com correspondência de padrões exaustiva e recursos de introspecção em tempo de compilação. É implementada em C99 puro, então não requer ferramentas externas.
Principais características
- Segurança de tipos: variantes com tipo inadequado, correspondência de padrões incompleta e acesso inválido a campos são detectados em tempo de compilação.
- Portabilidade: basta ter um compilador C99 em conformidade com o padrão. Não são necessários biblioteca padrão, recursos específicos de compilador/plataforma, VLA etc.
- Previsibilidade: há uma semântica formal de geração de código definida, garantindo que o layout de dados gerado seja sempre o mesmo.
- Erros fáceis de entender: robusto contra código incorreto.
- Comprovado na prática: está sendo usado no OpenIPC no desenvolvimento de software de streaming em tempo real para câmeras IP. Inclui uma implementação de RTSP 1.0 e cerca de 50 mil linhas de código privado.
Instalação
- O Datatype99 é composto por um único arquivo de cabeçalho
datatype99.he por uma dependência, o Metalang99. - Se você usa CMake, é recomendável obtê-lo via
FetchContent. - Se necessário, é possível usar cabeçalhos pré-compilados. Isso pode reduzir o tempo de compilação.
Como usar
- O Datatype99 é um simples açúcar sintático para uniões etiquetadas. É mais seguro e conciso.
- Exemplo de árvore binária:
- Para implementar diretamente em C, é preciso usar structs, unions, enums etc.
- Com Datatype99, é possível definir isso de forma simples com uma chamada ao macro
datatype - Também é simples calcular a soma da árvore usando correspondência de padrões
- Segurança em tempo de compilação: ao acessar um binding de uma variante incorreta, ocorre erro de compilação
- Flexibilidade: os bindings são do tipo ponteiro, então podem ser modificados, e é possível obter valores por dereferência
- Funções construtoras de variantes são geradas automaticamente
- Breve explicação sobre correspondência de padrões:
- O caso padrão é tratado com
otherwise - Para ignorar bindings, usa-se
_ - Em
ofeifLet, é proibido usarbreak/continueno nível mais alto. Use rótulos comgoto.
- O caso padrão é tratado com
Sintaxe e semântica
- São fornecidas uma definição gramatical em EBNF e explicações da semântica.
- No cabeçalho da biblioteca, recomenda-se usar as versões postfix dos macros.
Tipo unit
- Fornecido como
UnitT99eunit_v99.
Opinião do GN⁺
- Usar o Datatype99 parece trazer a grande vantagem de permitir o uso de tipos de dados algébricos em C de forma segura e prática. Também parece fácil integrá-lo a codebases C existentes.
- No entanto, se for usado em C++, pode haver sobreposição com recursos da própria linguagem, como templates ou
constexpr. Em comparação com C, a vantagem pode ser menor. - Garantir segurança em tempo de compilação é uma grande vantagem, mas parece difícil aproveitá-lo em casos nos quais o tipo de dado muda dinamicamente. É uma limitação da tipagem estática.
- Em projetos pequenos, talvez dê para implementar isso manualmente, mas à medida que a codebase cresce, usar uma biblioteca como Datatype99 provavelmente ajuda em produtividade e estabilidade.
- Bibliotecas com funcionalidades semelhantes incluem LibADT, Kitsune e P99.
Ainda não há comentários.