# Namespaces and Structures

Namespaces are a convenient way to manage sets of conflicting words. For
example, assemblers often have the same mnemonics, so loading two assemblers
in the global namespaces makes the first one unusable. Namespaces to the rescue!

  : foo 54 ;
  ns[ MyNS
    : foo 42 ;
  ]ns
  foo . \ Prints 54
  MyNS foo . \ Prints 42

In the example above, the second "foo" exists only in the namespace "MyNS" and
can be invoked my calling MyNS followed by the target word in the namespace.

The "ns[ ( -- blkctx )" word creates a new namespace with the specified name and
then "enters" it, that is, it replaces the current context (CURCONTEXT) with its
own context, the one it just created by forking the current context.

When you're "inside" a namespace, you do your stuff like you would normally. You
can load files with f<<, no problem. When you're ready to exit the namespace,
you call "]ns ( bkpctx -- )". When you do so, you need to have PS at the same
level as your "enter" level so that "bkpctx" (taken from CURCONTEXT at "enter"
time) can be properly restored.

And you know why that is? Because namespaces are nestable!

  ns[ MyNS
    : foo 42 ;
    ns[ Nested
      : foo 54 ;
    ]ns
    foo . \ Prints 42
    Nested foo . \ Prints 54
  ]ns
  MyNS Nested foo . \ Prints 54

Therefore, "]ns" doesn't always return to the system context.

You can "extend" an existing context with the word "extends". An extended
context is the same thing as a nested context except that its name live in the
parent context:

  ns[ MyNS
    : foo 42 ;
    : bar 123 ;
  ]ns
  extends MyNS ns[ Extended
    : foo 54 ;
  ]ns
  Extended foo . \ Prints 54
  MyNS foo . \ Prints 42
  Extended bar . \ Prints 123

You can also "enter" a namespace after it's been created. It's done with the
"intons[ ( "name" -- bkpctx )" word. You leave with "]ns":

  ns[ MyNS
    : foo 42 ;
  ]ns
  intons[ MyNS
    foo . \ Prints 42
    : bar 54 ;
  ]ns
  MyNS bar . \ Prints 54

Namespace accesses work as you'd expect in compiled words. If you need the
address of a word in a particular namespace, you can use "ns'" and "[ns']", the
equivalent to "'" and "[']":

  ns[ MyNS
    : foo 42 ;
  ]ns
  : cfoo MyNS foo . ;
  cfoo \ Prints 42
  ns' MyNS foo execute . \ Prints 42
  : cfoo [ns'] MyNS foo execute . ;
  cfoo \ Prints 42

## Structures

Structures are namespaces and fields [doc/usage/bind] put together. The way they
work is very similar to namepaces, with a few differences:

* You create structs with "struct[" and close them with "]struct".
* When "]struct" is called, a constant "SZ" is created inside the namespace with
  the current value of "fieldsoff".
* When "struct[" is called, the "fieldsoff" value is initialized to 0 if it's a
  new struct or to "SZ" if "extends" is used.
* As with any namespace, you can use "intons[" to augment an existing struct,
  but you must close it with "]ns", not "]struct"! If you do, you'll corrupt
  "SZ".
* Under certain circumstances, you can add fields through "intons[", but you
  have to manage "fieldsoff" and "SZ" manually to have your fields exist at
  proper offsets. Also, be aware that if you add fields to a struct that has
  alread been extended, you might end up with offset conflicts.

## Structure binds

You will often want to bind data to structs. You can do so with "structbind":

  data1 structbind Foo MyData1
  MyData1 :bleh . \ prints 3
  : someword MyData1 bar ;
  someword . \ prints 2

A structbind is compiled with a level of indirection that allows it to be
rebound. So, you can rebind structbinds with the word "rebind" (we can't use
"to" because that applies to the original bind's field):

  data2 rebind' MyData1
  MyData1 :bleh . \ prints 7
  someword . \ prints 4

All namespaces have a ":self" method which is a noop, and thus returns a
reference to the associated data. This can be used to get a structbind's data
reference:

  MyData1 :self \ data2 is on PS TOS

Note: structbinds work with regular namespaces, but they have no obvious use,
which is why this word is called "structbind" and not "nsbind".

## Extending Dusk structures

When a structure extends another, it's common practice for the extending struct
to call its base struct's ":new" method and add to it.

Structure methods initialization is a bit tricky. The whole point of those
methods is to allow a structure that extends another structure to override them.
For this to be done harmoniously, the "extender" struct, at *compile* time,
needs to make a list of those methods it want to write, and overwrite the
methods that were written by the base struct. For simplicity, this is often done
using a combination of ",[" and "-cmove,". Example:

  struct[ MyAbstract
    method :foo
    : :new here ['] abort , ;
  ]struct
  extends MyAbstract struct[ MyImpl
    field myfield
    : impl drop 42 ;
    : :new MyAbstract :new ,[ ' impl , ], -cmove, 54 ( myfield ) , ;
  ]struct
  MyImpl :new dup :foo . \ prints 42
  myfield . \ prints 54

For this to work, methods need to be the last fields of the struct (but
"extenders" can add other fields on top of it).

Because the pattern above requires every struct "extender" to repeat the name
of the methods and because this is tedious and verbose, another convention
emerges from that: Method implementations have the name of the method, minus the
":" prefix, and base structs have a ":[methods]" word that dynamically look for
those names and write them. Then, "extenders" call this method at compile time
and write this string down in their ":new" implementation. This results in code
that looks like this:

    struct[ MyAbstract
      method :foo
      : :new here ['] abort , ;
      : :[methods] '" foo" , ;
    ]struct
    extends MyAbstract struct[ MyImpl
      field myfield
      : foo drop 42 ;
      : :new MyAbstract :new ,[ :[methods] , ], -cmove, 54 ( myfield ) , ;
    ]struct

With one "extender", the gain is slim (null in fact), but as extenders multiply,
this patterns allows us to minimize code duplication and make changes in base
structures much easier.

Note that this pattern only works for direct extension overrides (the most
frequent case). If a struct extender needs to override a method from a structure
more than 1 level deep in the hierarchy, the pattern is a bit more complex and
involves base structures creating a ":methods(" constant. Here's an example:

  struct[ A
    field a
    0 field' :methods(
    method :foo
    : :new here 0 ( a ) , ['] abort , ;
    : :[methods] '" foo" , ;
  ]struct
  extends A struct[ B
   field b
    : :new A :new 0 ( b ) , ;
  ]struct
  extends B struct[ C
    field c
    : :new B :new 0 ( c ) ,
      ,[ A :[methods] ], dip over A :methods( | cmove ;
  ]struct

So, a bit more verbose than the direct variant, but it happens much less often.
