myco 0.1.1 → 0.1.2

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/myco/code_loader.rb +1 -1
  3. data/lib/myco/parser/ast/ToRuby.my +400 -0
  4. data/lib/myco/parser/ast/ToRuby.my.rb +574 -0
  5. data/lib/myco/parser/ast.rb +1 -1
  6. data/lib/myco/version.rb +1 -1
  7. data/lib/myco.rb +24 -2
  8. metadata +3 -40
  9. data/lib/myco/parser/ast/to_ruby/array_assembly.rb +0 -15
  10. data/lib/myco/parser/ast/to_ruby/block.rb +0 -14
  11. data/lib/myco/parser/ast/to_ruby/block_pass.rb +0 -6
  12. data/lib/myco/parser/ast/to_ruby/branch_operator.rb +0 -9
  13. data/lib/myco/parser/ast/to_ruby/constant_access.rb +0 -10
  14. data/lib/myco/parser/ast/to_ruby/constant_assignment.rb +0 -6
  15. data/lib/myco/parser/ast/to_ruby/constant_define.rb +0 -9
  16. data/lib/myco/parser/ast/to_ruby/constant_reopen.rb +0 -6
  17. data/lib/myco/parser/ast/to_ruby/declare_category.rb +0 -7
  18. data/lib/myco/parser/ast/to_ruby/declare_decorator.rb +0 -6
  19. data/lib/myco/parser/ast/to_ruby/declare_file.rb +0 -6
  20. data/lib/myco/parser/ast/to_ruby/declare_meme.rb +0 -16
  21. data/lib/myco/parser/ast/to_ruby/declare_object.rb +0 -8
  22. data/lib/myco/parser/ast/to_ruby/declare_string.rb +0 -6
  23. data/lib/myco/parser/ast/to_ruby/dynamic_string.rb +0 -14
  24. data/lib/myco/parser/ast/to_ruby/dynamic_symbol.rb +0 -7
  25. data/lib/myco/parser/ast/to_ruby/eval_expression.rb +0 -6
  26. data/lib/myco/parser/ast/to_ruby/false_literal.rb +0 -6
  27. data/lib/myco/parser/ast/to_ruby/hash_literal.rb +0 -16
  28. data/lib/myco/parser/ast/to_ruby/invoke.rb +0 -6
  29. data/lib/myco/parser/ast/to_ruby/invoke_method.rb +0 -35
  30. data/lib/myco/parser/ast/to_ruby/iter.rb +0 -10
  31. data/lib/myco/parser/ast/to_ruby/local_variable_access_ambiguous.rb +0 -16
  32. data/lib/myco/parser/ast/to_ruby/local_variable_assignment.rb +0 -8
  33. data/lib/myco/parser/ast/to_ruby/myco_module_scope.rb +0 -8
  34. data/lib/myco/parser/ast/to_ruby/null_literal.rb +0 -6
  35. data/lib/myco/parser/ast/to_ruby/parameters.rb +0 -60
  36. data/lib/myco/parser/ast/to_ruby/quest.rb +0 -13
  37. data/lib/myco/parser/ast/to_ruby/return.rb +0 -7
  38. data/lib/myco/parser/ast/to_ruby/scoped_constant.rb +0 -11
  39. data/lib/myco/parser/ast/to_ruby/self.rb +0 -6
  40. data/lib/myco/parser/ast/to_ruby/splat_value.rb +0 -33
  41. data/lib/myco/parser/ast/to_ruby/string_literal.rb +0 -6
  42. data/lib/myco/parser/ast/to_ruby/symbol_literal.rb +0 -6
  43. data/lib/myco/parser/ast/to_ruby/toplevel_constant.rb +0 -11
  44. data/lib/myco/parser/ast/to_ruby/true_literal.rb +0 -6
  45. data/lib/myco/parser/ast/to_ruby/void_literal.rb +0 -6
  46. data/lib/myco/parser/ast/to_ruby.rb +0 -138
  47. data/lib/myco/toolset.rb +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c7120707eb3cf4f2630bbda7bddbf88a64956cb9
4
- data.tar.gz: 6fe624e6aab7c551c6b9d313acc7dcdf9c37eeff
3
+ metadata.gz: bc50c42ea202118c68b826111198d91b40615181
4
+ data.tar.gz: 3a7b9505f106be896c06b78e8398bfa6bff9c89a
5
5
  SHA512:
6
- metadata.gz: 90a9b6c2b8c7d9523cb71d9740e314c743565d9a9128c8c7bd273335be190fc87f76e45b82fec69f0a530bb24342ba60d11a1ca8d14b3bc4784945454408aa83
7
- data.tar.gz: 771063aed886cd75ea2a88cf1d5222f04a5a2fa49bbd55e2497bb9e1453a3df2f4de034ca055adc8bcc7dec88d2a4a69b6ef7ff1e376248d705f8dda22763a83
6
+ metadata.gz: 13d8580696387328fbe7ff490a8005d5f6112bcd0854f9a2d887be015b7d436141f3c86f57ad3d51818e560000696adffc374f0c0aa48dd0d534105b47606d63
7
+ data.tar.gz: 1b8a255e325b29af1be99af379ef2d7788576734a2521f1f9f1f5cea3ec972511a26506a41bcccf27cd41f95d6c04bea2ce44ff1dbae89b1c299665149bc1db8
@@ -42,7 +42,7 @@ module Myco
42
42
  use_path = resolve_file(path, load_paths)
43
43
 
44
44
  # TODO: This logic could be refactored to look cleaner
45
- if use_path
45
+ if use_path && defined? Myco::ToolSet
46
46
  # Try to find an implementation with higher precedence than :myco
47
47
  # With a file that has been modified at least as recently as
48
48
  # the resolved file in use_path.
@@ -0,0 +1,400 @@
1
+
2
+ CodeTools::AST << {
3
+
4
+ # A Ruby code generation visitor
5
+ ToRuby < ::Myco::Object {
6
+ var lines: [""]
7
+
8
+ # The currently held string of generated ruby code
9
+ to_s: lines.join("\n")
10
+
11
+ # Add to the current line the given list of Strings
12
+ # and/or objects that respond to :to_ruby
13
+ add: |*strings| strings.each |string| {
14
+ string.is_a?(String)
15
+ &? lines.last.concat(string.dup)
16
+ ?? string.to_ruby(self)
17
+ }
18
+
19
+ # Start a new line, optionally adding a list of Strings
20
+ # and/or objects that respond to :to_ruby
21
+ line: |*strings|
22
+ lines.push(indents.last.dup); add(*strings)
23
+
24
+ # Add the given items to the current line,
25
+ # using the given separator between items.
26
+ # If a block is given, it is called on
27
+ # each iteration with the item instead.
28
+ # Returns true if any items were written, else false.
29
+ list: |items, separator="", auto_lines:false, &block| {
30
+ items.any? && (
31
+ items = items.dup
32
+ last_item = items.pop
33
+
34
+ use_lines = items.any? && auto_lines
35
+ use_lines && self.push_indent
36
+
37
+ items.each |item| {
38
+ use_lines && self.line
39
+ block &? block.call(item) ?? add(item)
40
+ add(separator)
41
+ }
42
+ use_lines && self.line
43
+ block &? block.call(last_item) ?? add(last_item)
44
+
45
+ use_lines && self.pop_indent
46
+ use_lines && self.line
47
+ )
48
+ }
49
+
50
+ # Stack of indent levels (as strings to be prefixed)
51
+ var indents: [""]
52
+ var indent_amount: 2
53
+ pop_indent: indents.pop
54
+ push_indent: |amount=indent_amount|
55
+ indents.push(indents.last + " " * amount)
56
+
57
+ # Stack of every AST node in hierarchy that can hold local variables
58
+ var var_scopes: []
59
+ var_scope: var_scopes.last
60
+
61
+ with_nested_var_scope: |node, &block| {
62
+ var_scopes.push(node)
63
+ block.call
64
+ var_scopes.pop
65
+ }
66
+
67
+ var_scope_declare_local: |name|
68
+ var_scope.variables[name] = true
69
+
70
+ var_scope_declare_locals: |*names| {
71
+ names.each |name| { var_scope_declare_local(name) }
72
+ }
73
+
74
+ var_scope_has_local?: |name| {
75
+ !!var_scopes.reverse.detect |scope| {
76
+ scope.variables.has_key?(name)
77
+ }
78
+ }
79
+
80
+ # Helper methods
81
+
82
+ # Return false if the given indent might be problematic in generated Ruby
83
+ # TODO: make comprehensive
84
+ easy_ident?: |sym| {
85
+ str = sym.to_s
86
+ (str =~ Regexp.new("^[a-z_][A-Za-z_]*$"))
87
+ && (![:if,:unless,:and,:or,:def,:do,:class,
88
+ :module,:end,:break,:begin,:rescue,:ensure].include?(sym))
89
+ }
90
+ }
91
+
92
+ # Allow any Node to be visited with the to_ruby meme
93
+ Node << {
94
+ to_ruby_code: {
95
+ g = ToRuby.new
96
+ to_ruby(g)
97
+ g.to_s
98
+ }
99
+ }
100
+
101
+ Self << { to_ruby: |g| g.add("self") }
102
+ NullLiteral << { to_ruby: |g| g.add("nil") }
103
+ VoidLiteral << { to_ruby: |g| g.add("::Myco::Void") }
104
+ TrueLiteral << { to_ruby: |g| g.add("true") }
105
+ FalseLiteral << { to_ruby: |g| g.add("false") }
106
+
107
+ StringLiteral << { to_ruby: |g| g.add(self.string.inspect) }
108
+ SymbolLiteral << { to_ruby: |g| g.add(self.value.inspect) }
109
+
110
+ DynamicString << {
111
+ to_ruby: |g| {
112
+ inspect_escape = Proc.new |str| { str.inspect.slice(::Range.new(1, -2)) }
113
+
114
+ g.add('"')
115
+ g.add(inspect_escape.call(self.string))
116
+ self.array.each_slice(2) |interpolated, inner_string| {
117
+ g.add('#{'); g.add(interpolated.value); g.add('}')
118
+ g.add(inspect_escape.call(inner_string.value))
119
+ }
120
+ g.add('"')
121
+ }
122
+ }
123
+
124
+ DynamicSymbol << {
125
+ to_ruby: |g| {
126
+ g.add(":")
127
+ # TODO: use super here
128
+ DynamicString.instance_method(:to_ruby).bind(self).call(g)
129
+ }
130
+ }
131
+
132
+ HashLiteral << {
133
+ to_ruby: |g| {
134
+ g.add("{")
135
+ g.list(self.array.each_slice(2).to_a, ",", auto_lines:true) |pair| {
136
+ g.add(pair.first, " => ", pair.last)
137
+ }
138
+ g.add("}")
139
+ }
140
+ }
141
+
142
+ ArrayAssembly << {
143
+ to_ruby: |g|
144
+ g.add("["); g.list(self.body, ",", auto_lines:true); g.add("]")
145
+ }
146
+
147
+ ScopedConstant << {
148
+ to_ruby: |g|
149
+ g.add(self.parent); g.add("::"self.name"")
150
+
151
+ to_ruby_assign: |g, value|
152
+ to_ruby(g); g.add(" = "); g.add(value)
153
+ }
154
+
155
+ ToplevelConstant << {
156
+ to_ruby: |g|
157
+ g.add("::"self.name"")
158
+
159
+ to_ruby_assign: |g, value|
160
+ to_ruby(g); g.add(" = "); g.add(value)
161
+ }
162
+
163
+ ConstantAccess << {
164
+ to_ruby: |g|
165
+ g.add("::Myco.find_constant("self.name.inspect")")
166
+
167
+ to_ruby_assign: |g, value| {
168
+ g.add("::Myco.cscope.for_method_definition.const_set("self.name.inspect", ")
169
+ g.add(value); g.add(")")
170
+ }
171
+ }
172
+
173
+ ConstantAssignment << {
174
+ to_ruby: |g| self.constant.to_ruby_assign(g, self.value)
175
+ }
176
+
177
+ ConstantDefine << {
178
+ to_ruby: |g| {
179
+ g.add(implementation)
180
+ g.line(".tap { |__c__| __c__.__name__ = ")
181
+ g.add(self.name.name.inspect)
182
+ g.add(" }")
183
+ }
184
+ }
185
+
186
+ ConstantReopen << {
187
+ to_ruby: |g| {
188
+ g.add(self.name); g.add(".component_eval {")
189
+ g.add(self.body); g.add("}")
190
+ }
191
+ }
192
+
193
+ MycoModuleScope << {
194
+ to_ruby: |g|
195
+ g.with_nested_var_scope(self) { g.add(self.body) }
196
+ }
197
+
198
+ EvalExpression << { to_ruby: |g| g.add(self.body) }
199
+ DeclareFile << { to_ruby: |g| implementation.to_ruby(g) }
200
+
201
+ DeclareObject << {
202
+ to_ruby: |g| {
203
+ g.add("::Myco::Component.new("); g.add(self.types); g.add(", ::Myco.cscope.for_method_definition, __FILE__, __LINE__)")
204
+ g.line(".tap { |__c__| __c__.__last__ = __c__.component_eval {"); g.add(scope_implementation); g.add("}}")
205
+ self.create && g.add(".instance")
206
+ }
207
+ }
208
+
209
+ DeclareString << { to_ruby: |g| g.add(implementation) }
210
+
211
+ DeclareCategory << {
212
+ to_ruby: |g| {
213
+ g.add("__category__("self.name.value.inspect")")
214
+ g.add(".component_eval {"); g.add(self.body); g.add("}")
215
+ }
216
+ }
217
+
218
+ DeclareMeme << {
219
+ to_ruby: |g| {
220
+ g.with_nested_var_scope(body_implementation) {
221
+ g.var_scope_declare_locals(*self.arguments.names)
222
+
223
+ g.add("declare_meme(")
224
+ g.add(""self.name.inspect", ")
225
+ g.add(self.decorations); g.add(", nil, ::Myco.cscope.dup)")
226
+ g.add(" { ");
227
+ g.add(self.arguments); g.add(" ")
228
+ g.add(self.body);
229
+ g.add("}")
230
+ }
231
+ }
232
+ }
233
+
234
+ DeclareDecorator << {
235
+ to_ruby: |g|
236
+ g.add("["self.name.value.inspect", "); g.add(self.arguments); g.add("]")
237
+ }
238
+
239
+ Parameters << {
240
+ to_ruby: |g| {
241
+ list = []
242
+ list_add = Proc.new |&blk| { list.push(Proc.new(&blk)) }
243
+
244
+ self.required.each |item| { list_add.call { g.add(item.to_s) } }
245
+
246
+ self.defaults &? (
247
+ self.defaults.arguments.each |asgn| {
248
+ name = asgn.name
249
+ value = asgn.value
250
+ list_add.call {
251
+ g.add(""name"=")
252
+ (value.is_a?(SymbolLiteral) && value.value==:"*") || g.add(value)
253
+ }
254
+ }
255
+ )
256
+
257
+ (self.splat == :"*") &? (
258
+ list_add.call { g.add("*") }
259
+ ) ?? (self.splat &? ( # TODO: make prettier elsif alternative
260
+ list_add.call { g.add("*"self.splat"") }
261
+ ))
262
+
263
+ self.keywords &? (
264
+ self.keywords.arguments.each |asgn| {
265
+ name = asgn.name
266
+ value = asgn.value
267
+ list_add.call {
268
+ g.add(""name":")
269
+ (value.is_a?(SymbolLiteral) && value.value==:"*") || g.add(value)
270
+ }
271
+ }
272
+
273
+ (self.keywords.kwrest == true) &? (
274
+ list_add.call { g.add("**") }
275
+ ) ?? self.keywords.kwrest &? (
276
+ list_add.call { g.add("**"self.keywords.kwrest.name"") }
277
+ )
278
+ )
279
+
280
+ self.block_arg &? (
281
+ list_add.call { g.add("&"self.block_arg.name"") }
282
+ )
283
+
284
+ g.add("|"); g.list(list, ", ") |proc| { proc.call }; g.add("|")
285
+ }
286
+ }
287
+
288
+ Block << {
289
+ to_ruby: |g|
290
+ g.add("("); g.list(self.array, "", auto_lines:true); g.add(")")
291
+ }
292
+
293
+ Invoke << { to_ruby: |g| g.add(implementation) }
294
+
295
+ InvokeMethod << {
296
+ to_ruby: |g| {
297
+ list = self.arguments &? self.arguments.body.dup ?? []
298
+ self.arguments.block.is_a?(BlockPass) &&
299
+ list.push(self.arguments.block)
300
+
301
+ g.add(self.receiver)
302
+
303
+ g.easy_ident?(self.name) &? (
304
+ g.add("."self.name"")
305
+ ) ?? (
306
+ g.add(".__send__")
307
+ list.unshift(SymbolLiteral.new(self.line, self.name))
308
+ )
309
+
310
+ list.any? && (
311
+ g.add("(")
312
+ g.list(list, ",", auto_lines:true)
313
+ g.add(")")
314
+ )
315
+
316
+ self.arguments.block.is_a?(Iter) && (
317
+ g.add(" {"); g.add(self.arguments.block); g.add("}")
318
+ )
319
+ }
320
+ }
321
+
322
+ LocalVariableAssignment << {
323
+ to_ruby: |g| {
324
+ g.var_scope_declare_local(self.name)
325
+ g.var_scope.variables[self.name] = true
326
+ g.add(self.name.to_s); g.add(" = "); g.add(self.value)
327
+ }
328
+ }
329
+
330
+ LocalVariableAccessAmbiguous << {
331
+ to_ruby: |g| {
332
+ g.var_scope_has_local?(self.name) &? (
333
+ g.add(self.name.to_s)
334
+ ) ?? (
335
+ g.add("self")
336
+
337
+ g.easy_ident?(self.name) &? (
338
+ g.add("."self.name"")
339
+ ) ?? (
340
+ g.add(".__send__("self.name.inspect")")
341
+ )
342
+ )
343
+ }
344
+ }
345
+
346
+ SplatValue << {
347
+ to_ruby: |g| {
348
+ self.value.is_a?(self.class) &? (
349
+ self.value.to_ruby(g)
350
+ ) ?? (
351
+ g.add("*")
352
+ self.value.to_ruby(g)
353
+ )
354
+ }
355
+ }
356
+ CollectSplat << { to_ruby: |g| { } } # TODO
357
+ ConcatArgs << { to_ruby: |g| { } } # TODO
358
+ PushArgs << { to_ruby: |g| { } } # TODO
359
+
360
+ BlockPass << {
361
+ to_ruby: |g| g.add("&"); g.add(self.body)
362
+ }
363
+
364
+ Iter << {
365
+ to_ruby: |g| {
366
+ g.with_nested_var_scope(self) {
367
+ g.var_scope_declare_locals(*self.arguments.names)
368
+
369
+ g.add(" "); g.add(self.arguments); g.add(" "); g.add(self.body)
370
+ }
371
+ }
372
+ }
373
+
374
+ Quest << {
375
+ to_ruby: |g| {
376
+ associated_questable = self.questable.dup
377
+ associated_questable.receiver = self.receiver
378
+
379
+ g.add("(")
380
+ g.add(self.receiver)
381
+ g.add(".respond_to?("self.questable.name.inspect").false?")
382
+ g.add(" ? ::Myco::Void : ")
383
+ g.add(associated_questable)
384
+ g.add(")")
385
+ }
386
+ }
387
+
388
+ BranchOperator << {
389
+ to_ruby: |g| {
390
+ g.add('::Myco.branch_op(')
391
+ g.add(self.type.inspect); g.add(', ')
392
+ g.add(self.left); g.add(') {')
393
+ g.add(self.right); g.add('}')
394
+ }
395
+ }
396
+
397
+ Return << {
398
+ to_ruby: |g| g.add("return "); g.add(self.value)
399
+ }
400
+ }