color syntaxThere are several elements in common between Final and Color Forth (http://www.colorforth.com):
Basic SyntaxAn example is probably the best way to introduce the various language elements, so this Smalltalk method
merge: aRectangle
| minPoint maxPoint |
minPoint <- origin min: aRectangle origin.
maxPoint <- corner max: aRectangle corner.
^ Rectangle origin: minPoint
corner: maxPoint
is written in Final as:merge [dup] corner corner max [swap] origin origin min {Rectangle} copy origin! corner! The yellow tokens translate into "call" instructions (see the hardware platform description) while the green tokens are messages to be sent to the value on the top of the stack. The above is only a crude representation of the actual graphical code view. The "{Rectangle}" text would really be an image showing a kind of hyperlink to the actual Rectangle object. We call this a "portal". Portals in the source are translated into a "push literal" instruction. Embedded Code FragmentsThe code shown between square brackets would really be inside a box with a different background in the graphical representation. These embedded code fragments are translated in a previous step and then executed when compiling the source they are embedded in. This execution can cause any side effect in the generated code, but the fragments are also stored to help with decompilation later on. Embedded code fragments can also include embedded code to any level of nesting. Since embedded code is executed whenever its outer source is edited instead of at a separate load and compile time, it doesn't have the same range of applications that Forth's immediate mode does.Note that code fragments are first class objects and that we can have a portal to one instead of embedding it. In that case, a pointer to the code will be pushed on the stack when the outer code executes, which in many ways is the opposite effect of embedding. The reason why the "dup" and "swap" messages are embedded in the above (not very readable) example is that we don't want to compile instructions to send these messages but we want to actually execute them generating primitive instructions in the code as a side effect. GlobalsEach object is like a small Forth dictionary and is shown as a vertical stack of entries like the one above.There is no color or syntax for comments, but the GUI allows text and drawings to be placed anywhere.ImplementationName lookup happens when the editor generates machine code. All entries with the same name are associated with a global offset. For example, the message PRINT might be associated with the offset 120. This means that if we want to send PRINT to an object, we push its address on the data stack and execute the SEND 120 instruction. This will fetch the word 120 from the object`s code segment and load it into the instruction register. If an object wants to send PRINT to itself,, CALL 120 will have the right effect. Only even offsets are used, so methods with only one or two words (up to six instructions, including RETURN) can be very efficient. Longer methods will include a JMP to the rest of the code in those words.Garbage CollectionHenry Baker's real time treadmill algorithm (http://linux.rice.edu/~rahul/hbaker/NoMotionGC.html) is used to minimize the non determinancy in execution times in the system. This has a rather large overhead (two words per object), but makes a lot of things simpler by keeping each object in the same memory position throughout its lifetime. Moving code fragments around would be particularly messy since the processor doesn't have relative jump instructions. |