atomy 0.1.1 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +13 -0
- data/LICENSE.md +201 -0
- data/bin/atomy +16 -133
- data/kernel/array.ay +6 -0
- data/kernel/atomy.ay +18 -0
- data/kernel/condition.ay +171 -271
- data/kernel/control-flow.ay +197 -192
- data/kernel/core.ay +120 -0
- data/kernel/data.ay +83 -39
- data/kernel/define.ay +84 -93
- data/kernel/doc.ay +282 -449
- data/kernel/dynamic.ay +25 -29
- data/kernel/file.ay +9 -0
- data/kernel/grammar.ay +267 -0
- data/kernel/hash.ay +17 -0
- data/kernel/interpolation.ay +59 -0
- data/kernel/io.ay +70 -244
- data/kernel/let-macro.ay +24 -0
- data/kernel/let-pattern.ay +24 -0
- data/kernel/loop.ay +80 -0
- data/kernel/mutation.ay +53 -0
- data/kernel/particles.ay +176 -39
- data/kernel/patterns.ay +527 -191
- data/kernel/pretty.ay +311 -277
- data/kernel/quotes.ay +29 -0
- data/kernel/range.ay +4 -0
- data/kernel/regexp.ay +23 -0
- data/kernel/repl.ay +83 -109
- data/kernel/stack-local.ay +21 -0
- data/lib/atomy.rb +37 -0
- data/lib/atomy/bootstrap.rb +256 -0
- data/lib/atomy/code/assign.rb +64 -0
- data/lib/atomy/code/block.rb +98 -0
- data/lib/atomy/code/class_variable.rb +17 -0
- data/lib/atomy/code/constant.rb +21 -0
- data/lib/atomy/code/define.rb +242 -0
- data/lib/atomy/code/define_function.rb +51 -0
- data/lib/atomy/code/define_method.rb +20 -0
- data/lib/atomy/code/false.rb +9 -0
- data/lib/atomy/code/instance_variable.rb +15 -0
- data/lib/atomy/code/integer.rb +13 -0
- data/lib/atomy/code/list.rb +17 -0
- data/lib/atomy/code/nil.rb +9 -0
- data/lib/atomy/code/pattern.rb +23 -0
- data/lib/atomy/code/pattern/and.rb +61 -0
- data/lib/atomy/code/pattern/quasi_quote.rb +185 -0
- data/lib/atomy/code/pattern/splat.rb +29 -0
- data/lib/atomy/code/pattern/wildcard.rb +37 -0
- data/lib/atomy/code/quasi_quote.rb +118 -0
- data/lib/atomy/code/quote.rb +13 -0
- data/lib/atomy/code/self.rb +9 -0
- data/lib/atomy/code/send.rb +110 -0
- data/lib/atomy/code/sequence.rb +23 -0
- data/lib/atomy/code/string_literal.rb +53 -0
- data/lib/atomy/code/symbol.rb +13 -0
- data/lib/atomy/code/true.rb +9 -0
- data/lib/atomy/code/undefined.rb +9 -0
- data/lib/atomy/code/variable.rb +17 -0
- data/lib/atomy/codeloader.rb +218 -0
- data/lib/atomy/compiler.rb +57 -0
- data/lib/atomy/errors.rb +54 -0
- data/lib/atomy/grammar.rb +2278 -0
- data/lib/atomy/locals.rb +75 -0
- data/lib/atomy/message_structure.rb +277 -0
- data/lib/atomy/method.rb +343 -0
- data/lib/atomy/module.rb +144 -0
- data/lib/atomy/node/constructable.rb +169 -0
- data/lib/atomy/node/equality.rb +113 -0
- data/lib/atomy/node/meta.rb +206 -0
- data/lib/atomy/node/pretty.rb +108 -0
- data/lib/atomy/parser.rb +21 -0
- data/lib/atomy/pattern.rb +26 -0
- data/lib/atomy/pattern/and.rb +59 -0
- data/lib/atomy/pattern/attribute.rb +16 -0
- data/lib/atomy/pattern/class_variable.rb +15 -0
- data/lib/atomy/pattern/equality.rb +42 -0
- data/lib/atomy/pattern/instance_variable.rb +15 -0
- data/lib/atomy/pattern/kind_of.rb +20 -0
- data/lib/atomy/pattern/or.rb +48 -0
- data/lib/atomy/pattern/quasi_quote.rb +164 -0
- data/lib/atomy/pattern/splat.rb +15 -0
- data/lib/atomy/pattern/wildcard.rb +18 -0
- data/lib/atomy/rubygems.rb +48 -0
- data/lib/atomy/version.rb +3 -0
- metadata +169 -134
- data/COPYING +0 -30
- data/README.md +0 -1
- data/kernel/block.ay +0 -30
- data/kernel/boot.ay +0 -10
- data/kernel/comparison.ay +0 -61
- data/kernel/concurrency.ay +0 -84
- data/kernel/cosmetics.ay +0 -3
- data/kernel/data-delta.ay +0 -105
- data/kernel/documentation.ay +0 -135
- data/kernel/errors.ay +0 -6
- data/kernel/format.ay +0 -13
- data/kernel/format/data.ay +0 -89
- data/kernel/format/formatter.ay +0 -345
- data/kernel/format/parser.ay +0 -13
- data/kernel/hashes.ay +0 -39
- data/kernel/namespaces.ay +0 -63
- data/kernel/node.ay +0 -48
- data/kernel/operators.ay +0 -28
- data/kernel/precision.ay +0 -148
- data/kernel/therie.ay +0 -204
- data/lib/ast/binary_send.rb +0 -44
- data/lib/ast/block.rb +0 -268
- data/lib/ast/constant.rb +0 -88
- data/lib/ast/internal/assign.rb +0 -19
- data/lib/ast/internal/block_pass.rb +0 -21
- data/lib/ast/internal/catch.rb +0 -247
- data/lib/ast/internal/class.rb +0 -30
- data/lib/ast/internal/class_variable.rb +0 -23
- data/lib/ast/internal/define.rb +0 -174
- data/lib/ast/internal/ensure.rb +0 -135
- data/lib/ast/internal/file.rb +0 -14
- data/lib/ast/internal/global_variable.rb +0 -20
- data/lib/ast/internal/if_then_else.rb +0 -24
- data/lib/ast/internal/instance_variable.rb +0 -17
- data/lib/ast/internal/let_macro.rb +0 -35
- data/lib/ast/internal/macro_quote.rb +0 -23
- data/lib/ast/internal/match.rb +0 -53
- data/lib/ast/internal/module.rb +0 -30
- data/lib/ast/internal/pattern.rb +0 -17
- data/lib/ast/internal/return.rb +0 -29
- data/lib/ast/internal/set.rb +0 -19
- data/lib/ast/internal/singleton_class.rb +0 -18
- data/lib/ast/internal/splat.rb +0 -14
- data/lib/ast/internal/when.rb +0 -24
- data/lib/ast/list.rb +0 -25
- data/lib/ast/macro.rb +0 -37
- data/lib/ast/node.rb +0 -599
- data/lib/ast/operator.rb +0 -21
- data/lib/ast/particle.rb +0 -13
- data/lib/ast/primitive.rb +0 -20
- data/lib/ast/quasi_quote.rb +0 -20
- data/lib/ast/quote.rb +0 -13
- data/lib/ast/send.rb +0 -104
- data/lib/ast/splice.rb +0 -32
- data/lib/ast/string.rb +0 -23
- data/lib/ast/unary.rb +0 -44
- data/lib/ast/unquote.rb +0 -45
- data/lib/ast/variable.rb +0 -64
- data/lib/atomy.kpeg.rb +0 -3995
- data/lib/code_loader.rb +0 -137
- data/lib/compiler/compiler.rb +0 -155
- data/lib/compiler/stages.rb +0 -81
- data/lib/formatter.kpeg.rb +0 -1394
- data/lib/macros.rb +0 -317
- data/lib/method.rb +0 -261
- data/lib/namespace.rb +0 -236
- data/lib/parser.rb +0 -28
- data/lib/patterns.rb +0 -276
- data/lib/patterns/any.rb +0 -21
- data/lib/patterns/attribute.rb +0 -59
- data/lib/patterns/block_pass.rb +0 -54
- data/lib/patterns/constant.rb +0 -33
- data/lib/patterns/default.rb +0 -44
- data/lib/patterns/head_tail.rb +0 -63
- data/lib/patterns/list.rb +0 -77
- data/lib/patterns/match.rb +0 -45
- data/lib/patterns/named.rb +0 -55
- data/lib/patterns/named_class.rb +0 -46
- data/lib/patterns/named_global.rb +0 -46
- data/lib/patterns/named_instance.rb +0 -46
- data/lib/patterns/particle.rb +0 -29
- data/lib/patterns/quasi_quote.rb +0 -184
- data/lib/patterns/quote.rb +0 -33
- data/lib/patterns/singleton_class.rb +0 -31
- data/lib/patterns/splat.rb +0 -57
- data/lib/util.rb +0 -37
data/kernel/data.ay
CHANGED
@@ -1,56 +1,100 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
-- TODO: make this work:
|
2
|
+
--
|
3
|
+
-- module:
|
4
|
+
-- data(A(@x))
|
5
|
+
-- A(x) foo := x
|
6
|
+
--
|
7
|
+
-- right now pattern definitions can only be at the toplevel
|
3
8
|
|
4
|
-
|
5
|
-
|
9
|
+
use(require("core"))
|
10
|
+
use(require("define"))
|
11
|
+
use(require("control-flow"))
|
6
12
|
|
7
|
-
|
8
|
-
|
13
|
+
-- patterns defined by dsl use 'with', so make sure it's exported
|
14
|
+
export(use(require("patterns")))
|
9
15
|
|
10
|
-
|
11
|
-
|
16
|
+
fn(define-class(root, e & Atomy Grammar AST Constant)):
|
17
|
+
define-class(root, `((~e)()))
|
12
18
|
|
13
|
-
|
14
|
-
|
19
|
+
fn(define-class(root, x & `((~name)(~*as)))):
|
20
|
+
define-class(root, `(~x {}))
|
15
21
|
|
16
|
-
|
17
|
-
|
22
|
+
fn(define-class(root, `(~(n & Atomy Grammar AST Constant) { ~*cs }))):
|
23
|
+
define-class(root, `((~n)() { ~*cs }))
|
18
24
|
|
19
|
-
|
20
|
-
|
25
|
+
fn(define-class(root, `((~name)(~*as): ~*cs))):
|
26
|
+
attrs = []
|
27
|
+
as each [x]:
|
28
|
+
x match:
|
29
|
+
(`@~_):
|
30
|
+
attrs << x
|
21
31
|
|
22
|
-
|
23
|
-
|
32
|
+
`(@~_ = ~_):
|
33
|
+
attrs << x left
|
24
34
|
|
25
|
-
|
26
|
-
Atomy::AST::GlobalVariable new(line, x value)
|
35
|
+
tmps = attrs collect [`@~name]: Atomy Grammar AST Unquote new(name)
|
27
36
|
|
28
|
-
|
29
|
-
|
37
|
+
pat = name
|
38
|
+
attrs zip(tmps) [attr, tmp]:
|
39
|
+
&pat = `(~pat & with(~attr, ~tmp))
|
30
40
|
|
31
|
-
|
32
|
-
Atomy::AST::GlobalVariable new(x line, x name)
|
41
|
+
cons = `((~name)(~*tmps))
|
33
42
|
|
34
|
-
|
35
|
-
|
43
|
+
pat-def =
|
44
|
+
`(pattern(~cons):
|
45
|
+
pattern(~make-quasiquote(pat)))
|
36
46
|
|
37
|
-
|
38
|
-
Atomy::AST::Particle new(x line, x name)
|
47
|
+
parent = (root || 'Object)
|
39
48
|
|
40
|
-
|
41
|
-
|
49
|
+
`(do:
|
50
|
+
~parent class(~name):
|
51
|
+
attr-accessor(
|
52
|
+
~*(attrs collect [a]:
|
53
|
+
`.~(a node)))
|
42
54
|
|
43
|
-
|
44
|
-
Atomy::AST::Particle new(x line, x value to-s)
|
55
|
+
def(initialize(~*as)): nil
|
45
56
|
|
46
|
-
|
47
|
-
|
57
|
+
def(inspect):
|
58
|
+
result = (~(Atomy Code StringLiteral new(name text to-s)) + "(")
|
48
59
|
|
49
|
-
|
60
|
+
args = []
|
61
|
+
recursed = //Thread detect-recursion(self):
|
62
|
+
[~*attrs] each [v]:
|
63
|
+
args << v inspect
|
50
64
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
65
|
+
when(recursed):
|
66
|
+
args << "..."
|
67
|
+
|
68
|
+
result << args join(", ")
|
69
|
+
result << ")"
|
70
|
+
|
71
|
+
Rubinius Type infect(result, self)
|
72
|
+
|
73
|
+
result
|
74
|
+
|
75
|
+
~pat-def
|
76
|
+
|
77
|
+
~*(cs collect [c]: define-class(name, c)))
|
78
|
+
|
79
|
+
macro(data: ~*children):
|
80
|
+
`(Object data: ~*children)
|
81
|
+
|
82
|
+
macro(data(~x)):
|
83
|
+
`(Object data(~x) {})
|
84
|
+
|
85
|
+
macro(~root data(~x)):
|
86
|
+
`(~root data(~x) {})
|
87
|
+
|
88
|
+
macro(data(~parent): ~*children):
|
89
|
+
`(Object data(~parent): ~*children)
|
90
|
+
|
91
|
+
macro(~root data: ~*children):
|
92
|
+
`(do:
|
93
|
+
~*(children collect [c]:
|
94
|
+
define-class(root, c))
|
95
|
+
nil)
|
96
|
+
|
97
|
+
macro(~root data(~parent): ~*children):
|
98
|
+
`(do:
|
99
|
+
~(define-class(root, `(~(parent): ~*children)))
|
100
|
+
nil)
|
data/kernel/define.ay
CHANGED
@@ -1,93 +1,84 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
macro(
|
7
|
-
Atomy
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
macro(
|
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
|
-
macro(
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
macro(
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
macro(for-macro(&b)):
|
86
|
-
`(evaluate-when(compile, load):
|
87
|
-
~b block call-on-instance(Atomy::Macro::Environment singleton-class))
|
88
|
-
|
89
|
-
macro(let-macro(*ms, &body)):
|
90
|
-
macros = ms collect [`(~p = ~b)]:
|
91
|
-
Atomy::AST::Macro new(p line, p, b)
|
92
|
-
|
93
|
-
Atomy::AST::LetMacro new(line, body caller, macros)
|
1
|
+
use(require("core"))
|
2
|
+
|
3
|
+
require("atomy/message_structure")
|
4
|
+
|
5
|
+
-- function definition
|
6
|
+
macro(fn(~message): ~*body):
|
7
|
+
structure = Atomy MessageStructure new(message)
|
8
|
+
|
9
|
+
Atomy Code DefineFunction new(
|
10
|
+
structure name
|
11
|
+
`(do: ~*body)
|
12
|
+
structure receiver
|
13
|
+
structure arguments
|
14
|
+
structure default-arguments
|
15
|
+
structure splat-argument
|
16
|
+
structure post-arguments
|
17
|
+
structure proc-argument
|
18
|
+
)
|
19
|
+
|
20
|
+
macro(fn(~dummy-message)):
|
21
|
+
structure = Atomy MessageStructure new(dummy-message)
|
22
|
+
Atomy Code DefineFunction new(structure name)
|
23
|
+
|
24
|
+
|
25
|
+
-- method definition
|
26
|
+
macro(def(~message): ~*body):
|
27
|
+
structure = Atomy MessageStructure new(message)
|
28
|
+
|
29
|
+
Atomy Code DefineMethod new(
|
30
|
+
structure name
|
31
|
+
`(do: ~*body)
|
32
|
+
structure receiver
|
33
|
+
structure arguments
|
34
|
+
structure default-arguments
|
35
|
+
structure splat-argument
|
36
|
+
structure post-arguments
|
37
|
+
structure proc-argument
|
38
|
+
)
|
39
|
+
|
40
|
+
-- helper for adding a module to the constant scope
|
41
|
+
with-module = Class new:
|
42
|
+
def(bytecode(gen, _)):
|
43
|
+
gen push-self
|
44
|
+
gen add-scope
|
45
|
+
gen push-nil
|
46
|
+
|
47
|
+
current-module = Class new:
|
48
|
+
def(bytecode(gen, _)):
|
49
|
+
gen push-scope
|
50
|
+
gen send(.module, 0)
|
51
|
+
|
52
|
+
-- module/class opening
|
53
|
+
macro(~x open: ~*body):
|
54
|
+
`(~x module-eval:
|
55
|
+
~(with-module new)
|
56
|
+
~*body)
|
57
|
+
|
58
|
+
-- anonymous class creation
|
59
|
+
macro(class: ~*body): `(Object class: ~*body)
|
60
|
+
|
61
|
+
macro(~parent class: ~*body):
|
62
|
+
`(//Class new(~parent) open:
|
63
|
+
~*body
|
64
|
+
self)
|
65
|
+
|
66
|
+
-- named class creation
|
67
|
+
macro(class(~name): ~*body): `(Object class(~name): ~*body)
|
68
|
+
|
69
|
+
macro(~parent class(~name): ~*body):
|
70
|
+
`(//Class new(~parent, .~name, ~(current-module new)) open:
|
71
|
+
~*body
|
72
|
+
self)
|
73
|
+
|
74
|
+
-- singleton class opening
|
75
|
+
macro(singleton: ~*body): `(self singleton: ~*body)
|
76
|
+
|
77
|
+
macro(~x singleton: ~*body):
|
78
|
+
`(~x singleton-class open: ~*body)
|
79
|
+
|
80
|
+
-- module creation
|
81
|
+
macro(module: ~*body):
|
82
|
+
`(//Module new open:
|
83
|
+
~*body
|
84
|
+
self)
|
data/kernel/doc.ay
CHANGED
@@ -1,453 +1,286 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
use(require("core"))
|
2
|
+
use(require("data"))
|
3
|
+
use(require("define"))
|
4
|
+
use(require("control-flow"))
|
5
|
+
use(require("array"))
|
6
|
+
use(require("patterns"))
|
7
|
+
condition = use(require("condition"))
|
8
|
+
|
9
|
+
-- combinatorial structures
|
5
10
|
data(Doc):
|
6
11
|
Empty
|
7
|
-
|
8
|
-
|
9
|
-
Nest(@body, @depth)
|
12
|
+
Cat(@x, @y)
|
13
|
+
Nest(@depth, @doc)
|
10
14
|
Text(@value)
|
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
|
-
|
15
|
+
Raw(@value)
|
16
|
+
Line(@space?)
|
17
|
+
Union(@x-thunk, @y-thunk, @prefer? = false)
|
18
|
+
Column(@thunk) -- @thunk is (Integer -> Doc)
|
19
|
+
Nesting(@thunk) -- @thunk is (Integer -> Doc)
|
20
|
+
|
21
|
+
-- simple documents (used internally)
|
22
|
+
data(SDoc):
|
23
|
+
SEmpty
|
24
|
+
SText(@value, @rest-thunk)
|
25
|
+
SRaw(@value, @rest-thunk)
|
26
|
+
SLine(@space?, @indentation, @rest-thunk)
|
27
|
+
|
28
|
+
fn(inject-right(xs, i = _) &block):
|
29
|
+
xs reverse inject(i) [x, y]: block [y, x]
|
30
|
+
|
31
|
+
-- lazy values
|
32
|
+
def(Union x): @x ||= @x-thunk call
|
33
|
+
def(Union y): @y ||= @y-thunk call
|
34
|
+
def(SText rest): @rest ||= @rest-thunk call
|
35
|
+
def(SRaw rest): @rest ||= @rest-thunk call
|
36
|
+
def(SLine rest): @rest ||= @rest-thunk call
|
37
|
+
|
38
|
+
-- constructors
|
39
|
+
def(Empty <> y ): y
|
40
|
+
def(Doc <> Empty): self
|
41
|
+
def(Doc <> y ): Cat new(self, y)
|
42
|
+
|
43
|
+
def(Proc <|> y): Union new(self, y)
|
44
|
+
def(Doc <|> y): Union new({ self }, { y })
|
45
|
+
|
46
|
+
def(Proc <||> y): Union new(self, y, true)
|
47
|
+
def(Doc <||> y): Union new({ self }, { y }, true)
|
48
|
+
|
49
|
+
def(Doc nest(i)): Nest new(i, self)
|
50
|
+
|
51
|
+
-- flatten a document
|
52
|
+
def(Empty flatten): Self empty
|
53
|
+
def(Cat(x, y) flatten): x flatten <> y flatten
|
54
|
+
def(Nest(i, x) flatten): x flatten
|
55
|
+
def(Text(s) flatten): Self text(s)
|
56
|
+
def(Raw(s) flatten): Self raw(s)
|
57
|
+
def(Line(true) flatten): Self text(" ")
|
58
|
+
def(Line(false) flatten): Self empty
|
59
|
+
def(Union flatten): x flatten
|
60
|
+
def(Column(f) flatten): Self column [x]: f [x] flatten
|
61
|
+
def(Nesting(f) flatten): Self nesting [x]: f [x] flatten
|
62
|
+
|
63
|
+
-- hanging indentation
|
64
|
+
def(Doc hang(i)): Self align(nest(i))
|
65
|
+
|
66
|
+
-- full indentation
|
67
|
+
def(Doc indent(i)): (Self text(" " * i) <> self) hang(i)
|
68
|
+
|
69
|
+
-- p punctuate([d1, d2, ..., dn]) => [d1 <> p, d2 <> p, ..., dn]
|
70
|
+
def(Doc punctuate([]) ): []
|
71
|
+
def(Doc punctuate([d]) ): [d]
|
72
|
+
def(Doc punctuate(d . ds)): [d <> self] + punctuate(ds)
|
73
|
+
|
74
|
+
-- sep + punctuate
|
75
|
+
def(Doc separate(ds)): Self align(Self sep(Self punctuate(ds)))
|
76
|
+
|
77
|
+
-- concatenate two documents, with a space in-between
|
78
|
+
def(Empty <+> y ): y
|
79
|
+
def(Doc <+> Empty): self
|
80
|
+
def(Doc <+> y ): (self <> Self space) <> y
|
81
|
+
|
82
|
+
-- concatenates two documents, with a `softline' in between
|
83
|
+
def(Empty </> y ): y
|
84
|
+
def(Doc </> Empty): self
|
85
|
+
def(Doc </> y ): (self <> Self softline) <> y
|
86
|
+
|
87
|
+
-- concatenates two documents, with a `suggestline' in between
|
88
|
+
def(Empty <\> y ): y
|
89
|
+
def(Doc <\> Empty): self
|
90
|
+
def(Doc <\> y ): (self <> Self suggestline) <> y
|
91
|
+
|
92
|
+
-- concatenates two documents, with a `softbreak' in between
|
93
|
+
def(Empty <//> y ): y
|
94
|
+
def(Doc <//> Empty): self
|
95
|
+
def(Doc <//> y ): (self <> Self softbreak) <> y
|
96
|
+
|
97
|
+
-- concatenates two documents, with a `suggestbreak' in between
|
98
|
+
def(Empty <\\> y ): y
|
99
|
+
def(Doc <\\> Empty): self
|
100
|
+
def(Doc <\\> y ): (self <> Self suggestbreak) <> y
|
101
|
+
|
102
|
+
-- concatenates two documents, with a `line' in between
|
103
|
+
def(Empty <$> y ): y
|
104
|
+
def(Doc <$> Empty): self
|
105
|
+
def(Doc <$> y ): (self <> Self line) <> y
|
106
|
+
|
107
|
+
-- concatenates two documents, with a `linebreak' in between
|
108
|
+
def(Empty <$$> y ): y
|
109
|
+
def(Doc <$$> Empty): self
|
110
|
+
def(Doc <$$> y ): (self <> Self linebreak) <> y
|
111
|
+
|
112
|
+
-- predeclare so pick-union can use it
|
113
|
+
fn(fit)
|
114
|
+
|
115
|
+
-- chose the side of a Union that best fits the given width
|
116
|
+
fn(pick-union(w, k, i, ds, x, y, prefer?)):
|
117
|
+
flattened = fit(w, k, [i, x] . ds, prefer?)
|
118
|
+
if(flattened fits?(w - k))
|
119
|
+
then: flattened
|
120
|
+
else:
|
121
|
+
condition signal(.no-fit)
|
122
|
+
fit(w, k, [i, y] . ds, prefer?)
|
123
|
+
|
124
|
+
-- helper for `best' by linearizing documents
|
125
|
+
fn(fit(_, _, [], pref = false)): SEmpty new
|
126
|
+
fn(fit(w, k, [i, d] . ds, pref = false)):
|
127
|
+
d match:
|
128
|
+
Empty : fit(w, k, ds, pref)
|
129
|
+
Cat(x, y) : fit(w, k, [[i, x], [i, y]] + ds, pref)
|
130
|
+
Nest(j, x) : fit(w, k, [i + j, x] . ds, pref)
|
131
|
+
Text(s) : SText new(s, { fit(w, k + s size, ds, pref) })
|
132
|
+
Raw(s) : SRaw new(s, { fit(w, k, ds, pref) })
|
133
|
+
Line(s) : SLine new(s, i, { fit(w, i, ds, false) })
|
134
|
+
Column(f) : fit(w, k, [i, f[k]] . ds, pref)
|
135
|
+
Nesting(f) : fit(w, k, [i, f[i]] . ds, pref)
|
136
|
+
Union:
|
137
|
+
if(d prefer? && !pref)
|
119
138
|
then:
|
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
|
-
text(s) := Text new(s)
|
269
|
-
|
270
|
-
doc"
|
271
|
-
Create a \hl{Text} document with \hl{x inspect}.
|
272
|
-
" spec {
|
273
|
-
=> "Doc"
|
274
|
-
} for:
|
275
|
-
"value(x)"
|
276
|
-
value(x) := Text new(x inspect)
|
277
|
-
|
278
|
-
doc"
|
279
|
-
Shortcut for \hl{text(\";\")}.
|
280
|
-
" spec {
|
281
|
-
=> "Doc"
|
282
|
-
} for:
|
283
|
-
"semi"
|
284
|
-
semi := text(";")
|
285
|
-
|
286
|
-
doc"
|
287
|
-
Shortcut for \hl{text(\",\")}.
|
288
|
-
" spec {
|
289
|
-
=> "Doc"
|
290
|
-
} for:
|
291
|
-
"comma"
|
292
|
-
comma := text(",")
|
293
|
-
|
294
|
-
doc"
|
295
|
-
Shortcut for \hl{text(\":\")}.
|
296
|
-
" spec {
|
297
|
-
=> "Doc"
|
298
|
-
} for:
|
299
|
-
"colon"
|
300
|
-
colon := text(":")
|
301
|
-
|
302
|
-
doc"
|
303
|
-
Shortcut for \hl{text(\" \")}.
|
304
|
-
" spec {
|
305
|
-
=> "Doc"
|
306
|
-
} for:
|
307
|
-
"space"
|
308
|
-
space := text(" ")
|
309
|
-
|
310
|
-
doc"
|
311
|
-
Shortcut for \hl{text(\"=\")}.
|
312
|
-
" spec {
|
313
|
-
=> "Doc"
|
314
|
-
} for:
|
315
|
-
"equals"
|
316
|
-
equals := text("=")
|
317
|
-
|
318
|
-
doc"
|
319
|
-
Shortcut for \hl{text(\"(\")}.
|
320
|
-
" spec {
|
321
|
-
=> "Doc"
|
322
|
-
} for:
|
323
|
-
"lparen"
|
324
|
-
lparen := text("(")
|
325
|
-
|
326
|
-
doc"
|
327
|
-
Shortcut for \hl{text(\")\")}.
|
328
|
-
" spec {
|
329
|
-
=> "Doc"
|
330
|
-
} for:
|
331
|
-
"rparen"
|
332
|
-
rparen := text(")")
|
333
|
-
|
334
|
-
doc"
|
335
|
-
Shortcut for \hl{text(\"[\")}.
|
336
|
-
" spec {
|
337
|
-
=> "Doc"
|
338
|
-
} for:
|
339
|
-
"lbrack"
|
340
|
-
lbrack := text("[")
|
341
|
-
|
342
|
-
doc"
|
343
|
-
Shortcut for \hl{text(\"]\")}.
|
344
|
-
" spec {
|
345
|
-
=> "Doc"
|
346
|
-
} for:
|
347
|
-
"rbrack"
|
348
|
-
rbrack := text("]")
|
349
|
-
|
350
|
-
doc"
|
351
|
-
Shortcut for \hl{text(\"\{\")}.
|
352
|
-
" spec {
|
353
|
-
=> "Doc"
|
354
|
-
} for:
|
355
|
-
"lbrace"
|
356
|
-
lbrace := text("{")
|
357
|
-
|
358
|
-
doc"
|
359
|
-
Shortcut for \hl{text(\"\}\")}.
|
360
|
-
" spec {
|
361
|
-
=> "Doc"
|
362
|
-
} for:
|
363
|
-
"rbrace"
|
364
|
-
rbrace := text("}")
|
365
|
-
|
366
|
-
section("Wrapping"):
|
367
|
-
doc"
|
368
|
-
More shortcuts for common cases in pretty-printing, dealing with \
|
369
|
-
wrapping a document in delimiters.
|
370
|
-
"
|
371
|
-
|
372
|
-
doc"
|
373
|
-
Wrap a document in parentheses.
|
374
|
-
" spec {
|
375
|
-
=> "Doc"
|
376
|
-
} for:
|
377
|
-
"parens(d)"
|
378
|
-
parens(d) := lparen <> d <> rparen
|
379
|
-
|
380
|
-
doc"
|
381
|
-
Wrap a document in brackets (\code{[]}).
|
382
|
-
" spec {
|
383
|
-
=> "Doc"
|
384
|
-
} for:
|
385
|
-
"brackets(d: Doc)"
|
386
|
-
brackets(d) := lbrack <> d <> rbrack
|
387
|
-
|
388
|
-
doc"
|
389
|
-
Wrap a document in braces (\code{\{\}}).
|
390
|
-
" spec {
|
391
|
-
=> "Doc"
|
392
|
-
} for:
|
393
|
-
"braces(d: Doc)"
|
394
|
-
braces(d) := lbrace <> d <> rbrace
|
395
|
-
|
396
|
-
doc"
|
397
|
-
Wrap a document in single-quotes.
|
398
|
-
" spec {
|
399
|
-
=> "Doc"
|
400
|
-
} for:
|
401
|
-
"quotes(d: Doc)"
|
402
|
-
quotes(d) := text("'") <> d <> text("'")
|
403
|
-
|
404
|
-
doc"
|
405
|
-
Wrap a document in double-quotes.
|
406
|
-
" spec {
|
407
|
-
=> "Doc"
|
408
|
-
} for:
|
409
|
-
"double-quotes(d: Doc)"
|
410
|
-
double-quotes(d) := text("\"") <> d <> text("\"")
|
411
|
-
|
412
|
-
section("Combining"):
|
413
|
-
doc"
|
414
|
-
Helpers for creating a single document from many.
|
415
|
-
"
|
416
|
-
|
417
|
-
doc"
|
418
|
-
An empty document. The identity for \hl{<>}, \hl{<+>}, \hl{//}, \
|
419
|
-
\hl{/+/}, and anywhere in the following methods.
|
420
|
-
" spec {
|
421
|
-
=> "Doc"
|
422
|
-
} for:
|
423
|
-
"empty"
|
424
|
-
empty := Empty new
|
425
|
-
|
426
|
-
doc"
|
427
|
-
Reduce a list of documents with \hl{<>}.
|
428
|
-
" spec {
|
429
|
-
"ds all?(&#is-a?(Doc))"
|
430
|
-
=> "Doc"
|
431
|
-
} for:
|
432
|
-
"hcat(ds)"
|
433
|
-
hcat(ds) := ds inject(empty) [a, b]: a <> b
|
434
|
-
|
435
|
-
doc"
|
436
|
-
Reduce a list of documents with \hl{<+>}.
|
437
|
-
" spec {
|
438
|
-
"ds all?(&#is-a?(Doc))"
|
439
|
-
=> "Doc"
|
440
|
-
} for:
|
441
|
-
"hsep(ds)"
|
442
|
-
hsep(ds) := ds inject(empty) [a, b]: a <+> b
|
443
|
-
|
444
|
-
doc"
|
445
|
-
Reduce a list of documents with \hl{//}.
|
446
|
-
" spec {
|
447
|
-
"ds all?(&#is-a?(Doc))"
|
448
|
-
=> "Doc"
|
449
|
-
} for:
|
450
|
-
"vcat(ds)"
|
451
|
-
vcat(ds) := ds inject(empty) [a, b]: a // b
|
452
|
-
|
453
|
-
Doc extend(Pretty)
|
139
|
+
with-restarts(use-fit: fit(w, k, [i, d y] . ds, false)) {
|
140
|
+
pick-union(w, k, i, ds, d x, d y, true)
|
141
|
+
} bind:
|
142
|
+
.no-fit: condition restart(.use-fit)
|
143
|
+
else: pick-union(w, k, i, ds, d x, d y, pref)
|
144
|
+
|
145
|
+
-- find the best configuration to fit document X in width w
|
146
|
+
def(Doc best(w, k)): fit(w, k, [[0, self]])
|
147
|
+
|
148
|
+
-- test that a document can fit in a given width
|
149
|
+
def(SText fits?(w)): (w >= 0) && rest fits?(w - @value size)
|
150
|
+
def(SRaw fits?(w)): (w >= 0) && rest fits?(w)
|
151
|
+
def(SDoc fits?(w)): w >= 0
|
152
|
+
|
153
|
+
-- rendering to a string
|
154
|
+
def(SEmpty layout): ""
|
155
|
+
def(SText layout): @value + rest layout
|
156
|
+
def(SRaw layout): @value + rest layout
|
157
|
+
def(SLine layout): ("\n" + (" " * @indentation)) + rest layout
|
158
|
+
|
159
|
+
-- rendering to a string
|
160
|
+
def(Cat(x, y) layout): x layout + y layout
|
161
|
+
def(Empty layout): ""
|
162
|
+
def(Text(s) layout): s
|
163
|
+
def(Raw(s) layout): s
|
164
|
+
def(Line layout): "\n"
|
165
|
+
def(Union layout): y layout
|
166
|
+
def(Nest(i, d) layout):
|
167
|
+
d match:
|
168
|
+
Cat(x, y) : x nest(i) layout + y nest(i) layout
|
169
|
+
Empty : ""
|
170
|
+
Text(s) : s
|
171
|
+
Raw(s) : s
|
172
|
+
Line : "\n" + (" " * i)
|
173
|
+
Nest(e, x) : Nest new(i + e, x) layout
|
174
|
+
Union : Nest new(i, d y) layout
|
175
|
+
|
176
|
+
-- trivial emptiness check
|
177
|
+
def(Empty empty?): true
|
178
|
+
def(Doc empty?): false
|
179
|
+
|
180
|
+
-- pretty-printing with a maximum width
|
181
|
+
def(Doc render(width = 70)): best(width, 0) layout
|
182
|
+
|
183
|
+
-- trivial constructors
|
184
|
+
def(empty): Empty new
|
185
|
+
def(text(s)): Text new(s to-s)
|
186
|
+
def(raw(s)): Raw new(s to-s)
|
187
|
+
def(line): Line new(true)
|
188
|
+
def(linebreak): Line new(false)
|
189
|
+
def(column &f): Column new(f)
|
190
|
+
def(nesting &f): Nesting new(f)
|
191
|
+
def(group(x)): { x flatten } <|> { x }
|
192
|
+
def(preferred-group(x)): { x flatten } <||> { x }
|
193
|
+
def(softline): group(line)
|
194
|
+
def(softbreak): group(linebreak)
|
195
|
+
def(suggestline): preferred-group(line)
|
196
|
+
def(suggestbreak): preferred-group(linebreak)
|
197
|
+
|
198
|
+
-- render x with the nesting level set to the current column
|
199
|
+
def(align(x)):
|
200
|
+
column [k]:
|
201
|
+
nesting [i]:
|
202
|
+
x nest(k - i)
|
203
|
+
|
204
|
+
-- wrap `x' in `left' and `right'
|
205
|
+
def(enclose(left, right, x)): (left <> x) <> right
|
206
|
+
|
207
|
+
-- punctuate `xs' with `delim', separating with a space, and wrapping with
|
208
|
+
-- `left` and `right`
|
209
|
+
def(enclose-sep(left, right, delim, xs)):
|
210
|
+
enclose(left, right, align(sep(delim punctuate(xs))))
|
211
|
+
|
212
|
+
-- punctuate `xs' with `delim', and wrapping with `left` and `right`
|
213
|
+
def(enclose-cat(left, right, delim, xs)):
|
214
|
+
enclose(left, right, align(cat(delim punctuate(xs))))
|
215
|
+
|
216
|
+
-- separating lists
|
217
|
+
def(hsep(xs)): inject-right(xs, empty) [x, y]: x <+> y
|
218
|
+
def(vsep(xs)): inject-right(xs, empty) [x, y]: x <$> y
|
219
|
+
def(sep(xs)): group(vsep(xs))
|
220
|
+
def(fill-sep(xs)): inject-right(xs, empty) [x, y]: x </> y
|
221
|
+
def(suggest-sep(xs)): inject-right(xs, empty) [x, y]: x <\> y
|
222
|
+
|
223
|
+
-- concatenating lists
|
224
|
+
def(hcat(xs)): inject-right(xs, empty) [x, y]: x <> y
|
225
|
+
def(vcat(xs)): inject-right(xs, empty) [x, y]: x <$$> y
|
226
|
+
def(cat(xs)): group(vcat(xs))
|
227
|
+
def(fill-cat(xs)): inject-right(xs, empty) [x, y]: x <//> y
|
228
|
+
def(suggest-cat(xs)): inject-right(xs, empty) [x, y]: x <\\> y
|
229
|
+
|
230
|
+
-- fill a document with whitespace to width `i'
|
231
|
+
def(fill(i, d)):
|
232
|
+
width(d) [w]:
|
233
|
+
if(w >= i)
|
234
|
+
then: empty
|
235
|
+
else: text(" " * (i - w))
|
236
|
+
|
237
|
+
-- fill a document with whitespace to width `i', breaking onto a new line if
|
238
|
+
-- the document gets too long
|
239
|
+
def(fill-break(i, d)):
|
240
|
+
width(d) [w]:
|
241
|
+
if(w > i)
|
242
|
+
then: linebreak nest(i)
|
243
|
+
else: text(" " * (i - w))
|
244
|
+
|
245
|
+
-- call `f' with the width of the passed document, and render the result
|
246
|
+
-- after it
|
247
|
+
def(width(d) &f):
|
248
|
+
column [c1]: d <> column [c2]: f [c2 - c1]
|
249
|
+
|
250
|
+
-- helper documents
|
251
|
+
def(lparen): text("(")
|
252
|
+
def(rparen): text(")")
|
253
|
+
def(langle): text("<")
|
254
|
+
def(rangle): text(">")
|
255
|
+
def(lbrace): text("{")
|
256
|
+
def(rbrace): text("}")
|
257
|
+
def(lbracket): text("[")
|
258
|
+
def(rbracket): text("]")
|
259
|
+
def(squote): text("'")
|
260
|
+
def(dquote): text("\"")
|
261
|
+
def(semi): text(";")
|
262
|
+
def(colon): text(":")
|
263
|
+
def(comma): text(",")
|
264
|
+
def(space): text(" ")
|
265
|
+
def(dot): text(".")
|
266
|
+
def(backslash): text("\\")
|
267
|
+
def(equals): text("=")
|
268
|
+
|
269
|
+
-- helper for creating text from a string that may contain newlines
|
270
|
+
def(string(s)): hcat(line punctuate(s split("\n") collect [x]: text(x)))
|
271
|
+
|
272
|
+
-- wrappers
|
273
|
+
def(parens(x)): (lparen <> x) <> rparen
|
274
|
+
def(angles(x)): (langle <> x) <> rangle
|
275
|
+
def(braces(x)): (lbrace <> x) <> rbrace
|
276
|
+
def(brackets(x)): (lbracket <> x) <> rbracket
|
277
|
+
def(squotes(x)): (squote <> x) <> squote
|
278
|
+
def(dquotes(x)): (dquote <> x) <> dquote
|
279
|
+
|
280
|
+
-- helpers for common syntax
|
281
|
+
def(list(xs)):
|
282
|
+
enclose(lbracket, rbracket, align(fill-sep(comma punctuate(xs))))
|
283
|
+
def(tupled(xs)):
|
284
|
+
enclose(lparen, rparen, align(fill-sep(comma punctuate(xs))))
|
285
|
+
def(semi-braces(xs)):
|
286
|
+
enclose-sep(lbrace, rbrace, semi, xs)
|