Quels sont les opérateurs primitifs de Forth?
je suis intéressé à implémenter un système Forth, juste pour avoir un peu d'expérience dans la construction d'une VM simple et de l'exécution.
au début de Forth, on apprend généralement à connaître la pile et ses opérateurs (DROP, DUP, SWAP, etc. en premier, il est donc naturel de penser que parmi les primitives des opérateurs. Mais ils ne sont pas. Chacun d'eux peut être décomposé en opérateurs qui manipulent directement la mémoire et les pointeurs de pile. Plus tard, on apprend à propos de store (!) et d'extraction (@) qui peut être utilisé pour mettre en œuvre DUP, SWAP, et ainsi de suite (ha!).
alors que sont les opérateurs primitifs? Lesquels doivent être mis en œuvre directement dans l'environnement runtime à partir duquel tous les autres peuvent être construits? Je ne suis pas intéressé par la haute performance; je veux quelque chose que je (et d'autres) peut apprendre. L'optimisation de l'opérateur peut venir plus tard.
(Oui, je sais que je peux commencer avec une machine de Turing et partir de là. C'est un peu extrême.)
Modifier: Ce que je vise pour est semblable à l'amorçage d'un système d'exploitation ou d'un nouveau compilateur. De quoi ai-je besoin pour mettre en œuvre, au minimum, pour que je puisse construire le reste du système à partir de ces éléments de construction primitifs? Je ne vais pas mettre en œuvre cela sur du matériel simple; comme un exercice éducatif, je voudrais écrire ma propre VM minimale.
7 réponses
Ce fil couvre votre question exacte. Voici un mise en oeuvre du programme "de la soupe aux noix" avec documentation complète.
j'ai écrit un sous-programme threaded Forth ciblant 68 K quand j'étais au collège. J'ai défini l'environnement d'exécution et le format du dictionnaire, puis j'ai écrit du code C qui a boot attaché une application Macintosh qui a chargé un dictionnaire par défaut, a rempli quelques vecteurs d'E/S et a fait tourner le code. Puis J'ai pris le Leo Brodie livre À Partir De et a commencé à implémenter le dictionnaire de base en 68K langage assembleur. J'ai commencé par des mots arithmétiques/logiques, puis j'ai fait des structures de contrôle puis des mots de définition/manipulation de mots. Ma compréhension est qu'au minimum vous devez @, !, +, -, * et /. Le reste peut être implémenté en termes de ceux-ci, mais c'est comme essayer d'écrire une bibliothèque graphique entière basée sur SetPixel
et GetPixel
: ça va marcher, mais Beurk, pourquoi?
j'ai apprécié le processus de il y avait quelques puzzles vraiment intéressants, comme obtenir DOES>
exactement à droite (et une fois que j'ai eu un solide DOES>
implémentation, je créais des fermetures qui se transformaient en minuscules, minuscules quantités de code).
il y a longtemps, j'ai eu un livre intitulé "Threaded Interpretive Languages", publié je pense par Byte, qui a discuté comment mettre en œuvre un langage de type Forth (Je ne pense pas qu'ils l'ont jamais appelé) dans l'Assemblée Z80.
vous pouvez ne pas avoir un Z80 à portée de main, ou en vouloir un, mais le livre pourrait être instructif.
Ce poste comp.lang.forth énumère quelques "Forths minimaux".
http://groups.google.com/group/comp.lang.forth/msg/10872cb68edcb526
pourquoi je le sais? Mon frère, Mikael, a écrit #3 et il a aussi écrit un papier à propos de faire un "minimum" (en suédois). Si je me souviens bien, il voulait obtenir un minimum d'opérateurs qui pourraient être construits en silicium.
Je ne suis toujours pas convaincu que la question est bien formée. Par exemple, les instructions de Plinth peuvent être réduites; après tout,*
et /
peut être implémenté en termes de +
et -
, mais alors '+' peut être implémenté en termes de fonction de successeur (voir axiomes de Peano. Ce qui vous place dans le voisinage d'une machine de Turing. Comment savoir où s'arrêter?
Vous pouvez également jeter un oeil à Hans Bezemer 4ème compilateur.
quelle autre implémentation utilisez-vous qui ne fournit pas cette information dans la documentation? Étant donné la nature du Forth, il pourrait dépendre de sa mise en œuvre. Il y a un ensemble standard de mots dans le dictionnaire, mais s'ils sont arrivés par assembly/C/whatever ou par Forth ne devrait pas avoir d'importance, puisque Forth est par définition un langage auto-extensible.
contrairement à ce que vous dites, généralement DROP SWAP etc sont considérés de base pour les opérations. La raison en est que si vous les implémentez en utilisant des opérations de mémoire comme vous le suggérez, le système dans son ensemble devient plus, et non moins compliqué. Il n'y a pas non plus de distinction claire entre ce qui est fondamental et ce qui ne l'est pas. Dans les années 80, une recherche dans un dictionnaire serait basique, et codée en assembleur pour la vitesse, alors qu'un linux moderne hébergé peut se permettre de coder que dans ce qu'on appelle le niveau élevé. Aussi Forthers ont tendance à recoder régulièrement les mots assembleur dans le haut niveau, et les mots de haut niveau dans assembleur. Je suis l'auteur de ciforth et yourforth. Il est possible de définir <= comme "> pas" comme je l'ai fait dans ciforth . Mais dans yourforth, j'ai décidé que le fait d'avoir toutes les < <= > >= comme petites routines de montage similaires et à apparence uniforme était effectivement plus simple. C'est un jugement d'appel, et une question de goût, certainement pas une question de principe.
Dans le contexte, j'interprète la question: "qu'est-Ce que une taille raisonnable pour que le nombre d'opérations primitives arrive à une puissance raisonnable avec une vitesse raisonnable?" Il est clair que vous n'êtes pas intéressé par des astuces astucieuses pour vous débarrasser d'un mot assembleur au détriment de frais généraux énormes comme trouvé dans certains des fils de discussion de ce sujet.
Maintenant vous pouvez regarder un certain nombre de petits Forth comme jonesforth yourforth eforth et conclure que la plupart du temps un arrive à environ 50 à 100 primitives. Ces Retours sont définis en assembleur. Si vous voulez pour définir vos primitives en c, python ou Java , la situation est à nouveau différente. Maintenant pour par exemple la recherche de dictionnaire ci-dessus vous avez un choix entre c et Forth. Des considérations qui n'ont rien à voir avec la conception linguistique entrent en ligne de compte. Vous pouvez être un programmeur C prolifique, ou vous pouvez insister sur le codage en Forth parce que c'est un projet d'apprentissage.