Pergunta

Estou interessado em implementar um sistema de Forth, só assim eu posso obter alguma experiência construindo um simples VM e tempo de execução.

Ao iniciar em Forth, um normalmente aprende sobre a pilha e seus operadores (GOTA, DUP, SWAP, etc.) em primeiro lugar, por isso é natural que se pense delas como estando entre os operadores primitivos. Mas eles não são. Cada um deles pode ser dividido em operadores que manipulam diretamente ponteiros de memória ea pilha. Mais tarde se aprende sobre armazenamento (!) E fetch (@), que pode ser usado para implementar DUP, SWAP, e assim por diante (ha!).

Então, o que são os operadores primitivos? Quais os que devem ser implementados diretamente no ambiente de tempo de execução a partir do qual todos os outros podem ser construídas? Eu não estou interessado em de alto desempenho; Eu quero algo que eu (e outros) pode aprender. otimização operador pode vir mais tarde.

(Sim, estou ciente de que posso começar com uma máquina de Turing e de lá ir. Isso é um pouco extremo.)

Edit: O que eu estou querendo é semelhante a bootstrapping um sistema operacional ou um novo compilador. O que eu preciso fazer implementar, no mínimo, para que eu possa construir o resto do sistema a partir desses blocos de construção primitivos? Eu não vou implementar isso em hardware nu; como um exercício educacional, eu ia escrever minha própria VM mínimo.

Foi útil?

Solução

Esta discussão cobre o seu pergunta exata. Aqui é um sopa de nozes implementação com documentação completa.

Eu escrevi uma sub-rotina rosca Forth alvo 68K quando eu estava na faculdade. I definido o ambiente de execução e formato de dicionário, em seguida, escreveu algum código C que inicialização amarrado um aplicativo Macintosh que carregou um dicionário padrão, povoada alguns vetores de I / O e tem o código de execução. Então eu levei o livro Leo Brodie Começando Forth e começou a implementar o dicionário básico em 68K linguagem assembly. Comecei com palavras / lógica aritmética, então fez estruturas de controle, em seguida, palavra palavras definição / manipulação. O meu entendimento é que, no mínimo você precisa @,, +, -, * e /. O resto pode ser implementado em termos daqueles, mas isso é como tentar escrever toda uma biblioteca de gráficos com base em SetPixel e GetPixel:? Isso vai funcionar, mas yikes, porque

Eu gostava do processo como houve alguns puzzles realmente interessantes, como a obtenção de DOES> exatamente certo (e uma vez eu tive uma implementação DOES> sólida, eu estava criando fechamentos que se transformaram em pequenas, pequenas quantidades de código).

Outras dicas

Há muito tempo atrás, eu tinha um livro chamado "Rosqueou Interpretativos Línguas", publicado Acho que por Byte, que discutiu como implementar um Forth-como idioma (eu não acho que eles nunca chamou-Forth) em Z80 montagem .

Você não pode ter um Z80 acessível, ou quer um, mas o livro pode ser instrutivo.

Este post em listas comp.lang.forth alguns "forths mínimas".

http://groups.google.com/group/comp .lang.forth / msg / 10872cb68edcb526

Por que eu sei disso? Meu irmão, Mikael, escreveu # 3 e ele também escreveu um papel sobre como fazer uma "Forth mínima "(em sueco, embora). Se bem me lembro, ele queria obter um conjunto mínimo de operadores que poderiam ser construídas em silício.

Estou ainda não está convencido a questão está bem formado. Por exemplo, as instruções de Rodapés podem ser reduzidos; afinal, * e / pode ser implementado em termos de + e -, mas, em seguida, '+' pode ser implementado em termos de uma função sucessor (veja o Peano axiomas .) que o coloca na vizinhança de uma máquina de Turing. Como você sabe onde parar?

Você também pode querer dar uma olhada de Hans Bezemer 4ª compilador .

Qual aplicação que você está usando que não fornecer essas informações na documentação Forth? Dada a natureza do Forth, pode ser dependente de implementação. Há um conjunto padrão de palavras no dicionário, mas se eles chegaram lá por montagem / C / whatever ou por Forth não deve importar, já que Forth é por definição uma linguagem auto-extensível.

Ao contrário do que você diz, geralmente GOTA SWAP etc são consideradas operações básicas diante. A razão é que se você implementá-las usando operações de memória, como você sugere, todo o sistema torna-se mais, e não menos complicado. Também não há distinção clara em Forth entre o que é básico e quais não. Na década de 80 a busca do dicionário seria básico, e codificado em assembler para a velocidade, enquanto um linux moderna hospedado pode dar ao luxo de código que no chamado alto nível. Também tendem a Forthers palavras rotineiramente recodificação assembler em alto nível, e palavras de alto nível em montador. Eu sou o autor de ciforth e yourforth. É possível definir <= como "> não" como eu fiz no ciforth. Mas, em yourforth eu decidi que ter todos <<=>> = como semelhante, de maneira uniforme olhando, pequenas rotinas assembler foi efetivamente mais simples. Isso é um julgamento, e uma questão de gosto, certamente não uma questão de princípio.

No contexto I interpretar a questão: "O que é um tamanho razoável para o número de operações primitivas para chegar a uma Forth poderosa razoável com uma velocidade razoável" É claro que você não está interessado em truques inteligentes de se livrar de uma palavra assembler à custa de enorme sobrecarga como encontrado em alguns dos tópicos a discutir este assunto.

Agora você pode olhar para uma série de pequenas Forth é como jonesforth yourforth eforth e concluir que a maioria chega-se a cerca de 50 a 100 primitivos. Aqueles de Forth são definidos em assembler. Se você quiser definir seus primitivos em C, Python ou Java, a situação é novamente diferente. Agora, para por exemplo, procurar o dicionário acima, você tem uma escolha entre c e Forth. Considerações que nada têm a ver com o projeto de linguagem entram em jogo. Você pode ser um prolífico c-programador, ou você pode insistir em codificá-lo em Forth, porque é um projeto de aprendizagem.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top