Pretty.c - Scripting sobre C
(github.com/aartaka)- Pretty C é uma nova linguagem de scripting compatível com C que adiciona recursos de conveniência a programas em C, como tipagem dinâmica, iteração genérica e rastreamento de recursos
- A forma de uso é como uma biblioteca header-only que inclui apenas
pretty.h, podendo ser usada junto com arquivos C e bibliotecas C existentes - Os recursos oferecidos incluem aliases como
string,anyenil, inferência de tipos comvar/let, saída genérica comprint/println, comparação genérica comequale macros de operador ternário mais legíveis - Para reduzir repetição em laços e operações de memória, fornece uma sintaxe baseada em macros como
foreach,forthese,fortimes,forrange,new,vector,delete,with,lambdaetry/catch - Alguns recursos dependem de condições como GCC, Clang, C23+ e C11+, e variáveis agrupadas com
withsãovoid *, então pode ser necessário converter o tipo antes de usar
Objetivos e forma de uso do Pretty C
- Pretty C é uma linguagem de scripting compatível com C que adiciona a programas em C tipagem dinâmica, iteração genérica, rastreamento de recursos e várias conveniências de sintaxe
- Mantém compatibilidade retroativa com C existente e com bibliotecas C
- É inspirado em Lua, Python, JavaScript e Lisp
- A instalação pode ser feita clonando o repositório ou copiando apenas o arquivo
pretty.h- Pode ser incluído em qualquer arquivo C com
#include "pretty.h" - Também pode ser usado definindo o caminho do Pretty C no include path
- Pode ser incluído em qualquer arquivo C com
Headers incluídos por padrão e macros simples
- Pretty C inclui headers padrão para permitir o uso imediato de tipos comuns e expressões alternativas de operadores
- Também fornece macros simples frequentemente definidas
max,min: maior e menor valor entre dois númeroslen: comprimento de arraydefault: fornece um valor de fallbacklimit: limita um valor a uma faixabetween: verifica se um número está dentro de uma faixadivisible: verifica se é divisível por outro número
Tipos e aliases
- Pretty C fornece aliases de tipo curtos para tipos de C
stringéchar*byteécharbyteséchar*anyévoid*- Também oferece formas abreviadas de inteiros como
uchar,ushort,uint,ulong
- Também inclui aliases de sintaxe influenciados por Lua e Lisp
eq,is:==bitnot,bitxor: aliases para operações de bitsuccess,fail,failure: aliases para o padrãosuccess == 0below,above,upto,downto: operadores de comparaçãoeven,odd,positive,negative,zero,empty: predicados para números e dadosnil:NULLuntil:whilenegadoelif:else ififnt,elifnt: expressões da famíliaif(!...)repeat: alias estilo Lua paradodone,finish,pass: aliases parabreakecontinuealways,forever,loop,indefinitely: expressões para loop infinitonever,comment: expressões que não executam código, mas ainda permitem análise pelo compilador
Inferência de tipos, saída, comparação e ternário
- A inferência de tipos pode ser usada com GCC, Clang ou C23+
- Exemplos fornecidos:
var t = time(0);,let lt = localtime(&t);,local at = asctime(lt);
- Exemplos fornecidos:
- A saída genérica está disponível em C11+
printexibe o valor passadoprintlnadiciona uma quebra de linha após a saída
- A comparação genérica de igualdade também é oferecida como recurso de C11+
- Comparações de string como
equal("NA", line) - Inclui exemplos como
equal(0.3, 0.2 + 0.1)
- Comparações de string como
- O operador ternário pode se tornar mais legível com macros baseadas em texto
whense expande para string vazia para fins de legibilidadeunlessse expande paranot, funcionando como forma negativa dewhenthené?othereotherwisesão:onlyé usado quando a cláusulaotherwisenão é necessáriaotherwhené usado para encadear a próxima condição
Macros de iteração
- Pretty C abstrai padrões frequentes de loop
forcom macros foreach (var, type, length, ...)- Percorre um array ou bloco de memória
- Em cada iteração,
varse torna um ponteiro para o elemento correspondente do array - Como é um ponteiro, o elemento pode ser modificado in-place quando necessário
forthese (var, type, ...)- Percorre os argumentos variáveis passados, vinculando cada valor a
vardo tipotype
- Percorre os argumentos variáveis passados, vinculando cada valor a
fortimes (var, times)- Reduz o padrão comum de repetir de 0 até um número positivo de vezes
forrange (var, init, target)- Percorre um intervalo numérico de
initatétarget initetargetpodem ser quaisquer inteiros signed ou unsigned- Se
initfor maior quetarget, o passo da iteração diminui
- Percorre um intervalo numérico de
forrangeby (var, type, init, target, by)- Percorre
vardo tipo especificado deinitatétargetem passos deby
- Percorre
Utilitários de alocação e de bloco
- As macros de alocação simplificam padrões comuns de alocação de memória em um formato inspirado em C++
new (type, ...): cria structs e outros objetos em uma forma parecida com onewdo C++vector (length, type, ...): simplifica o padrão de alocar um array com comprimento e tipo definidos, além de preencher o conteúdo inicialdelete (...): equivalente afree, mas útil para quem prefere um nome ao estilo C++
- Os utilitários de bloco fornecem macros para binding local, execução adiada e operações em nível de bloco
lambda (ret, name, ...): permite usar em C formas de função aninhada, lambda e closure com GCC, Clang ou C++with (var, close, ...): fornece antecipadamente a função de liberação de recursosclose, sendo útil para objetos alocados dinamicamente ou file handles- Como desvantagem, a variável vinculada
varévoid *, então pode ser necessário convertê-la para o tipo desejado antes de usar
- Como desvantagem, a variável vinculada
defer: foi removido, e é indicado usar o novodeferagora disponíveltryecatch: permitem escrever tratamento de erros em C de forma mais sofisticadaNOERR,NOERROR: fornecidos para conveniência em switch-case de erro
Como contribuir
- Ao adicionar funções, é pedido seguir o Linux Kernel Style Guide
- Recomenda-se executar
make indentantes de fazer commit
- Recomenda-se executar
- Seguir o A’s Commit Message Guide é preferido, mas não obrigatório
1 comentários
Comentários do Hacker News
A tradição de criar linguagens específicas de domínio dentro de C é antiga
Stephen Bourne queria escrever o shell em ALGOL, então martelou obstinadamente o pré-processador de C até fazê-lo parecer com a linguagem que ele preferia
https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh...
https://www.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd/sh...
https://www.ioccc.org/
Queria ver alguém explicar se isso é uma piada ou se o autor está realmente confuso
Nada faz sentido. Não é “scripting”, diz que introduz “tipagem forte”, mas não faz absolutamente nada com tipos, e os apelidos de operadores supostamente inspirados em Lua e Lisp na verdade não existem em nenhuma das duas linguagens. Mas também não parece claramente uma paródia, então é realmente confuso
Diz que é uma linguagem de scripting, mas ainda é preciso compilar o programa. Que vaia
Se acoplar o CINT(https://root.cern.ch/root/html534/guides/users-guide/CINT.ht...), dá para executar na hora e ter REPL também
Vi há algum tempo um post de blog que explicava em detalhes como
./foofunciona e como arquivos ELF são executados. Talvez desse para registrar programas.cda mesma forma, para compilar e executar em seguida[0] https://gist.github.com/jdarpinian/1952a58b823222627cc1a8b83...
[0] https://bellard.org/tcc/tcc-doc.html
“Fornece açúcar sintático suficiente para causar um ataque cardíaco diabético em desenvolvedores C.”
Adorei essa frase
Estou vendo algumas coisas para adicionar ao CNoEvil[0] e ao ogw[1]. Parece que toda vez que esse projeto ressurge a cada poucos meses, sempre aparece mais material
[0] https://git.sr.ht/~shakna/cnoevil3/
[1] https://git.sr.ht/~shakna/ogw
É uma frase pela qual eu sinceramente acabo me apaixonando do fundo do coração
Isso está repetindo o mesmo erro do Python 2. Strings e bytes não são o mesmo tipo, e não deveriam ser tratados assim
argvou a saída de subprocessosAquilo pode conter lixo arbitrário, então não é uma string UTF-8 válida, mas ferramentas como awk e grep são usadas em todo lugar
Dá para considerar strings e bytes como o mesmo tipo geral, mas acho útil dar internamente um tipo diferente a bytes UTF-8 válidos quando isso fizer sentido. Rust lida com isso razoavelmente bem com OsString e String
https://en.cppreference.com/w/c/string/multibyte
Nada disso é sempre verdade. É útil encapsular sequências de bytes validadas em um tipo que só possa ser construído por validação, mas, uma vez feito isso,
Utf8StringeEmailAddresspassam a ser praticamente da mesma categoria. Não há motivo para dar tratamento especial apenas à codificação no sistema de tiposSe for “texto legível por humanos”, concordo que strings não são a mesma coisa que um array arbitrário de bytes. Mas muitas linguagens não impõem essa definição
Isso me lembra de uma base de código em C++ que precisei inspecionar certa vez. Tudo parecia ter sido escrito como se fosse Java: camel case em tudo, getter/setter para todas as variáveis de classe e interfaces espalhadas por toda parte
https://minnie.tuhs.org/cgi-bin/utree.pl?file=V7/usr/src/cmd...
É difícil acreditar que não seja ALGOL
std::string, mas com métodos no estilo Javahttps://learn.microsoft.com/en-us/cpp/cpp/property-cpp?view=...
f(String *), então o código C++ ficava tipof(new String("Hello")Se isso te parece interessante, talvez você também goste de libcello.h
https://www.libcello.org
Os nomes dos tipos são bons, e a escolha de macros de funções embutidas como
miné perfeita. Também gosto deLenOs operadores booleanos nomeados talvez sejam um pouco demais, mas vale experimentar, e o operador ternário já é difícil de ler por natureza, então há espaço para melhorar. Não fiquei totalmente convencido por todas as definições de repetição, mas algumas fazem sentido. O rastreamento de recursos é impressionante, e a forma
for...é um pouco feia, então talvez desse para dar outro nome.No geral, é uma tentativa bem sólida. Eu daria algo como 8/10 para o design. O jeito como isso foi esboçado com macros de C é realmente elegante e de fato parece bom código. Não sei se eu usaria pessoalmente. É uma linguagem nova, e eu já gosto de C. Ainda assim, a forma de implementação é muito clara, então pode ajudar as pessoas a aprender C e pensar sobre design de linguagens
len(),max/mine algumas macros de operadores. É que eu ainda não precisei muito das outras funcionalidades saborosas. Então seria legal experimentar nem que seja só com algumas macros de operadoresSe existe
ifntparaif(!...), então unless parece mais legível do queifntfor(;;)dealwaysEm outras linguagens já vi
loop. Mas o Qt chama isso deforever, e isso é realmente bonito. É bem a cara do Qtifnté divertido de falar em voz altaunlesspara a condição ternária. De qualquer forma, ele é mais útil aliAh, espera, é o John Tromp. O criador de BLC! Sou fã