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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 62af6cac78961b06d75c20c9dc3ae90f7fca1fdd
4
- data.tar.gz: c0ac851cfa0bb9689b15f442767f9f0cdb8128ad
3
+ metadata.gz: eb2b96c8ce99460a0f0600c74786046f08607e3b
4
+ data.tar.gz: 275292c5f7ab03b089bcb7625b77f65e882db345
5
5
  SHA512:
6
- metadata.gz: 7749e039df36ab97e64a173178d3822a44aa0fe91b5a3dd236d5ad66e754c894c07c3cc1a6538466d9b92093e142aa8cf9b0f89e5b07749080b1afdfca9c93e1
7
- data.tar.gz: cdb16e0afc5cd0919b82679c5feb42706223e46d3534e3c5d7bdf779d35c1737f66020108d19806f5ee3eab4aabe2f37c40387001b7a9b1280d65b3a0b709621
6
+ metadata.gz: 8c56afef1d99fa1cb8e22c57dfe7a68520b09081a8699fac80293931a541ca751ab02cc852eef1e82dca3e5b8355cce4eaa2ce2deeb1fb30f30f47a50071f035
7
+ data.tar.gz: 6233206c5afa18e8aa828baa06fd8d9d5b96ecfb31a6aa66f74e6bd7c42dd28c2703aa435c44a2a292bd47ebc4ddbcd479899a3bc12bd69834d221ccc1d95dc8
@@ -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
@@ -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"
@@ -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 = evaluate_sequences(node, mod)
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
- res = evaluate_sequences(sub, mod)
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}")
@@ -1,3 +1,3 @@
1
1
  module Atomy
2
- VERSION = "0.6.4"
2
+ VERSION = "0.6.5"
3
3
  end
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
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-09 00:00:00.000000000 Z
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