summaryrefslogtreecommitdiff
path: root/LANGUAGE.rst
blob: 1ed3400fe9aa6850025edfb68c787fa5ceebfbd3 (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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
#################################
The Actinide Programming Language
#################################

*****
Forms
*****

* The basic unit of Actinide syntax.

* The basic unit of Actinide evaluation.

* A program is evaluated by *reducing* forms to produce a final value, applying
  side effects during the reduction.

* What does a form look like?

    * Simple forms: literals (and intro to types)

        * Integers: a leading - sign for negative numbers, followed by a
          sequence of digits and underscores. Represent base-ten values with no
          fractional part. Examples: ``10``, ``-2_049``.

        * Decimals: a leading - sign for negative numbers, followed by a
          sequence of digits and underscores, followed by a dot, followed by a
          sequence of digits and underscores. Represent base-ten values which
          may have a factional part. Examples: ``10.0``, ``-2_049.501_2``.

        * Strings: any sequence of characters other than ``"`` or ``\``,
          enclosed in matching ``"`` marks. The sequences ``\"`` and ``\\`` are
          "escape" sequences, representing a ``"`` or ``\`` character
          respectively. Examples: ``"Hello, world."``, ``"😡💩🚀"``, ``"Quoth
          the raven, \"Four Oh Four.\""``.

        * Booleans: the special values meaning "true" and "false." Preferred
          for boolean logic operations. They are ``#t`` for true, and ``#f``
          for false.

    * Simple forms: symbols

        * Sequences of letters, numbers, and symbols not surrounded by quotes,
          and which are not themselves integers, decimals, or booleans.

        * Represent variables and constants in the program's source.

        * Evaluation of variables is covered later in this document.

        * Examples: ``hello``, ``+``, ``my-🚀``.

    * Special mention: comments

        * Cannot appear *inside* a string.

        * Starts with a ``;``, continues to the end of the line.

        * Dropped from the program entirely.

        * Examples: ``; this function is extremely spicy.``

* Compound forms: lists

    * An opening ``(``, followed by a sequence of "subforms" separated by
      spaces, followed by a closing ``)``.

    * Subforms may be any form, including another list.

    * Represent function application as well as special

* Compound forms: quotes, quasiquotes, and unqoute forms.

    * The forms ``'``, ``\```, ``,``, and ``,@`` represent "quote" forms.

    * These are discussed in detail in the Macros section, later on.

******************
Simple Expressions
******************

* Evaluation of a form *reduces* the form to a simpler form - ideally, into a
  list of atomic values.

* Every kind of form can be evaluated.

* Evaluation of literals:

    * Integers, decimals, strings, booleans evaluate to themselves. The number
      ``1`` or the string ``"Hello, world"`` cannot be reduced any further.

* Evaluation of symbols:

    * The symbol is replaced by a value from the current *environment*.

    * This is analogous to variable expansion in other languages.

    * How do environments get their values? Defines and function application,
      covered below.

    * Certain symbols are *built in* and are automatically given values in the
      top-level environment before the program starts.

********************
Function Application
********************

* Evaluation of lists:

    * A list that starts with the symbols ``begin``, ``values``, ``if``,
      ``lambda``, ``define``, ``define-macro``, or ``quote`` is a *special
      form*, which are covered separately.

    * Any other list represents a function application.

* The subforms representing the list elements are evaluated first, left to
  right.

* If the first subform evaluates to a procedure

* During application:

    * A new environment is created, with the names of the arguments bound to
      the values from the function application expression.

    * The body of the function is run as a program, in this environment.

    * The result of the last form in the function is the result of the function
      application.

*************
Special Forms
*************

Lists that begin with one of the following symbols are evaluated specially.

* ``begin``: A ``begin`` form evaluates a sequence of subforms, reducing to the
  result of the last subform in the sequence. Example:

    ::

        (begin
            ; define a function...
            (define (f) 1)
            ; ...and call it
            (f))

    The forms whose results are discarded are still evaluated for their side
    effects.

* ``values``: A ``values`` form evaluates a sequence of subforms, then reduces
  to those values in the context of the containing form. This allows functions
  to return multiple values. Example:

    ::

        (begin
            (define (two x) (values x x))
            (= (two 53)))

    The ``two`` function returns two values, which are placed in the argument
    positions for the ``=`` function. This program reduces to ``#t`` if run,
    and defines ``two`` as a side effect.

* ``if``: An ``if`` form must include a ``cond`` subform producing exactly one
  value, and either one or two consequent subforms (named ``true`` and
  ``false`` subforms in this document).

      * The ``if`` form first evaluates the ``cond`` subform.

      * If it evaluates to a true value (``#t``, a non-zero integer, a non-zero
        decimal, a non-empty string, or a non-nil ``cons``), then the ``if``
        form evaluates the ``true`` subform.

      * If the ``cond`` subform evaluates to a false value (any other value),
        then the ``if`` form evaluates the ``false`` subform.

      * If the ``if`` form does not have a ``false`` subform, the ``if`` form
        evaluates to ``nil`` when the ``cond`` subform evaluates to a false
        value.

     * Examples: ``(if #t 1)`` (always equal to ``1``), ``(if some-var "okay"
       "failure")``.

* ``lambda``: A ``lambda`` form defines a procedure, and evaluates to a
  procedure value which can be used to apply the newly-defined procedure.

    * Must include a ``formals`` subform, which is generally a list of argument
      names (as symbols).

    * May include a sequence of body subforms, which are evaluated in order (as
      if by ``begin``) whenever the function is applied.

    * Functions capture the environment in effect when they are defined.
      Symbols within the function body can refer to names defined in the
      surrounding lexical context.

    * Function bodies are evaluated in a new environment for each application,
      with the symbols representing the arguments bound to the corresponding
      values in the function application form.

    * Examples:

    ::

        (lambda () 1)

      This defines a constant function (which takes no arguments) whose
      evaluation is always 1.

    ::

        (begin
            (define x 5)
            (lambda () x))

      This defines a constant function whose evaluation is always the value of
      ``x`` in the top-level environment (initially 5).

    ::

        (lambda (a b) (+ a b))

      This defines a binary function (which takes two arguments) whose
      evaluation is the sum of those arguments. This is a simple replacement
      for the ``+`` function itself, but it illustrates the idea that functions
      can include other functions.

* ``define``: A ``declare`` form sets the value of a new binding in the current
  environment. This has two forms:

    * ``(define symbol value)``: evaluates the ``value`` subform, and binds the
      result to ``symbol`` in the current environment. Example:

    ::

        (begin
            ; Bind x to a value
            (define x 5)
            ; Expands x in the same environment
            x)

      This program evaluates to ``5``.

    * ``(define (name formals...) body...)``: defines a function and binds it
      to ``name`` in the current environemnt.

      This is expanded to an equivalent ``lambda`` form, within a ``define``
      form binding the resulting procedure to ``name``. For example:

    ::

        (define (f a b) (+ a b))

      is equivalent to

    ::

        (define f
                (lambda (a b) (+ a b)))

* ``define-macro``: This has the same syntaxes as the ``define`` form, but it
  binds values to a special "macro table" which is used to transform code prior
  to evaluation. Macros are described later in this document.

* ``quote``: A ``quote`` form must have exactly one form in argument position.
  It evaluates to exactly the argument form, without evaluating it. For example:

::

    (quote (+ 1 2))

  evaluates to the list ``(+ 1 2)``. Quote forms are the easiest way to obtain
  unevaluated symbols as values, and are an integral part of the Actinide macro
  system.

*******************
Loops and Recursion
*******************

* To loop, a function must recurse. Actinide has no looping primitives other
  than function application.

* Actinide guarantees that functions that recurse in tail position, either
  directly or indirectly, can recurse indefinitely.

* What is tail position?

    * Function bodies: the final form of the function is in tail position with
      respect to the function.

    * ``begin`` forms: the final subform is in tail position with respect to
      the ``begin`` form.

    * ``if`` forms: the ``true`` subform is in tail position with respect to
      the ``if`` form if the ``cond`` subform reduces to a true value. The
      ``false`` subform is in tail position with respect to the ``if`` form if
      the ``cond`` subform reduces to a false value.

    * If a form is in tail position with respect to its containing form, it is
      in tail position with respect to *that* form's containing form, and so
      on, out to the nearest ``lambda`` body or to the top level of the program.

* Example:

    * Simple recursive factorial:

    ::

        (define (factorial n)
                (if (= n 1)
                    1
                    (* n (factorial (- n 1)))))

      The ``factorial`` function *is not* called in tail position with respect
      to the body of the ``factorial`` function: After reducing that function
      application, the reduction of the outer ``factorial`` application still
      needs to apply the ``*`` function to the result.

      Attempting to evaluate ``(factorial 1000)`` fails due to limits on call
      depth: ``maximum recursion depth exceeded while calling a Python object``

    ::

        (define (fact n a)
                (if (= n 1)
                    a
                    (fact (- n 1) (* n a))))

      The ``fact`` function *is* called in tail position with respect to the
      body of ``fact``. Specifically, it is in tail position with respect to
      the ``if`` form whenever ``n`` is not equal to ``1``, and the ``if`` form
      is in tail position with respect to the body of the ``fact`` function.

      Evaluating ``(fact 1000 1)`` correctly computes the factorial of ``1000``
      on any machine with enough memory to store the result.

******
Macros
******

* Before Actinide evaluates a program, it *expands* a program.

* Expansion replaces macros (defined by ``define-macro``, as above).

* A *macro* is an Actinide procedure, as with ``lambda``, which accepts forms
  as arguments and reduces to a new form.

* Macros can be used to define new syntax.

* Macro expansion is recursive: the result of expanding a macro is expanded
  again, which allows macros to produce macro forms.

* Example: The ``let-one`` macro defines a single local variable, with a known
  value, and evaluates a body form in a temporary environment with that
  variable bound.

::

    (define-macro (let-one binding body)
        (begin
            (define name (head binding))
            (define val (head (tail binding)))
            `((lambda (,name) ,body) ,val))))

  To use this macro, apply it as if it were a function:

::

    (let-one (x 1) x)

  The macro procedure accepts the forms ``(x 1)`` and ``x``, unevaluated, as
  arguments, and substitutes them into a *quasiquoted* form, which is used as a
  template. The three *unquoted* parts (``,name``, ``,body``, and ``val``) are
  replaced by evaluating the symbols in the context of the macro procedure, and
  expand to the relevant parts of the input forms.

  The returned form is approximately

::

  ((lambda (x) x) 1)

  and evaluates as such.

  This program evaluates to 1, but *does not* bind ``x`` in the top-level
  environment.

* Actinide macros are *not hygienic*. A quoted symbol in the macro body will be
  evaluated in the location where the macro is expanded, with full access to
  the environment at that location. Similarly, symbols defined in the macro
  will be fully visible to code running in the environment where the macro is
  expanded.

* Macros often use quote notation to build the returned form. Quote notation is
  ultimately a sequence of ``quote`` forms. However, Actinide supports
  *quasiquote* notation to simplify the creation of nested quoted forms
  containing unquoted parts.

    * A quasiquote form begins with ``\```. If the form contains no unquoted
      parts, this will quasiquote each subform, terminating by quoting each
      symbol or literal form and ``cons``ing them into a new list. ``\`(a b)``
      expands to ``('a 'b)``.`

    * Within a quasiquote form, an *unquote* form prevents the following form
      from being quoted. An unquote form begins with ``,``, followed by a
      single form (often, but not always, a single symbol). ``\`(a ,b c)``
      expands to ``('a b 'c)``.

    * Within a quasiquote form, an *unquote-splicing* form prevents the
      following form from being quoted. An unquote-splicing form begins with
      ``,@``, followed by a single form, which must evaluate to a list. The
      elements of that list are grafted into the resulting form. Given
      ``(define x (list 1 2))``, the form ``\`(a ,@x b)`` expands to ``('a 1 2
      'b)``.