myco 0.1.4 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/lib/myco/bootstrap/find_constant.rb +4 -11
  3. data/lib/myco/code_loader.rb +2 -1
  4. data/lib/myco/code_tools/AST/ConstantAccess.my +47 -3
  5. data/lib/myco/code_tools/AST/ConstantAccess.my.rb +13 -9
  6. data/lib/myco/code_tools/AST/ConstantAssignment.my +1 -5
  7. data/lib/myco/code_tools/AST/ConstantAssignment.my.rb +3 -9
  8. data/lib/myco/code_tools/AST/ToRuby.my +5 -2
  9. data/lib/myco/code_tools/AST/ToRuby.my.rb +7 -3
  10. data/lib/myco/code_tools/AST.my +1 -0
  11. data/lib/myco/code_tools/AST.my.rb +9 -1
  12. data/lib/myco/code_tools/Parser.my +24 -0
  13. data/lib/myco/code_tools/Parser.my.rb +25 -0
  14. data/lib/myco/code_tools/parser/MycoBuilder.my +67 -0
  15. data/lib/myco/code_tools/parser/MycoBuilder.my.rb +99 -0
  16. data/lib/myco/code_tools/parser/MycoCharacterClasses.my +20 -0
  17. data/lib/myco/code_tools/parser/MycoCharacterClasses.my.rb +56 -0
  18. data/lib/myco/code_tools/parser/MycoGrammar.my +564 -0
  19. data/lib/myco/code_tools/parser/MycoGrammar.my.rb +1851 -0
  20. data/lib/myco/code_tools/parser/MycoTokens.my +78 -0
  21. data/lib/myco/code_tools/parser/MycoTokens.my.rb +170 -0
  22. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Builder.my +4 -0
  23. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Builder.my.rb +5 -0
  24. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeHelpers.my +142 -0
  25. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeHelpers.my.rb +181 -0
  26. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeInstructions.my +420 -0
  27. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeInstructions.my.rb +415 -0
  28. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeParser.my +137 -0
  29. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/BytecodeParser.my.rb +237 -0
  30. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Constructions.my +183 -0
  31. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Constructions.my.rb +370 -0
  32. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Grammar.my +65 -0
  33. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Grammar.my.rb +83 -0
  34. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Instructions.my +139 -0
  35. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Instructions.my.rb +284 -0
  36. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Machine.my +37 -0
  37. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Machine.my.rb +24 -0
  38. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Parser.my +42 -0
  39. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Parser.my.rb +52 -0
  40. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Patterns.my +123 -0
  41. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Patterns.my.rb +164 -0
  42. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Processor.my +236 -0
  43. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces/Processor.my.rb +339 -0
  44. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces.my +15 -0
  45. data/lib/myco/code_tools/parser/pegleromyces/lib/pegleromyces.my.rb +14 -0
  46. data/lib/myco/code_tools.rb +1 -1
  47. data/lib/myco/version.rb +1 -1
  48. data/lib/myco.rb +2 -0
  49. metadata +44 -25
  50. data/lib/myco/code_tools/parser/peg_parser.rb +0 -7182
  51. data/lib/myco/code_tools/parser.rb +0 -39
@@ -0,0 +1,420 @@
1
+ ##
2
+ # The following code is based on code from Pegarus by Brian Shirai.
3
+ # A link to the code in question and the relevant license is reproduced below.
4
+ #
5
+ # https://github.com/brixen/pegarus/blob/master/lib/pegarus/rubinius/compiler.rb
6
+ #
7
+ # Copyright (c) 2014, Brian Shirai
8
+ # All rights reserved.
9
+ #
10
+ # Redistribution and use in source and binary forms, with or without
11
+ # modification, are permitted provided that the following conditions are met:
12
+ #
13
+ # 1. Redistributions of source code must retain the above copyright notice, this
14
+ # list of conditions and the following disclaimer.
15
+ # 2. Redistributions in binary form must reproduce the above copyright notice,
16
+ # this list of conditions and the following disclaimer in the documentation
17
+ # and/or other materials provided with the distribution.
18
+ # 3. Neither the name of the library nor the names of its contributors may be
19
+ # used to endorse or promote products derived from this software without
20
+ # specific prior written permission.
21
+ #
22
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25
+ # DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY DIRECT,
26
+ # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27
+ # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
29
+ # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31
+ # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+
33
+ import "BytecodeHelpers.my"
34
+
35
+
36
+ # This set of instructions is not directly related to those in Instructions, as
37
+ # those are not necessarily suitable for direct translation to the Rubinius VM.
38
+ #
39
+ BytecodeInstructions < BasicObject {
40
+
41
+ Constructions << {
42
+ AnyCharacter << { bytecode: |m| m.any(1) }
43
+ Character << { bytecode: |m| m.char(code.chr) }
44
+ CharacterString << { bytecode: |m| m.char(codes.map(&:chr).join) }
45
+ CharacterSet << { bytecode: |m| m.set(codes.map(&:chr).join) }
46
+ CharacterRange << { bytecode: |m|
47
+ codes = Range.new(start,stop); m.set(codes.map(&:chr).join)
48
+ }
49
+
50
+ NegativePredicate << { bytecode: |m|
51
+ m.neg_predicate(
52
+ ::Proc.new { inner.bytecode(m) }
53
+ inner.bytecode_can_capture
54
+ )
55
+ }
56
+ PositivePredicate << { bytecode: |m|
57
+ m.pos_predicate(
58
+ ::Proc.new { inner.bytecode(m) }
59
+ inner.bytecode_can_capture
60
+ )
61
+ }
62
+ OneOrMore << { bytecode: |m|
63
+ m.many(
64
+ ::Proc.new { inner.bytecode(m); inlaid.?call }
65
+ inner.bytecode_can_capture
66
+ )
67
+ }
68
+ ZeroOrOne << {
69
+ bytecode: |m| {
70
+ m.choice(
71
+ ::Proc.new { inner.bytecode(m) },
72
+ ::Proc.new { },
73
+ inner.bytecode_can_capture,
74
+ )
75
+ }
76
+ }
77
+ ZeroOrMore << { bytecode: |m|
78
+ m.kleene(
79
+ ::Proc.new { inner.bytecode(m); inlaid.?call }
80
+ inner.bytecode_can_capture
81
+ )
82
+ }
83
+ OrderedChoice << {
84
+ bytecode: |m| {
85
+ m.choice(
86
+ ::Proc.new { first.bytecode(m) },
87
+ ::Proc.new { second.bytecode(m) },
88
+ first.bytecode_can_capture,
89
+ )
90
+ }
91
+ }
92
+ Concatenation << { bytecode: |m|
93
+ first.bytecode(m); second.bytecode(m)
94
+ }
95
+
96
+ NamedCapture << {
97
+ bytecode: |m| {
98
+ (inner.is_a?(OneOrMore) || inner.is_a?(ZeroOrMore)) &? (
99
+ inner.inlaid = ::Proc.new { m.capture(:m_split, captargs) }
100
+ m.capture(:m_start)
101
+ inner.bytecode(m)
102
+ m.capture(:m_end, captargs)
103
+ ) ?? (
104
+ m.capture(:c_start)
105
+ inner.bytecode(m)
106
+ m.capture(:c_end, captargs)
107
+ )
108
+ }
109
+ }
110
+
111
+ NamedTextCapture << {
112
+ bytecode: |m| {
113
+ m.capture(:s_start)
114
+ inner.bytecode(m)
115
+ m.capture(:s_end, captargs)
116
+ }
117
+ }
118
+
119
+ NamedTokenCapture << {
120
+ bytecode: |m| {
121
+ m.capture(:t_start)
122
+ inner.bytecode(m)
123
+ m.capture(:t_end, captargs)
124
+ }
125
+ }
126
+
127
+ Reduction << {
128
+ bytecode: |m| {
129
+ m.capture(:r_start)
130
+ inner.bytecode(m)
131
+ m.capture(:r_end, captargs)
132
+ }
133
+ }
134
+
135
+ # Hints for optimization (skip saving of temp captures for primitives)
136
+ AnyCharacter << { bytecode_can_capture: false }
137
+ Character << { bytecode_can_capture: false }
138
+ CharacterString << { bytecode_can_capture: false }
139
+ CharacterSet << { bytecode_can_capture: false }
140
+ CharacterRange << { bytecode_can_capture: false }
141
+ NegativePredicate << { bytecode_can_capture: inner.bytecode_can_capture }
142
+ PositivePredicate << { bytecode_can_capture: inner.bytecode_can_capture }
143
+ OneOrMore << { bytecode_can_capture: inner.bytecode_can_capture }
144
+ ZeroOrOne << { bytecode_can_capture: inner.bytecode_can_capture }
145
+ ZeroOrMore << { bytecode_can_capture: inner.bytecode_can_capture }
146
+ OrderedChoice << { bytecode_can_capture: first.bytecode_can_capture
147
+ || second.bytecode_can_capture }
148
+ Concatenation << { bytecode_can_capture: first.bytecode_can_capture
149
+ || second.bytecode_can_capture }
150
+ NamedCapture << { bytecode_can_capture: true }
151
+ NamedTextCapture << { bytecode_can_capture: true }
152
+ NamedTokenCapture << { bytecode_can_capture: true }
153
+ Reduction << { bytecode_can_capture: true }
154
+ }
155
+
156
+
157
+ var g # The generator to use
158
+
159
+ # Match any character, |count| number of times.
160
+ any: |count| {
161
+ g.push_idx
162
+ g.push_int(count)
163
+ g.send(:"+", 1)
164
+
165
+ g.push_subject
166
+ g.send(:size, 0)
167
+ g.send(:"<=", 1)
168
+ g.goto_if_false(g.overall_fail)
169
+
170
+ g.push_int(count)
171
+ g.increment_idx
172
+ }
173
+
174
+ # Match the given |string| of characters, one time.
175
+ char: |string| {
176
+ g.setup_unwind(g.overall_fail, 0) # "rescue" to overall fail
177
+
178
+ g.push_literal(string)
179
+ g.push_subject
180
+ g.push_idx
181
+ g.push_int(string.size)
182
+ g.send(:compare_substring, 3)
183
+ g.meta_push_0
184
+
185
+ g.pop_unwind # end rescued block
186
+
187
+ g.goto_if_not_equal(g.overall_fail)
188
+
189
+ g.push_int(string.size)
190
+ g.increment_idx
191
+ }
192
+
193
+ # Match if the character is included in the given |string|, one time.
194
+ set: |string| {
195
+ local_done = g.new_label
196
+ local_early_fail = g.new_label
197
+
198
+ g.push_literal(string)
199
+ g.push_subject_at_idx
200
+ g.dup_top
201
+ g.goto_if_false(local_early_fail)
202
+ g.meta_push_0
203
+ g.send(:find_string, 2)
204
+ g.goto_if_false(g.overall_fail)
205
+ g.goto(local_done)
206
+
207
+ local_early_fail.set!
208
+ g.pop # pop literal string
209
+ g.pop # pop subject_at_idx
210
+ g.goto(g.overall_fail)
211
+
212
+ local_done.set!
213
+ g.meta_push_1
214
+ g.increment_idx
215
+ }
216
+
217
+ # An ordered choice between |first| and |second|.
218
+ # Each argument should be a Proc that generates bytecode when called.
219
+ choice: |first, second, first_can_capture| {
220
+ local_done = g.new_label
221
+ local_fail = g.new_label
222
+ old_fail = g.overall_fail
223
+ g.overall_fail = local_fail
224
+
225
+ # Store index and captures for backtracking in case of failure
226
+ if(first_can_capture) { g.push_temp_captures }
227
+ g.push_idx
228
+
229
+ first.call
230
+
231
+ # Success, throw away backtrack entry
232
+ g.pop # keep idx
233
+ if(first_can_capture) { g.pop_to_accept_captures }
234
+ g.overall_fail = old_fail # reset fail
235
+ g.goto(local_done)
236
+
237
+ # Failure, backtrack index and captures
238
+ local_fail.set!
239
+ g.pop_to_set_idx
240
+ if(first_can_capture) { g.pop_to_reject_captures }
241
+ g.overall_fail = old_fail
242
+
243
+ second.call
244
+
245
+ local_done.set!
246
+ }
247
+
248
+ # Keep consuming |inner| until it doesn't match; it must match at least one.
249
+ # The argument should be a Proc that generates bytecode when called.
250
+ many: |inner, inner_can_capture| {
251
+ local_retry = g.new_label
252
+ local_fail = g.new_label
253
+ old_fail = g.overall_fail
254
+ g.overall_fail = local_fail
255
+ # push a false to indicate that no matches have occurred yet
256
+ g.push_false
257
+
258
+ local_retry.set!
259
+
260
+ # Store captures for restoration
261
+ if(inner_can_capture) { g.push_temp_captures }
262
+
263
+ inner.call
264
+
265
+ # Success, accept captures and try again, popping the last boolean
266
+ # to push a true to indicate at least one match was made.
267
+ if(inner_can_capture) { g.pop_to_accept_captures }
268
+ g.pop; g.push_true
269
+ g.goto(local_retry)
270
+
271
+ # Failure, reject captures and continue
272
+ local_fail.set!
273
+ if(inner_can_capture) { g.pop_to_reject_captures }
274
+ g.overall_fail = old_fail # reset fail
275
+
276
+ # If at least one match was not found, it is an overall failure
277
+ g.goto_if_false(g.overall_fail)
278
+ }
279
+
280
+ # Keep consuming |inner| until it doesn't match; it will not cause backtrack.
281
+ # The argument should be a Proc that generates bytecode when called.
282
+ kleene: |inner, inner_can_capture| {
283
+ local_retry = g.new_label
284
+ local_fail = g.new_label
285
+ old_fail = g.overall_fail
286
+ g.overall_fail = local_fail
287
+
288
+ local_retry.set!
289
+
290
+ # Store captures for restoration
291
+ if(inner_can_capture) { g.push_temp_captures }
292
+
293
+ inner.call
294
+
295
+ # Success, accept captures and try again
296
+ if(inner_can_capture) { g.pop_to_accept_captures }
297
+ g.goto(local_retry)
298
+
299
+ # Failure, reject captures and continue
300
+ local_fail.set!
301
+ if(inner_can_capture) { g.pop_to_reject_captures }
302
+ g.overall_fail = old_fail # reset fail
303
+ }
304
+
305
+ # Positive matching predicate that consumes no input.
306
+ # The argument should be a Proc that generates bytecode when called.
307
+ pos_predicate: |inner, inner_can_capture| {
308
+ local_done = g.new_label
309
+ local_fail = g.new_label
310
+ old_fail = g.overall_fail
311
+ g.overall_fail = local_fail
312
+
313
+ # Store index and captures for backtracking
314
+ if(inner_can_capture) { g.push_temp_captures }
315
+ g.push_idx
316
+
317
+ inner.call
318
+
319
+ # Success, but do not consume input, so backtrack index but keep captures
320
+ g.pop_to_set_idx
321
+ if(inner_can_capture) { g.pop_to_accept_captures }
322
+ g.overall_fail = old_fail # reset fail
323
+ g.goto(local_done)
324
+
325
+ # Failure, backtrack index and captures
326
+ local_fail.set!
327
+ g.pop_to_set_idx
328
+ if(inner_can_capture) { g.pop_to_reject_captures }
329
+ g.overall_fail = old_fail
330
+ g.goto(g.overall_fail)
331
+
332
+ local_done.set!
333
+ }
334
+
335
+ # Negative matching predicate that consumes no input.
336
+ # The argument should be a Proc that generates bytecode when called.
337
+ neg_predicate: |inner, inner_can_capture| {
338
+ local_fail = g.new_label
339
+ old_fail = g.overall_fail
340
+ g.overall_fail = local_fail
341
+
342
+ # Store index and captures for backtracking
343
+ if(inner_can_capture) { g.push_temp_captures }
344
+ g.push_idx
345
+
346
+ inner.call
347
+
348
+ # Success => Failure, backtrack index and captures
349
+ g.pop_to_set_idx
350
+ if(inner_can_capture) { g.pop_to_reject_captures }
351
+ g.overall_fail = old_fail # reset fail
352
+ g.goto(g.overall_fail)
353
+
354
+ # Failure => Success, backtrack index but keep captures
355
+ local_fail.set!
356
+ g.pop_to_set_idx
357
+ if(inner_can_capture) { g.pop_to_accept_captures }
358
+ g.overall_fail = old_fail
359
+ }
360
+
361
+ # Call the compiled rule by |name| and continue or fail based on the result.
362
+ call: |name, memoize=true| {
363
+ result_check = g.new_label
364
+ memo_result_check = g.new_label
365
+ local_success = g.new_label
366
+ local_fail = g.new_label
367
+
368
+ # Push @captures onto stack and set @captures to a new empty array
369
+ g.push_temp_captures
370
+
371
+ if(memoize) {
372
+ # Check if a memoized result exists;
373
+ # If one does, go straight to memo_result_check label
374
+ g.memo_or_eq_new_hash(name)
375
+ g.goto_if_memo_for_idx(name, memo_result_check)
376
+ }
377
+
378
+ # Call the method; sets @captures and returns the result_idx (or nil)
379
+ g.push_self
380
+ g.push_subject
381
+ g.push_idx
382
+ g.send(name, 2)
383
+
384
+ # Check result and memoize the result
385
+ result_check.set!
386
+ g.copy_result_to_memo(name)
387
+ g.dup_top
388
+ g.goto_if_true(local_success)
389
+ g.goto(local_fail)
390
+
391
+ if(memoize) {
392
+ # Check result, but skip memo copy
393
+ memo_result_check.set!
394
+ g.dup_top
395
+ g.goto_if_true(local_success)
396
+ g.goto(local_fail)
397
+ }
398
+
399
+ # Failure, reject index and captures
400
+ local_fail.set!
401
+ g.pop # reject idx (which is actually null here)
402
+ g.pop_to_reject_captures
403
+ g.goto(g.overall_fail)
404
+
405
+ # Success, accept new index and captures
406
+ local_success.set!
407
+ g.pop_to_set_idx # set to the new index given by the call's return value
408
+ g.pop_to_accept_captures
409
+ }
410
+
411
+ capture: |*metadata| {
412
+ g.push_captures
413
+ g.push_idx
414
+ g.push_literal_or_array(metadata)
415
+ g.make_array(2)
416
+ g.make_array(1)
417
+ g.send(:concat, 1)
418
+ g.pop
419
+ }
420
+ }