Você tem lido minha mente.
Quando fiz um curso de compiladores, há alguns anos, descobri que, se você pegar um AST e serializá-lo, com a notação de prefixo em vez da notação infixa usual, e usar parênteses para delimitar instruções inteiras, você obterá Lisp. Enquanto eu aprendi sobre Scheme (um dialeto de Lisp) em meus estudos de graduação, eu nunca realmente ganhei uma apreciação por isso. Eu definitivamente ganhei uma apreciação por Lisp e seus dialetos, como resultado desse curso.
Problemas com o que você propõe:
-
é difícil / lento compor um AST em um ambiente gráfico. Afinal, a maioria de nós pode digitar mais rápido do que podemos mover um mouse. E ainda, uma questão emergente é "como você escreve código de programa com um tablet?" Digitar em um tablet é lento / incômodo, comparado a um teclado / laptop com um teclado de hardware. Se você pudesse criar uma AST arrastando e soltando componentes de uma paleta em uma tela em uma tela grande, a programação do dispositivo touchscreen em um tablet poderia se tornar uma coisa real.
-
poucas / nenhuma de nossas ferramentas existentes suportam isso. Temos décadas de desenvolvimento envolvidos na criação de IDEs cada vez mais complexos e editores cada vez mais inteligentes. Temos todas essas ferramentas para reformatar texto, comparar texto, pesquisar texto. Onde estão as ferramentas que podem fazer o equivalente a uma pesquisa de expressão regular em uma árvore? Ou um diff de duas árvores? Todas essas coisas são facilmente feitas com texto. Mas eles só podem comparar as palavras. Altere o nome de uma variável, de forma que as palavras sejam diferentes, mas o significado semântico é o mesmo, e essas ferramentas de diferenças têm problemas. Tais ferramentas, desenvolvidas para operar em ASTs ao invés de texto, permitiriam que você chegasse mais perto de comparar o significado semântico. Isso seria uma coisa boa.
-
enquanto transformar o código-fonte do programa em um AST é relativamente bem compreendido (temos compiladores e intérpretes, não é?), transformar um AST em código de programa não é tão bem compreendido. Multiplicar dois números primos para obter um grande número composto é relativamente simples, mas incluir um número grande e composto em números primos é muito mais difícil; é aí que estamos analisando vs descompilando ASTs. É aí que as diferenças entre idiomas se tornam um problema. Mesmo dentro de um idioma específico, existem várias maneiras de descompilar um AST. Iterando através de uma coleção de objetos e obtendo algum tipo de resultado, por exemplo. Use um loop for, percorrendo uma matriz? Isso seria compacto e rápido, mas há limitações. Use um Iterator de algum tipo, operando em uma coleção? Essa coleção pode ser de tamanho variável, o que aumenta a flexibilidade com a (possível) despesa de velocidade. Mapear / Reduzir? Mais complexo, mas implicitamente paralelizável. E isso é apenas para Java, dependendo de suas preferências.
Com o tempo, o esforço de desenvolvimento será gasto e estaremos desenvolvendo usando telas de toque e ASTs. A digitação se tornará menos necessária. Eu vejo isso como uma progressão lógica de onde estamos, olhando como usamos computadores, hoje, Isso vai resolver # 1.
Já estamos trabalhando com árvores. Lisp é meramente serializado ASTs. XML (e HTML, por extensão) é apenas uma árvore serializada. Para pesquisar, já temos alguns protótipos: XPath e CSS (para XML e HTML, respectivamente). Quando são criadas ferramentas gráficas que nos permitem criar seletores e modificadores no estilo CSS, teremos resolvido parte do # 2. Quando esses seletores puderem ser estendidos para suportar regexes, estaremos mais próximos. Ainda procurando uma boa ferramenta de comparação gráfica para comparar dois documentos XML ou HTML. À medida que as pessoas desenvolvem essas ferramentas, o nº 2 será resolvido. As pessoas já estão trabalhando nessas coisas; eles simplesmente não estão lá ainda.
A única maneira que eu vejo para poder descompilar os ASTs para o texto da linguagem de programação seria algo que busca objetivos. Se estou modificando o código existente, o objetivo pode ser alcançado por um algoritmo que torna meu código modificado o mais semelhante possível ao código inicial (diff textual mínimo). Se eu estou escrevendo código a partir do zero, o objetivo pode ser o código mais pequeno e mais tight (provavelmente um loop for). Ou pode ser um código que paralelize de forma tão eficiente quanto possível (provavelmente um mapa / reduzir ou algo que envolva CSP). Assim, a mesma AST poderia resultar em código significativamente diferente, mesmo na mesma linguagem, com base em como as metas foram definidas. Desenvolver tal sistema resolveria o nº 3. Seria computacionalmente complexo, o que significa que provavelmente precisaríamos de algum tipo de arranjo cliente-servidor, permitindo que seu tablet portátil descarregasse muito trabalho pesado em algum servidor baseado em nuvem.