myco 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ }