# 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'
  Whitespace characters as well as the " and { characters cannot be represented
  this way. You can use constants such as SPC, DQUOT or MOUSTACHE instead.

## 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:

  "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

In most Forths, string literals are awkward because the word to construct them
needs to be followed by a whitespace because of Forth's tokenization rules.

Not in Dusk. In Dusk, string literal are created by enclosing the contents of
the string in double quotes, without any requirement for a whitespace prefix.
This is an example of a string literal:

  "hello"

You can read more about how this works in [doc/usage/io]. For now, what you need
to know is that this exception that Dusk has with regards to double quotes apply
to all words ending with '"'. For example, to print a string, you do:

  ."hello"

When a string handling word such as " ," 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 (that it has a
"w" or "c" prefixed version) the word width 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.
"wmove ( 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"
