3 pontos por GN⁺ 2023-07-19 | 1 comentários | Compartilhar no WhatsApp
  • Hylo busca programação de sistemas e genérica segura com base em semântica de valor; o compilador e a biblioteca padrão ainda estão em estágio inicial, mas já é possível executar exemplos no Compiler Explorer
  • A pesquisa da linguagem se concentra em temas como a extensão de inout projection para o subscript do Swift, method bundles, concorrência estruturada e listas duplamente encadeadas baseadas em semântica de valor
  • O compilador usa LLVM e também aborda compilação genérica com coherence, cache e serialização do estado do programa, além de pesquisa sobre interoperabilidade com C
  • O ambiente de desenvolvimento oferece extensão para VSCode, compilador de documentação e protótipo de Language Server, com suporte a SPM/CMake, Ninja/Xcode, Windows/Linux/macOS e imagens Docker de toolchain de desenvolvimento
  • Os exemplos mostram, por meio de projection segura e sink method, como as regras de posse e liberação aparecem no nível do código e como uma linguagem de sistemas pode impor segurança

Escopo e estado atual do Hylo

  • O compilador e a biblioteca padrão do Hylo ainda estão em estágio inicial
  • Exemplos avançados de código Hylo podem ser executados no Compiler Explorer
  • A página inicial também oferece um link para experimentar Hylo no Compiler Explorer

Semântica de valor e pesquisa da linguagem

Compilador e biblioteca padrão

  • O trabalho no compilador abrange compilação baseada em LLVM, genéricos, persistência de estado e interoperabilidade com C
    • Compilação usando LLVM
    • Nova técnica para compilação genérica com coherence
    • Cache e serialização do estado do programa no compilador
    • Pesquisa sobre C interop
  • Do lado da biblioteca padrão, já foram publicados documentos da implementação atual e trabalhos relacionados a algoritmos de coleção

Experiência do desenvolvedor e ambiente de build

  • Ferramentas para editor, documentação e servidor de linguagem são fornecidas em conjunto
  • O ambiente de build e desenvolvimento oferece suporte a vários sistemas operacionais e fluxos baseados em contêineres
    • Suporte a Development Containers para reduzir o processo inicial
    • Suporte a SPM/CMake, Ninja/Xcode, Windows/Linux/macOS
    • Plugin de compilador para geração de testes
    • Imagens Docker pré-compiladas da Hylo development toolchain
    • O compilador é escrito em Swift 6.2

Pesquisas e materiais de apresentação sobre Hylo

Exemplo de código: projection segura e liberação explícita

  • O exemplo Subscripts - A Safe Projection Mechanism mostra uma estrutura em que o tipo Angle armazena o valor radians e oferece a propriedade degrees com blocos let e inout
    • O bloco let de degrees converte radians em degrees e retorna o resultado
    • O bloco inout expõe um valor temporário em degrees, d, com yield &d e depois converte o valor alterado de volta para radians, refletindo-o em self.radians
    • main obtém a projection com inout d = &a.degrees, altera d para 0.0 e então verifica a.radians == 0.0
  • O exemplo Sink Methods - Capability for Deinitializing apresenta uma estrutura em que o tipo Computer fornece shutdown() como sink method
    • shutdown() imprime o conteúdo da memória e depois aplica sink a self.ram
    • Em test1, um Computer é criado e não é desligado, então ocorre Cannot deinit computer
    • Em test2, shutdown() é chamado apenas dentro de if random_bool(), então no caminho em que o if não é executado ocorre Cannot deinit computer
    • Em test3, chamar shutdown() dentro de while causa, após a primeira iteração, um problema de uso de objeto já consumido, e no caminho em que o while não é executado permanece a impossibilidade de deinit
  • Exemplos adicionais podem ser vistos na compiler test suite

1 comentários

 
GN⁺ 2023-07-19
Opiniões do Hacker News
  • Talvez eu esteja mais animado com Val como sucessor de C++ do que com o excelente CppFront de Herb Sutter. Só vi as duas apresentações abaixo, mas os pontos centrais parecem ser compilação estática, tipagem estática, interoperabilidade com C++, segurança de memória, segurança de tipos e ausência de data races
    Quando explico, digo algo como: “suponha que você esteja começando um novo projeto em C++ e não se importe com desempenho; se passar tudo por valor e retornar tudo por valor, sem ponteiros nem referências, não seria bom por não precisar se preocupar com efeitos colaterais ou data races?” O interessante no Val é que, mesmo removendo ponteiros e referências da linguagem, o compilador internamente aplica passagem por referência const e otimização de valor de retorno, preservando ao mesmo tempo a semântica e o desempenho desejados
    Val: A Safe Language to Interoperate with C++ - Dimitri Racordon - CppCon 2022 https://www.youtube.com/watch?v=ws-Z8xKbP4w
    https://cppcast.com/val-and-mutable-value-semantics/

    • Vale a pena ouvir os dois episódios recentes do ADSP Podcast em que Sean Parent fala sobre Val. O Adobe Research Labs está patrocinando o desenvolvimento de forma bem séria
      https://adspthepodcast.com/
    • “Interoperabilidade com C++” me parece suspeito. É difícil acreditar que outra linguagem consiga interoperar direito com C++, e até entre compiladores C++ a compatibilidade binária quebra, às vezes até entre versões do mesmo compilador
    • Parece uma estrutura que confia demais no compilador. Fico preocupado que uma pequena mudança possa quebrar uma otimização em um código distante e destruir o desempenho
    • Se você “passa por valor e retorna por valor o dia todo”, fica mais difícil modificar ou armazenar referências de forma eficiente dentro de structs. Se o programa precisar de qualquer estrutura de dados minimamente fora do padrão ou complexa, isso parece uma limitação fatal. Claro que, considerando como é difícil implementar corretamente essas estruturas de dados, isso talvez seja até uma vantagem
    • Há anos venho escrevendo programas PHP de verdade desse jeito, passando arrays para lá e para cá sem me preocupar
      Imagino que o interpretador PHP seja esperto o bastante para usar cópia na escrita (copy-on-write) na prática, mas nunca fiz profiling por conta própria. Mesmo assim, ao fazer processamento de dados bem complexo, parsing de DSL caractere por caractere, geração dinâmica de SQL e transformação dos resultados em estruturas arbitrárias a cada carregamento de página, nunca senti problemas de desempenho
      Na época do PHP 4, objetos também se comportavam como valores armazenados em variáveis; depois, quando mudaram variáveis de objeto para semântica de referência, acho que foi uma oportunidade perdida não transformar “valor, referência de variável, ponteiro para valor” em atributos de variável ortogonais ao tipo armazenado
      $a = $b; // copia o valor de $b para $a
      $a = &$b; // $a e $b agora são a mesma variável
      $a = *$b; // $a aponta para o mesmo objeto que $b, mas, ao contrário de $a = &$b, as variáveis em si não ficam vinculadas
  • Por um lado, é bom ver surgirem tantas linguagens de abstração de custo zero, mas eu também queria que os programadores de sistemas escolhessem logo uma vencedora. Espero que a comunidade já pequena de programadores de sistemas não se fragmente ainda mais entre Rust, Zig, Val etc., e que a guerra das linguagens de sistemas acabe logo

    • Talvez tenhamos escolhido uma cedo demais e, por isso, faltou inovação nessa área por tempo demais. Que venham as guerras
    • A esta altura, acho que Rust é a vencedora. Ela já superou a enorme barreira de entrar de fato nos kernels do Linux e do Windows. Nesse sentido, não parece haver muito espaço para uma nova linguagem de sistemas se estabelecer agora
    • Acho que não vai ser assim. Por isso mesmo há ainda mais motivo para ampliar o suporte a wasm + wasi em todos os lugares
  • O fluxo de sentimentos ao conhecer Val hoje pela primeira vez foi mais ou menos assim: “Ah, uma nova linguagem de sistemas. Talvez não seja nada demais, mas vamos ver. A documentação é boa. As ideias sobre ownership são bem ponderadas e a sintaxe faz sentido. Mas ela é diferente o bastante para justificar existir por conta própria? Quem está por trás?”
    Então vi que Dave Abrahams está trabalhando nela e fiquei mais interessado. Já o encontrei na Apple e lembro da palestra Crusty[1] dele sobre Swift. Gostei das opiniões fortes, mas a Apple depois retirou o vídeo alegando que havia conselhos desatualizados. Agora ele está na Adobe, então fico pensando se esta é uma linguagem da Adobe
    A conclusão é que vale acompanhar, assistir à apresentação linkada e esperar para ver
    [1] Encontrei a palestra Crusty: "I don't do Object Oriented!" https://www.youtube.com/watch?v=p3zo4ptMBiQ

    • David Abrahams já era um contribuidor muito importante do Boost antes de estar na Apple, além de membro do comitê de C++ e forte defensor da programação genérica no estilo de Stepanov. Não é surpresa que tenha se juntado ao projeto Val
  • Como desenvolvedor de compiladores, fiquei chocado ao ver os issues abaixo
    https://github.com/val-lang/val/issues/758
    https://github.com/val-lang/val/issues/711
    Isso cheira a um estado de implementação ruim. Eles precisam chegar ao auto-hospedagem o quanto antes; assim vão encontrar mais bugs básicos desse tipo. Mesmo assim, já tem mais de 500 estrelas

    • Vendo como outro desenvolvedor de compiladores, poucos erros são tão prejudiciais quanto partir cedo demais para a auto-hospedagem. Mesmo que a linguagem traga ganho líquido para programas pequenos e médios, demora muito mais até ela ser adequada para um projeto grande como um compilador e ter ferramentas à altura. Ainda bem que não estão se apressando
    • Se esses bugs estivessem em um compilador em produção, seria preocupante, mas, se é o compilador de uma linguagem ainda em definição, não chega a ser um problema tão grande. Comparando Rust 1.0 e 1.71, dá para ver o tamanho do abismo entre “primeira versão estável” e “compilador de uma linguagem estável com muito uso real”
      Auto-hospedagem também não é tudo. Acima de tudo, é mais um marco simbólico; quando alcançado, é algo a celebrar, mas não acho que deva ser usado como fraqueza da linguagem até bem mais adiante no ciclo de desenvolvimento
    • O próprio Swift ainda não é auto-hospedado e está prestes a lançar a versão 6. Não sou desenvolvedor de compiladores, mas, na comunidade Swift, a conclusão das discussões em torno desse tema foi que ainda não vale a pena
  • Há tempos eu vinha adiando “brincar com Val” e hoje finalmente tentei; mesmo com mais de 4.000 commits, ainda está longe de ser utilizável. A maioria dos exemplos do tour da linguagem não compila, e até exemplos aparentemente simples falham
    Carbon ainda não apresentou nada de fato, e Sean Baxter vem fazendo muito progresso no compilador Circle, implementando também várias das boas partes de Carbon. Se ainda é difícil chamar de linguagem, também é difícil ser sucessora

  • Agora temos V, Val, Vala e Vale. Tem alguma outra linguagem que estou esquecendo?

    • Também existe VAL. Uma linguagem dos anos 80 que, por meio de SISAL, influenciou Haskell. Mas acho que pouca gente conhece esse VAL fora da comunidade de linguagens paralelas
    • Nomes parecidos podem até funcionar a favor. Quem aprende uma linguagem dessas provavelmente está procurando “a nova coisa quente”, e pode acabar conhecendo e pesquisando outras linguagens de nome semelhante. JavaScript também foi assim, e o resultado não foi ruim
    • Eu realmente achei que isso fosse Vale. Essa colisão de nomes é bem lamentável
    • Além disso, V também é chamada de Vlang, e Vale também já foi chamada de Vlang no passado
  • É um assunto recorrente, mas a única coisa de que não gosto em Val é que Vale e V também são novas linguagens de sistemas. Por causa dos nomes, é fácil demais confundir as três

    • Também existe Vala. O domínio é um pouco diferente, mas há mais uma linguagem com nome parecido
    • Tive que entrar no link só para conferir se era a linguagem de projection ou a linguagem de region
    • Também existe VAL: Variable Assembly Language https://en.m.wikipedia.org/wiki/Variable_Assembly_Language
  • Há um post relacionado. Tem outros?
    Val, a new programing language inspired by Swift and Rust - https://news.ycombinator.com/item?id=31788527 - junho de 2022, 19 comentários

  • Dei uma passada pelo artigo sobre “mutable value semantics” e fiquei me perguntando se entendi certo que os autores propõem substituir referências e ponteiros por a) alguma indireção e verificação em runtime via structs aninhadas e Any, e b) índices de arrays
    Um trecho que me chamou a atenção foi: “É justo perguntar como estruturas de dados autorreferenciais, como listas duplamente encadeadas ou grafos direcionados, podem ser expressas com tipos de valor mutáveis. Na verdade, grafos arbitrários podem ser representados como listas de adjacência…”. Não vejo muito bem como implementar uma lista duplamente encadeada de forma razoável sem recriar, dentro da implementação, um heap de memória e alguma forma de garbage collection
    Além disso, encontrei uma discussão em https://github.com/orgs/val-lang/discussions/736, e parece que vai surgir uma válvula de escape como o unsafe do Rust. Isso resolve todos os problemas, mas a pergunta “o subconjunto seguro de Val é suficiente para criar aplicações práticas?” deve continuar sendo debatida por muito tempo

    • Se você usar arrays e índices de arrays em vez de ponteiros, de fato dá para recriar a memória
      O motivo pelo qual isso é menos tolo do que parece é que esses índices ficam vinculados a uma estrutura de dados específica, por exemplo uma lista duplamente encadeada ou um grafo, então não é fácil manipulá-los para acessar outras partes do programa. Isso vale tanto quando o compilador verifica isso quanto em tentativas de quebrar o programa
  • Não sei como ler a explicação do exemplo na página inicial. Ela diz: “Não ocorrem alocações desnecessárias. Como o resultado de longer_of é uma projection do argumento mais longo, quando emphasize altera z, a mudança acontece diretamente no valor de y. O valor não é copiado nem movido, mas também não é passado por referência para emphasize
    É uma situação em que um argumento string é passado para uma função e um caractere é acrescentado, mas a string existente deveria ter um comprimento inicial e uma posição/tamanho específicos na stack; então não entendo como isso seria possível sem uma nova cópia de y. Será que deixam um padding extra no fim da string para o caso de alguém acrescentar algo? Se for isso, quanto padding deixam, e por que isso não seria, no geral, mais ineficiente?

    • Um prefixo de quatro espaços não é para citação, e sim para blocos de código/monoespaçados. No HN, normalmente se usa a convenção > para citar, e funciona bem mesmo sem o parser tratar isso de forma especial
    • O fato de ser um valor imutável não significa necessariamente que ele precise estar na stack
      Ainda assim, tenho uma dúvida parecida. O que acontece ao modificar uma string de 1 GB? É copy-on-write?
      Em 99% dos casos isso pode desaparecer por otimização, mas tenho a impressão de que no 1% restante poderia surgir uma queda de desempenho muito difícil de encontrar
    • Tentando responder a mim mesmo alguns dias depois: parece possível se o nome da variável alterada for silenciosamente shadowed na stack por um novo valor mais longo. Talvez seja isso que “projection” queira dizer. Nesse caso, como a stack já está alocada, não ocorre uma nova alocação. Não sou especialista em linguagens ou compiladores, então talvez esse termo seja bem conhecido nessa área
    • Há uma explicação mais abaixo. longer_of não é uma função, mas um subscript, e dizem que um subscript não retorna um valor; ele faz uma projection do valor e concede ao chamador acesso temporário de leitura/escrita
      Não entendo muito bem como isso não conta como movimento. No caso de strings, talvez elas possam ficar no heap, como em Rust, para permitir tamanho variável