chitselb / pettil

6502 Forth-83 dialect for the Commodore PET 2001
http://pettil.tumblr.com
34 stars 3 forks source link

create..does> does not behave as expected #50

Closed jkotlinski closed 9 years ago

jkotlinski commented 9 years ago
: const create , does> @ ;
42 const meaning
meaning .

PETTIL will print "7418", but expected output is 42

chitselb commented 9 years ago

A few things:

See issue #31

CREATE ... DOES> will probably be '<BUILDS ... DOES>' because I like the symmettry of the angle brackets. CREATE is implemented. are currently unimplemented.

PETTIL has a split dictionary, tracked by DP (the "core") and wherever TDICT ends (currently untracked but will probably call the user variable TDP (the "transient dictionary")

consider something like this:

: MAKER
<BUILDS , , DOES> 2 0 DO DUP @ SWAP 2+ LOOP DROP ;

  1. MAKER FOO
  2. MAKER BAR

The two commas will be in the transient dictionary, as they are only required at compile time. The part between DOES> and semicolon (';') is required by any child word at runtime and will live in the core dictionary. The code for the children ('JSR DODOES' code and the values 7. and 5.) would also need to live in the core dictionary.

The ASSEMBLER vocabulary (a modified version of the Blazin' Forth assembler, which is itself a modified Ragsdale assembler, and currently unimplemented) will rely on and eventually will come built in to the TDICT when PETTIL loads.

jkotlinski commented 9 years ago

Not sure if I get it. What does "compile time" mean? Is it not possible to use MAKER from the interpreter?

chitselb commented 9 years ago

The editor, interpreter, assembler, compiler and all word names are present for "compile time" but are unneeded when the application is running. I call this "run time"

jkotlinski commented 9 years ago

OK, cool! I suppose the reason of splitting the dictionary is so that the resulting final executable can be smaller in the end? (No need to save the TDICT.) I haven't really considered this for my Forth since disk space is anyway so big :) and good packers are available for the C64.

chitselb commented 9 years ago

The dividing line is DOES>, an IMMEDIATE word that runs at compile time. Right now it commonly compiles the execution token of (;CODE) , complies a machine code fragment, and then the compiler continues through the remaining code:

... foo foo DOES> bar bar ... is compiled to |foo xt|foo xt|(;CODE) xt|JSR DODOES|bar xt|bar xt|

...foo foo ;CODE assembly-code ... is compiled to |foo xt|foo xt|(;CODE) xt|assembly code|

(;CODE) is performed while executing the parent word; its action is to stuff the following address into the code field of the newly created child word, and then exit the parent word. So the child word ends with a code field pointing to the JSR DODOES, and the action of JSR DODOES is to stack the child word's parameter field address, and start the thread that follows the JSR DODOES.

What you'd need to do is have DOES> lay down the xt of (;CODE) and a pointer to the permanent dictionary, and then switch to the permanent dictionary to continue compilation:

... foo foo DOES> bar bar ... is compiled to (transient) |foo xt|foo xt|(;CODE) xt|adrs of X| (permanent) X: |JSR DODOES|bar xt|bar xt|

So now (;CODE), instead of stuffing the following address into the child's code field, fetches the contents of the following address, and stuffs that into the child's code field.

I hope that's clear. The revised ;CODE is left as an exercise for the student. :)

chitselb commented 9 years ago

CREATE DOES> will not work, use instead. Distributes the compile-time and run-time behavior between the core and transient dictionaries

: KONST <BUILDS , DOES> @ ; 42 KONST MEANING MEANING . 42 OK