2012-01-01 6 views
5

J'ai essayé d'implémenter un mot qui produit une chaîne à partir d'un tableau quand on lui donne un nombre sur la pile dans Forth.Comment implémenter un tableau de chaînes?

Ma première tentative naïve était:

create myarray s" Alpha", s" Beta", s" Charlie", 

Cela a été accepté, mais il ne fonctionne pas comme prévu - myarray @ type produit un résultat incohérent (au lieu de mon attente naïve qu'il pourrait imprimer « Alpha »).

Lors de la recherche sur le web, j'ai trouvé dans this tutorial qu'une chaîne créée avec s" a une durée de vie limitée, ce qui signifie que mon ansatz est voué à l'échec depuis le début. D'un autre côté, même les tableaux d'objets réguliers ne semblent pas être normalisés selon this page.

< Mise à jour> Apparemment, ce n'est pas un problème trivial avec Forth. Il existe des bibliothèques sur le Web qui implémentent la fonctionnalité de chaîne manquante: here et here. C'est un bon point de départ, bien qu'il faille encore du travail pour aller de là à un éventail de chaînes. </Mise à jour>

Alors, comment puis-je implémenter un mot qui renvoie une chaîne d'un tableau donné?

Répondre

2

Pour adresser des parties de votre code, s" laisse addr u sur la pile, une adresse et la longueur de la chaîne. , ne stocke qu'une seule valeur de sorte que vous n'obtiendrez pas les résultats souhaités de cette façon. 2, pourrait le faire car cela permettrait de stocker les deux éléments de la pile qui représentent la chaîne. Une fois que vous avez fait cela, vous devez récupérer les deux valeurs aussi, donc [email protected] est ce que vous voulez.

Mon rewrite ressemblerait à ceci:

create myarray s" Alpha" 2, s" Beta" 2, s" Charlie" 2, 

\ Test 
myarray [email protected] type Alpha **ok** 

Obtenir les autres éléments de votre tableau est un peu plus compliqué. Lorsque vous tapez myarray vous obtenez l'adresse du début des données dans cette entrée de dictionnaire, et vous pouvez ensuite utiliser 2 @ pour obtenir les choses que les deux premières adresses pointent (qui sont l'adresse et la longueur de "Alpha") . Si vous voulez « Beta vous avez besoin la paire suivante d'adresses. Vous pouvez donc utiliser

myarray 2 cells + \ increment the address by two cells 

Pour obtenir les adresses qui pointent vers « Beta » et ainsi de suite. Donc, pour accéder à « Beta » vous entrez

myarray 2 cells + [email protected] type Beta **ok** 

J'ai testé avec gforth et il semble à tous les travaux, bien que je ne suis pas sûr de savoir comment tester rigoureusement la persistance.

Votre mot devrait être en mesure de faire l'adresse incrémenter basée sur ce que est sur la pile pour commencer. Vous pourriez vouloir entrer dans un peu plus create does> stuff. Je peux donner quelques indications mais je ne veux pas gâcher le plaisir de la découverte.

Si je saute trop de détails sur ce que cela signifie réellement, je le répète, et je vais essayer à nouveau. Peut-être que c'est trop grossier, mais j'ai essayé de faire un "type de chaîne" de sortes il ya quelque temps.

: string         (addr u "name" --) 
    create 2,        \ add address and length to dict entry "name" 
    does> dup cell+ @ swap @ ;    \ push addr u 

\ Example 
s" Some Words" string words **ok** 
word type Some Words **ok** 

Il définit un mot avec un nom de votre choix (dans ce cas, les « mots ») qui vont pousser la longueur et l'adresse début de votre chaîne (dans ce cas, « quelques mots ») quand il est interprété. Pour autant que je sache quand la chaîne est dans une définition comme celle-ci, elle est persistante.

Cela ne répond pas entièrement à votre question, mais cela peut aider.


J'ai eu un autre aller à une chaîne persistante, celle-ci définitivement allot de la mémoire dans une entrée de dictionnaire et sera en sécurité aussi longtemps que ce mot existe. Avant la chaîne "type" seulement stocké l'adresse et la longueur que s" créé qui est seulement tout bien jusqu'à ce que quelque chose d'autre écrit sur cette région de la mémoire. Ceci copie maintenant la chaîne d'où s" la crée dans un article de dictionnaire appelé "nom" où il est garanti pour durer aussi longtemps que "nom" lui-même.

: string         (addr u "name" --) 
    create         \ create dict entry called "name" 
    dup >r here >r       \ keep copies of string length and start of "name"'s memory 
    dup 2 cells + allot      \ allot memory for the number of chars/bytes of the string plus 2 
              \ for the new addr u 
    [email protected] 2 cells +       \ Get the address two cells from the start the space for "name" 
    swap cmove        \ copy the string at addr u into the alloted space for "name" 

    \ Now "name" looks like this: "name" -blank1- -blank2- "the text of the string at addr u" 
    \ blank1 should be the address of the start of the the text = addr2 and blank2 should be u 

    [email protected] dup 2 cells + swap !     \ get the address of blank1, copy it, increment by 2 to get addr2 
              \ and then store that in blank1 
    r> cell+ r> swap !      \ get address of blank1, increment to get address of blank2, then get u and 
              \ store it in blank2 

    \ Now "name" looks like this: "name" addr2 u "the text of the string at addr u" 

    does> dup @ swap cell+ @ ;    \ push addr2 u 

Pour amusement, je pensais que je pourrais montrer comment peu de sens ce qui rend sans formatage utile

: string-no-comments   (addr u "name" --) 
    create dup >r here >r dup 2 cells + allot [email protected] 
    2 cells + swap cmove [email protected] dup 2 cells + swap ! 
    r> cell+ r> swap ! does> dup @ swap cell+ @ ; 
+1

En fait, je peux suivre jusqu'au point où vous commentaire sur « CREATE fait>' des trucs". Je vais devoir creuser plus profondément pour comprendre aussi le reste. En dehors de cela, je pense que vous avez résolu mon problème (avec le problème de persistance qui est clairement mal documenté dans le manuel de GForth). Je vous remercie! – user8472

+0

Ouais c'était plutôt vague, au fond je n'étais pas sûr de savoir comment le faire sans y penser pendant un moment. Il semble que tout ce qui est dans une définition est persistant (c'est ce que j'ai pris dans le manuel). – sheepez

+0

@ user8472 Je voulais juste vous avertir de mes modifications, la nouvelle version est définitivement persistante. – sheepez

Questions connexes