retroforth/doc/book/tech-notes/ngaro-to-nga

74 lines
3.2 KiB
Text
Raw Normal View History

## On The Evolution Of Ngaro Into Nga
When I decided to begin work on what became Retro 12, I knew
the process would involve updating Ngaro, the virtual machine
that Retro 10 and 11 ran on.
Ngaro rose out of an earlier experimental virtual machine I had
written back in 2005-2006. This earlier VM, called Maunga, was
very close to what Ngaro ended up being, though it had a very
different approach to I/O. (All I/O in Maunga was intended to be
memory mapped; Ngaro adopted a port based I/O system).
Ngaro itself evolved along with Retro, gaining features like
automated skipping of NOPs and a LOOP opcode to help improve
performance. But the I/O model proved to be a problem. When I
created Ngaro, I had the idea that I would always be able to
assume a console/terminal style environment. The assumption was
that all code would be entered via the keyboard (or maybe a
block editor), and that proved to be the fundamental flaw as
time went on.
As Retro grew it was evident that the model had some serious
problems. Need to load code from a file? The VM and language had
functionality to pretend it was being typed in. Want to run on
something like a browser, Android, or iOS? The VM would need to
be implemented in a way that simulates input being typed into
the VM via a simulated keyboard. And Retro was built around this.
I couldn't change it because of a promise to maintain, as much
as possible, source compatibility for a period of at least five
years.
When the time came to fix this, I decided at the start to keep
the I/O model separate from the core VM. I also decided that the
core Retro language would provide some means of interpreting
code without requiring an assumption that a traditional terminal
was being used.
So Nga began. I took the opportunity to simplify the instruction
set to just 26 essential instructions, add support for packing
multiple instructions per memory location (allowing a long due
reduction in memory footprint), and to generally just make a far
simpler design.
I've been pleased with Nga. On its own it really isn't useful
though. So with Retro I embed it into a larger framework that
adds some basic I/O functionality. The *interfaces* handle the
details of passing tokens into the language and capturing any
output. They are free to do this in whatever model makes most
sense on a given platform.
So far I've implemented:
- a scripting interface, reading input from a file and
offering file i/o, gopher, and reading from stdin, and
sending output to stdout.
- an interactive interface, built around ncurses, reading
input from stdin, and displaying output to a scrolling
buffer.
- an iOS interface, built around a text editor, directing
output to a separate interface pane.
- an interactive block editor, using a gopher-based block
data store. Output is displayed to stdout, and input is
done via the blocks being evaluated or by reading from
stdin.
In all cases, the only common I/O word that has to map to an
exposed instruction is `putc`, to display a single character to
some output device. There is no requirement for a traditional
keyboard input model.
By doing this I was able to solve the biggest portability issue
with the Retro 10/11 model, and make a much simpler, cleaner
language in the end.