How to change the value of a name to itself while including its old value

Hi all,

I’ve been stuck on this for a few days. I’m writing a simple evaluator for the Forth exercise on Exercism.
My progress can be found here.

For the life of me I can’t seem to figure out how to pass the “can use different words with the same name” test and the test after understandably infinitely loops. I know my approach is wrong within the assignCommand function but I can’t think of how to force the value out of the pair and then use the new value as part of the new definition.

I’ve tried creating a temp variable/environment and trying to run the name first to see I can get the value in a new env and then redefining the name in the new environment but those don’t work.

Or maybe I need a new function which checks to see if the Text supplied to mkState is an existing member of the environment and forces it to use old values…but for now I’m out of ideas.

Any help is greatly appreciated. Thank you.

1 Like

I believe choosing Map to implement the dictionary may set you up for tricky problems.

A number of Forth implementations have the dictionary as a linked list where each entry (word) is:

  • a pointer to the previous word
  • some flags + name length + the name itself
  • the definition

So the trick that is made possible by this implementation is that redefinition of old words are not replacements, but additions.

Let me illustrate with the test:

      it "can use different words with the same name" $
        runTexts [ ": foo 5 ;"
                 , ": bar foo ;"
                 , ": foo 6 ;"
                 , "bar foo"     ] `shouldBe` Right [5, 6]

The ASCII diagram of the test dictionary would be:

  NIL <-- foo <-- bar <-- foo
           |       |       |
           V       V       V
           5      foo      6

Notice that foo was added twice. This representation is far from efficient but allows you to pass the test easily: bar fetches the foo at the time of definition; foo just fetches the last defined value, in a LIFO fashion.

2 Likes

I’ve been reading and rereading this all day and I think I have a strategy to implement this and it makes sense now, so I’ll try when I’m back from work later :slight_smile: .

Thank you.

Regarding a more efficient implementation: could you briefly describe an overall strategy there as nothing is immediately coming to mind other than maybe having some form of stateful Map and the values coming from different states of the Map before returning a final state with the update one?

1 Like

Hashtable, yes, plus pointer references for words inside of compiled definitions. In this way you only do lookup once, at compile time. Example:

   0x010 foo [value 6 is stored here]
   0x011 bar [pointer to 0x010]                \ no need to lookup at runtime
   0x012 foo [value 6 is storye here]

Optimising is trickier than it looks becuase of words like FORGET, which explicitly talk about dictionary state.

But each Forth is a language you weave yourself, so pick something you are happy with (and that passes tests) and it will be fine.

1 Like