# Binding data to behavior

The traditional Forth way of binding data to behavior is "does>". Dusk OS has
this word, but it behaves a little differently than the traditional one. For
example, in a traditional Forth, you'd have:

  : adder ( n -- ) create , does> @ + ;
  42 adder foo
  1 foo . \ prints 43

In the snippet above, the creation of the "foo" word happens at "create", and
"does>" does its magic to graft the following behavior to this newly created
"foo". In Dusk, it looks like this:

  : adder ( n -- ) does> + ;
  42 adder foo
  1 foo . \ prints 43

The creation of "foo" happens during the execution of the "does>" and the
associated word is called with the value directly (rather than a pointer to it).

The vast majority of "does>" data (at least, the way it's used in Dusk OS) fit a
cell, so this data dereferencing removes a layer of cruft. What to do when your
data doesn't fit a cell or refers to something mutable? Something like this:

  : mydoer ( a b -- ) here# rot> , , does> @+ . spc> @ . ;
  12 42 mydoer foo
  foo \ prints "42 12"

You can also have your "doer" word produce immediate words. In this case, use
"immdoes>", which works exactly the same way as "does>", but sets the immediate
flag on the created words.

All this mechanism rests on "bind ( w n "name" -- )", which binds a number to
a word, that is, create a new word that places the specified number on PS before
jumping to the specified word:

  ' + 42 bind foo
  1 foo . \ prints 43

## Values, cells, constants

A "cell" is a word that refers to an area in memory. Calling this word yields
the address directly following it:

  create mycell 5 c, 'h' c, 'e' c, 'l' c, 'l' c, 'o' c,

Calling "mycell" will yield the string "hello".

A "value" is a 4 bytes area where a value is stored. It's a bit like a cell,
but calling the value dereferences its address.

  42 value myvalue

Calling "myvalue" yields 42. Moreover, it obeys to "to" semantics (see below).

There is also "@value", which instead of allocating its own cell, applies "to"
semantics to the supplied address:

  create mycell 42 ,
  mycell @value myval
  myval . \ Prints 42

A constant is a read-only value that doesn't obey "to" semantics:

  42 const myconst

## "to" semantics

Values are very similar to cells: they're a piece of memory attached to a
"handling" routine. With the cell, the routine is a noop, it returns the address
of the piece of memory.

With values, the "@" routine is attached to the cell and automatically called
(or "equivalent to called", some pretty HAL magic happens at compile time making
"to" semantics pretty efficient) when the value is invoked. This means that
calling a value returns the value in the cell rather than the address of the
cell.

This is convenient, but raises a question: How can you modify a value? You need
a "to" word.

The "to" words ("to", "to+", etc.) set a global variable with a pointer to an
alternate routine for value words to execute. The "to" word makes that global
variable point to "!", "to+" makes it point to "1+!", etc..

This means that when you do "42 to myvalue", instead of "myvalue" executing the
equivalent of "addr-of-myvalue @", it executes "addr-of-myvalue !".

As soon as a "to" override is used once, the global "to" pointer is reset to 0
(meaning "@").

Refer to [doc/dict] for a complete list of "to" words.

Warning: this variable is global. any usage of "to" will affect the next value
that pops up. To avoid problems, always put your "to" call very, very close to
your value call.

### Creating "to" words

It's relatively easy to create new words obeying "to" semantics, but you have to
know what you're doing. Let's create a new "to-obeying" word that prints out
what it's doing.

The first thing is to ask yourself what "to" words you'll want to support.
There's of course the "default" word (no "to"), but there's also:

  to to+ to1+ to1- to& to| to^ to@! to@+ to!+ to'

When you create a new to-obeying word, you need to create a table of those
words. For brievety, let's support only "to":

  : _@ '@' emit dup . ;
  : _! '!' emit . . ;
  totbl mytotbl
    _@ _! toerr toerr toerr toerr toerr toerr toerr toerr toerr toerr

"totbl" is a core word that looks up the correct number (12) of supplied names
and generates a lookup table from those names. In the example above, we create
such a lookup table named "mytotbl".

With that table, we can define the actual "to-obeying" word:

  : foo 42 mytotbl toexec ;
  foo \ prints "@42"
  54 to foo \ prints "!4254"

The magic happens at "toexec ( ? tbl -- ? )", which is a word with a really
weird signature. At all times when calling it, PS top is a "to table", but other
arguments and results depend on two conditions: whether we're in compiling mode
and which "to" word (if any) is active. To help, let's list all possible
signatures:

  foo             ( a tbl -- n )
  to foo          ( n a tbl -- )
  : ... foo ... ; ( halop tbl -- )

As you can see, our definition of "foo" above satisfies the first two signature
requirements. When "toexec" is called, "toexec" does it magic and executes the
right word.

This new word, however, will only work in interpret mode. "to" words are
designed to be applied at compile time. Therefore, if you do something like:

  : bar 54 to foo ;

it will not do what you expect because "to" is an immediate that will set the
global "to" mode at compile time, leaving "foo" to be executed with an empty
"to" mode.

The reason why it is done thus is for "to" semantics to be able to fully
leverage the HAL [doc/hal] and compile very efficient "to" words.

So! what we need to do is to make "foo" immediate and have that immediate
version of "foo" to compile our "to" word rather than execute it. We can do so
with ":compiling" [doc/usage/imm].

To have a proper implementation, we would have to implement a second "compile
time totbl", which we certainly can, but let's be lazy and use "toexecwrap":

  : foo 42 mytotbl toexec ; :compiling 42 mytotbl toexecwrap ;

The "toexecwrap" word will compile the supplied literal (42) along with a call
to the proper "to" word. It results in slower code than creating a specialized
compile time table, but it saves you the hassle.

So far, so good? Alright! Now, what you might want to do is to go one meta-level
higher and have "foo" be a creator of "to-obeying" words, which is what "value"
and "field" are. Parametrizing 42 is a bit tricky: how will you make
":compiling" into a ":compiling factory"? With "immbind":

  : _exec mytotbl toexec ;
  : _[exec] mytotbl toexecwrap ;
  : metafoo ['] _[exec] ['] _exec 42 immbind ;
  metafoo foo

This code results in "foo" being the functional equivalent of what we had
before. "immbind" creates a new immediate word that bind runtime and compile
time words to the same data.

You can see very well, I hope, how you can now parametrize 42, I won't bother
with an example. Godspeed!

## Fields

Fields are an effective way to access values through a base address with a fixed
added offset, in other words, structured data. For example, if you have a field
"foo" with an offset 4, then doing "mydata foo" is the equivalent of doing
"mydata 4 + @" (but much faster when compiled).

Fields come in groups. You being a field group with "fields$", which resets the
global value "fieldsoff" (fields offset) to 0. Then, you can begin defining
fields:

  fields$
  field foo
  field bar

Whenever we define a field, "fieldsoff" is incremented by the appropriate value,
in this case 4. Therefore, "foo" will have a 0 offset and "bar" will have a 4
offset.

Fields support "to" semantics and binary width modulation [doc/usage/bwm]:

  fields$
  16b field foo
  8b field bar
  8b field baz
  field last
  create mydata 123 16b , 42 c, 12 c, 12345678 ,
  3 mydata to+ baz \ mydata+1's 8b cell is now 45

Fields must follow alignment discipline [doc/usage/mem]. In the example above,
if you remove "baz", you'll get an error when you define "last" because it
results in unaligned 32-bit access.

If your structure has holes in it, you can manually adjust "fieldsoff" which is
a regular value. You can also use "fallot ( n -- )" as a convenient way to
increase it.

There is also "method", which is like "alias" with an offset. Moreover, methods
duplicate PS top (the data pointer) to supply the target word with a "self"
element:

  fields$
  field foo
  method bar ( n self -- )

  : barimpl ( n self -- ) to+ foo ;
  create mydata 42 , ' barimpl ,
  3 mydata bar
  mydata foo . \ prints 45
  : otherimpl ( n self -- ) dip neg | to+ foo ;
  ' otherimpl mydata 4 + !
  7 mydata bar
  mydata foo . \ prints 38

It's frequent that fields contain references to structures. For convenient
accesses to these fields, there's the `fstructbind`, which behaves like a
`structbind` [doc/usage/ns], but for a field.

A `fstructbind` isn't really a field, but a field wrapper. You create your field
normally, then create a `fstructbind` right afterwards with a new name for it.
In Dusk OS, the convention for `fstructbind`s is to have the same name as the
related field with a ":" prefix. Example:

  field mystruct fstructbind mystruct MyStruct :mystruct

See [doc/dict] for a complete list of fields-related words.
