summaryrefslogtreecommitdiff
path: root/docs/syntax.rst
blob: b84e0ae5e41dbb26c3ee9794357dccb843be78c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
######
Syntax
######

.. highlight:: scheme

The most basic unit of Actinide's syntax is the *form*. An Actinide program
consists of a single top-level form, which may include subforms and
sub-subforms within it nested arbitrarily deeply.

********
Comments
********

An Actinide program may contain comments. Comments are removed during parsing
and are not technically forms, but they're included here for completeness. A comment begins with a ``;`` and continues to the next newline character or until the end of the program, whichever comes first.

Examples:

* ``; this is a comment.``

*****
Atoms
*****

The following forms are *atomic* - they do not contain any subforms, and can be
reduced in a single step to a final value.

~~~~~~~~
Integers
~~~~~~~~

An Actinide integer represents a mathematical integer: a precise number with no
fractional part, which may be positive, negative, or zero. Actinide integers do
not have a fixed range - there is no built-in maximum or minimum integer.

The syntax of an integer consists of an optional leading ``-`` sign for
negative integers, followed by any sequence of digits and underscores.
Underscores should be used to separate thousands.

Examples:

* ``10``
* ``-2_049``

.. note::

    Practically, Actinide integers are represented by Python ``int`` objects,
    and share their characteristics. This is not part of their specification,
    but the formal properties of Actinide constracts aren't fully separable
    from the implementation at this time.

~~~~~~~~
Decimals
~~~~~~~~

An Acdinide decimal represents a precise base-ten fractional value with a
finite number of decimal places. Actinide decimals do not have a fixed limit on
range or precision.

The syntax of a decimal consists of an optional leading ``-`` sign for negative
decimal numbers, followed by an optional sequence of digits and underscores for
the integral part, followed by a ``.``, followed by an optional sequence of
digits and underscores for the fractional part, followed by an optional
exponent part consisting of an ``e`` and a sequence of digits and underscores.

A decimal form *must* have a non-empty integral part or a non-empty fractional
part. As with integers, underscores should be used as thousands separators.

Examples:

* ``0.0``
* ``-2_049.501_2``
* ``2e10``

.. note::

    Practically, Actinide decimals are represented by Python
    ``decimal.Decimal`` values in the default decimal context. I haven't fully
    fleshed out the Actinide semantics of decimal operations, so the Python
    semantics leak through. This means that, for example, there is a negative
    zero (which is equal to zero), and that ``1e1`` and ``10`` are different
    (but equal) values.

~~~~~~~
Strings
~~~~~~~

An Actinide string represents a sequence of Unicode characters.

The syntax of a string consists of a leading ``"``, followed by any sequence of
unescaped characters or escaped characters, followed by a trailing ``"``. An
escaped character is either the sequence ``\"`` or the sequence ``\\``; an
unescaped character is any Unicode character other than ``\`` or ``"``. The
enclosing quote marks and escape marks are not part of the string's value, and
are removed during parsing.

Line breaks and non-printing characters can appear within a string.

Examples:

* ``"Hello, world."``
* ``"😡💩🚀"``
* ``"Quoth the raven, \"Four Oh Four.\""``.

.. note::

    As with most other Actinide primitives, strings are implemented directly on
    top of a common Python type: ``str`` itself. The Python representation is
    not part of the language, but does leak through in places.

~~~~~~~~
Booleans
~~~~~~~~

A boolean value represents one of two logical states: true (represented by
exactly ``#t``) and false (``#f``).

~~~~~~~
Symbols
~~~~~~~

Symbols represent variables and special keywords in an Actinide program.

The syntax of a symbol is a sequence of unicode characters other than quotes,
semicolons, tabs, spaces, and newlines, which is not an integer, decimal, or
boolean.

Examples:

* ``x``
* ``if``
* ``+``
* ``my-🚀``

**************
Compound Forms
**************

The following forms consist of both the compound form itself and a sequence of
subforms.

~~~~~
Lists
~~~~~

Lists represent most kinds of Actinide syntax other than atoms.

The syntax of a list consists of an opening ``(``, followed by zero or more
subforms, separated by spaces, tabs, or newlines, followed by a closing ``)``.
The subforms of a list can be any Actinide form, including another list.

Examples:

* ``(foo)``
* ``()``
* ``(1 a #f)``

~~~~~~
Conses
~~~~~~

Conses represent pairs of forms.

The syntax of a dotted pair consists of an opening ``(``, followed by a *head*
form, followed by a ``.``, followed by a *tail* form, followed by a closing
``)``. A dotted pair appearing as the tail of a dotted pair does not need to be
enclosed in parentheses, and can be represented by removing the preceding
``.``, instead.

Examples:

* ``(1 . 2)``
* ``(1 2 . 3)``
* ``((ll . lr) . (rl . rr))``

Conses whose tail form is the empty list are themselves lists. A cons whose
tail form is not a list is an *improper list*.

~~~~~~
Quotes
~~~~~~

A quote form prevents the evaluation of its contained form.

The syntax of a quote form is either a list beginning with the symbol ``quote``
and containing exactly two subforms, or a leading ``'`` followed by a single
form (which is exactly equivalent to ``(quote form)``).

Examples:

* ``'()``, ``(quote ())``
* ``'a``, ``(quote a)``
* ``'(1 . 2)``, ``(quote (1 . 2))``

~~~~~~~~~~~
Quasiquotes
~~~~~~~~~~~

Actinide has a fully-featured :ref:`macro system <macros>`. To support the
macro system, the language includes a system for constructing syntactic forms
programmatically. The following special forms are part of that system:

* ```form``, ``(quasiquote form)``
* ``,form``, ``(unquote form)``
* ``,@form``, ``(unquote-splicing form)``

Full discussion of quasiquoted forms is covered in the section on macros. These
forms cannot be reduced, and will generally raise an error if they're
evaluated, but they're normally eliminated during macro expansion before
evaluation.