atomy 0.1.1
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.
- data/COPYING +30 -0
- data/README.md +1 -0
- data/bin/atomy +134 -0
- data/kernel/block.ay +30 -0
- data/kernel/boot.ay +10 -0
- data/kernel/comparison.ay +61 -0
- data/kernel/concurrency.ay +84 -0
- data/kernel/condition.ay +277 -0
- data/kernel/control-flow.ay +222 -0
- data/kernel/cosmetics.ay +3 -0
- data/kernel/data-delta.ay +105 -0
- data/kernel/data.ay +56 -0
- data/kernel/define.ay +93 -0
- data/kernel/doc.ay +453 -0
- data/kernel/documentation.ay +135 -0
- data/kernel/dynamic.ay +42 -0
- data/kernel/errors.ay +6 -0
- data/kernel/format.ay +13 -0
- data/kernel/format/data.ay +89 -0
- data/kernel/format/formatter.ay +345 -0
- data/kernel/format/parser.ay +13 -0
- data/kernel/hashes.ay +39 -0
- data/kernel/io.ay +244 -0
- data/kernel/namespaces.ay +63 -0
- data/kernel/node.ay +48 -0
- data/kernel/operators.ay +28 -0
- data/kernel/particles.ay +53 -0
- data/kernel/patterns.ay +256 -0
- data/kernel/precision.ay +148 -0
- data/kernel/pretty.ay +283 -0
- data/kernel/repl.ay +140 -0
- data/kernel/therie.ay +204 -0
- data/lib/ast/binary_send.rb +44 -0
- data/lib/ast/block.rb +268 -0
- data/lib/ast/constant.rb +88 -0
- data/lib/ast/internal/assign.rb +19 -0
- data/lib/ast/internal/block_pass.rb +21 -0
- data/lib/ast/internal/catch.rb +247 -0
- data/lib/ast/internal/class.rb +30 -0
- data/lib/ast/internal/class_variable.rb +23 -0
- data/lib/ast/internal/define.rb +174 -0
- data/lib/ast/internal/ensure.rb +135 -0
- data/lib/ast/internal/file.rb +14 -0
- data/lib/ast/internal/global_variable.rb +20 -0
- data/lib/ast/internal/if_then_else.rb +24 -0
- data/lib/ast/internal/instance_variable.rb +17 -0
- data/lib/ast/internal/let_macro.rb +35 -0
- data/lib/ast/internal/macro_quote.rb +23 -0
- data/lib/ast/internal/match.rb +53 -0
- data/lib/ast/internal/module.rb +30 -0
- data/lib/ast/internal/pattern.rb +17 -0
- data/lib/ast/internal/return.rb +29 -0
- data/lib/ast/internal/set.rb +19 -0
- data/lib/ast/internal/singleton_class.rb +18 -0
- data/lib/ast/internal/splat.rb +14 -0
- data/lib/ast/internal/when.rb +24 -0
- data/lib/ast/list.rb +25 -0
- data/lib/ast/macro.rb +37 -0
- data/lib/ast/node.rb +599 -0
- data/lib/ast/operator.rb +21 -0
- data/lib/ast/particle.rb +13 -0
- data/lib/ast/primitive.rb +20 -0
- data/lib/ast/quasi_quote.rb +20 -0
- data/lib/ast/quote.rb +13 -0
- data/lib/ast/send.rb +104 -0
- data/lib/ast/splice.rb +32 -0
- data/lib/ast/string.rb +23 -0
- data/lib/ast/unary.rb +44 -0
- data/lib/ast/unquote.rb +45 -0
- data/lib/ast/variable.rb +64 -0
- data/lib/atomy.kpeg.rb +3995 -0
- data/lib/code_loader.rb +137 -0
- data/lib/compiler/compiler.rb +155 -0
- data/lib/compiler/stages.rb +81 -0
- data/lib/formatter.kpeg.rb +1394 -0
- data/lib/macros.rb +317 -0
- data/lib/method.rb +261 -0
- data/lib/namespace.rb +236 -0
- data/lib/parser.rb +28 -0
- data/lib/patterns.rb +276 -0
- data/lib/patterns/any.rb +21 -0
- data/lib/patterns/attribute.rb +59 -0
- data/lib/patterns/block_pass.rb +54 -0
- data/lib/patterns/constant.rb +33 -0
- data/lib/patterns/default.rb +44 -0
- data/lib/patterns/head_tail.rb +63 -0
- data/lib/patterns/list.rb +77 -0
- data/lib/patterns/match.rb +45 -0
- data/lib/patterns/named.rb +55 -0
- data/lib/patterns/named_class.rb +46 -0
- data/lib/patterns/named_global.rb +46 -0
- data/lib/patterns/named_instance.rb +46 -0
- data/lib/patterns/particle.rb +29 -0
- data/lib/patterns/quasi_quote.rb +184 -0
- data/lib/patterns/quote.rb +33 -0
- data/lib/patterns/singleton_class.rb +31 -0
- data/lib/patterns/splat.rb +57 -0
- data/lib/util.rb +37 -0
- metadata +164 -0
data/kernel/patterns.ay
ADDED
@@ -0,0 +1,256 @@
|
|
1
|
+
namespace(atomy)
|
2
|
+
|
3
|
+
module(Atomy::Patterns):
|
4
|
+
export:
|
5
|
+
class(RuntimeClass < Pattern):
|
6
|
+
initialize(@body, @name) := #ok
|
7
|
+
|
8
|
+
construct(g) := do:
|
9
|
+
get(g)
|
10
|
+
@body construct(g)
|
11
|
+
@body compile(g)
|
12
|
+
g send(#name, 0)
|
13
|
+
g send(#new, 2)
|
14
|
+
|
15
|
+
(== b) :=
|
16
|
+
b kind-of?(RuntimeClass) &&
|
17
|
+
@body == b body &&
|
18
|
+
@name == b name
|
19
|
+
|
20
|
+
target(g) :=
|
21
|
+
@body compile(g)
|
22
|
+
|
23
|
+
matches?(g) := do:
|
24
|
+
Atomy const-from-string(g, @name)
|
25
|
+
g swap
|
26
|
+
g kind-of
|
27
|
+
|
28
|
+
class(Predicate < Pattern):
|
29
|
+
initialize(@pattern, @test) := #ok
|
30
|
+
|
31
|
+
construct(g) := do:
|
32
|
+
get(g)
|
33
|
+
@pattern construct(g)
|
34
|
+
@test construct(g)
|
35
|
+
g send(#new, 2)
|
36
|
+
|
37
|
+
(== b) :=
|
38
|
+
b kind-of?(Predicate) &&
|
39
|
+
@pattern == b pattern &&
|
40
|
+
@test == b test
|
41
|
+
|
42
|
+
target(g) := @pattern target(g)
|
43
|
+
|
44
|
+
matches?(g) := do:
|
45
|
+
mismatch = g new-label
|
46
|
+
done = g new-label
|
47
|
+
|
48
|
+
g dup
|
49
|
+
@pattern matches?(g)
|
50
|
+
g gif(mismatch)
|
51
|
+
|
52
|
+
`{ ~@test } bytecode(g)
|
53
|
+
g send(#block, 0)
|
54
|
+
g swap
|
55
|
+
g send(#call-on-instance, 1)
|
56
|
+
g goto(done)
|
57
|
+
|
58
|
+
mismatch set!
|
59
|
+
g pop
|
60
|
+
g push-false
|
61
|
+
|
62
|
+
done set!
|
63
|
+
|
64
|
+
deconstruct(g, locals = Hash new) :=
|
65
|
+
@pattern deconstruct(g, locals)
|
66
|
+
|
67
|
+
local-names := @pattern local-names
|
68
|
+
|
69
|
+
bindings := @pattern bindings
|
70
|
+
|
71
|
+
class(With < Pattern):
|
72
|
+
initialize(@expression, @pattern) := #ok
|
73
|
+
|
74
|
+
construct(g) := do:
|
75
|
+
get(g)
|
76
|
+
@expression construct(g)
|
77
|
+
@pattern construct(g)
|
78
|
+
g send(#new, 2)
|
79
|
+
|
80
|
+
(== b) :=
|
81
|
+
b kind-of?(With) &&
|
82
|
+
@expression == b expression &&
|
83
|
+
@pattern == b pattern
|
84
|
+
|
85
|
+
target(g) := Any new target(g)
|
86
|
+
|
87
|
+
matches?(g) := do:
|
88
|
+
`{ ~@expression } bytecode(g)
|
89
|
+
g send(#block, 0)
|
90
|
+
g swap
|
91
|
+
g send(#call-on-instance, 1)
|
92
|
+
@pattern matches?(g)
|
93
|
+
|
94
|
+
deconstruct(g, locals = Hash new) := do:
|
95
|
+
`{ ~@expression } bytecode(g)
|
96
|
+
g send(#block, 0)
|
97
|
+
g swap
|
98
|
+
g send(#call-on-instance, 1)
|
99
|
+
@pattern deconstruct(g, locals)
|
100
|
+
|
101
|
+
local-names := @pattern local-names
|
102
|
+
|
103
|
+
bindings := @pattern bindings
|
104
|
+
|
105
|
+
class(And < Pattern):
|
106
|
+
initialize(@a, @b) := #ok
|
107
|
+
|
108
|
+
construct(g) := do:
|
109
|
+
get(g)
|
110
|
+
@a construct(g)
|
111
|
+
@b construct(g)
|
112
|
+
g send(#new, 2)
|
113
|
+
|
114
|
+
(== b) :=
|
115
|
+
b kind-of?(And) &&
|
116
|
+
@a == b a &&
|
117
|
+
@b == b b
|
118
|
+
|
119
|
+
target(g) :=
|
120
|
+
@a target(g)
|
121
|
+
|
122
|
+
matches?(g) := do:
|
123
|
+
mismatch = g new-label
|
124
|
+
done = g new-label
|
125
|
+
|
126
|
+
g dup
|
127
|
+
@a matches?(g)
|
128
|
+
g gif(mismatch)
|
129
|
+
|
130
|
+
@b matches?(g)
|
131
|
+
g dup
|
132
|
+
g git(done)
|
133
|
+
|
134
|
+
mismatch set!
|
135
|
+
g pop
|
136
|
+
g push-false
|
137
|
+
|
138
|
+
done set!
|
139
|
+
|
140
|
+
deconstruct(g, locals = Hash new) := do:
|
141
|
+
g dup
|
142
|
+
@a deconstruct(g, locals)
|
143
|
+
@b deconstruct(g, locals)
|
144
|
+
|
145
|
+
local-names := [@a local-names + @b local-names] uniq
|
146
|
+
|
147
|
+
class(Or < Pattern):
|
148
|
+
initialize(@a, @b) := #ok
|
149
|
+
|
150
|
+
construct(g) := do:
|
151
|
+
get(g)
|
152
|
+
@a construct(g)
|
153
|
+
@b construct(g)
|
154
|
+
g send(#new, 2)
|
155
|
+
|
156
|
+
(== b) :=
|
157
|
+
b kind-of?(Or) &&
|
158
|
+
@a == b a &&
|
159
|
+
@b == b b
|
160
|
+
|
161
|
+
target(g) :=
|
162
|
+
@a target(g)
|
163
|
+
|
164
|
+
matches?(g) := do:
|
165
|
+
matched = g new-label
|
166
|
+
done = g new-label
|
167
|
+
|
168
|
+
g dup
|
169
|
+
@a matches?(g)
|
170
|
+
g git(matched)
|
171
|
+
|
172
|
+
@b matches?(g)
|
173
|
+
g dup
|
174
|
+
g gif(done)
|
175
|
+
|
176
|
+
matched set!
|
177
|
+
g pop
|
178
|
+
g push-true
|
179
|
+
|
180
|
+
done set!
|
181
|
+
|
182
|
+
deconstruct(g, locals = #[]) := do:
|
183
|
+
b = g new-label
|
184
|
+
done = g new-label
|
185
|
+
|
186
|
+
g dup
|
187
|
+
g dup
|
188
|
+
@a matches?(g)
|
189
|
+
g gif(b)
|
190
|
+
|
191
|
+
@a deconstruct(g, locals)
|
192
|
+
g pop
|
193
|
+
g goto(done)
|
194
|
+
|
195
|
+
b set!
|
196
|
+
g pop
|
197
|
+
@b deconstruct(g, locals)
|
198
|
+
|
199
|
+
done set!
|
200
|
+
|
201
|
+
local-names := [@a local-names + @b local-names] uniq
|
202
|
+
|
203
|
+
|
204
|
+
-- base patterns
|
205
|
+
module(Atomy::AST):
|
206
|
+
export:
|
207
|
+
Variable pattern :=
|
208
|
+
Atomy::Patterns::Named new $:
|
209
|
+
@name
|
210
|
+
Atomy::Patterns::Any new
|
211
|
+
|
212
|
+
Primitive pattern :=
|
213
|
+
Atomy::Patterns::Match new(@value)
|
214
|
+
|
215
|
+
List pattern :=
|
216
|
+
Atomy::Patterns::List new $:
|
217
|
+
@elements collect [e]: e to-pattern
|
218
|
+
|
219
|
+
Constant pattern :=
|
220
|
+
Atomy::Patterns::Constant new(self)
|
221
|
+
|
222
|
+
ScopedConstant pattern :=
|
223
|
+
Atomy::Patterns::Constant new(self)
|
224
|
+
|
225
|
+
ToplevelConstant pattern :=
|
226
|
+
Atomy::Patterns::Constant new(self)
|
227
|
+
|
228
|
+
Quote pattern :=
|
229
|
+
Atomy::Patterns::Quote new(@expression)
|
230
|
+
|
231
|
+
Block pattern :=
|
232
|
+
Atomy::Patterns::SingletonClass new(self)
|
233
|
+
|
234
|
+
Particle pattern :=
|
235
|
+
Atomy::Patterns::Particle new(@name to-sym)
|
236
|
+
|
237
|
+
QuasiQuote pattern :=
|
238
|
+
Atomy::Patterns::QuasiQuote new(self)
|
239
|
+
|
240
|
+
Send pattern :=
|
241
|
+
if(@block)
|
242
|
+
then:
|
243
|
+
Atomy::Patterns::Named new $:
|
244
|
+
@method-name
|
245
|
+
@block contents [0] to-pattern
|
246
|
+
else:
|
247
|
+
Atomy::Patterns::Attribute new $:
|
248
|
+
@receiver
|
249
|
+
@method-name
|
250
|
+
@arguments
|
251
|
+
|
252
|
+
String pattern :=
|
253
|
+
Atomy::Patterns::Match new(@value)
|
254
|
+
|
255
|
+
Node pattern :=
|
256
|
+
raise("unknown pattern: " + self inspect)
|
data/kernel/precision.ay
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
namespace(atomy)
|
2
|
+
|
3
|
+
export:
|
4
|
+
module(Atomy::Patterns):
|
5
|
+
-- pattern precision hierarchy, from least precise to most
|
6
|
+
[ [ Any, BlockPass, Splat, Attribute,
|
7
|
+
NamedClass, NamedGlobal, NamedInstance
|
8
|
+
]
|
9
|
+
|
10
|
+
[Constant, SingletonClass, RuntimeClass]
|
11
|
+
|
12
|
+
[HeadTail]
|
13
|
+
|
14
|
+
[List, QuasiQuote, Particle]
|
15
|
+
|
16
|
+
[Match, Quote]
|
17
|
+
] each-with-index [ps, i]:
|
18
|
+
ps each [a]:
|
19
|
+
a send(#define-method, #precision):
|
20
|
+
i
|
21
|
+
|
22
|
+
Pattern precision := 0
|
23
|
+
|
24
|
+
Named precision := @pattern precision
|
25
|
+
|
26
|
+
Predicate precision :=
|
27
|
+
@pattern precision + 1
|
28
|
+
|
29
|
+
(a: Pattern) <=> (b: Pattern) :=
|
30
|
+
a precision <=> b precision
|
31
|
+
|
32
|
+
(a: BlockPass) <=> (b: BlockPass) :=
|
33
|
+
a pattern <=> b pattern
|
34
|
+
|
35
|
+
-- if one constant is a subclass of another, it is
|
36
|
+
-- higher precision.
|
37
|
+
(a: Constant) <=> (b: Constant) :=
|
38
|
+
condition:
|
39
|
+
(a ancestors nil? || b ancestors nil?) ->
|
40
|
+
0
|
41
|
+
|
42
|
+
(a ancestors first == b ancestors first) ->
|
43
|
+
0
|
44
|
+
|
45
|
+
b ancestors include?(a ancestors first) ->
|
46
|
+
-1
|
47
|
+
|
48
|
+
a ancestors include?(b ancestors first) ->
|
49
|
+
1
|
50
|
+
|
51
|
+
otherwise ->
|
52
|
+
0
|
53
|
+
|
54
|
+
(a: HeadTail) <=> (b: HeadTail) :=
|
55
|
+
Atomy::Patterns
|
56
|
+
compare([a head, a tail], [b head, b tail])
|
57
|
+
|
58
|
+
(a: List) <=> (b: List) :=
|
59
|
+
Atomy::Patterns
|
60
|
+
compare(a patterns, b patterns)
|
61
|
+
|
62
|
+
(a: Splat) <=> (b: Splat) :=
|
63
|
+
a pattern <=> b pattern
|
64
|
+
|
65
|
+
(a: Default) <=> (b: Default) :=
|
66
|
+
a pattern <=> b pattern
|
67
|
+
(d: Default) <=> (p: Pattern) := d pattern <=> p
|
68
|
+
(p: Pattern) <=> (d: Default) := p <=> d pattern
|
69
|
+
|
70
|
+
(a: Named) <=> (b: Named) :=
|
71
|
+
a pattern <=> b pattern
|
72
|
+
(n: Named) <=> (p: Pattern) :=
|
73
|
+
n pattern <=> p
|
74
|
+
(p: Pattern) <=> (n: Named) :=
|
75
|
+
p <=> n pattern
|
76
|
+
|
77
|
+
|
78
|
+
-- equivalence ignores named patterns
|
79
|
+
(a: Named) =~ (b: Named) :=
|
80
|
+
a pattern =~ b pattern
|
81
|
+
Named =~ (p: Pattern) := pattern =~ p
|
82
|
+
Pattern =~ (n: Named) := (=~ n pattern)
|
83
|
+
|
84
|
+
Any =~ Any := true
|
85
|
+
|
86
|
+
(a: BlockPass) =~ (b: BlockPass) :=
|
87
|
+
a pattern =~ b pattern
|
88
|
+
|
89
|
+
(a: Constant) =~ (b: Constant) :=
|
90
|
+
a constant =~ b constant
|
91
|
+
|
92
|
+
(a: Default) =~ (b: Default) :=
|
93
|
+
a pattern =~ b pattern
|
94
|
+
Default =~ (p: Pattern) := pattern =~ p
|
95
|
+
Pattern =~ (n: Default) := (=~ n pattern)
|
96
|
+
|
97
|
+
(a: HeadTail) =~ (b: HeadTail) :=
|
98
|
+
a head =~ b head && a tail =~ b tail
|
99
|
+
|
100
|
+
(a: List) =~ (b: List) :=
|
101
|
+
a patterns zip(b patterns) all? [[a, b]]:
|
102
|
+
when(a nil? || b nil?):
|
103
|
+
return(false)
|
104
|
+
|
105
|
+
a =~ b
|
106
|
+
|
107
|
+
(a: Match) =~ (b: Match) :=
|
108
|
+
a value == b value
|
109
|
+
|
110
|
+
(a: SingletonClass) =~ (b: SingletonClass) :=
|
111
|
+
a body == b body
|
112
|
+
|
113
|
+
NamedClass =~ NamedClass := true
|
114
|
+
|
115
|
+
NamedGlobal =~ NamedGlobal := true
|
116
|
+
|
117
|
+
NamedInstance =~ NamedInstance := true
|
118
|
+
|
119
|
+
(a: Particle) =~ (b: Particle) :=
|
120
|
+
a value == b value
|
121
|
+
|
122
|
+
(a: QuasiQuote) =~ (b: QuasiQuote) :=
|
123
|
+
-- TODO: go through quotes.
|
124
|
+
a expression == b expression
|
125
|
+
|
126
|
+
(a: Quote) =~ (b: Quote) :=
|
127
|
+
a expression == b expression
|
128
|
+
|
129
|
+
(a: Splat) =~ (b: Splat) :=
|
130
|
+
a pattern =~ b pattern
|
131
|
+
|
132
|
+
(a: Attribute) =~ (b: Attribute) :=
|
133
|
+
a receiver == b receiver &&
|
134
|
+
a name == b name &&
|
135
|
+
a arguments == b arguments
|
136
|
+
|
137
|
+
Pattern =~ Pattern := false
|
138
|
+
|
139
|
+
|
140
|
+
-- helper for comparing aggregate patterns like lists
|
141
|
+
{ self } compare(xs, ys) := do:
|
142
|
+
total = 0
|
143
|
+
|
144
|
+
xs zip(ys) [[x, y]]:
|
145
|
+
unless(x nil? || y nil?):
|
146
|
+
total += x <=> y
|
147
|
+
|
148
|
+
total <=> 0
|
data/kernel/pretty.ay
ADDED
@@ -0,0 +1,283 @@
|
|
1
|
+
namespace(atomy/pretty)
|
2
|
+
|
3
|
+
dynamic(multiline?, false)
|
4
|
+
dynamic(context, #top)
|
5
|
+
dynamic(colored?, false)
|
6
|
+
|
7
|
+
comma-delim(ds) :=
|
8
|
+
hsep(comma punctuate(ds))
|
9
|
+
|
10
|
+
ident(n) := text(n [0, 1] + n [1 .. -1] tr("_", "-") gsub("_ns_", "/"))
|
11
|
+
|
12
|
+
module(Atomy::AST):
|
13
|
+
Block unamb := pretty
|
14
|
+
ClassVariable unamb := pretty
|
15
|
+
Constant unamb := pretty
|
16
|
+
GlobalVariable unamb := pretty
|
17
|
+
(InlinedBody ? @contents size < 2) unamb := pretty
|
18
|
+
InstanceVariable unamb := pretty
|
19
|
+
List unamb := pretty
|
20
|
+
Particle unamb := pretty
|
21
|
+
Primitive unamb := pretty
|
22
|
+
QuasiQuote unamb := pretty
|
23
|
+
Quote unamb := pretty
|
24
|
+
ScopedConstant unamb := pretty
|
25
|
+
Send unamb :=
|
26
|
+
if(from?(#binary, #send))
|
27
|
+
then: pretty
|
28
|
+
else: Doc parens(pretty)
|
29
|
+
Splice unamb := pretty
|
30
|
+
String unamb := pretty
|
31
|
+
ToplevelConstant unamb := pretty
|
32
|
+
Unary unamb := pretty
|
33
|
+
Unquote unamb := pretty
|
34
|
+
Variable unamb := pretty
|
35
|
+
Node unamb := Doc parens(pretty)
|
36
|
+
_ unamb := pretty
|
37
|
+
|
38
|
+
from(*where, &y) :=
|
39
|
+
let(context = where flatten, &y)
|
40
|
+
|
41
|
+
from?(*where) :=
|
42
|
+
[^context, where] match:
|
43
|
+
[(a: Array), (b: Array)] ->
|
44
|
+
a any? [x]: b include?(x)
|
45
|
+
[(a: Array), b] ->
|
46
|
+
a include?(b)
|
47
|
+
[a, (b: Array)] ->
|
48
|
+
b include?(a)
|
49
|
+
[a, b] ->
|
50
|
+
a == b
|
51
|
+
|
52
|
+
export-to(atomy):
|
53
|
+
String pretty := super colored(#yellow)
|
54
|
+
Integer pretty := super colored(#blue)
|
55
|
+
Float pretty := super colored(#blue)
|
56
|
+
TrueClass pretty := super colored(#green)
|
57
|
+
FalseClass pretty := super colored(#red)
|
58
|
+
NilClass pretty := super colored(#black)
|
59
|
+
Object pretty := Doc text(inspect)
|
60
|
+
|
61
|
+
Object show := pretty render
|
62
|
+
|
63
|
+
Doc pretty := self
|
64
|
+
|
65
|
+
Array pretty :=
|
66
|
+
doc: brackets(comma-delim(self all-pretty))
|
67
|
+
|
68
|
+
Particle pretty := doc:
|
69
|
+
wildcard = [c]:
|
70
|
+
if(c equal?(_undefined))
|
71
|
+
then: '_
|
72
|
+
else: c
|
73
|
+
|
74
|
+
operator? = self message to-s !~ r"^[a-z_]"
|
75
|
+
|
76
|
+
args = self arguments collect(&#(wildcard [_]))
|
77
|
+
|
78
|
+
msg+args =
|
79
|
+
if(operator?)
|
80
|
+
then:
|
81
|
+
text(self message to-s) <+> args first unamb
|
82
|
+
else:
|
83
|
+
ident(self message to-s) <>
|
84
|
+
parens(comma-delim(args all-pretty))
|
85
|
+
|
86
|
+
partial =
|
87
|
+
if(self receiver equal?(_undefined))
|
88
|
+
then:
|
89
|
+
if(operator?)
|
90
|
+
then: parens(msg+args)
|
91
|
+
else: msg+args
|
92
|
+
else: parens(self receiver unamb <+> msg+args)
|
93
|
+
|
94
|
+
text("#") <> partial
|
95
|
+
|
96
|
+
Particle to-s := show
|
97
|
+
|
98
|
+
Symbol pretty := do:
|
99
|
+
s = to-s
|
100
|
+
if(s =~ r"^[\p{Ll}_]([\p{L}\d\p{S}!@#%&*\-_\\:.\/\?])*$"(u))
|
101
|
+
then: Doc text("#") <> Doc ident(s)
|
102
|
+
else: Doc text("#") <> s pretty
|
103
|
+
|
104
|
+
Hash pretty := doc:
|
105
|
+
text("#") <>
|
106
|
+
brackets $:
|
107
|
+
comma-delim $:
|
108
|
+
self to-a collect [[k, v]]:
|
109
|
+
k unamb <+> text("->") <+> v unamb
|
110
|
+
|
111
|
+
module(Atomy::AST):
|
112
|
+
Assign pretty :=
|
113
|
+
from(#assign):
|
114
|
+
doc: @lhs unamb <+> text("=") <+> @rhs unamb
|
115
|
+
|
116
|
+
BinarySend pretty :=
|
117
|
+
from(#binary):
|
118
|
+
doc: @lhs unamb <+> text(@operator) <+> @rhs unamb
|
119
|
+
|
120
|
+
Block pretty :=
|
121
|
+
doc:
|
122
|
+
args =
|
123
|
+
if(@arguments empty?)
|
124
|
+
then: empty
|
125
|
+
else: brackets(from(#list): comma-delim(@arguments all-pretty))
|
126
|
+
|
127
|
+
contents = from(#list): comma-delim(@contents all-pretty)
|
128
|
+
if(from?(#send-block) && from?(#top))
|
129
|
+
then: args <> colon <+> contents
|
130
|
+
else: args <+> lbrace <+> contents <+> rbrace
|
131
|
+
|
132
|
+
BlockPass pretty :=
|
133
|
+
from(#unary):
|
134
|
+
doc: text("&") <> @body unamb
|
135
|
+
|
136
|
+
Class pretty := doc:
|
137
|
+
sub =
|
138
|
+
if(@superclass kind-of?(Primitive) && @superclass value == #nil)
|
139
|
+
then: empty
|
140
|
+
else: text("<") <+> from(#binary): @superclass unamb
|
141
|
+
|
142
|
+
name =
|
143
|
+
@name match:
|
144
|
+
Rubinius::AST::ClassName -> text(@name) name to-s
|
145
|
+
_ -> @name unamb
|
146
|
+
|
147
|
+
body = lbrace <+> semi-delim(@body) expressions <+> rbrace
|
148
|
+
|
149
|
+
text("class") <> text("(") <> name <+> sub <> text(")") <+> body
|
150
|
+
|
151
|
+
ClassVariable pretty := doc: ident(name to-s)
|
152
|
+
|
153
|
+
Constant pretty := doc: text(@identifier)
|
154
|
+
|
155
|
+
Define pretty :=
|
156
|
+
from(#define):
|
157
|
+
doc: @lhs unamb <+> text(":=") <+> @body unamb
|
158
|
+
|
159
|
+
GlobalVariable pretty := doc: ident(name to-s)
|
160
|
+
|
161
|
+
InstanceVariable pretty := doc: ident(name to-s)
|
162
|
+
|
163
|
+
List pretty :=
|
164
|
+
from(#list):
|
165
|
+
doc: brackets(comma-delim(@elements all-pretty))
|
166
|
+
|
167
|
+
Macro pretty := doc:
|
168
|
+
text("macro") <+> parens(@pattern pretty) <+> @body pretty
|
169
|
+
|
170
|
+
Particle pretty := doc: text("#") <> ident(@name)
|
171
|
+
|
172
|
+
Primitive pretty := doc:
|
173
|
+
@value match:
|
174
|
+
-- TODO: glitch with #doc/#onto
|
175
|
+
#"self" -> text("self")
|
176
|
+
#true -> text("true")
|
177
|
+
#false -> text("false")
|
178
|
+
#nil -> text("nil")
|
179
|
+
x -> text(x inspect)
|
180
|
+
|
181
|
+
QuasiQuote pretty :=
|
182
|
+
from(#unary):
|
183
|
+
doc: text("`") <> @expression unamb
|
184
|
+
|
185
|
+
Quote pretty :=
|
186
|
+
from(#unary):
|
187
|
+
doc: text("'") <> @expression unamb
|
188
|
+
|
189
|
+
ScopedConstant pretty :=
|
190
|
+
from(#scoped-constant):
|
191
|
+
doc:
|
192
|
+
@parent unamb <> text("::") <> text(@identifier)
|
193
|
+
|
194
|
+
Send pretty :=
|
195
|
+
doc:
|
196
|
+
block =
|
197
|
+
from(#send-block, ^context):
|
198
|
+
if(@block) then: @block unamb; else: empty
|
199
|
+
|
200
|
+
with-block = [x]:
|
201
|
+
condition:
|
202
|
+
^multiline? && @block is-a?(Block) -> do:
|
203
|
+
cs = from(#top): vcat(@block contents all-pretty) nest(2)
|
204
|
+
if(from?(#top))
|
205
|
+
then: x <> colon // cs
|
206
|
+
else: x <+> lbrace // cs // rbrace
|
207
|
+
|
208
|
+
from?(#top) && @block is-a?(Block) && @block arguments empty? ->
|
209
|
+
x <> block
|
210
|
+
|
211
|
+
otherwise ->
|
212
|
+
x <+> block
|
213
|
+
|
214
|
+
args =
|
215
|
+
from(#list):
|
216
|
+
if(@arguments empty?)
|
217
|
+
then: empty
|
218
|
+
else: parens(comma-delim(@arguments all-pretty))
|
219
|
+
|
220
|
+
condition:
|
221
|
+
@receiver kind-of?(Primitive) && @receiver value == #"self" ->
|
222
|
+
with-block [ident(@method-name) <> args]
|
223
|
+
|
224
|
+
otherwise ->
|
225
|
+
with-block [
|
226
|
+
from(#send) { @receiver unamb } <+>
|
227
|
+
ident(@method-name) <> args
|
228
|
+
]
|
229
|
+
|
230
|
+
Splice pretty :=
|
231
|
+
from(#unary):
|
232
|
+
doc: text("~*") <> @expression unamb
|
233
|
+
|
234
|
+
String pretty := Doc text(@value inspect)
|
235
|
+
|
236
|
+
ToplevelConstant pretty := doc: text("::") <> text(@identifier)
|
237
|
+
|
238
|
+
Unary pretty :=
|
239
|
+
from(#unary):
|
240
|
+
doc: text(@operator) <> @receiver unamb
|
241
|
+
|
242
|
+
Unquote pretty :=
|
243
|
+
from(#unary):
|
244
|
+
doc: text("~") <> @expression unamb
|
245
|
+
|
246
|
+
Variable pretty := doc: ident(@name)
|
247
|
+
|
248
|
+
InlinedBody pretty := doc:
|
249
|
+
if(^multiline?)
|
250
|
+
then:
|
251
|
+
from(#top): vcat(@expressions all-pretty)
|
252
|
+
else:
|
253
|
+
from(#list): comma-delim(@expressions all-pretty)
|
254
|
+
|
255
|
+
Or pretty := `(~@a || ~@b) pretty
|
256
|
+
|
257
|
+
And pretty := `(~@a && ~@b) pretty
|
258
|
+
|
259
|
+
Ensure pretty := doc:
|
260
|
+
@body pretty <+> text("ensuring:") <+> @ensure pretty
|
261
|
+
|
262
|
+
|
263
|
+
Array all-pretty := collect [x]: x pretty
|
264
|
+
|
265
|
+
Doc colored(color) := do:
|
266
|
+
-- only makes sense to colorize if we're outputting to a terminal
|
267
|
+
unless(^output-port tty? && ^colored?):
|
268
|
+
return(self)
|
269
|
+
|
270
|
+
codes =
|
271
|
+
[ #black
|
272
|
+
#red
|
273
|
+
#green
|
274
|
+
#yellow
|
275
|
+
#blue
|
276
|
+
#magenta
|
277
|
+
#cyan
|
278
|
+
#white
|
279
|
+
] zip((0 .. 7) to-a)
|
280
|
+
|
281
|
+
hash = Hash [codes]
|
282
|
+
|
283
|
+
Doc text("\e[9" + hash [color] to-s + "m") <> self <> Doc text("\e[0m")
|