# Compiler signatures

The unit at [comp/sig.fs] is a small extension over [lib/type] that defines a
Signature type and provides convenience words to attach signatures to Forth
words, the goal being to allow compilers to interface with those words.

Once a word has been annotated with a signature, it can be called from any
language that support all the types used in that signature.

## Usage

Here's how we can annotate the word "max ( a b -- n )":

  DWord 1 DWord DWord 2 annotate max

## Common signatures

In addition to supplying the mechanism to tag words with signatures, it also
tags some core words from other units used during the bootstrapping process (and
thus, for which adding "comp/sig" to their dependencies is not possible).

The signatures below use the C syntax, but this doesn't mean that these
signatures can only be used in C. They can be used in any language.

### core

void abort();
void quit();

### io/drive

void readsector(*Drive drv, uint dst, uint sec);
void writesector(*Drive drv, uint dst, uint sec);

### io/stream

uint read(*Stream s, uint u, uint a);
uint write(*Stream s, uint u, uint a);
void close(*Stream s);

### fs/core

void seek(*File f, uint pos);
void flush(*File f);

### lib/diag

void dump(uint addr);

## API

### Signature category

The Signature category has this structure:

+00 Category
+04 Number of input elements
+08 Number of output elements
... array of pointers to types for each input, then output elements.

The input and output fields are ordered from the shallowest (PS top) to the
deepest. For example, if we have a Forth signature "( a b -- c d )", "b" is the
first element of the "in" array and "d" is the first element of the "out" array.

Some signature don't make sense because of the PS restriction that all arguments
are 32-bits in size. For example, an Array can't go there. You'll want a Pointer
to an Array. comp/sig doesn't validate this stuff.

"typesz" of a Signature yields 0.

### Words

signaturetype ( ... n ... n -- type )
  Take two counted lists from PS where each is a list of types. The shallowest
  list is the Input signature and the deepest list is the Output. The shallowest
  item of each list represents the shallowest item of the signature.

  For example, the signature "( a b -- c d )" would go thus:

    typeC typeD 2 typeA typeB 2 signaturetype

sigcounts ( type -- inputcount outputcount )
  Yields the IN/OUT counts for specified signature.

siginputs ( type -- a )
  Yields the address of the first input type of the signature.

sigoutputs ( type -- a )
  Yields the address of the first output type of the signature.

annotate ( ... n ... n "name" -- )
  Create a signature through "signaturetype", then look for "name" in sysdict.
  Then, in [lib/tagl], add tag the found execution token with "SIGT" and the
  created signature as a value.

findannotated ( name -- ?sig xt-or-0 )
  Find name in sysdict and, if the entry is tagged with "SIGT", yield the found
  xt along with the annotated signature. Otherwise, xt=0 and sig is absent.
