summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/09a8a14f5f6826f2bin0 -> 10 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/0e88086df05175271
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/19bb68f9d92692f9bin0 -> 67 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/3ee6ff39f2ac6deabin33 -> 0 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/49e6f38c5cc772ecbin28 -> 0 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/56980d5ed7b87686bin0 -> 9 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/5b55ec37559bb1101
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/61b71c2df2d87966bin0 -> 8 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/69b43aa9ca8c9717bin0 -> 27 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/745fc588673e7088bin0 -> 13 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/79086a9d57f9948dbin0 -> 6 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/8065c2327096a7a3bin28 -> 0 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/8221fd2283c91e1fbin0 -> 243 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/8611cbd7e46390b8bin0 -> 10 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/8b092171a745ad441
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/8ee2d9884de49d9abin0 -> 5 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/ae775858a7e56781bin6 -> 0 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/b0d0244d1f73df81bin0 -> 105 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/c92920944247d80c1
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/ddaf0ed54dfc227cbin0 -> 4 bytes
-rw-r--r--.hypothesis/examples/17015ad1b47afd98/df031fe309e7c5bf1
-rw-r--r--.hypothesis/examples/641567e7f1117698/005f5867178a5b251
-rw-r--r--.hypothesis/examples/641567e7f1117698/0478b7c7ead9c10dbin0 -> 1238 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/1cd68f1893d28b931
-rw-r--r--.hypothesis/examples/641567e7f1117698/1d14332589e1f360bin0 -> 28 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/1e7cf357b0153edabin11 -> 0 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/203107b3bbad5816bin0 -> 6 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/2bd9f6ed10af66c0bin0 -> 32 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/2f69395da78f14d8bin0 -> 13 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/3923acd66c0b7e181
-rw-r--r--.hypothesis/examples/641567e7f1117698/3c6c5c8e00e8affebin0 -> 6 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/45f01200098f83febin0 -> 33 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/5be455f23fea5189bin0 -> 7 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/5e762c293b8926eabin11 -> 0 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/5ec5c4954a59b6a4bin13 -> 0 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/63399f455589d4babin0 -> 15 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/6d688fd550d32db0bin0 -> 25 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/7f8faf9da637e86fbin0 -> 34 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/881b6ce80b5bd1fcbin0 -> 42 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/a6039ffc453749e1bin0 -> 29 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/b19b7b820dddb3c6bin0 -> 15 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/b52e65a9e0e8f9dbbin0 -> 6 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/b6420ce3b52b1ab7bin28 -> 0 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/c17293c1c7f91651bin0 -> 8 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/cfb16a37ef90423bbin0 -> 7 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/d1f7b282fca409b2bin57 -> 0 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/ea786d015fba3beebin0 -> 9 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/f41cb651e160d454bin0 -> 8 bytes
-rw-r--r--.hypothesis/examples/641567e7f1117698/f7b6a134061a22a3bin0 -> 13 bytes
-rw-r--r--.hypothesis/examples/c5004b86438ec8a9/a1a8c54704cd3ce5bin0 -> 24 bytes
-rw-r--r--.hypothesis/examples/c72254ca7f2d3ae9/18c072a6c0de03a3bin0 -> 7 bytes
-rw-r--r--.hypothesis/examples/c72254ca7f2d3ae9/76c7ab7f4af319c7bin0 -> 12 bytes
-rw-r--r--.hypothesis/examples/dc26b29be33957c5/3ac7fd17438f7df3bin8 -> 0 bytes
-rw-r--r--.hypothesis/examples/dc26b29be33957c5/4b5882e6feb52553bin0 -> 10 bytes
-rw-r--r--.hypothesis/examples/dc26b29be33957c5/5b55ec37559bb1101
-rw-r--r--.hypothesis/examples/dc26b29be33957c5/c512123626a989141
-rw-r--r--.hypothesis/examples/dc26b29be33957c5/d6459ab29c7b9a9fbin4 -> 0 bytes
-rw-r--r--.hypothesis/examples/dc26b29be33957c5/ee3ad785c37b610dbin0 -> 7 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/00d874a28a65de9bbin0 -> 39 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/0c69f7daba8b9b86bin0 -> 10 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/0f42e404bef2b1a3bin0 -> 11 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/16bceb1530a91002bin4 -> 0 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/207b79c0dd1b6fbabin0 -> 5 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/218d87f650043d4dbin0 -> 21 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/275df7aaf0e8504bbin0 -> 4 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/28a055f3278de950bin0 -> 21 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/29a465ca925a55c2bin0 -> 115 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/36d7ba28eb961f14bin0 -> 32 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/3b15208ee23b0387bin0 -> 5 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/3be6ee08630f7415bin0 -> 9 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/41d22663c8456cf1bin0 -> 6 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/4566df4571cae443bin0 -> 5 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/51ab005a386f8742bin0 -> 5 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/52f15fc15e039804bin0 -> 16 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/56622e534f8c66dbbin0 -> 12 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/5bcf6972d8812615bin17 -> 0 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/5e1b75e52e4472a7bin0 -> 14 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/619a0adc5abca17ebin7 -> 0 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/b2d7ebd146f76d3dbin0 -> 8 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/b691cacbafa2b728bin0 -> 70 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/bdff285d783ed32fbin0 -> 59 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/f01e2bfd10c9b16ebin0 -> 4 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/f41ac3052b176061bin0 -> 6 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/f635e57ce2b75454bin0 -> 5 bytes
-rw-r--r--.hypothesis/examples/ec453dcb33aa8b66/faf1cd4bdf2d5926bin0 -> 6 bytes
-rw-r--r--.hypothesis/examples/ef6354fc2348e0ad/2d0134ed3b9de1321
-rw-r--r--.hypothesis/examples/ef6354fc2348e0ad/54d00d52177f7dc5bin6 -> 0 bytes
-rw-r--r--.hypothesis/examples/ef6354fc2348e0ad/5d1be7e9dda1ee881
-rw-r--r--.hypothesis/examples/ef6354fc2348e0ad/a42c6cf1de3abfde1
-rw-r--r--.hypothesis/examples/ef6354fc2348e0ad/e7faf0b097a6f469bin0 -> 6 bytes
-rw-r--r--actinide/__init__.py29
-rw-r--r--actinide/evaluator.py85
-rw-r--r--actinide/expander.py138
-rw-r--r--actinide/reader.py24
-rw-r--r--actinide/tokenizer.py33
-rw-r--r--actinide/types.py73
-rwxr-xr-xbin/actinide-repl2
-rw-r--r--primer.py10
-rw-r--r--tests/forms.py12
-rw-r--r--tests/test_evaluator.py3
-rw-r--r--tests/test_reader.py4
-rw-r--r--tests/tokens.py38
102 files changed, 342 insertions, 122 deletions
diff --git a/.hypothesis/examples/17015ad1b47afd98/09a8a14f5f6826f2 b/.hypothesis/examples/17015ad1b47afd98/09a8a14f5f6826f2
new file mode 100644
index 0000000..85074f4
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/09a8a14f5f6826f2
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/0e88086df0517527 b/.hypothesis/examples/17015ad1b47afd98/0e88086df0517527
deleted file mode 100644
index 2bcc35b..0000000
--- a/.hypothesis/examples/17015ad1b47afd98/0e88086df0517527
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/.hypothesis/examples/17015ad1b47afd98/19bb68f9d92692f9 b/.hypothesis/examples/17015ad1b47afd98/19bb68f9d92692f9
new file mode 100644
index 0000000..05d7933
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/19bb68f9d92692f9
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/3ee6ff39f2ac6dea b/.hypothesis/examples/17015ad1b47afd98/3ee6ff39f2ac6dea
deleted file mode 100644
index 8da7f4b..0000000
--- a/.hypothesis/examples/17015ad1b47afd98/3ee6ff39f2ac6dea
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/49e6f38c5cc772ec b/.hypothesis/examples/17015ad1b47afd98/49e6f38c5cc772ec
deleted file mode 100644
index 5c100e8..0000000
--- a/.hypothesis/examples/17015ad1b47afd98/49e6f38c5cc772ec
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/56980d5ed7b87686 b/.hypothesis/examples/17015ad1b47afd98/56980d5ed7b87686
new file mode 100644
index 0000000..7361f5f
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/56980d5ed7b87686
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/5b55ec37559bb110 b/.hypothesis/examples/17015ad1b47afd98/5b55ec37559bb110
deleted file mode 100644
index 5e2ed41..0000000
--- a/.hypothesis/examples/17015ad1b47afd98/5b55ec37559bb110
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/.hypothesis/examples/17015ad1b47afd98/61b71c2df2d87966 b/.hypothesis/examples/17015ad1b47afd98/61b71c2df2d87966
new file mode 100644
index 0000000..d03d367
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/61b71c2df2d87966
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/69b43aa9ca8c9717 b/.hypothesis/examples/17015ad1b47afd98/69b43aa9ca8c9717
new file mode 100644
index 0000000..9398068
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/69b43aa9ca8c9717
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/745fc588673e7088 b/.hypothesis/examples/17015ad1b47afd98/745fc588673e7088
new file mode 100644
index 0000000..4a6a131
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/745fc588673e7088
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/79086a9d57f9948d b/.hypothesis/examples/17015ad1b47afd98/79086a9d57f9948d
new file mode 100644
index 0000000..460c58e
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/79086a9d57f9948d
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/8065c2327096a7a3 b/.hypothesis/examples/17015ad1b47afd98/8065c2327096a7a3
deleted file mode 100644
index fad8af1..0000000
--- a/.hypothesis/examples/17015ad1b47afd98/8065c2327096a7a3
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/8221fd2283c91e1f b/.hypothesis/examples/17015ad1b47afd98/8221fd2283c91e1f
new file mode 100644
index 0000000..7401b2e
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/8221fd2283c91e1f
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/8611cbd7e46390b8 b/.hypothesis/examples/17015ad1b47afd98/8611cbd7e46390b8
new file mode 100644
index 0000000..f906aa7
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/8611cbd7e46390b8
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/8b092171a745ad44 b/.hypothesis/examples/17015ad1b47afd98/8b092171a745ad44
new file mode 100644
index 0000000..6368d9d
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/8b092171a745ad44
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/.hypothesis/examples/17015ad1b47afd98/8ee2d9884de49d9a b/.hypothesis/examples/17015ad1b47afd98/8ee2d9884de49d9a
new file mode 100644
index 0000000..87376ae
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/8ee2d9884de49d9a
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/ae775858a7e56781 b/.hypothesis/examples/17015ad1b47afd98/ae775858a7e56781
deleted file mode 100644
index ec47c8b..0000000
--- a/.hypothesis/examples/17015ad1b47afd98/ae775858a7e56781
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/b0d0244d1f73df81 b/.hypothesis/examples/17015ad1b47afd98/b0d0244d1f73df81
new file mode 100644
index 0000000..ec53a8a
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/b0d0244d1f73df81
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/c92920944247d80c b/.hypothesis/examples/17015ad1b47afd98/c92920944247d80c
new file mode 100644
index 0000000..03afaa5
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/c92920944247d80c
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/.hypothesis/examples/17015ad1b47afd98/ddaf0ed54dfc227c b/.hypothesis/examples/17015ad1b47afd98/ddaf0ed54dfc227c
new file mode 100644
index 0000000..a786e12
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/ddaf0ed54dfc227c
Binary files differ
diff --git a/.hypothesis/examples/17015ad1b47afd98/df031fe309e7c5bf b/.hypothesis/examples/17015ad1b47afd98/df031fe309e7c5bf
new file mode 100644
index 0000000..6e595fc
--- /dev/null
+++ b/.hypothesis/examples/17015ad1b47afd98/df031fe309e7c5bf
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/.hypothesis/examples/641567e7f1117698/005f5867178a5b25 b/.hypothesis/examples/641567e7f1117698/005f5867178a5b25
new file mode 100644
index 0000000..99d1269
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/005f5867178a5b25
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/.hypothesis/examples/641567e7f1117698/0478b7c7ead9c10d b/.hypothesis/examples/641567e7f1117698/0478b7c7ead9c10d
new file mode 100644
index 0000000..893e09d
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/0478b7c7ead9c10d
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/1cd68f1893d28b93 b/.hypothesis/examples/641567e7f1117698/1cd68f1893d28b93
new file mode 100644
index 0000000..1e4c7a3
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/1cd68f1893d28b93
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/.hypothesis/examples/641567e7f1117698/1d14332589e1f360 b/.hypothesis/examples/641567e7f1117698/1d14332589e1f360
new file mode 100644
index 0000000..4b05fc7
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/1d14332589e1f360
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/1e7cf357b0153eda b/.hypothesis/examples/641567e7f1117698/1e7cf357b0153eda
deleted file mode 100644
index da412f0..0000000
--- a/.hypothesis/examples/641567e7f1117698/1e7cf357b0153eda
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/203107b3bbad5816 b/.hypothesis/examples/641567e7f1117698/203107b3bbad5816
new file mode 100644
index 0000000..406c80a
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/203107b3bbad5816
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/2bd9f6ed10af66c0 b/.hypothesis/examples/641567e7f1117698/2bd9f6ed10af66c0
new file mode 100644
index 0000000..938aced
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/2bd9f6ed10af66c0
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/2f69395da78f14d8 b/.hypothesis/examples/641567e7f1117698/2f69395da78f14d8
new file mode 100644
index 0000000..77a7ec0
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/2f69395da78f14d8
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/3923acd66c0b7e18 b/.hypothesis/examples/641567e7f1117698/3923acd66c0b7e18
deleted file mode 100644
index 70f3b85..0000000
--- a/.hypothesis/examples/641567e7f1117698/3923acd66c0b7e18
+++ /dev/null
@@ -1 +0,0 @@
-  \ No newline at end of file
diff --git a/.hypothesis/examples/641567e7f1117698/3c6c5c8e00e8affe b/.hypothesis/examples/641567e7f1117698/3c6c5c8e00e8affe
new file mode 100644
index 0000000..4943902
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/3c6c5c8e00e8affe
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/45f01200098f83fe b/.hypothesis/examples/641567e7f1117698/45f01200098f83fe
new file mode 100644
index 0000000..f38d7c8
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/45f01200098f83fe
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/5be455f23fea5189 b/.hypothesis/examples/641567e7f1117698/5be455f23fea5189
new file mode 100644
index 0000000..f4afa45
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/5be455f23fea5189
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/5e762c293b8926ea b/.hypothesis/examples/641567e7f1117698/5e762c293b8926ea
deleted file mode 100644
index cdf9180..0000000
--- a/.hypothesis/examples/641567e7f1117698/5e762c293b8926ea
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/5ec5c4954a59b6a4 b/.hypothesis/examples/641567e7f1117698/5ec5c4954a59b6a4
deleted file mode 100644
index e915073..0000000
--- a/.hypothesis/examples/641567e7f1117698/5ec5c4954a59b6a4
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/63399f455589d4ba b/.hypothesis/examples/641567e7f1117698/63399f455589d4ba
new file mode 100644
index 0000000..ab41705
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/63399f455589d4ba
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/6d688fd550d32db0 b/.hypothesis/examples/641567e7f1117698/6d688fd550d32db0
new file mode 100644
index 0000000..9e6d12c
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/6d688fd550d32db0
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/7f8faf9da637e86f b/.hypothesis/examples/641567e7f1117698/7f8faf9da637e86f
new file mode 100644
index 0000000..474cc5c
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/7f8faf9da637e86f
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/881b6ce80b5bd1fc b/.hypothesis/examples/641567e7f1117698/881b6ce80b5bd1fc
new file mode 100644
index 0000000..c8c74ca
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/881b6ce80b5bd1fc
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/a6039ffc453749e1 b/.hypothesis/examples/641567e7f1117698/a6039ffc453749e1
new file mode 100644
index 0000000..9878f1a
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/a6039ffc453749e1
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/b19b7b820dddb3c6 b/.hypothesis/examples/641567e7f1117698/b19b7b820dddb3c6
new file mode 100644
index 0000000..ecb949e
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/b19b7b820dddb3c6
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/b52e65a9e0e8f9db b/.hypothesis/examples/641567e7f1117698/b52e65a9e0e8f9db
new file mode 100644
index 0000000..cfd86fa
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/b52e65a9e0e8f9db
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/b6420ce3b52b1ab7 b/.hypothesis/examples/641567e7f1117698/b6420ce3b52b1ab7
deleted file mode 100644
index 798716b..0000000
--- a/.hypothesis/examples/641567e7f1117698/b6420ce3b52b1ab7
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/c17293c1c7f91651 b/.hypothesis/examples/641567e7f1117698/c17293c1c7f91651
new file mode 100644
index 0000000..29ce808
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/c17293c1c7f91651
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/cfb16a37ef90423b b/.hypothesis/examples/641567e7f1117698/cfb16a37ef90423b
new file mode 100644
index 0000000..6402578
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/cfb16a37ef90423b
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/d1f7b282fca409b2 b/.hypothesis/examples/641567e7f1117698/d1f7b282fca409b2
deleted file mode 100644
index 5d072ed..0000000
--- a/.hypothesis/examples/641567e7f1117698/d1f7b282fca409b2
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/ea786d015fba3bee b/.hypothesis/examples/641567e7f1117698/ea786d015fba3bee
new file mode 100644
index 0000000..23dcd5a
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/ea786d015fba3bee
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/f41cb651e160d454 b/.hypothesis/examples/641567e7f1117698/f41cb651e160d454
new file mode 100644
index 0000000..4f7bfb6
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/f41cb651e160d454
Binary files differ
diff --git a/.hypothesis/examples/641567e7f1117698/f7b6a134061a22a3 b/.hypothesis/examples/641567e7f1117698/f7b6a134061a22a3
new file mode 100644
index 0000000..f4de7f5
--- /dev/null
+++ b/.hypothesis/examples/641567e7f1117698/f7b6a134061a22a3
Binary files differ
diff --git a/.hypothesis/examples/c5004b86438ec8a9/a1a8c54704cd3ce5 b/.hypothesis/examples/c5004b86438ec8a9/a1a8c54704cd3ce5
new file mode 100644
index 0000000..ee13fd2
--- /dev/null
+++ b/.hypothesis/examples/c5004b86438ec8a9/a1a8c54704cd3ce5
Binary files differ
diff --git a/.hypothesis/examples/c72254ca7f2d3ae9/18c072a6c0de03a3 b/.hypothesis/examples/c72254ca7f2d3ae9/18c072a6c0de03a3
new file mode 100644
index 0000000..9d4e4f1
--- /dev/null
+++ b/.hypothesis/examples/c72254ca7f2d3ae9/18c072a6c0de03a3
Binary files differ
diff --git a/.hypothesis/examples/c72254ca7f2d3ae9/76c7ab7f4af319c7 b/.hypothesis/examples/c72254ca7f2d3ae9/76c7ab7f4af319c7
new file mode 100644
index 0000000..c28f678
--- /dev/null
+++ b/.hypothesis/examples/c72254ca7f2d3ae9/76c7ab7f4af319c7
Binary files differ
diff --git a/.hypothesis/examples/dc26b29be33957c5/3ac7fd17438f7df3 b/.hypothesis/examples/dc26b29be33957c5/3ac7fd17438f7df3
deleted file mode 100644
index 0419200..0000000
--- a/.hypothesis/examples/dc26b29be33957c5/3ac7fd17438f7df3
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/dc26b29be33957c5/4b5882e6feb52553 b/.hypothesis/examples/dc26b29be33957c5/4b5882e6feb52553
new file mode 100644
index 0000000..5c95675
--- /dev/null
+++ b/.hypothesis/examples/dc26b29be33957c5/4b5882e6feb52553
Binary files differ
diff --git a/.hypothesis/examples/dc26b29be33957c5/5b55ec37559bb110 b/.hypothesis/examples/dc26b29be33957c5/5b55ec37559bb110
deleted file mode 100644
index 5e2ed41..0000000
--- a/.hypothesis/examples/dc26b29be33957c5/5b55ec37559bb110
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/.hypothesis/examples/dc26b29be33957c5/c512123626a98914 b/.hypothesis/examples/dc26b29be33957c5/c512123626a98914
deleted file mode 100644
index 9388380..0000000
--- a/.hypothesis/examples/dc26b29be33957c5/c512123626a98914
+++ /dev/null
@@ -1 +0,0 @@
- \ No newline at end of file
diff --git a/.hypothesis/examples/dc26b29be33957c5/d6459ab29c7b9a9f b/.hypothesis/examples/dc26b29be33957c5/d6459ab29c7b9a9f
deleted file mode 100644
index 86906d2..0000000
--- a/.hypothesis/examples/dc26b29be33957c5/d6459ab29c7b9a9f
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/dc26b29be33957c5/ee3ad785c37b610d b/.hypothesis/examples/dc26b29be33957c5/ee3ad785c37b610d
new file mode 100644
index 0000000..81d5bc2
--- /dev/null
+++ b/.hypothesis/examples/dc26b29be33957c5/ee3ad785c37b610d
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/00d874a28a65de9b b/.hypothesis/examples/ec453dcb33aa8b66/00d874a28a65de9b
new file mode 100644
index 0000000..97fbfa6
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/00d874a28a65de9b
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/0c69f7daba8b9b86 b/.hypothesis/examples/ec453dcb33aa8b66/0c69f7daba8b9b86
new file mode 100644
index 0000000..9034b55
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/0c69f7daba8b9b86
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/0f42e404bef2b1a3 b/.hypothesis/examples/ec453dcb33aa8b66/0f42e404bef2b1a3
new file mode 100644
index 0000000..1471346
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/0f42e404bef2b1a3
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/16bceb1530a91002 b/.hypothesis/examples/ec453dcb33aa8b66/16bceb1530a91002
deleted file mode 100644
index 2e7651b..0000000
--- a/.hypothesis/examples/ec453dcb33aa8b66/16bceb1530a91002
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/207b79c0dd1b6fba b/.hypothesis/examples/ec453dcb33aa8b66/207b79c0dd1b6fba
new file mode 100644
index 0000000..6345bd4
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/207b79c0dd1b6fba
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/218d87f650043d4d b/.hypothesis/examples/ec453dcb33aa8b66/218d87f650043d4d
new file mode 100644
index 0000000..cfd6a40
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/218d87f650043d4d
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/275df7aaf0e8504b b/.hypothesis/examples/ec453dcb33aa8b66/275df7aaf0e8504b
new file mode 100644
index 0000000..235b250
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/275df7aaf0e8504b
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/28a055f3278de950 b/.hypothesis/examples/ec453dcb33aa8b66/28a055f3278de950
new file mode 100644
index 0000000..bfce649
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/28a055f3278de950
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/29a465ca925a55c2 b/.hypothesis/examples/ec453dcb33aa8b66/29a465ca925a55c2
new file mode 100644
index 0000000..1a9248f
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/29a465ca925a55c2
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/36d7ba28eb961f14 b/.hypothesis/examples/ec453dcb33aa8b66/36d7ba28eb961f14
new file mode 100644
index 0000000..bd1fa9b
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/36d7ba28eb961f14
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/3b15208ee23b0387 b/.hypothesis/examples/ec453dcb33aa8b66/3b15208ee23b0387
new file mode 100644
index 0000000..0bbbf2f
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/3b15208ee23b0387
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/3be6ee08630f7415 b/.hypothesis/examples/ec453dcb33aa8b66/3be6ee08630f7415
new file mode 100644
index 0000000..da37579
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/3be6ee08630f7415
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/41d22663c8456cf1 b/.hypothesis/examples/ec453dcb33aa8b66/41d22663c8456cf1
new file mode 100644
index 0000000..8ed04c1
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/41d22663c8456cf1
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/4566df4571cae443 b/.hypothesis/examples/ec453dcb33aa8b66/4566df4571cae443
new file mode 100644
index 0000000..1e11405
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/4566df4571cae443
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/51ab005a386f8742 b/.hypothesis/examples/ec453dcb33aa8b66/51ab005a386f8742
new file mode 100644
index 0000000..6af7a69
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/51ab005a386f8742
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/52f15fc15e039804 b/.hypothesis/examples/ec453dcb33aa8b66/52f15fc15e039804
new file mode 100644
index 0000000..11037b4
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/52f15fc15e039804
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/56622e534f8c66db b/.hypothesis/examples/ec453dcb33aa8b66/56622e534f8c66db
new file mode 100644
index 0000000..97c0daf
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/56622e534f8c66db
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/5bcf6972d8812615 b/.hypothesis/examples/ec453dcb33aa8b66/5bcf6972d8812615
deleted file mode 100644
index f677871..0000000
--- a/.hypothesis/examples/ec453dcb33aa8b66/5bcf6972d8812615
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/5e1b75e52e4472a7 b/.hypothesis/examples/ec453dcb33aa8b66/5e1b75e52e4472a7
new file mode 100644
index 0000000..47ff157
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/5e1b75e52e4472a7
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/619a0adc5abca17e b/.hypothesis/examples/ec453dcb33aa8b66/619a0adc5abca17e
deleted file mode 100644
index 3436347..0000000
--- a/.hypothesis/examples/ec453dcb33aa8b66/619a0adc5abca17e
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/b2d7ebd146f76d3d b/.hypothesis/examples/ec453dcb33aa8b66/b2d7ebd146f76d3d
new file mode 100644
index 0000000..5ed6ebb
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/b2d7ebd146f76d3d
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/b691cacbafa2b728 b/.hypothesis/examples/ec453dcb33aa8b66/b691cacbafa2b728
new file mode 100644
index 0000000..2502421
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/b691cacbafa2b728
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/bdff285d783ed32f b/.hypothesis/examples/ec453dcb33aa8b66/bdff285d783ed32f
new file mode 100644
index 0000000..0c77431
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/bdff285d783ed32f
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/f01e2bfd10c9b16e b/.hypothesis/examples/ec453dcb33aa8b66/f01e2bfd10c9b16e
new file mode 100644
index 0000000..9fb6e87
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/f01e2bfd10c9b16e
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/f41ac3052b176061 b/.hypothesis/examples/ec453dcb33aa8b66/f41ac3052b176061
new file mode 100644
index 0000000..683ea2e
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/f41ac3052b176061
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/f635e57ce2b75454 b/.hypothesis/examples/ec453dcb33aa8b66/f635e57ce2b75454
new file mode 100644
index 0000000..d3ef683
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/f635e57ce2b75454
Binary files differ
diff --git a/.hypothesis/examples/ec453dcb33aa8b66/faf1cd4bdf2d5926 b/.hypothesis/examples/ec453dcb33aa8b66/faf1cd4bdf2d5926
new file mode 100644
index 0000000..135723e
--- /dev/null
+++ b/.hypothesis/examples/ec453dcb33aa8b66/faf1cd4bdf2d5926
Binary files differ
diff --git a/.hypothesis/examples/ef6354fc2348e0ad/2d0134ed3b9de132 b/.hypothesis/examples/ef6354fc2348e0ad/2d0134ed3b9de132
new file mode 100644
index 0000000..f8fa5a2
--- /dev/null
+++ b/.hypothesis/examples/ef6354fc2348e0ad/2d0134ed3b9de132
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/.hypothesis/examples/ef6354fc2348e0ad/54d00d52177f7dc5 b/.hypothesis/examples/ef6354fc2348e0ad/54d00d52177f7dc5
deleted file mode 100644
index 1fa7e76..0000000
--- a/.hypothesis/examples/ef6354fc2348e0ad/54d00d52177f7dc5
+++ /dev/null
Binary files differ
diff --git a/.hypothesis/examples/ef6354fc2348e0ad/5d1be7e9dda1ee88 b/.hypothesis/examples/ef6354fc2348e0ad/5d1be7e9dda1ee88
new file mode 100644
index 0000000..303e398
--- /dev/null
+++ b/.hypothesis/examples/ef6354fc2348e0ad/5d1be7e9dda1ee88
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/.hypothesis/examples/ef6354fc2348e0ad/a42c6cf1de3abfde b/.hypothesis/examples/ef6354fc2348e0ad/a42c6cf1de3abfde
new file mode 100644
index 0000000..45a8ca0
--- /dev/null
+++ b/.hypothesis/examples/ef6354fc2348e0ad/a42c6cf1de3abfde
@@ -0,0 +1 @@
+ \ No newline at end of file
diff --git a/.hypothesis/examples/ef6354fc2348e0ad/e7faf0b097a6f469 b/.hypothesis/examples/ef6354fc2348e0ad/e7faf0b097a6f469
new file mode 100644
index 0000000..cf2a103
--- /dev/null
+++ b/.hypothesis/examples/ef6354fc2348e0ad/e7faf0b097a6f469
Binary files differ
diff --git a/actinide/__init__.py b/actinide/__init__.py
index 0f09299..b6ace49 100644
--- a/actinide/__init__.py
+++ b/actinide/__init__.py
@@ -5,6 +5,7 @@ class BaseSession(object):
def __init__(self):
self.symbols = symbol_table.SymbolTable()
self.environment = evaluator.Environment()
+ self.macros = evaluator.Environment()
self.core_builtins()
self.standard_library()
@@ -14,9 +15,9 @@ class BaseSession(object):
return reader.read(port, self.symbols)
def eval(self, form):
- form = expander.expand(form, self.symbols)
+ form = expander.expand(form, self.symbols, self.macros)
cps = evaluator.eval(form, self.symbols, None)
- return evaluator.run(cps, self.environment)
+ return evaluator.run(cps, self.environment, self.macros)
def run(self, port):
form = self.read(port)
@@ -56,17 +57,10 @@ class BaseSession(object):
symb = types.symbol(symb, self.symbols)
return symb
- def core_builtins(self):
- self.bind_module(core)
-
- def standard_library(self):
- pass
+ def display(self, form):
+ return types.display(form, self.symbols)
-class Session(BaseSession):
- def standard_library(self):
- @self.bind_fn
- def symbol(val):
- return types.symbol(val, self.symbols)
+ def core_builtins(self):
@self.bind_fn
def read(port):
return reader.read(port, self.symbols)
@@ -76,6 +70,17 @@ class Session(BaseSession):
@self.bind_fn
def expand(form):
return expander.expand(form, self.symbols)
+ @self.bind_fn
+ def symbol(val):
+ return types.symbol(val, self.symbols)
self.bind_module(types)
+ self.bind_module(core)
+ self.bind_fn(self.display)
+
+ def standard_library(self):
+ pass
+
+class Session(BaseSession):
+ def standard_library(self):
self.bind_module(stdlib)
self.bind_module(ports)
diff --git a/actinide/evaluator.py b/actinide/evaluator.py
index 042f4b0..89878f8 100644
--- a/actinide/evaluator.py
+++ b/actinide/evaluator.py
@@ -44,9 +44,9 @@ from . import types as t
# The result of evaluating a continuation is always a Python tuple. For
# expressions, this tuple contains the value(s) produced by the expression. For
# forms which do not produce a value, this returns the empty tuple.
-def run(continuation, environment, args=()):
+def run(continuation, env, macros, args=()):
while continuation is not None:
- continuation, environment, *args = continuation(environment, *args)
+ continuation, env, macros, *args = continuation(env, macros, *args)
return tuple(args)
# ## FLAT CONTINUATIONS
@@ -57,13 +57,20 @@ def run(continuation, environment, args=()):
# Returns a continuation which yields a single value, verbatim, and chains to a
# known target continuation. This implements evaluation for literals.
def literal(value, continuation):
- return lambda environment: (continuation, environment, value)
+ return lambda env, macros: (continuation, env, macros, value)
# Returns a continuation which looks up a symbol in an environment, yields the
# result, and chains to a known target continuation. This implements evaluation
# for variable lookups.
def symbol(symb, continuation):
- return lambda environment: (continuation, environment, environment.find(symb))
+ return lambda env, macros: (continuation, env, macros, env.find(symb))
+
+# Unquotes the tail of a quoted form, yielding the form as a literal value
+# before chaining to the known target continuation. This implements unquoting of
+# quoted forms.
+def quote(quoted, continuation):
+ value, = t.flatten(quoted)
+ return literal(value, continuation)
# Returns a continuation which yields a newly-created procedure, and chains to a
# known target continuation. This implements evaluation for the tail of a lambda
@@ -72,37 +79,43 @@ def symbol(symb, continuation):
def lambda_(defn, symbols, continuation):
formals = t.flatten(t.head(defn))
body = t.head(t.tail(defn))
- def lambda__(environment):
- proc = t.Procedure(body, formals, environment, symbols)
- return (continuation, environment, proc)
+ def lambda__(env, macros):
+ proc = t.Procedure(body, formals, env, macros, symbols)
+ return (continuation, env, macros, proc)
return lambda__
# Returns a continuation which takes a value and binds that value to a symbol in
# a specific environment, then chains to a known target continuation. This
# implements evaluation of the `define` special form, once the value is known.
def bind(symbol, continuation):
- def bind_(environment, value):
- environment.define(symbol, value)
- return (continuation, environment)
+ def bind_(env, macros, value):
+ env.define(symbol, value)
+ return (continuation, env, macros)
return bind_
+def macro_bind(symbol, continuation):
+ def macro_bind_(env, macros, value):
+ macros.define(symbol, value)
+ return (continuation, env, macros)
+ return macro_bind_
+
# Returns a continuation which takes a value and returns one of two known target
# continuations based on the value. If the value is true (Python truthy), this
# chains to the `on_true` continuation. If the value is not true (Python falsy),
# this chains to the `on_false` continuation. In either case, the continuation
# not chained to is discarded.
def branch(on_true, on_false):
- return lambda environment, val: (on_true if val else on_false, environment)
+ return lambda env, macros, val: (on_true if val else on_false, env, macros)
# Returns a continuation which receives values, and appends them to the values
# passed to this factory, before chaining to a known target continuation. This
# implements intermediate evaluation of list forms, where part of the list is
# already known, as well as splicing for forms that yield multiple values.
def append(args, continuation):
- return lambda environment, *tail: (continuation, environment, *args, *tail)
+ return lambda env, macros, *tail: (continuation, env, macros, *args, *tail)
def begin(continuation):
- return lambda environment, *args: (continuation, environment, *(args[-1:] if args else ()))
+ return lambda env, macros, *args: (continuation, env, macros, *(args[-1:] if args else ()))
# Transforms a continuation which should receive function results into a
# function call continuation. A function call continuation receives a function
@@ -111,20 +124,21 @@ def begin(continuation):
# If the function is a procedure, this instead returns a continuation which will
# invoke the procedure, then chain to the wrapped continuation.
def invoke(continuation):
- def invoke_(environment, fn, *args):
+ def invoke_(env, macros, fn, *args):
if isinstance(fn, t.Procedure):
- return procedure_call(environment, fn, *args)
- return builtin(environment, fn, *args)
+ return procedure_call(env, macros, fn, *args)
+ return builtin(env, macros, fn, *args)
- def procedure_call(environment, fn, *args):
+ def procedure_call(env, macros, fn, *args):
call_env = fn.invocation_environment(*args)
+ call_macros = Environment(parent=macros)
call_cont = fn.continuation
- return_cont = tail_graft(continuation, environment, call_cont)
- return (return_cont, call_env)
+ return_cont = tail_graft(continuation, env, macros, call_cont)
+ return (return_cont, call_env, call_macros)
- def builtin(environment, fn, *args):
+ def builtin(env, macros, fn, *args):
result = fn(*args)
- return (continuation, environment, *result)
+ return (continuation, env, macros, *result)
return invoke_
# Continuation transformer. Given a guarded continuation, and a graft
@@ -136,17 +150,20 @@ def invoke(continuation):
# continuation chains to None, the guard replaces the returned continuation and
# environment with the graft continuation and environment. This handles
# environment restoration after a function call.
-def tail_graft(continuation, environment, guarded):
+def tail_graft(continuation, environment, macros, guarded):
# Tail call magic: if we're not going to transition to another continuation,
# don't bother grafting environment recovery on.
if continuation is None:
return guarded
- def guard(env, *args):
- next, env, *args = guarded(env, *args)
+ def guard(env, macros, *args):
+ next, env, macros, *args = guarded(env, macros, *args)
if next is None:
- return (continuation, environment, *args)
- return (tail_graft(continuation, environment, next), env, *args)
+ return (continuation, environment, macros, *args)
+ return (
+ tail_graft(continuation, environment, macros, next),
+ env, macros, *args,
+ )
return guard
@@ -171,9 +188,13 @@ def eval(value, symbols, continuation):
if t.head(value) == symbols['if']:
return if_(t.tail(value), symbols, continuation)
if t.head(value) == symbols['define']:
- return define(t.tail(value), symbols, continuation)
+ return define(t.tail(value), symbols, continuation, bind)
+ if t.head(value) == symbols['defmacro']:
+ return define(t.tail(value), symbols, continuation, macro_bind)
if t.head(value) == symbols['lambda']:
return lambda_(t.tail(value), symbols, continuation)
+ if t.head(value) == symbols['quote']:
+ return quote(t.tail(value), continuation)
if t.head(value) == symbols['begin']:
return apply(t.tail(value), symbols, begin(continuation))
# Ran out of alternatives, must be a function application
@@ -185,7 +206,7 @@ def eval(value, symbols, continuation):
# continuation`. The result of this evaluation is chained to a `bind`
# continuation, to store the result of evaluation in the target environment.
# Finally, the `bind` continuation chains to the target continuation.
-def define(value, symbols, continuation):
+def define(value, symbols, continuation, bind):
symb, expr = t.flatten(value)
if not t.symbol_p(symb):
@@ -193,7 +214,7 @@ def define(value, symbols, continuation):
bind_cont = bind(symb, continuation)
eval_cont = eval(expr, symbols, bind_cont)
- return lambda environment: (eval_cont, environment)
+ return lambda env, macros: (eval_cont, env, macros)
# Returns a continuation which fully evaluates an `(if cond if-true if-false)`
# form, before chaining to a known target continuation. First, the returned
@@ -219,9 +240,9 @@ def if_(value, symbols, continuation):
# calling `apply` on the tail of the list.
def apply(list, symbols, continuation):
if t.nil_p(list):
- return lambda environment, *args: (continuation, environment, *args)
+ return lambda env, macros, *args: (continuation, env, macros, *args)
tail_cont = apply(t.tail(list), symbols, continuation)
- return lambda environment, *args: (
+ return lambda env, macros, *args: (
eval(t.head(list), symbols, append(args, tail_cont)),
- environment,
+ env, macros,
)
diff --git a/actinide/expander.py b/actinide/expander.py
index b8bc56d..a72a64e 100644
--- a/actinide/expander.py
+++ b/actinide/expander.py
@@ -2,6 +2,10 @@
from .types import *
+# Raised if expansion of a form fails.
+class ExpansionError(Exception):
+ pass
+
# Expand and syntax-check a form.
#
# This replaces shorthand notations, such as ``(define (a b c) body)``, with
@@ -9,26 +13,118 @@ from .types import *
#
# Because this deals with unevaluated programs, this algorithm can safely
# recurse: the input depth simply isn't that large.
-def expand(form, symbols):
- if nil_p(form) or not list_p(form):
+def expand(form, symbols, macros):
+ if nil_p(form) or not cons_p(form):
return form
- # huge cheat. Working with python lists is hugely easier for this than
- # working with conses, and it's after midnight. Flatten the form, expand it,
- # and reconstitute it. This incurs two bonus copies per form: suck it up.
- symb, *args = flatten(form)
- if symb == symbols['if'] and len(args) == 2:
- args.append(None)
- elif symb == symbols['define']:
- decl, *body = args
- if list_p(decl):
- decl = flatten(decl)
- name, *formals = decl
- lambda_ = list(symbols['lambda'], list(*formals), *body)
- args = [name, lambda_]
- elif symb == symbols['lambda']:
- formals, *body = args
- if len(body) != 1:
- body = [list(symbols['begin'], *body)]
- args = [formals, *body]
- form = list(expand(symb, symbols), *[expand(subform, symbols) for subform in args])
+ if head(form) == symbols['if']:
+ form = expand_if(form)
+ elif head(form) == symbols['define']:
+ form = expand_define(form, symbols)
+ elif head(form) == symbols['defmacro']:
+ form = expand_define(form, symbols)
+ elif head(form) == symbols['lambda']:
+ form = expand_lambda(form, symbols)
+ elif head(form) == symbols['quasiquote']:
+ form = expand_quasiquote(form, symbols)
+ elif symbol_p(head(form)) and head(form) in macros:
+ form = expand_macro(form, symbols, macros)
+ form = expand_subforms(form, symbols, macros)
return form
+
+# Recursively expand subforms in an already-expanded top-level form.
+def expand_subforms(list, symbols, macros):
+ if nil_p(list):
+ return nil
+ if not cons_p(list):
+ return expand_subforms(list, symbols, macros)
+ head, tail = uncons(list)
+ return cons(
+ expand(head, symbols, macros),
+ expand_subforms(tail, symbols, macros),
+ )
+
+# Expand an `if` form.
+#
+# (if COND TRUE)
+# => (if COND TRUE nil)
+def expand_if(form):
+ head, form = uncons(form)
+ cond, form = uncons(form)
+ true, form = uncons(form)
+ if nil_p(form):
+ return list(head, cond, true, None)
+ false, form = uncons(form)
+ return list(head, cond, true, false)
+
+# Expand a define or defmacro form.
+#
+# (define (NAME FORMALS) BODY)
+# => (define name (lambda FORMALS BODY))
+def expand_define(form, symbols):
+ head, form = uncons(form)
+ symb, form = uncons(form)
+ if cons_p(symb):
+ return expand_lambda_define(head, symb, form, symbols)
+ val, form = uncons(form)
+ return list(head, symb, val)
+
+def expand_lambda_define(head, symb, body, symbols):
+ name, formals = uncons(symb)
+ return list(head, name, cons(symbols['lambda'], cons(formals, body)))
+
+# Expands a lambda.
+#
+# (lambda FORMALS FORM)
+# => unchanged
+# (lambda FORMALS)
+# => (lambda FORMALS (begin))
+# (lambda FORMALS FORM ...FORMS)
+# => (lambda FORMALS (begin FORM ...FORMS))
+def expand_lambda(form, symbols):
+ head, form = uncons(form)
+ formals, form = uncons(form)
+ # XXX check formals
+ if cons_p(form) and not nil_p(tail(form)):
+ form = list(cons(symbols['begin'], form))
+ return cons(head, cons(formals, form))
+
+# Expands a quasiquote, recursively, expanding unquotes as needed.
+def expand_quasiquote(form, symbols):
+ head, form = uncons(form)
+ body, form = uncons(form)
+ return expand_quasiquoted(body, symbols)
+
+def expand_quasiquoted(form, symbols):
+ if nil_p(form):
+ return form
+ if not cons_p(form):
+ return list(symbols['quote'], form)
+ first, rest = uncons(form)
+ if first == symbols['unquote']:
+ next, rest = uncons(rest)
+ return next
+ if not nil_p(first) and cons_p(first):
+ candidate, body = uncons(first)
+ if candidate == symbols['unquote-splicing']:
+ next, rest = uncons(body)
+ return list(
+ symbols['append'],
+ next,
+ expand_quasiquoted(body, symbols),
+ )
+ return list(
+ symbols['cons'],
+ expand_quasiquoted(first, symbols),
+ expand_quasiquoted(rest, symbols),
+ )
+
+# Expands macro definitions, iterating until no further expansion is possible.
+def expand_macro(form, symbols, macros):
+ macro, args = uncons(form)
+ macro_body = macros[macro]
+ args = flatten(args)
+ expansion, = macro_body(*args)
+ return expand(expansion, symbols, macros)
+
+def uncons(value):
+ return head(value), tail(value)
diff --git a/actinide/reader.py b/actinide/reader.py
index f7703b5..9c21beb 100644
--- a/actinide/reader.py
+++ b/actinide/reader.py
@@ -32,7 +32,7 @@ def read(port, symbols):
raise SyntaxError("Unexpected ')'")
if head == '(':
return read_list(port, symbols)
- return read_atom(head, symbols)
+ return read_atom(head, port, symbols)
# Reads the body of a list from a port. This will read forms, recursively, until
# it encounters the terminating ``)`` that closes the current list, or until it
@@ -53,7 +53,7 @@ def read_list(port, symbols):
read_list_tail(port, symbols),
)
return cons(
- read_atom(head, symbols),
+ read_atom(head, port, symbols),
read_list_tail(port, symbols),
)
@@ -74,7 +74,7 @@ def read_list_tail(port, symbols):
if head == '.':
return read_cons_head(port, symbols)
return cons(
- read_atom(head, symbols),
+ read_atom(head, port, symbols),
read_list_tail(port, symbols),
)
@@ -92,7 +92,7 @@ def read_cons_head(port, symbols):
port,
symbols,
)
- return read_cons_tail(read_atom(head, symbols), port, symbols)
+ return read_cons_tail(read_atom(head, port, symbols), port, symbols)
# Reads the second form of a dotted pair from the input. This must either be a
# terminating ``)``, or another dotted pair.
@@ -116,14 +116,28 @@ def read_cons_tail(head, port, symbols):
# * ``read_decimal``
# * ``read_symbol`` in the current symbol table (which always succeeds)
#
+# This also reconstructs quoted forms.
+#
# The first reader to accept the string determines the type of the result.
-def read_atom(atom, symbols):
+quotes = {
+ "'": 'quote',
+ "`": 'quasiquote',
+ ",": 'unquote',
+ ",@": 'unquote-splicing',
+}
+def read_atom(atom, port, symbols):
def read_as_first(val, *funcs):
for func in funcs:
result = func(val)
if result is not None:
return result
+ if atom in quotes:
+ quoted = read(port, symbols)
+ if quoted == EOF:
+ raise SyntaxError("Unexpected end of input")
+ return list(symbols[quotes[atom]], quoted)
+
if atom[0] == '"':
return read_string(atom)
return read_as_first(
diff --git a/actinide/tokenizer.py b/actinide/tokenizer.py
index 449fc3d..b17bb48 100644
--- a/actinide/tokenizer.py
+++ b/actinide/tokenizer.py
@@ -44,6 +44,13 @@ class TokenError(Exception):
'''
pass
+whitespace = " \n\t"
+parens = "()"
+quotes = "'`," # ,@ is also a quote, but not a single-character quote
+comment_delim = ';'
+string_delim = '"'
+string_escaped = '"\\'
+
# Read one token from a port.
#
# This is the top-level driver for the state machine that divides the underlying
@@ -73,11 +80,13 @@ def tokenize_any(port):
lookahead = peek_next(port)
if lookahead == '':
return None, tokenize_eof
- if lookahead == ';':
+ if lookahead in comment_delim:
return None, tokenize_comment
- if lookahead in '()':
+ if lookahead in parens:
return None, tokenize_syntax
- if lookahead in ' \t\n':
+ if lookahead in quotes:
+ return None, tokenize_quote
+ if lookahead in whitespace:
return None, tokenize_whitespace
return None, tokenize_atom
@@ -105,6 +114,20 @@ def tokenize_comment(port):
return None, tokenize_any
return None, tokenize_comment
+def tokenize_quote(port):
+ next = read_next(port)
+ if next == ',':
+ return None, tokenize_unquote(next)
+ return next, tokenize_any
+
+def tokenize_unquote(state):
+ def tokenize_unquote_next(port):
+ next = peek_next(port)
+ if next == '@':
+ return state + read_next(port), tokenize_any
+ return state, tokenize_any
+ return tokenize_unquote_next
+
# Consumes one character, returning it as a token, before transitioning back to
# the ``tokenize_any`` state. This correctly tokenizes the ``(`` and ``)``
# tokens if they are at the front of the port.
@@ -206,9 +229,7 @@ def tokenize_escaped_string_character(state):
next = read_next(port)
if next == '':
raise TokenError('Unclosed string literal')
- if next in '\\"':
- return None, tokenize_string_character(state + next)
- raise TokenError(f"Invalid string escape '\\{next}'")
+ return None, tokenize_string_character(state + next)
return tokenize_escaped_string_character_next
# A state factory which terminates a string literal. These states read off the
diff --git a/actinide/types.py b/actinide/types.py
index b5b87cd..17f7a3f 100644
--- a/actinide/types.py
+++ b/actinide/types.py
@@ -27,7 +27,6 @@ def nil_p(value):
def read_nil(value):
return nil
-@fn
def display_nil(value):
return '()'
@@ -50,7 +49,6 @@ def read_boolean(value):
return false
return None
-@fn
def display_boolean(value):
return '#t' if value else '#f'
@@ -73,7 +71,6 @@ def read_integer(value):
except ValueError:
return nil
-@fn
def display_integer(value):
return str(value)
@@ -94,7 +91,6 @@ def read_decimal(value):
except InvalidOperation:
return nil
-@fn
def display_decimal(value):
return str(value)
@@ -115,7 +111,6 @@ def read_string(value):
value = value.replace('\\\\', '\\')
return value
-@fn
def display_string(value):
value = value.replace('\\', '\\\\')
value = value.replace('"', '\\"')
@@ -148,7 +143,6 @@ def symbol_p(value):
def read_symbol(value, symbol_table):
return symbol(value, symbol_table)
-@fn
def display_symbol(value):
return str(value)
@@ -174,15 +168,14 @@ def head(cons):
def tail(cons):
return cons.tail
-@fn
-def display_cons(value):
+def display_cons(value, symbols):
parts = []
while cons_p(value):
- parts.append(display(head(value)))
+ parts.append(display(head(value), symbols))
value = tail(value)
if not nil_p(value):
parts.append('.')
- parts.append(display(value))
+ parts.append(display(value, symbols))
return '(' + ' '.join(parts) + ')'
# ### Lists
@@ -199,6 +192,23 @@ def list(*elems):
def list_p(value):
return nil_p(value) or cons_p(value) and list_p(tail(value))
+@fn
+def append(list, *lists):
+ if not lists:
+ return list
+ if nil_p(list):
+ return append(*lists)
+ value, next = head(list), tail(list)
+ return cons(value, append(next, *lists))
+
+@fn
+def len(list):
+ l = 0
+ while not nil_p(list):
+ l += 1
+ list = tail(list)
+ return l
+
def flatten(list):
r = []
while not nil_p(list):
@@ -209,15 +219,17 @@ def flatten(list):
# ### Procedures
class Procedure(object):
- def __init__(self, body, formals, environment, symbols):
+ def __init__(self, body, formals, environment, macros, symbols):
self.body = body
self.continuation = e.eval(body, symbols, None)
self.formals = formals
self.environment = environment
+ self.macros = macros
def __call__(self, *args):
call_env = self.invocation_environment(*args)
- return e.run(self.continuation, call_env, ())
+ call_macros = Environment(parent=self.macros)
+ return e.run(self.continuation, call_env, call_macros, ())
def invocation_environment(self, *args):
return Environment(zip(self.formals, args), self.environment)
@@ -226,19 +238,21 @@ class Procedure(object):
def procedure_p(value):
return callable(value)
-@fn
-def display_procedure(proc):
+def display_procedure(proc, symbols):
if isinstance(proc, Procedure):
- formals = ' '.join(display(formal) for formal in proc.formals)
- body = display(proc.body)
+ formals = ' '.join(display(formal, symbols) for formal in proc.formals)
+ body = display(proc.body, symbols)
return f'<procedure: (lambda ({formals}) {body})>'
return f'<builtin: {proc.__name__}>'
# ### General-purpose functions
-@fn
-def display(value):
+
+# Bind manually, fixing the symbol table at the bind site
+def display(value, symbols):
+ if quote_p(value, symbols):
+ return display_quote(value, symbols)
if cons_p(value):
- return display_cons(value)
+ return display_cons(value, symbols)
if symbol_p(value):
return display_symbol(value)
if string_p(value):
@@ -252,6 +266,25 @@ def display(value):
if decimal_p(value):
return display_decimal(value)
if procedure_p(value):
- return display_procedure(value)
+ return display_procedure(value, symbols)
# Give up and use repr to avoid printing `None`.
return repr(value)
+
+def quote_p(value, symbols):
+ return cons_p(value) and head(value) in [
+ symbols[q]
+ for q in ['quote', 'quasiquote', 'unquote', 'unquote-splicing']
+ ]
+
+def display_quote(value, symbols):
+ quote, form = flatten(value)
+ if quote == symbols['quote']:
+ return "'" + display(form, symbols)
+ if quote == symbols['quasiquote']:
+ return "`" + display(form, symbols)
+ if quote == symbols['unquote']:
+ return "," + display(form, symbols)
+ if quote == symbols['unquote-splicing']:
+ return ",@" + display(form, symbols)
+ # emergency fallback
+ return display_cons(value, symbols)
diff --git a/bin/actinide-repl b/bin/actinide-repl
index c4343b6..9b66891 100755
--- a/bin/actinide-repl
+++ b/bin/actinide-repl
@@ -17,7 +17,7 @@ def repl(session, port):
print()
return 0
results = session.eval(form)
- print(*(at.display(result) for result in results))
+ print(*(session.display(result) for result in results))
except Exception as e:
print(e)
except KeyboardInterrupt:
diff --git a/primer.py b/primer.py
new file mode 100644
index 0000000..6954bea
--- /dev/null
+++ b/primer.py
@@ -0,0 +1,10 @@
+import actinide as a
+import actinide.types as t
+import actinide.expander as x
+
+s = a.Session()
+
+def expand(form):
+ return x.expand(form, s.symbols, s.macros)
+
+s.macros[s.symbol('twice')] = lambda f: (t.list(f, f),)
diff --git a/tests/forms.py b/tests/forms.py
index 1a49636..7ea216f 100644
--- a/tests/forms.py
+++ b/tests/forms.py
@@ -1,6 +1,7 @@
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 import tokenizer as t
from actinide.symbol_table import *
from actinide.types import *
@@ -37,7 +38,7 @@ def strings():
# 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();"')
+ return characters(blacklist_characters='01234567890#' + t.whitespace + t.parens + t.quotes + t.string_delim + t.comment_delim)
# Generates symbols guaranteed not to conflict with other kinds of literal. This
# is a subset of the legal symbols.
@@ -45,6 +46,15 @@ def symbols():
return text(symbol_characters(), min_size=1)\
.map(lambda item: symbol_table[item])
+def quoted_forms():
+ return tuples(
+ one_of(
+ symbol_table[q]
+ for q in ['quote', 'quasiquote', 'unquote', 'unquote-splicing']
+ ),
+ deferred(lambda: forms),
+ ).map(lambda elems: list(*elems))
+
# Generates atoms.
def atoms():
return one_of(
diff --git a/tests/test_evaluator.py b/tests/test_evaluator.py
index dbccbce..cb7c11c 100644
--- a/tests/test_evaluator.py
+++ b/tests/test_evaluator.py
@@ -13,6 +13,7 @@ from .programs import *
def test_evaluator(program_result):
program, result, bindings = program_result
environment = Environment()
- assert run(eval(program, symbol_table, None), environment) == result
+ macros = Environment()
+ assert run(eval(program, symbol_table, None), environment, macros) == result
for symbol, value in bindings:
assert environment[symbol] == value
diff --git a/tests/test_reader.py b/tests/test_reader.py
index 54a1681..b67c05e 100644
--- a/tests/test_reader.py
+++ b/tests/test_reader.py
@@ -12,7 +12,7 @@ from .forms import *
# * Given a form, can the reader recover it from its display?
@given(forms())
def test_reader(form):
- input = display(form)
+ input = display(form, symbol_table)
port = string_to_input_port(input)
assert read(port, symbol_table) == form
@@ -21,7 +21,7 @@ def test_reader(form):
# without touching the garbage? This is only reliable with lists and conses.
@given(lists() | conses(), text())
def test_reader_with_trailing(form, text):
- input = display(form) + text
+ input = display(form, symbol_table) + text
port = string_to_input_port(input)
assert read(port, symbol_table) == form
diff --git a/tests/tokens.py b/tests/tokens.py
index 3eb58b8..0e98494 100644
--- a/tests/tokens.py
+++ b/tests/tokens.py
@@ -1,23 +1,29 @@
from hypothesis.strategies import just, one_of, characters, text, lists, tuples
from hypothesis.strategies import composite, recursive
+from actinide import tokenizer as t
+
# Generators for token families
-# Generates the `(` token.
-def open_parens():
- return just('(')
+# Generates the `(` and ')' tokens.
+def parens():
+ return one_of(just(p) for p in t.parens)
-# Generates the ')' token.
-def close_parens():
- return just(')')
+def quotes():
+ return one_of(
+ just("'"),
+ just('`'),
+ just(','),
+ just(',@'),
+ )
# Generates characters that are legal, unescaped, inside of a string.
def string_bare_characters():
- return characters(blacklist_characters='\\"')
+ return characters(blacklist_characters=t.string_escaped)
# Generates legal string escape sequences.
def string_escaped_characters():
- return one_of(just('"'), just('\\')).map(lambda c: '\\' + c)
+ return one_of(just(c) for c in t.string_escaped).map(lambda c: '\\' + c)
# Generates single-character string representations, including escapes.
def string_characters():
@@ -34,7 +40,7 @@ def strings():
# Generates characters which are legal within a symbol.
def symbol_characters():
- return characters(blacklist_characters=' \t\n();"')
+ return characters(blacklist_characters=t.whitespace + t.parens + t.quotes + t.string_delim + t.comment_delim)
# Generates legal symbols.
def symbols():
@@ -42,11 +48,11 @@ def symbols():
# Generates single whitespace characters.
def whitespace_characters():
- return one_of(just('\n'), just(' '), just('\t'))
+ return one_of(just(c) for c in t.whitespace)
# Generates a single token.
def tokens():
- return one_of(symbols(), strings(), open_parens(), close_parens())
+ return one_of(symbols(), strings(), parens(), quotes())
# Generates a string which may not be empty, but which does not contain a token.
def nontokens():
@@ -78,16 +84,16 @@ def spaced_tokens():
return tuples(intertokens(), strategy)
def unspaced(strategy):
return tuples(one_of(just(''), intertokens()), strategy)
+ def spaced_quotes():
+ return spaced(quotes())
def spaced_symbols():
return spaced(symbols())
def spaced_strings():
return unspaced(strings())
- def spaced_open_parens():
- return unspaced(open_parens())
- def spaced_close_parens():
- return unspaced(close_parens())
+ def spaced_parens():
+ return unspaced(parens())
- return one_of(spaced_symbols(), spaced_strings(), spaced_open_parens(), spaced_close_parens())
+ return one_of(spaced_symbols(), spaced_quotes(), spaced_strings(), spaced_parens())
# Generats a list of pairs as per spaced_token().
def spaced_token_sequences():