# 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".
