# Literals and strings

## Number literals

Unlike traditional forths, Dusk has no DEC/HEX mode. Number literals are parsed
using a prefix system.

* "naked" numbers are parsed as decimal: 1234
* "$" is the prefix for hexadecimal notation: $12fe
* "'" is the prefix for a character literal and must be closed: 'A'
  The space character (as well as any whitespace character) cannot be
  represented this way and the SPC constant must be used to refer to it.

## Strings

A string is an address to an area in memory starting with a length byte
followed by that many bytes (also known as a "counted string"). When we refer
to a "string", we refer to that address.  For example, this code will yield a
"hello" string to PS (Parameter Stack):

  here 5 c, 'h' c, 'e' c, 'l' c, 'l' c, 'o' c,

The code above is the equivalent of:

  S" hello"

Strings in Dusk are not limited to textual data and can refer to binary data.
It only refers to the "first byte length followed by that much data" structure.

### Frequent string patterns

Except in C code, you won't see any reference to a "strlen" word, because
getting a length for a string is as simple as c@, so c@ is used.

Another frequent pattern is using c@+ on a string. This yields the range of a
given string.

## String literals

When a string literal word such as S" ." or ," is used, the following content
is parsed in an almost verbatim manner until the closing " is reached. We say
almost verbatim because we can write special characters with the '\' escape
character:

\n: newline ($0a)
\r: carriage return ($0d)
\0: null byte (0)
\\: '\' character
\": '"' character

Any other character following the '\' results in that character being parsed as-
is, the preceding '\' being ignored.

## Ranges

In Dusk, the word "range" refers to a pair of numbers (very often "a u")
representing contiguous elements at a specific address. The first number is the
starting address of the range, the second number is the length in units, which
can be 1, 2 or 4 bytes. When a "range" word is binary modulable [doc/usage/bwm],
the binary selector determines the unit size. When it's not, the size is
implicitly 1 byte.

Examples:

"rtype ( a u -- )" emits "u" characters (1 byte) starting at address "a".
"c@+" applied to a string will yield a range for that string.
"16b move ( src dst u -- )" copies u*2 bytes from src to dst.

The symbol associated with ranges is "[]". For example, "[]= ( a1 a2 u -- f )"
means "compare two ranges for equality". Many "range words" don't use this
symbol though, for example "move" and "idx".

A range with "u=0" is a null range and words dealing with ranges will generally
deal gracefully with null ones. For example, "move" with a null range will be a
noop, "cidx" will always yield "f=0", and so on. If a "range word" doesn't
handle null ranges gracefully, it has to mention it in its description.

## The ,[ immediate builder

You can also build a piece of data at compile time by executing arbitrary code.
This is done through the ,[ words, which drops to intepret mode in the same way
"[" does. Then, it lets you write whatever you want to write. When this mode is
closed by "],", written length is calculated, and then the resulting range is
yielded as two "a u" literals. Example usage:

  : foo ( -- a u ) ,[ $68 c, $65 c, $6c dup c, c, $6f c, ], ;
  foo rtype \ prints "hello"
