
Major Goals:
	Represent programs as abstract syntax trees, not text.  Programs can
be read & written as text, in prefix, infix, or postfix notation.
	"An object is a function" - don't make the object system more
complicated than it needs to be.  (Think of Forth "everything is a word" or
LISP "everything is a S-EXP")


Parser (frontend): Translate textual sourcecode ==> syntree
Evaluator: Simplify a syntree
Code Generator (backend): Translate syntree ==> (optimized) machine code


Everything boils down to combinational and sequential logic.  If we have
computers with reconfigurable logic, compilers must translate to a
combination of RISC/MISC instructions and 'hardwired' logic circuits, making
tradeoffs..


Check out 'linear logic' languages, especially Linear LISP.  It's supposed
to be better for distributed/parallel computing than regular LISP, and more
intuitive.  Also, it maps directly to a stack machine - just what we need to
integrate it with FORTH.  See H. Baker's article in ACM CAN 3/94, "Linear
Logic and Permutation Stacks--The Forth Shall Be First"... also "Linear
Lisp" (1992).


REBOL is similar to LISP, but without the parenthesis.  It does this by
allowing only fixed arity (arity = # of arguments to a function). 
Essentially, it's like Forth written backwards, in prefix instead of postfix
notation.


Source code & help linkage:
	When an object is compiled from source, the compiler should add a
'source' sub-object to it, which links to the source object (typically a
plaintext/binary object) and also specifies the location of the object
within the source code.  You type something like 'edit-source foo' to
view/edit it. Note: Source code need not be plaintext; a language could
conceivably include a high-level graphical programming environment, which
would store source code in a specialized data structure.
	Optionally, an object can include a 'help' sub-object, which tells
how to use it, or whatever.  A 'help foo' command would look for a 'help'
object under the 'foo' object.


Parameter passing:
	1. On stack. Can be used to return values, too.. either the caller
does "add esp, ?*4" to allocate space for them, or the callee pops the EIP,
pushes the return values, and pushes EIP back, and RETurns.
	2. By register. In C, the single return value is placed in EAX.
	3. In memory


Here's something useful I noticed in NASM's Wishlist:
- A good ALIGN mechanism, similar to GAS's. GAS pads out space by
  means of the following (32-bit) instructions:
          8DB42600000000    lea esi,[esi+0x0]
          8DB600000000      lea esi,[esi+0x0]
          8D742600          lea esi,[esi+0x0]
          8D7600            lea esi,[esi+0x0]
          8D36              lea esi,[esi]
          90                nop
  It uses up to two of these instructions to do up to 14-byte pads;
  when more than 14 bytes are needed, it issues a (short) jump to
  the end of the padded section and then NOPs the rest. Come up with
  a similar scheme for 16 bit mode, and also come up with a way to
  use it - internal to the assembler, so that programs using ALIGN
  don't knock over preprocess-only mode.
    Also re-work the macro form so that when given one argument in a
  code section it calls this feature.
