Hacker News new | ask | show | jobs
by frompdx 2199 days ago
Definitely interesting, but I don't see any mention of being able to use this interactively or incremental compilation, which is what makes Forth, Forth. Forth isn't just syntax. It's an operating system and a programable programming language.
2 comments

The term "concatenative language" fits better for adaptations of Forth that also discard major semantics of Forth. There is a holistic quality to Forth that results in a lot of idioms that are not obvious, and concatenative systems that deviate from the whole tend to fall into an unexplored territory.

For example, in CASE ... OF ... ENDOF ... ENDCASE, the input value is consumed when OF is entered. But this means that the default result, positioned before ENDCASE, has to move the input value to the top of stack so that it can be consumed before the result. The examples in the ANS standard prefer using >R ... R> as a scratchpad for this purpose, so that any number of results may be pushed into the data stack, while the input is moved onto the result stack and then pushed back to the data stack. But the whole existence of the return stack and words that use it is a curious detail that doesn't come up if you start from an RPN calculator instead of a complete Forth system. Someone writing a RPN system in an applicative language, upon seeing this semantic, might be tempted to beef up the syntax rather than add this idiom. And in Forth this idea likely was only arrived at through the numerous iterations Moore made to achieve better expression in fewer words, since the return stack is useful everywhere.

You got me. I was too lazy to implement the return stack. But it should be fully possible. The hardest part was not implementing things in the trait system, but parsing any non-trivial syntax using the clunky macro_rules!. For this reason if/else/then are not a special syntax but words that block and unblock subsequent word execution.
The trait system and macros run at compile time and sadly there is no way to interact with the Rust compiler. However the macro is fully incremental (creating new words too). Which means in theory if it were possible to ask for input and pass it to the macro it would behave more like a VM:

  // create a word
  forth!(: inc 1 + ;);
  // ask user for $input
  type Stack = forth!($input inc return);
  // if you keep the stack around it can be used again
  forth!({ Stack } inc .);
  // should print $input + 2