# What's in a word?

Like in any Forth, Dusk's main mechanism for creating new words is ":".

  : foo bar baz ;

What this does is:

1. Create a new dictionary entry named "foo".
2. On some platforms, create a word mark [doc/hal].
3. Enter compile mode.
4. Compile calls to "bar", then "baz".
5. Call "exit," [doc/hal].
6. Stop compile mode.

There are other ways to create words differently. For example, "entry ( name
dict -- )" creates an entry in dictionary "dict" without creating a word mark or
entering compile mode. "code ( "name" -- )" creates a dictionary entry and a
word mark, but doesn't enter compile mode.

Those are relatively straightforward mechanisms. There are other ones that are a
bit more special, described below.

## Setters

Dusk has the word "to", which works both at runtime and compile time, which
hook to generalized "setters", that is, any word that has a "setter" will work
with "to". You create such "setters" with the word "setter", which works like
"immediate" or "compileonly" [doc/usage/imm] :

  : hello ."Hello!" ;
  : hello ."Setting to: " . ; setter

As with "compileonly", the "setter" flag makes the word "unfindable"... except
when "to" is called!

  hello \ prints "Hello!"
  42 to hello \ prints "Setting to: 42"
  : foo 42 to hello ; \ nothing is printed
  foo \ prints "Setting to: 42"

## Aliases

An alias is a shortcut to another word:

  alias noop myalias

Calling "myalias" is the same as calling "noop". An alias is a native jump to
its target, so there's almost no runtime overhead to using aliases.

You can change the target of an alias, you can use the word
"realias ( w tgt -- )" which makes target word "tgt" alias to word "w". Example:

  ' anotherword ' myalias realias

Note that while "tgt" is usually an alias, it doesn't have to be. You can make
a "hostile takeover" of a word with realias and brutally make it point
elsewhere. If you do, make sure that the word is big enough for a native jump.
For example, using realias on the word "noop", which only contains a "return"
op, would likely corrupt the dictionary entry of the following word.

Aliases have two main usages: dynamically pluggable words, or forward
declarations. For the latter type, there is also the syntactically more pleasant
word ":realias", which is a combination of, drum roll, ":" and "realias" and can
be used thus:

  alias abort foo \ Forward declaration
  : bar foo ;
  :realias foo bar ;

It is the equivalent of:

  alias abort foo \ Forward declaration
  : bar foo ;
  : _ bar ;
  current ' foo realias

except that further references to "foo" will link directly to the actual word
rather than going through the alias.

## Binding and Scrying

Like any Forth, Dusk has does>, but it works slightly differently than the
traditional does> where it's a binding of a "create" and behavior.

Dusk's "does>" has one less level of indirection, that is, it can yield any
number as its "does parameter". Example:

  : foo does> . ;
  42 foo bar
  bar \ prints 42

The word "bar" is created by "does>", which has the signature ( n "name" -- ).

If you want to reproduce the "traditional" does>, you can do this:

  : foo here# swap , does> @ . ;
  42 foo bar
  bar \ prints 42

Note that we didn't use "create" because otherwise, two words would be created,
one by "create" and one by "does>".

"does>" is a wrapper around "bind ( w n "name")" which binds the word "w" to
parameter "n". Our first "does>" above is the equivalent of:

  ' . 42 bind bar
  bar \ prints 42

"immdoes>" is the exact same as "does>", but it makes the resulting word
immediate.

### Scrying

The binding created by bind is a conditional call that checks on the global
"SCRYING" variable. Each "check" resets the "SCRYING" flag to 0. When SCRYING is
1, the bind isn't called. Instead, the parameter is yielded, as would a simple
"create". Example:

  : foo does> . ;
  42 foo bar
  scry bar .x \ prints 0000002a
  bar \ prints 42

All words created with "bind" (does> and immdoes> among them) are "scryable".

Any word can be made "scryable" with "scrying? ( -- f )":

  : foo scrying? if 42 else 54 then ;
  foo . \ prints 54
  scry foo . \ prints 42

There's a "compiling" version of "scrying?", "scrying?," which compiles a very
fast version of the same check and instead of yielding a flag to PS, it sets the
Z flag, allowing for a branchC, to follow. For example, this is the
implementation of "bind":

  : bind ( w n "name" ) code litn scrying?, Z) branchC, drop exit, ;

SCRYING being a global flag that keeps its value until toggled by a "scrying?",
one must be careful not to use "scry" with words that don't actually support
scrying. Doing so will corrupt the call of the next "scryable" word call and
will likely catastrophilosophically crash the system. Scrying is powerful but
dangerous!

## Anonymous words with :~

Its a common pattern to define words that are used in very local context and
then never needed anymore. They can be called something like "_" to indicate
that their name don't matter and that they'll never be referenced anywhere.

This will, however, create a dictionary entry for "_". In addition to being a
bit wasteful, it's also an unwanted side effect in some cases, for example in
namespaces that represent a precise API. For example, operators in the C
compiler are defined in terms of namespaces and defining a "_" word in it
defines the "_" operator, something we don't want.

The ":~" and "~" words allow the definition and referencing of words without
creating dictionary entries:

  :~ 1+ . ;
  : print42 41 ~ ;

## :override

:override allows you to redefine a word while still using its previous behavior,
often to augment that behavior. Upon definition, the "~" pointer is updated to
provide the implementer with a way to reference the old word.

  : foo 1+ . ;
  42 foo \ prints 43
  :override foo 1+ ~ ;
  42 foo \ prints 44
