atomy 0.6.4 → 0.6.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/kernel/format.ay +14 -0
- data/kernel/format/data.ay +56 -0
- data/kernel/format/formatter.ay +346 -0
- data/kernel/format/parser.ay +75 -0
- data/kernel/therie.ay +193 -0
- data/lib/atomy/codeloader.rb +75 -5
- data/lib/atomy/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb2b96c8ce99460a0f0600c74786046f08607e3b
|
4
|
+
data.tar.gz: 275292c5f7ab03b089bcb7625b77f65e882db345
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c56afef1d99fa1cb8e22c57dfe7a68520b09081a8699fac80293931a541ca751ab02cc852eef1e82dca3e5b8355cce4eaa2ce2deeb1fb30f30f47a50071f035
|
7
|
+
data.tar.gz: 6233206c5afa18e8aa828baa06fd8d9d5b96ecfb31a6aa66f74e6bd7c42dd28c2703aa435c44a2a292bd47ebc4ddbcd479899a3bc12bd69834d221ccc1d95dc8
|
data/kernel/format.ay
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
use(require("core"))
|
2
|
+
use(require("quotes"))
|
3
|
+
use(require("file"))
|
4
|
+
|
5
|
+
base = File expand-path("../", __FILE__)
|
6
|
+
|
7
|
+
Atomy const-set(.Format, Module new)
|
8
|
+
|
9
|
+
use(require(base + "/format/data"))
|
10
|
+
use(require(base + "/format/formatter"))
|
11
|
+
use(require(base + "/format/parser"))
|
12
|
+
|
13
|
+
macro-quoter(f) [c]:
|
14
|
+
Atomy Format Parser parse(c)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
use(require("core"))
|
2
|
+
use(require("define"))
|
3
|
+
use(require("array"))
|
4
|
+
use(require("control-flow"))
|
5
|
+
use(require("node"))
|
6
|
+
use(require("cosmetics"))
|
7
|
+
use(require("particles"))
|
8
|
+
|
9
|
+
Atomy Format open:
|
10
|
+
ast:
|
11
|
+
Segment:
|
12
|
+
Chunk([.flags], @text)
|
13
|
+
String([.flags])
|
14
|
+
Decimal([.flags])
|
15
|
+
Hex([.flags])
|
16
|
+
Octal([.flags])
|
17
|
+
Binary([.flags])
|
18
|
+
Radix([.flags])
|
19
|
+
Float([.flags])
|
20
|
+
Exponent([.flags])
|
21
|
+
General([.flags])
|
22
|
+
Character([.flags])
|
23
|
+
Any([.flags])
|
24
|
+
Pluralize(.singular, [.flags], .plural?)
|
25
|
+
Lowercase(.content, [.flags])
|
26
|
+
Capitalize(.content, [.flags])
|
27
|
+
Uppercase(.content, [.flags])
|
28
|
+
Justify([.segments], [.flags])
|
29
|
+
Skip([.flags])
|
30
|
+
Indirection([.flags])
|
31
|
+
Iterate(.content, [.flags])
|
32
|
+
Break([.flags])
|
33
|
+
Conditional([.branches], [.flags], .default?)
|
34
|
+
|
35
|
+
Flag:
|
36
|
+
Number(@value?)
|
37
|
+
Symbol(@character)
|
38
|
+
ZeroPad
|
39
|
+
Precision(@value)
|
40
|
+
|
41
|
+
Formatter([.segments])
|
42
|
+
|
43
|
+
Segment symbol(m)? :=
|
44
|
+
@flags any? [f]:
|
45
|
+
f match:
|
46
|
+
Symbol -> f character == m
|
47
|
+
_ -> false
|
48
|
+
|
49
|
+
Segment precision :=
|
50
|
+
@flags find .is-a(Precision)? ?value()
|
51
|
+
|
52
|
+
Segment zero-pad? :=
|
53
|
+
@flags any? [f]:
|
54
|
+
f match:
|
55
|
+
ZeroPad -> true
|
56
|
+
_ -> false
|
@@ -0,0 +1,346 @@
|
|
1
|
+
use("core")
|
2
|
+
use("define")
|
3
|
+
use("control-flow")
|
4
|
+
use("loop")
|
5
|
+
use("regexp")
|
6
|
+
use("particles")
|
7
|
+
use("patterns")
|
8
|
+
|
9
|
+
pretty = require("pretty")
|
10
|
+
|
11
|
+
|
12
|
+
Atomy Format open:
|
13
|
+
peek-input() = @input [@position]
|
14
|
+
|
15
|
+
next-input() =
|
16
|
+
peek-input tap:
|
17
|
+
@position += 1
|
18
|
+
|
19
|
+
next-inputs() = @input drop(@position) or []
|
20
|
+
|
21
|
+
pluralize(s) =
|
22
|
+
condition:
|
23
|
+
s =~ r"o$"(i) ->
|
24
|
+
s + "es"
|
25
|
+
|
26
|
+
s =~ r"[aeiou]$"(i) ->
|
27
|
+
s + "s"
|
28
|
+
|
29
|
+
s =~ r"(?<root>.+[aeiou])y$"(i) ->
|
30
|
+
s + "s"
|
31
|
+
|
32
|
+
s =~ r"(lay-by|stand-by)$"(i) ->
|
33
|
+
s + "s"
|
34
|
+
|
35
|
+
s =~ r"(.+)y$"(i) ->
|
36
|
+
$1 + "es"
|
37
|
+
|
38
|
+
s =~ r"(.+)us$"(i) ->
|
39
|
+
$1 + ""
|
40
|
+
|
41
|
+
s =~ r"(.+)sis$"(i) ->
|
42
|
+
$1 + "es"
|
43
|
+
|
44
|
+
s =~ r"(.+)(ex|ix)$"(i) ->
|
45
|
+
$1 + "ces"
|
46
|
+
|
47
|
+
s =~ r"(.+)(ss|sh|ch|dge)$"(i) ->
|
48
|
+
s + "es"
|
49
|
+
|
50
|
+
otherwise ->
|
51
|
+
s + "s"
|
52
|
+
|
53
|
+
sub-format(sub) = do:
|
54
|
+
sub position = @position
|
55
|
+
out = sub scan(*@input)
|
56
|
+
@position = sub position
|
57
|
+
sub reset!
|
58
|
+
out
|
59
|
+
|
60
|
+
iterate(f) =
|
61
|
+
until(next-inputs empty? or @stop?):
|
62
|
+
@output << sub-format(f)
|
63
|
+
|
64
|
+
iterate-max(max, f) =
|
65
|
+
max times:
|
66
|
+
when(next-inputs empty? or @stop?):
|
67
|
+
break
|
68
|
+
|
69
|
+
@output << sub-format(f)
|
70
|
+
|
71
|
+
number(s, default = 1) =
|
72
|
+
if(num = s flags find .is-a(Number)?)
|
73
|
+
then: num value or next-inputs size
|
74
|
+
else: default
|
75
|
+
|
76
|
+
next-number(s) =
|
77
|
+
number(s, nil) or next-input
|
78
|
+
|
79
|
+
justified(j, s, left? = false) =
|
80
|
+
if(w = number(j, nil))
|
81
|
+
then:
|
82
|
+
padding = if(j zero-pad?) then: "0"; else: " "
|
83
|
+
|
84
|
+
condition:
|
85
|
+
j symbol("=")? or j symbol("<")? and j symbol(">")? ->
|
86
|
+
s center(w, padding)
|
87
|
+
|
88
|
+
left? and not j symbol(">")? or j symbol("<")? ->
|
89
|
+
s ljust(w, padding)
|
90
|
+
|
91
|
+
otherwise ->
|
92
|
+
s rjust(w, padding)
|
93
|
+
else:
|
94
|
+
s
|
95
|
+
|
96
|
+
char(c, n: Integer) = justified(c, n chr, true)
|
97
|
+
char(c, s) = justified(c, s to-s [0, 1], true)
|
98
|
+
|
99
|
+
integer(i, base) = justified(i, Integer(next-input) to-s(base))
|
100
|
+
|
101
|
+
float(f, x) = do:
|
102
|
+
format =
|
103
|
+
if(f precision)
|
104
|
+
then: "%." + f precision to-s + x
|
105
|
+
else: "%" + x
|
106
|
+
|
107
|
+
justified(f, sprintf(format, Float(next-input)))
|
108
|
+
|
109
|
+
spaced(_, _, _, []) = ""
|
110
|
+
spaced(j, _, left, [s]) =
|
111
|
+
if(j symbol(">")? or j symbol("=")?)
|
112
|
+
then: s + " " * left
|
113
|
+
else: " " * left + s
|
114
|
+
spaced(j, average, left, s . ss) =
|
115
|
+
[ s
|
116
|
+
" " * average
|
117
|
+
spaced(j, average, left - average, ss)
|
118
|
+
] join
|
119
|
+
|
120
|
+
justify-to(_, _, []) = ""
|
121
|
+
justify-to(j, to, all: s . ss) = do:
|
122
|
+
needed = to - all collect .size inject .(+ _)
|
123
|
+
|
124
|
+
spacings =
|
125
|
+
condition:
|
126
|
+
j symbol("<")? and j symbol(">")? or j symbol("=")? ->
|
127
|
+
all size + 1
|
128
|
+
|
129
|
+
j symbol("<")? ->
|
130
|
+
all size
|
131
|
+
|
132
|
+
j symbol(">")? ->
|
133
|
+
all size
|
134
|
+
|
135
|
+
otherwise ->
|
136
|
+
all size - 1
|
137
|
+
|
138
|
+
naive-average = needed / spacings
|
139
|
+
|
140
|
+
average =
|
141
|
+
if(needed - naive-average * spacings >= spacings - 1)
|
142
|
+
then: naive-average + 1
|
143
|
+
else: naive-average
|
144
|
+
|
145
|
+
condition:
|
146
|
+
j symbol("<")? or j symbol("=")? ->
|
147
|
+
[ " " * naive-average
|
148
|
+
s
|
149
|
+
" " * average
|
150
|
+
spaced(j, average, needed - naive-average - average, ss)
|
151
|
+
] join
|
152
|
+
|
153
|
+
otherwise ->
|
154
|
+
[ s
|
155
|
+
" " * naive-average
|
156
|
+
spaced(j, average, needed - naive-average, ss)
|
157
|
+
] join
|
158
|
+
|
159
|
+
justify(j, [s]) = justified(j, s)
|
160
|
+
justify(j, ss) =
|
161
|
+
if(to = number(j, nil))
|
162
|
+
then: justify-to(j, to, ss)
|
163
|
+
else: ss join
|
164
|
+
|
165
|
+
|
166
|
+
process(c: Chunk) =
|
167
|
+
@output << c text
|
168
|
+
|
169
|
+
process(s: String) =
|
170
|
+
@output << justified(s, next-input to-s, true)
|
171
|
+
|
172
|
+
process(i: Decimal) =
|
173
|
+
@output << integer(i, 10)
|
174
|
+
|
175
|
+
process(i: Hex) =
|
176
|
+
@output << integer(i, 16)
|
177
|
+
|
178
|
+
process(i: Octal) =
|
179
|
+
@output << integer(i, 8)
|
180
|
+
|
181
|
+
process(i: Binary) =
|
182
|
+
@output << integer(i, 2)
|
183
|
+
|
184
|
+
process(i: Radix) =
|
185
|
+
@output << integer(i, i precision)
|
186
|
+
|
187
|
+
process(f: Float) =
|
188
|
+
@output << float(f, "f")
|
189
|
+
|
190
|
+
process(f: Exponent) =
|
191
|
+
@output << float(f, "e")
|
192
|
+
|
193
|
+
process(f: General) =
|
194
|
+
@output << float(f, "g")
|
195
|
+
|
196
|
+
process(c: Character) =
|
197
|
+
@output << char(c, next-input)
|
198
|
+
|
199
|
+
process(a: Any) =
|
200
|
+
@output << justified(a, pretty show(next-input), true)
|
201
|
+
|
202
|
+
process(p: Pluralize) = do:
|
203
|
+
num =
|
204
|
+
if(p symbol(">")?)
|
205
|
+
then: peek-input
|
206
|
+
else: next-input
|
207
|
+
|
208
|
+
@output <<
|
209
|
+
condition:
|
210
|
+
num == 1 ->
|
211
|
+
sub-format(p singular)
|
212
|
+
|
213
|
+
p plural ->
|
214
|
+
sub-format(p plural)
|
215
|
+
|
216
|
+
otherwise ->
|
217
|
+
pluralize(sub-format(p singular))
|
218
|
+
|
219
|
+
process(l: Lowercase) =
|
220
|
+
@output << sub-format(l content) downcase
|
221
|
+
|
222
|
+
process(c: Capitalize) = do:
|
223
|
+
words = sub-format(c content) split(" ")
|
224
|
+
number(c, words size) times [n]:
|
225
|
+
unless(n == 0):
|
226
|
+
@output << " "
|
227
|
+
|
228
|
+
@output << words shift capitalize
|
229
|
+
|
230
|
+
unless(words empty?):
|
231
|
+
@output << " " + words join(" ")
|
232
|
+
|
233
|
+
process(u: Uppercase) =
|
234
|
+
@output << sub-format(u content) upcase
|
235
|
+
|
236
|
+
process(s: Skip) =
|
237
|
+
if(s symbol("<")?)
|
238
|
+
then: @position -= number(s)
|
239
|
+
else: @position += number(s)
|
240
|
+
|
241
|
+
process(i: Indirection) =
|
242
|
+
@output <<
|
243
|
+
if(i symbol("*")?)
|
244
|
+
then: sub-format(next-input)
|
245
|
+
else: next-input format(*next-input)
|
246
|
+
|
247
|
+
process(i: Iterate) = do:
|
248
|
+
splat? = i symbol("*")?
|
249
|
+
sub? = i symbol(".")?
|
250
|
+
always-run? = i symbol("+")?
|
251
|
+
iterations = number(i, nil)
|
252
|
+
|
253
|
+
inputs =
|
254
|
+
if(splat?)
|
255
|
+
then: next-inputs
|
256
|
+
else: next-input
|
257
|
+
|
258
|
+
before = [@input, @position]
|
259
|
+
|
260
|
+
when(inputs empty? and always-run? and
|
261
|
+
iterations != 0):
|
262
|
+
@output << sub-format(i content)
|
263
|
+
return(nil)
|
264
|
+
|
265
|
+
condition:
|
266
|
+
iterations:
|
267
|
+
@input = inputs
|
268
|
+
@position = 0
|
269
|
+
iterate-max(iterations, i content)
|
270
|
+
|
271
|
+
sub?:
|
272
|
+
@iterating = inputs
|
273
|
+
inputs each [is]:
|
274
|
+
@output << i content format(*is)
|
275
|
+
|
276
|
+
otherwise:
|
277
|
+
@input = inputs
|
278
|
+
@position = 0
|
279
|
+
iterate(i content)
|
280
|
+
|
281
|
+
if(splat?)
|
282
|
+
then: @position = @input size
|
283
|
+
else: [@input, @position] = before
|
284
|
+
|
285
|
+
process(c: Conditional) =
|
286
|
+
[c symbol("?")?, c branches] match:
|
287
|
+
[true, t . (f . _)] ->
|
288
|
+
@output << sub-format(if(next-input) then: t; else: f)
|
289
|
+
|
290
|
+
[true, [t]] ->
|
291
|
+
when(next-input):
|
292
|
+
@output << sub-format(t)
|
293
|
+
|
294
|
+
_:
|
295
|
+
n = next-number(c)
|
296
|
+
if(n >= c branches size)
|
297
|
+
then:
|
298
|
+
when(c default):
|
299
|
+
@output << sub-format(c default)
|
300
|
+
else:
|
301
|
+
@output << sub-format(c branches [n])
|
302
|
+
|
303
|
+
process(j: Justify) =
|
304
|
+
@output <<
|
305
|
+
justify(j, j segments collect [s]: sub-format(s))
|
306
|
+
|
307
|
+
process(x) = raise("todo formatting: " + x inspect)
|
308
|
+
|
309
|
+
Formatter open:
|
310
|
+
attr-accessor(.position)
|
311
|
+
|
312
|
+
initialize(opts = nil) &blk := do:
|
313
|
+
super(opts) &blk
|
314
|
+
reset!
|
315
|
+
|
316
|
+
bytecode(g, mod) := do:
|
317
|
+
pos(g)
|
318
|
+
construct(g, mod)
|
319
|
+
|
320
|
+
reset! := do:
|
321
|
+
@input = []
|
322
|
+
@output = ""
|
323
|
+
@position = 0
|
324
|
+
@stop? = false
|
325
|
+
@iterating = []
|
326
|
+
|
327
|
+
scan(*@input) := do:
|
328
|
+
@segments each [s]:
|
329
|
+
s match:
|
330
|
+
Break ? symbol(".")? ->
|
331
|
+
when(@iterating empty?):
|
332
|
+
@stop? = true
|
333
|
+
break
|
334
|
+
|
335
|
+
Break ->
|
336
|
+
when(next-inputs empty?):
|
337
|
+
break
|
338
|
+
|
339
|
+
_ -> process(s)
|
340
|
+
|
341
|
+
@output
|
342
|
+
|
343
|
+
format(*inputs) :=
|
344
|
+
scan(*inputs) tap: reset!
|
345
|
+
|
346
|
+
alias-method(.[], .format)
|
@@ -0,0 +1,75 @@
|
|
1
|
+
use("core")
|
2
|
+
use("define")
|
3
|
+
use("block")
|
4
|
+
use("control-flow")
|
5
|
+
use("grammar")
|
6
|
+
use("init")
|
7
|
+
|
8
|
+
Atomy Format open:
|
9
|
+
parser(Parser):
|
10
|
+
%atomy := Atomy Parser
|
11
|
+
|
12
|
+
text(e) := [
|
13
|
+
<(/"[^\\%#{Regexp quote(e)}]+"/)> { text }
|
14
|
+
"\\" <(/"[%\(\)\{\}\[\]]"/)> { text }
|
15
|
+
"\\" e=(%atomy(escape)) { e }
|
16
|
+
]
|
17
|
+
|
18
|
+
nested(e) := c=(text(e)+) { init(Chunk, text: c join) }
|
19
|
+
|
20
|
+
chunk := nested("")
|
21
|
+
|
22
|
+
flagged := "%" fs=(flag*) s=(segment) { s flags = fs, s }
|
23
|
+
|
24
|
+
flag := [
|
25
|
+
"#" { Number new }
|
26
|
+
"0" &("." /"\d"/ | /"\d"/) { ZeroPad new }
|
27
|
+
"." <(/"\d+"/)> { init(Precision, value: text to-i) }
|
28
|
+
<(/"\d+"/)> { init(Number, value: text to-i) }
|
29
|
+
<(/"[\.\+\*=<>,\?]"/)> { init(Symbol, character: text) }
|
30
|
+
]
|
31
|
+
|
32
|
+
segment := [
|
33
|
+
"p" "(" s=(sub(")")) ")" ("(" p=(sub(")")) ")")? {
|
34
|
+
Pluralize new [n]:
|
35
|
+
n singular = s
|
36
|
+
n plural = p
|
37
|
+
}
|
38
|
+
"l" "(" c=(sub(")")) ")" { init(Lowercase, content: c) }
|
39
|
+
"c" "(" c=(sub(")")) ")" { init(Capitalize, content: c) }
|
40
|
+
"u" "(" c=(sub(")")) ")" { init(Uppercase, content: c) }
|
41
|
+
"j" cs=(("(" c=(sub(")")) ")" { c })+) { init(Justify, segments: cs) }
|
42
|
+
"{" c=(sub("}")) "}" { init(Iterate, content: c) }
|
43
|
+
bs=(("[" c=(sub("]")) "]" { c })+) ("(" d=(sub(")")) ")")? {
|
44
|
+
init(Conditional, branches -> Array(bs), default -> d)
|
45
|
+
}
|
46
|
+
"_" { Skip new }
|
47
|
+
"^" { Break new }
|
48
|
+
"%" { Indirection new }
|
49
|
+
"s" { String new }
|
50
|
+
"d" { Decimal new }
|
51
|
+
"x" { Hex new }
|
52
|
+
"o" { Octal new }
|
53
|
+
"b" { Binary new }
|
54
|
+
"r" { Radix new }
|
55
|
+
"f" { Float new }
|
56
|
+
"e" { Exponent new }
|
57
|
+
"g" { General new }
|
58
|
+
"c" { Character new }
|
59
|
+
"v" { Any new }
|
60
|
+
]
|
61
|
+
|
62
|
+
sub(e) := as=((flagged | nested(e))*) {
|
63
|
+
init(Formatter, segments -> Array(as))
|
64
|
+
}
|
65
|
+
|
66
|
+
root := x=(sub("")) !(/"."/) { x }
|
67
|
+
|
68
|
+
|
69
|
+
Parser singleton:
|
70
|
+
parse(source) :=
|
71
|
+
new(source) onto:
|
72
|
+
unless(parse):
|
73
|
+
raise-error
|
74
|
+
|
75
|
+
result
|
data/kernel/therie.ay
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
use(require("atomy"))
|
2
|
+
|
3
|
+
io = require("io")
|
4
|
+
|
5
|
+
nesting-level = dynamic(0)
|
6
|
+
running-stats = dynamic
|
7
|
+
|
8
|
+
data(Stats(@passed = 0, @failed = 0))
|
9
|
+
|
10
|
+
fn(indented(s)): (" " * (^nesting-level * 2)) + s
|
11
|
+
|
12
|
+
fn(colored(color, s)):
|
13
|
+
unless(^(io OutputPort) tty?):
|
14
|
+
return(s)
|
15
|
+
|
16
|
+
codes = [
|
17
|
+
.black
|
18
|
+
.red
|
19
|
+
.green
|
20
|
+
.yellow
|
21
|
+
.blue
|
22
|
+
.magenta
|
23
|
+
.cyan
|
24
|
+
.white
|
25
|
+
]
|
26
|
+
|
27
|
+
i"\e[3#{codes index(color)}m#{s}\e[0m"
|
28
|
+
|
29
|
+
fn(in-own-module &action):
|
30
|
+
ctx = Atomy Module new
|
31
|
+
ctx use(self)
|
32
|
+
ctx module-exec &action
|
33
|
+
|
34
|
+
|
35
|
+
def(theorize &tests):
|
36
|
+
with(running-stats = Stats new):
|
37
|
+
tests call
|
38
|
+
puts("")
|
39
|
+
|
40
|
+
stats = ^running-stats
|
41
|
+
|
42
|
+
puts(
|
43
|
+
f"total of %d tests (%s passed, %s failed)" [
|
44
|
+
stats failed + stats passed
|
45
|
+
colored(.green, stats passed)
|
46
|
+
if(stats failed == 0)
|
47
|
+
then: "0"
|
48
|
+
else: colored(.red, stats failed)
|
49
|
+
])
|
50
|
+
|
51
|
+
stats
|
52
|
+
|
53
|
+
|
54
|
+
def(describe(what) &body):
|
55
|
+
puts(indented(f"- %s" [what]))
|
56
|
+
|
57
|
+
with(nesting-level = (^nesting-level + 1)):
|
58
|
+
in-own-module &body
|
59
|
+
|
60
|
+
nil
|
61
|
+
|
62
|
+
alias-method(.context, .describe)
|
63
|
+
|
64
|
+
|
65
|
+
def(let(name) &body):
|
66
|
+
define-method(name):
|
67
|
+
res = instance-exec &body
|
68
|
+
|
69
|
+
singleton:
|
70
|
+
define-method(name): res
|
71
|
+
|
72
|
+
res
|
73
|
+
|
74
|
+
def(subject &body): def(.subject) &body
|
75
|
+
|
76
|
+
|
77
|
+
def(it(description) &tests):
|
78
|
+
do {
|
79
|
+
in-own-module &tests
|
80
|
+
puts(indented(colored(.green, f"✓ %s" [description])))
|
81
|
+
} rescue {
|
82
|
+
e:
|
83
|
+
when(^running-stats):
|
84
|
+
^running-stats failed += 1
|
85
|
+
|
86
|
+
puts(indented(colored(.red, f"✗ %s" [description])))
|
87
|
+
puts(
|
88
|
+
indented(
|
89
|
+
colored(
|
90
|
+
.yellow
|
91
|
+
f" ` %s: %s" [
|
92
|
+
e class name
|
93
|
+
e message
|
94
|
+
])))
|
95
|
+
|
96
|
+
e backtrace first((ENV["THERIE_BT_LIMIT"] or 5) to-i) each [l]:
|
97
|
+
puts(indented(f" %s" [colored(.cyan, l)]))
|
98
|
+
} else:
|
99
|
+
when(^running-stats):
|
100
|
+
^running-stats passed += 1
|
101
|
+
|
102
|
+
nil
|
103
|
+
|
104
|
+
|
105
|
+
data(Actuality(@value = nil, @action = nil))
|
106
|
+
|
107
|
+
def(expect(value)): Actuality new(value)
|
108
|
+
def(expect &action): Actuality new(nil, action)
|
109
|
+
|
110
|
+
def(Actuality to): ExpectTo new(self)
|
111
|
+
def(Actuality to-not): ExpectTo new(self, true)
|
112
|
+
|
113
|
+
|
114
|
+
data(ExpectTo(@actual, @negated? = false))
|
115
|
+
|
116
|
+
def(ExpectTo(actual, negated) match(matcher)):
|
117
|
+
matched = matcher matches?(actual)
|
118
|
+
|
119
|
+
condition:
|
120
|
+
negated && matched:
|
121
|
+
/raise(matcher negative-failure-message(actual))
|
122
|
+
|
123
|
+
negated && !matched:
|
124
|
+
true
|
125
|
+
|
126
|
+
!matched:
|
127
|
+
/raise(matcher failure-message(actual))
|
128
|
+
|
129
|
+
negated:
|
130
|
+
true
|
131
|
+
|
132
|
+
|
133
|
+
data(Matcher)
|
134
|
+
|
135
|
+
def(Matcher matches?(actual)): /error(.not-implemented)
|
136
|
+
def(Matcher failure-message(actual)): /error(.not-implemented)
|
137
|
+
def(Matcher negative-failure-message(actual)): /error(.not-implemented)
|
138
|
+
|
139
|
+
Matcher data: EqualityMatcher(@value)
|
140
|
+
def(ExpectTo be(value)): match(EqualityMatcher new(value))
|
141
|
+
def(EqualityMatcher(value) matches?(actual)): actual value == value
|
142
|
+
def(EqualityMatcher(value) failure-message(actual)):
|
143
|
+
i"expected #{actual value} to be #{value}"
|
144
|
+
def(EqualityMatcher(value) negative-failure-message(actual)):
|
145
|
+
i"expected #{actual value} to not be #{value}, but it was"
|
146
|
+
|
147
|
+
|
148
|
+
Matcher data: RaiseMatcher(@exception, @message = nil)
|
149
|
+
def(ExpectTo raise(exception, message = nil)):
|
150
|
+
match(RaiseMatcher new(exception, message))
|
151
|
+
def(RaiseMatcher matches?(actual)):
|
152
|
+
actual action rescue {
|
153
|
+
e:
|
154
|
+
@raised = e
|
155
|
+
@raised is-a?(@exception)
|
156
|
+
} else: false
|
157
|
+
def(RaiseMatcher failure-message(actual)):
|
158
|
+
if(@raised)
|
159
|
+
then: i"expected #{@exception}, got #{@raised class}: #{@raised}"
|
160
|
+
else: i"expected #{@exception} but nothing was raised"
|
161
|
+
def(RaiseMatcher negative-failure-message(actual)):
|
162
|
+
i"expected #{@exception} to not be raised, but it was"
|
163
|
+
|
164
|
+
|
165
|
+
Matcher data: ErrorMatcher(@error)
|
166
|
+
def(ExpectTo error(error)): match(ErrorMatcher new(error))
|
167
|
+
def(ErrorMatcher matches?(actual)):
|
168
|
+
with-restarts(errored(matched?) -> matched?) {
|
169
|
+
actual action call
|
170
|
+
false
|
171
|
+
} bind {
|
172
|
+
(e: ExceptionError):
|
173
|
+
raise(e exception)
|
174
|
+
|
175
|
+
(e: Error):
|
176
|
+
@errored = e
|
177
|
+
/restart(.errored, e kind-of?(@error))
|
178
|
+
}
|
179
|
+
def(ErrorMatcher failure-message(actual)):
|
180
|
+
if(@errored)
|
181
|
+
then: i"expected #{@error}, got #{@errored class}: #{@errored}"
|
182
|
+
else: i"expected #{@error} but nothing was signalled"
|
183
|
+
def(ErrorMatcher negative-failure-message(actual)):
|
184
|
+
i"expected #{@error} to not be signalled, but it was"
|
185
|
+
|
186
|
+
|
187
|
+
Matcher data: KindMatcher(@class)
|
188
|
+
def(ExpectTo be-a(class)): match(KindMatcher new(class))
|
189
|
+
def(KindMatcher matches?(actual)): actual value is-a?(@class)
|
190
|
+
def(KindMatcher failure-message(actual)):
|
191
|
+
i"expected #{actual value} (#{actual value class}) to be a #{@class}"
|
192
|
+
def(KindMatcher negative-failure-message(actual)):
|
193
|
+
i"expected #{actual value} (#{actual value class}) to not be a #{@class}, but it was"
|
data/lib/atomy/codeloader.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
|
1
3
|
require "atomy/bootstrap"
|
2
4
|
require "atomy/compiler"
|
3
5
|
require "atomy/parser"
|
4
6
|
require "atomy/module"
|
5
7
|
|
8
|
+
require "rubinius/compiler"
|
9
|
+
require "rubinius/compiler/compiled_file"
|
10
|
+
|
6
11
|
module Atomy
|
7
12
|
module CodeLoader
|
8
13
|
LOADED_MODULES = {}
|
@@ -143,24 +148,55 @@ module Atomy
|
|
143
148
|
mod = Atomy::Module.new { use(Atomy::Bootstrap) }
|
144
149
|
mod.file = file.to_sym
|
145
150
|
|
151
|
+
compiled_file_name = CodeTools::Compiler.compiled_name(file)
|
152
|
+
if should_load_compiled_file(compiled_file_name, file)
|
153
|
+
code_loader = Rubinius::CodeLoader.new(compiled_file_name)
|
154
|
+
code = code_loader.load_compiled_file(compiled_file_name, 0, 0)
|
155
|
+
|
156
|
+
Rubinius.attach_method(
|
157
|
+
:__script__,
|
158
|
+
code,
|
159
|
+
mod.compile_context.constant_scope,
|
160
|
+
mod)
|
161
|
+
|
162
|
+
res = mod.__script__
|
163
|
+
|
164
|
+
return [res, mod]
|
165
|
+
end
|
166
|
+
|
146
167
|
node = Atomy::Parser.parse_file(file)
|
147
168
|
|
148
|
-
res =
|
169
|
+
res = nil
|
170
|
+
code =
|
171
|
+
Atomy::Compiler.package(mod.file) do |gen|
|
172
|
+
res = evaluate_sequences(gen, node, mod)
|
173
|
+
end
|
174
|
+
|
175
|
+
if ENV["DEBUG"]
|
176
|
+
printer = CodeTools::Compiler::MethodPrinter.new
|
177
|
+
printer.bytecode = true
|
178
|
+
printer.print_method(code)
|
179
|
+
end
|
180
|
+
|
181
|
+
write_compiled_file(compiled_file_name, mod, code) if compiled_file_name
|
149
182
|
|
150
183
|
[res, mod]
|
151
184
|
end
|
152
185
|
|
153
|
-
def evaluate_sequences(n, mod)
|
186
|
+
def evaluate_sequences(gen, n, mod)
|
154
187
|
if n.is_a?(Atomy::Grammar::AST::Sequence)
|
155
188
|
res = nil
|
156
189
|
|
157
|
-
n.nodes.each do |sub|
|
158
|
-
|
190
|
+
n.nodes.each.with_index do |sub, i|
|
191
|
+
gen.pop unless i == 0
|
192
|
+
res = evaluate_sequences(gen, sub, mod)
|
159
193
|
end
|
160
194
|
|
161
195
|
res
|
162
196
|
else
|
163
|
-
mod.evaluate(n, mod.compile_context)
|
197
|
+
res = mod.evaluate(n, mod.compile_context)
|
198
|
+
mod.compile(gen, n)
|
199
|
+
res
|
164
200
|
end
|
165
201
|
end
|
166
202
|
|
@@ -191,6 +227,40 @@ module Atomy
|
|
191
227
|
".ay"
|
192
228
|
end
|
193
229
|
|
230
|
+
def should_load_compiled_file(compiled_file, source_file)
|
231
|
+
return false unless compiled_file
|
232
|
+
return false unless File.exists?(compiled_file)
|
233
|
+
|
234
|
+
compiled_mtime = File.mtime(compiled_file)
|
235
|
+
return false if File.mtime(source_file) > compiled_mtime
|
236
|
+
|
237
|
+
module_list_file_name = compiled_file + ".modules"
|
238
|
+
if File.exists?(module_list_file_name)
|
239
|
+
File.open(module_list_file_name, "r") do |io|
|
240
|
+
io.each_line do |line|
|
241
|
+
mod_file = line.rstrip
|
242
|
+
return false if File.mtime(mod_file) > compiled_mtime
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
true
|
248
|
+
end
|
249
|
+
|
250
|
+
def write_compiled_file(compiled_file_name, mod, code)
|
251
|
+
FileUtils.mkdir_p(File.expand_path("../", compiled_file_name))
|
252
|
+
CodeTools::CompiledFile.dump(code, compiled_file_name, Rubinius::Signature, 0)
|
253
|
+
|
254
|
+
module_list_file_name = compiled_file_name + ".modules"
|
255
|
+
File.open(module_list_file_name, "w") do |io|
|
256
|
+
mod.singleton_class.included_modules.each do |used_module|
|
257
|
+
next if used_module == mod
|
258
|
+
next unless used_module.is_a?(Atomy::Module) && used_module.file
|
259
|
+
io.puts(used_module.file.to_s)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
194
264
|
def search_path(path, load_paths)
|
195
265
|
load_paths.each do |load_path|
|
196
266
|
if found = find_source("#{load_path}/#{path}")
|
data/lib/atomy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: atomy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Suraci
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: kpeg
|
@@ -101,6 +101,10 @@ files:
|
|
101
101
|
- kernel/doc.ay
|
102
102
|
- kernel/dynamic.ay
|
103
103
|
- kernel/file.ay
|
104
|
+
- kernel/format.ay
|
105
|
+
- kernel/format/data.ay
|
106
|
+
- kernel/format/formatter.ay
|
107
|
+
- kernel/format/parser.ay
|
104
108
|
- kernel/grammar.ay
|
105
109
|
- kernel/hash.ay
|
106
110
|
- kernel/interpolation.ay
|
@@ -117,6 +121,7 @@ files:
|
|
117
121
|
- kernel/regexp.ay
|
118
122
|
- kernel/repl.ay
|
119
123
|
- kernel/stack-local.ay
|
124
|
+
- kernel/therie.ay
|
120
125
|
- lib/atomy.rb
|
121
126
|
- lib/atomy/bootstrap.rb
|
122
127
|
- lib/atomy/code/assign.rb
|