omg, I've tried to implement that is JS, and we're ending up with pretty interpreter-style "compiler", ain't we? how could we say that the code is actually compiled, if there're memory addresses for each instruction of a colon-sys definition, and we're yet to find out where to execute per an instruction... I do believe that a real Forth machine performs all that work when it is facing a colon-sys word, and bundles up a machine code for it.
Just consider that the docol opcode switches to "all instructions are subroutine call" mode. The pointers are opcodeless instructions in that mode, and next is a return from subroutine. dosemi might be implemented as >r drop next. Include the colon mode flag in the return stack, and calls don't need to care whether the target routine uses colon or primitive mode. This is similar to how ARM activates Thumb instruction encoding. You could shortcut by recognizing that some subroutines have corresponding primitive behaviours, such as dolit=load immediate and dosemi=return. If those opcodes are known to be invalid as pointers, you could have a boundary between instructions and subroutine calls, and do away with the modes entirely. And then you could optimize by inlining words (particularly prim-next words like those shown here). The operations performed by docol, next and dosemi here are precisely what you'd see in some CPUs as enter, instruction fetch (not even an instruction itself, but a pipeline stage) and leave. So yes, the inner interpreter processing words here (next) is an interpreter, but an extremely simple one that could easily be the instruction decoder instead. It's no accident its variables were referred to as registers; the description is RTL, how we build hardware.
i really don't understand the utility of having an instruction to increment the program counter. Why wouldn't this just happen automatically when control returns to the thing interpreting the instructions, like it does when a processor executes machine instructions? Seems really wasteful to not do something automatically that needs to be done for every non-branching/non-halting instruction anyhow.
The best way to understand this is to try to implement a machine yourself. in reality there are relatively few ways to do this. If you want to use the native machinery of the CPU, that's fine (it's called subroutine threading) but you will end up trading away other things and not necessarily be faster or as compact.
That was actually beautiful to watch.
"the fifteen minute limit for UA-cam" 😢 those were simpler times
thanks, very informative!
30 years ago i learned forth on apple II. where can i get?
You have to implement it :)
link of blog ???
blogs.msdn.com/ashleyf
Also, github.com/AshleyF/TransForth
@@briefcubing192 thanks!!
omg, I've tried to implement that is JS, and we're ending up with pretty interpreter-style "compiler", ain't we? how could we say that the code is actually compiled, if there're memory addresses for each instruction of a colon-sys definition, and we're yet to find out where to execute per an instruction... I do believe that a real Forth machine performs all that work when it is facing a colon-sys word, and bundles up a machine code for it.
Just consider that the docol opcode switches to "all instructions are subroutine call" mode. The pointers are opcodeless instructions in that mode, and next is a return from subroutine. dosemi might be implemented as >r drop next. Include the colon mode flag in the return stack, and calls don't need to care whether the target routine uses colon or primitive mode. This is similar to how ARM activates Thumb instruction encoding.
You could shortcut by recognizing that some subroutines have corresponding primitive behaviours, such as dolit=load immediate and dosemi=return. If those opcodes are known to be invalid as pointers, you could have a boundary between instructions and subroutine calls, and do away with the modes entirely. And then you could optimize by inlining words (particularly prim-next words like those shown here).
The operations performed by docol, next and dosemi here are precisely what you'd see in some CPUs as enter, instruction fetch (not even an instruction itself, but a pipeline stage) and leave.
So yes, the inner interpreter processing words here (next) is an interpreter, but an extremely simple one that could easily be the instruction decoder instead. It's no accident its variables were referred to as registers; the description is RTL, how we build hardware.
i really don't understand the utility of having an instruction to increment the program counter. Why wouldn't this just happen automatically when control returns to the thing interpreting the instructions, like it does when a processor executes machine instructions? Seems really wasteful to not do something automatically that needs to be done for every non-branching/non-halting instruction anyhow.
The best way to understand this is to try to implement a machine yourself. in reality there are relatively few ways to do this. If you want to use the native machinery of the CPU, that's fine (it's called subroutine threading) but you will end up trading away other things and not necessarily be faster or as compact.
@@jhlagado1 Are there any web frameworks or web micro frameworks made in Forth?