summaryrefslogtreecommitdiff
path: root/tests/forms.py
blob: 1a496368af95ef4ac6fd49f385d6a796941c74eb (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
from hypothesis.strategies import integers, decimals as hypo_decimals, booleans, characters, text, tuples, lists as hypo_lists, just, one_of
from hypothesis.strategies import deferred, recursive

from actinide.symbol_table import *
from actinide.types import *

# Generators for forms. Where these generators create a symbol, they will use
# the global symbol table defined in this module. Do not do this in your own
# code! A global symbol table is a memory leak, and only the fact that tests
# exit before they can do any substantial damage prevents this from being a
# bigger problem.
#
# Each generator produces the parsed version of a form.

symbol_table = SymbolTable()

# Generates nil.
def nils():
    return just(None)

# Generates integers.
def ints():
    return integers()

# Generates language decimals.
def decimals():
    return hypo_decimals(allow_nan=False, allow_infinity=False)

# Generates booleans.
def bools():
    return booleans()

# Generates strings.
def strings():
    return text()

# Generates any character legal in a symbol, which cannot be part of some other
# kind of atom.
def symbol_characters():
    return characters(blacklist_characters='01234567890#. \t\n();"')

# Generates symbols guaranteed not to conflict with other kinds of literal. This
# is a subset of the legal symbols.
def symbols():
    return text(symbol_characters(), min_size=1)\
        .map(lambda item: symbol_table[item])

# Generates atoms.
def atoms():
    return one_of(
        nils(),
        ints(),
        decimals(),
        bools(),
        strings(),
        symbols(),
    )

# Generates arbitrary conses, with varying depth. This may happen to generate
# lists by accident.
def conses():
    return recursive(
        tuples(atoms(), atoms()).map(lambda elems: cons(*elems)),
        lambda children: tuples(children | atoms(), children | atoms()).map(lambda elems: cons(*elems)),
    )

# Generates lists, with varying depth.
def lists():
    return recursive(
        hypo_lists(atoms()).map(lambda elems: list(*elems)),
        lambda children: hypo_lists(children | atoms()).map(lambda elems: list(*elems)),
    )

# Generates random forms.
def forms():
    return one_of(nils(), ints(), bools(), strings(), symbols(), conses(), lists())