Pages: 1
|
 |
|
Author
|
Topic: Changes coming in 8.3 (Read 2831 times)
|
Charles Childers
Administrator
Sr. Member
    
Karma: +2/-0
Offline
Posts: 745
|
For the 8.3 release, I've been doing a lot of work on the core assembly and bootstrap code. The wordset and features have changed a bit as the result of this, and I'm getting to be pretty happy with the way it's shaping up. (The new core is called Rx)
Changes in Rx so far include:
- No I/O support
All I/O words are defined by the port-specific code and the new (optional) extended bootstrap code. This has let me do a lot of cleanups internally, and means that the core itself is now completely independent from the ports.
- Words for accessing fields in the dictionary
Rx provides a word (>entry) for obtaining the address of a dictionary entry. It also provides several words to access the various fields in the entry. This aids in readability since we have symbolic names as opposed to hard-coded constants now.
- Flags are passed on the stack
The result flags from find, >number, and true, false are now passed on the stack rather than in the carry flag. This means that they can be checked with if. The ?if word is now gone.
- Additional conditionals
I'm adding a few new conditional words, taken from HelFORTH (;then) and HerkForth (if;)
- .inline class
The simple .inline class is now defined in the assembly part of the core and is used for a few of the words. This brings performance back up to the 8.1 level, and is reduces bootstrap time on my machine from 0.013s to 0.004s
Additionally, I've been refactoring and cleaning up the assembly portion. So the core has a few significant changes, but should remain pretty familiar to those who already know RetroForth.
At a higher level is the RetroForth environment. The ports now define the core I/O words, and include retro.forth for things like string output (.") and number output. retro.forth also provides a set of case words which are used later to implement interpret.forth, the interactive interpreter.
As a final note, I'm working to move the I/O words in the main ports to use syscalls and FFI as opposed to being in assembly. It just makes maintenance so much easier on my end
|
|
|
|
|
Logged
|
|
|
|
Chuck Adams
Contributor
Jr. Member
  
Karma: +0/-0
Offline
Posts: 24
|
>entry looks like a "push" word like >r or a conversion word like ">number". Wouldn't entry@ be more like an accessor? Actually if it's accessing a field, perhaps it's time to bite the bullet, add a simple struct mechanism, and define a dict entry struct with named fields.
Now that truth values are moving out of CF and onto the stack, could < and > perhaps grow an alias each so people can have numeric inequality words and still have an available syntax to use when they want ... whatever < and > do? (I know what they do, I'm just having trouble coming up with a one or two word phrase for it)
|
|
|
|
|
Logged
|
|
|
|
Charles Childers
Administrator
Sr. Member
    
Karma: +2/-0
Offline
Posts: 745
|
I'm considering renaming the current < and > to { }. This would free up < > for numeric comparisons.
|
|
|
|
|
Logged
|
|
|
|
Giant
Member
 
Karma: +0/-0
Offline
Posts: 10
|
I've been looking over the Rx info... As long as some unorthodox directions are being taken, I have a couple of suggestions: (from years of dealing with Forth-like systems. I've done very little Forth so pardon my ignorance. Also pardon the capitalization as I am not sure if the tagging works correctly) - Compiler state. The whole state issue can be eliminated like this: all words always compile code; the command line acts as a nameless definition that runs the compiled code as soon as it is compiled and resets the pointers to eliminate it. This actually cleans up the system conceptually, as you can use the looping constructs and compiling words the same way on the command line as inside definitions. - Local symbols. Keeping a clean namespace is important. I like the loc feature. However loc lops off the dictionary permanently, rendering all the local words inaccessible. There are times when you want to localize some words and not see them unless you need them specifically. I like the idea of vocabulary-like structures where the root word is globally visible and the words 'inside' it need to be explicitly prefixed by the root word. For instance, the word file can be the root for a set of filesystem-related words; inside it we can put words open, close, etc. To use them you would state file'open and file'close. (the searching words are aware of the ' syntax). This allows us to create 'libraries' of code that is available without polluting the global namespace. - Extending the class mechanism I like the class handler words. However, you can make the system even more flexible by using the localizing/vocabulary scheme above to create class-handler directories containing 'methods' for those classes. For instance, the class handler FORTH would have the words COMPILE DISPLAY DEFINE etc. inside. SELF would also have those words - but COMPILE in FORTH would compile a 'call xxx' whereas SELF's COMPILE would jump to the word itself. VAR's COMPILE perhaps could compile 'mov eax,[varaddr]. Similarly, DISPLAY could be called by the editor to print the name of the word, using a syntax coloring scheme or whatever. DEFINE for each class would know how to create the definition, etc. You would never call these directly, but the compiler would be simplified to looking up a word, finding the word COMPILE in the class directory of that word, and calling it. Dictionary searches are fast enough to make little difference in compilation speed.
I've implemented forth-like systems with these features and found them to be very useful. I can elaborate on implementation details if anyone cares to hear them.
I can keep going but perhaps this is a good time to stop for now.
|
|
|
|
« Last Edit: November 20, 2005, 11:37:38 PM by Giant »
|
Logged
|
|
|
|
Charles Childers
Administrator
Sr. Member
    
Karma: +2/-0
Offline
Posts: 745
|
- Compiler state. The whole state issue can be eliminated like this: all words always compile code; the command line acts as a nameless definition that runs the compiled code as soon as it is compiled and resets the pointers to eliminate it. This actually cleans up the system conceptually, as you can use the looping constructs and compiling words the same way on the command line as inside definitions. I have considered doing this, but I haven't managed to write a Forth implementation using it that was as clean as a two state model. One thing I dislike is having to switch between the "interpreted" heap and the permanent one. Consider something like:
: foo [ ... some complex, one-time calculation ] literal .... ; The system has to keep track of the code between [ and ] somewhere. Just compiling, running, and erasing it can work, but what if you did something like:
: foo [ " hello world!" $, ] .... ; This actually compiles a string into the current definition. If it was compiled to a separate temporary heap, it won't work, and if compiled into the main heap and then cleaned up it still won't work as expected.
There's also something to be said for parsing words, which use the interpreter. A situation like this:
create foo '1 1, '2 2, '3 3, Needs to be interpreted. With just a compile-only, it would compile a call to create, not find 'foo' (giving an error), and then compile the table. At runtime, it would not work as intended.
While not as efficient, having separate interpret/compile cycles takes care of situations like this nicely. Or perhaps I'm just missing something here....
|
|
|
|
|
Logged
|
|
|
|
|
|
Giant
Member
 
Karma: +0/-0
Offline
Posts: 10
|
State issues... You are right, there are situations in which a single-state system gets in trouble. I rarely came across these, and there is always a fairly simple way to get around it.
I still think it is still much more elegant than having the command-line words be different from compiled code words...But maybe it's just me.
create foo '1 1, '2 2, '3 3,
Right. Hmm, I did say I worked with Forth-like systems, not Forth... I see what you mean.
However, most of the time the code space is extended with definitions. My vote is for a syntax change to
: foo '1 1, '2 2, '3 3 , ; whatever reclass
It makes the whole thing much cleaner in my opinion (Sorry about bastardizing Forth).
While we are on the subject of bastardization of Forth, one thing I tried and liked (more control given to the programmer) was to explicitly push things on the stack with the , ( words to compile were renamed ). Therefore the equivalent of 1 2 + is 1 , 2 + Although it sounds cumbersome, it eliminates a lot of needless push and pop code. The syntax is quite natural - to put a list of numbers on the stack you say 1 , 2 , 3 , 4 etc. And if you don't care about what's on TOS, you can simply say 5 for instance and it overwrites it instead of drop 5. I understand that it is probably too much for most Forth programmers and offer it as an idle curiosity.
I would howerver LOVE to see Rx decoupled enough from Forth to allow me to dabble with bizzare dialects or build up completely different compilers on top.
|
|
|
|
« Last Edit: November 21, 2005, 01:12:45 AM by Giant »
|
Logged
|
|
|
|
Charles Childers
Administrator
Sr. Member
    
Karma: +2/-0
Offline
Posts: 745
|
I now have support for evaluating the command line in the hosted versions of RetroForth 8.3. This takes care of one of the most commonly requested features. See the blog entry for further information.
|
|
|
|
|
Logged
|
|
|
|
Pages: 1
|
|
|
|
|