myco 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/lib/myco/bootstrap/component.rb +6 -7
  3. data/lib/myco/bootstrap/instance.rb +14 -9
  4. data/lib/myco/bootstrap/meme.rb +34 -3
  5. data/lib/myco/code_loader.rb +17 -34
  6. data/lib/myco/code_tools/AST/ArgumentAssembly.my +60 -0
  7. data/lib/myco/code_tools/AST/ArgumentAssembly.my.rb +55 -0
  8. data/lib/myco/code_tools/AST/ArrayAssembly.my +43 -0
  9. data/lib/myco/code_tools/AST/ArrayAssembly.my.rb +37 -0
  10. data/lib/myco/code_tools/AST/BlockArgument.my +25 -0
  11. data/lib/myco/code_tools/AST/BlockArgument.my.rb +26 -0
  12. data/lib/myco/code_tools/AST/BlockLiteral.my +104 -0
  13. data/lib/myco/code_tools/AST/BlockLiteral.my.rb +126 -0
  14. data/lib/myco/code_tools/AST/BlockParameter.my +25 -0
  15. data/lib/myco/code_tools/AST/BlockParameter.my.rb +24 -0
  16. data/lib/myco/code_tools/AST/Body.my +18 -0
  17. data/lib/myco/code_tools/AST/Body.my.rb +20 -0
  18. data/lib/myco/code_tools/AST/BranchOperator.my +59 -0
  19. data/lib/myco/code_tools/AST/BranchOperator.my.rb +87 -0
  20. data/lib/myco/code_tools/AST/ConstantAccess.my +30 -0
  21. data/lib/myco/code_tools/AST/ConstantAccess.my.rb +32 -0
  22. data/lib/myco/code_tools/AST/ConstantAssignment.my +40 -0
  23. data/lib/myco/code_tools/AST/ConstantAssignment.my.rb +45 -0
  24. data/lib/myco/code_tools/AST/ConstantDefine.my +30 -0
  25. data/lib/myco/code_tools/AST/ConstantDefine.my.rb +36 -0
  26. data/lib/myco/code_tools/AST/ConstantReopen.my +29 -0
  27. data/lib/myco/code_tools/AST/ConstantReopen.my.rb +35 -0
  28. data/lib/myco/code_tools/AST/DeclareCategory.my +35 -0
  29. data/lib/myco/code_tools/AST/DeclareCategory.my.rb +40 -0
  30. data/lib/myco/code_tools/AST/DeclareDecorator.my +20 -0
  31. data/lib/myco/code_tools/AST/DeclareDecorator.my.rb +28 -0
  32. data/lib/myco/code_tools/AST/DeclareFile.my +38 -0
  33. data/lib/myco/code_tools/AST/DeclareFile.my.rb +53 -0
  34. data/lib/myco/code_tools/AST/DeclareMeme.my +79 -0
  35. data/lib/myco/code_tools/AST/DeclareMeme.my.rb +90 -0
  36. data/lib/myco/code_tools/AST/DeclareObject.my +58 -0
  37. data/lib/myco/code_tools/AST/DeclareObject.my.rb +67 -0
  38. data/lib/myco/code_tools/AST/DeclareString.my +26 -0
  39. data/lib/myco/code_tools/AST/DeclareString.my.rb +30 -0
  40. data/lib/myco/code_tools/AST/DynamicString.my +21 -0
  41. data/lib/myco/code_tools/AST/DynamicString.my.rb +22 -0
  42. data/lib/myco/code_tools/AST/DynamicSymbol.my +22 -0
  43. data/lib/myco/code_tools/AST/DynamicSymbol.my.rb +26 -0
  44. data/lib/myco/code_tools/AST/Invoke.my +37 -0
  45. data/lib/myco/code_tools/AST/Invoke.my.rb +58 -0
  46. data/lib/myco/code_tools/AST/InvokeMethod.my +19 -0
  47. data/lib/myco/code_tools/AST/InvokeMethod.my.rb +25 -0
  48. data/lib/myco/code_tools/AST/KeywordAssembly.my +30 -0
  49. data/lib/myco/code_tools/AST/KeywordAssembly.my.rb +36 -0
  50. data/lib/myco/code_tools/AST/LocalVariableAccessAmbiguous.my +22 -0
  51. data/lib/myco/code_tools/AST/LocalVariableAccessAmbiguous.my.rb +22 -0
  52. data/lib/myco/code_tools/AST/LocalVariableAssignment.my +20 -0
  53. data/lib/myco/code_tools/AST/LocalVariableAssignment.my.rb +20 -0
  54. data/lib/myco/{parser/ast/myco_module_scope.rb → code_tools/AST/MycoModuleScope.my} +32 -39
  55. data/lib/myco/code_tools/AST/MycoModuleScope.my.rb +82 -0
  56. data/lib/myco/code_tools/AST/Node.my +67 -0
  57. data/lib/myco/code_tools/AST/Node.my.rb +84 -0
  58. data/lib/myco/code_tools/AST/ParameterAssembly.my +248 -0
  59. data/lib/myco/code_tools/AST/ParameterAssembly.my.rb +314 -0
  60. data/lib/myco/code_tools/AST/Quest.my +61 -0
  61. data/lib/myco/code_tools/AST/Quest.my.rb +51 -0
  62. data/lib/myco/code_tools/AST/Script.my +27 -0
  63. data/lib/myco/code_tools/AST/Script.my.rb +33 -0
  64. data/lib/myco/code_tools/AST/SplatValue.my +23 -0
  65. data/lib/myco/code_tools/AST/SplatValue.my.rb +25 -0
  66. data/lib/myco/code_tools/AST/StringLiteral.my +17 -0
  67. data/lib/myco/code_tools/AST/StringLiteral.my.rb +16 -0
  68. data/lib/myco/code_tools/AST/SymbolLiteral.my +16 -0
  69. data/lib/myco/code_tools/AST/SymbolLiteral.my.rb +15 -0
  70. data/lib/myco/{parser/ast → code_tools/AST}/ToRuby.my +89 -90
  71. data/lib/myco/{parser/ast → code_tools/AST}/ToRuby.my.rb +89 -101
  72. data/lib/myco/code_tools/AST/misc.my +57 -0
  73. data/lib/myco/code_tools/AST/misc.my.rb +81 -0
  74. data/lib/myco/code_tools/AST.my +52 -0
  75. data/lib/myco/code_tools/AST.my.rb +40 -0
  76. data/lib/myco/{parser → code_tools/parser}/peg_parser.rb +107 -199
  77. data/lib/myco/{parser.rb → code_tools/parser.rb} +0 -17
  78. data/lib/myco/code_tools.rb +5 -0
  79. data/lib/myco/core/BasicDecorators.my +47 -0
  80. data/lib/myco/core/BasicDecorators.my.rb +66 -0
  81. data/lib/myco/core/FileToplevel.my +14 -3
  82. data/lib/myco/core/FileToplevel.my.rb +27 -12
  83. data/lib/myco/eval.rb +7 -37
  84. data/lib/myco/version.rb +1 -4
  85. data/lib/myco.rb +20 -22
  86. metadata +74 -66
  87. data/lib/myco/parser/ast/argument_assembly.rb +0 -76
  88. data/lib/myco/parser/ast/array_assembly.rb +0 -57
  89. data/lib/myco/parser/ast/branch_operator.rb +0 -73
  90. data/lib/myco/parser/ast/constant_access.rb +0 -15
  91. data/lib/myco/parser/ast/constant_define.rb +0 -40
  92. data/lib/myco/parser/ast/constant_reopen.rb +0 -46
  93. data/lib/myco/parser/ast/declare_category.rb +0 -53
  94. data/lib/myco/parser/ast/declare_decorator.rb +0 -35
  95. data/lib/myco/parser/ast/declare_file.rb +0 -54
  96. data/lib/myco/parser/ast/declare_meme.rb +0 -86
  97. data/lib/myco/parser/ast/declare_object.rb +0 -77
  98. data/lib/myco/parser/ast/declare_string.rb +0 -37
  99. data/lib/myco/parser/ast/invoke.rb +0 -48
  100. data/lib/myco/parser/ast/invoke_method.rb +0 -28
  101. data/lib/myco/parser/ast/local_variable_access_ambiguous.rb +0 -34
  102. data/lib/myco/parser/ast/misc.rb +0 -156
  103. data/lib/myco/parser/ast/quest.rb +0 -82
  104. data/lib/myco/parser/ast.rb +0 -21
@@ -0,0 +1,248 @@
1
+
2
+ CodeTools::AST << {
3
+
4
+ ParameterAssembly < Node {
5
+ var required: []
6
+ var optional: []
7
+ var splat: null
8
+ var post: []
9
+ var kwargs: []
10
+ var kwrest: null
11
+ var block: null
12
+
13
+ Form: [:args, :required, :optional, :splat, :post, :kwargs, :kwrest, :block]
14
+
15
+ # Called on a new method or block generator
16
+ # to set up various parameter-related properties.
17
+ generator_setup: |g| {
18
+ g.required_args = self.required.size + self.post.size
19
+
20
+ g.post_args = self.post.size
21
+
22
+ g.total_args =
23
+ self.required.size + self.optional.size + self.post.size
24
+ + ((self.kwargs.any? || self.kwrest) &? 1 ?? 0)
25
+
26
+ g.splat_index =
27
+ self.splat &? (self.required.size + self.optional.size) ?? null
28
+
29
+ g.block_index = self.block && (
30
+ self.required.size
31
+ + self.optional.size
32
+ + (self.splat &? 1 ?? 0)
33
+ + self.post.size
34
+ + ((self.kwargs.any? || self.kwrest) &? 1 ?? 0)
35
+ + 1 # for self.block
36
+ )
37
+
38
+ g.arity = self.arity
39
+
40
+ g.keywords = self.keyword_entries
41
+ }
42
+
43
+ # TODO: remove/refactor out
44
+ required_and_optional_kwargs: {
45
+ # TODO: perhaps make these be given separately?
46
+ required_kwargs = []
47
+ optional_kwargs = []
48
+
49
+ self.kwargs.each |param| {
50
+ # TODO: use nil or some other param.value to represent required kwarg
51
+ (param.value.kind_of?(SymbolLiteral) && param.value.value == :"*")
52
+ &? required_kwargs.push(param)
53
+ ?? optional_kwargs.push(param)
54
+ }
55
+
56
+ ret = [required_kwargs, optional_kwargs]
57
+ }
58
+
59
+ # TODO: remove/refactor out
60
+ keyword_entries: {
61
+ entries = required_and_optional_kwargs
62
+ entries.first.map! |x| { [x.name, true] }
63
+ entries.last.map! |x| { [x.name, false] }
64
+ entries = entries.flatten(2)
65
+ entries.empty? &? null ?? entries
66
+ }
67
+
68
+ # TODO: remove/refactor out
69
+ arity: {
70
+ arity = self.required.size + self.post.size
71
+
72
+ # Check for required kwargs
73
+ kwargs_are_required = self.kwargs.select |param| {
74
+ # TODO: use nil or some other param.value to represent required kwarg
75
+ (param.value.kind_of?(SymbolLiteral) && param.value.value == :"*")
76
+ }
77
+
78
+ kwargs_are_required && (
79
+ arity = arity + 1
80
+ )
81
+
82
+ (self.splat
83
+ || self.optional.any?
84
+ || (kwargs.any? && !kwargs_are_required)) && (
85
+ arity = arity + 1
86
+ arity = arity * -1
87
+ )
88
+
89
+ arity
90
+ }
91
+
92
+ names: [
93
+ *self.required,
94
+ *self.optional.map(&:name),
95
+ *(self.splat.is_a?(Symbol) &? [self.splat] ?? []),
96
+ *self.post,
97
+ *self.kwargs.map(&:name),
98
+ *(self.kwrest.is_a?(Symbol) &? [self.kwrest] ?? []),
99
+ *(self.block &? [self.block.name] ?? []),
100
+ ]
101
+
102
+ map_locals: |scope| {
103
+ self.required.each |name| { scope.new_local(name) }
104
+ self.optional.each |var| { scope.assign_local_reference(var) }
105
+ self.splat && (self.splat.is_a?(Symbol) &? scope.new_local(self.splat) ?? scope.new_local(:"*"))
106
+ self.post.each |name| { scope.new_local(name) }
107
+
108
+ (self.kwargs.any? || self.kwrest) && scope.new_local(:"__myco_kwargs_value__")
109
+ self.kwargs.each |var| { scope.assign_local_reference(var) }
110
+ self.kwrest && (self.kwrest.is_a?(Symbol) && scope.new_local(self.kwrest))
111
+
112
+ self.block && scope.assign_local_reference(self.block)
113
+ }
114
+
115
+ # TODO: simplify
116
+ bytecode: |g| {
117
+ g.state.check_for_locals = false
118
+ self.map_locals(g.state.scope)
119
+
120
+ self.optional.each |param| {
121
+ done = g.new_label
122
+
123
+ param.variable.get_bytecode(g)
124
+ g.goto_if_not_undefined(done)
125
+ param.bytecode(g)
126
+ g.pop
127
+
128
+ done.set!
129
+ }
130
+
131
+ (self.kwargs.any? || self.kwrest) && (
132
+ kw_done = g.new_label
133
+ assignments_label = g.new_label
134
+ missing_value_label = g.new_label
135
+ defaults_label = g.new_label
136
+
137
+ kwargs_value_var = g.state.scope.search_local(:"__myco_kwargs_value__")
138
+ kwargs_value_var.get_bytecode(g)
139
+
140
+ g.dup; g.goto_if_not_nil(assignments_label) # TODO: trivially remove this line?
141
+
142
+ g.pop
143
+ g.push_cpath_top
144
+ g.find_const(:"Hash")
145
+ g.send(:allocate, 0, true)
146
+
147
+ assignments_label.set!
148
+
149
+ entries = self.required_and_optional_kwargs
150
+ required_kwargs = entries.first
151
+ optional_kwargs = entries.last
152
+
153
+ required_kwargs.each |param| {
154
+ g.dup
155
+
156
+ g.push_literal(param.name)
157
+ g.send(:find_item, 1, true)
158
+
159
+ g.dup
160
+ g.goto_if_false(missing_value_label)
161
+
162
+ g.send(:value, 0, true)
163
+
164
+ param.variable.set_bytecode(g)
165
+ g.pop
166
+ }
167
+
168
+ g.goto(defaults_label)
169
+
170
+ missing_value_label.set!
171
+ g.pop
172
+ g.push_rubinius
173
+ g.find_const(:"Runtime")
174
+ g.swap
175
+ g.send(:keywords_missing, 1, true)
176
+ g.goto(kw_done)
177
+
178
+ defaults_label.set!
179
+
180
+ extra_keys_label = g.new_label
181
+
182
+ optional_kwargs.empty? &? (
183
+ g.dup
184
+ g.send(:size, 0, true)
185
+ g.push(required_kwargs.size)
186
+ g.goto_if_not_equal(extra_keys_label)
187
+
188
+ self.kwrest.is_a?(Symbol) && (
189
+ g.push_cpath_top
190
+ g.find_const(:"Hash")
191
+ g.send(:allocate, 0, true)
192
+ kwrest_asgn = g.state.scope.search_local(self.kwrest)
193
+ kwrest_asgn.set_bytecode(g)
194
+ g.pop
195
+ )
196
+
197
+ g.goto(kw_done)
198
+ ) ?? (
199
+ optional_kwargs.each |arg| {
200
+ next_value_label = g.new_label
201
+ default_value_label = g.new_label
202
+
203
+ g.dup
204
+ g.push_literal(arg.name)
205
+ g.send(:find_item, 1, true)
206
+
207
+ g.dup
208
+ g.goto_if_false(default_value_label)
209
+
210
+ g.send(:value, 0, true)
211
+ arg.variable.set_bytecode(g)
212
+ g.goto(next_value_label)
213
+
214
+ default_value_label.set!
215
+ g.pop
216
+ arg.bytecode(g)
217
+
218
+ next_value_label.set!
219
+ g.pop
220
+ }
221
+ )
222
+
223
+ extra_keys_label.set!
224
+
225
+ g.dup
226
+ g.push_rubinius
227
+ g.find_const(:"Runtime")
228
+ g.swap
229
+
230
+ self.kwrest &? g.push(:true) ?? g.push(:false)
231
+
232
+ g.send(:keywords_extra, 2, true)
233
+ self.kwrest.is_a?(Symbol) && (
234
+ kwrest_asgn = g.state.scope.search_local(self.kwrest)
235
+ kwrest_asgn.set_bytecode(g)
236
+ )
237
+ g.pop
238
+
239
+ kw_done.set!
240
+ )
241
+
242
+ self.block && self.block.bytecode(g)
243
+
244
+ g.state.check_for_locals = true
245
+ }
246
+ }
247
+
248
+ }
@@ -0,0 +1,314 @@
1
+
2
+ ::Myco::Component.new([::Myco::FileToplevel], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
3
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(::Myco.find_constant(:CodeTools)::AST.component_eval {(::Myco.cscope.for_method_definition.const_set(:ParameterAssembly, ::Myco::Component.new([::Myco.find_constant(:Node)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
4
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(
5
+ declare_meme(:required, [[:var, []]], nil, ::Myco.cscope.dup) { |*| ([])}
6
+ declare_meme(:optional, [[:var, []]], nil, ::Myco.cscope.dup) { |*| ([])}
7
+ declare_meme(:splat, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (nil)}
8
+ declare_meme(:post, [[:var, []]], nil, ::Myco.cscope.dup) { |*| ([])}
9
+ declare_meme(:kwargs, [[:var, []]], nil, ::Myco.cscope.dup) { |*| ([])}
10
+ declare_meme(:kwrest, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (nil)}
11
+ declare_meme(:block, [[:var, []]], nil, ::Myco.cscope.dup) { |*| (nil)}
12
+ ::Myco.cscope.for_method_definition.const_set(:Form, ([
13
+ :args,
14
+ :required,
15
+ :optional,
16
+ :splat,
17
+ :post,
18
+ :kwargs,
19
+ :kwrest,
20
+ :block
21
+ ]))
22
+ declare_meme(:generator_setup, [], nil, ::Myco.cscope.dup) { |g| (
23
+ g.__send__(
24
+ :required_args=,
25
+ self.required.size.__send__(
26
+ :+,
27
+ self.post.size
28
+ )
29
+ )
30
+ g.__send__(
31
+ :post_args=,
32
+ self.post.size
33
+ )
34
+ g.__send__(
35
+ :total_args=,
36
+ self.required.size.__send__(
37
+ :+,
38
+ self.optional.size
39
+ ).__send__(
40
+ :+,
41
+ self.post.size
42
+ ).__send__(
43
+ :+,
44
+ ::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", ::Myco.branch_op(:"||", self.kwargs.__send__(:any?)) {self.kwrest}) {1}) {0}
45
+ )
46
+ )
47
+ g.__send__(
48
+ :splat_index=,
49
+ ::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", self.splat) {self.required.size.__send__(
50
+ :+,
51
+ self.optional.size
52
+ )}) {nil}
53
+ )
54
+ g.__send__(
55
+ :block_index=,
56
+ ::Myco.branch_op(:"&&", self.block) {self.required.size.__send__(
57
+ :+,
58
+ self.optional.size
59
+ ).__send__(
60
+ :+,
61
+ ::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", self.splat) {1}) {0}
62
+ ).__send__(
63
+ :+,
64
+ self.post.size
65
+ ).__send__(
66
+ :+,
67
+ ::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", ::Myco.branch_op(:"||", self.kwargs.__send__(:any?)) {self.kwrest}) {1}) {0}
68
+ ).__send__(
69
+ :+,
70
+ 1
71
+ )}
72
+ )
73
+ g.__send__(
74
+ :arity=,
75
+ self.arity
76
+ )
77
+ g.__send__(
78
+ :keywords=,
79
+ self.keyword_entries
80
+ )
81
+ )}
82
+ declare_meme(:required_and_optional_kwargs, [], nil, ::Myco.cscope.dup) { |*| (
83
+ required_kwargs = []
84
+ optional_kwargs = []
85
+ self.kwargs.each { |param| (::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", ::Myco.branch_op(:"&&", param.value.__send__(
86
+ :kind_of?,
87
+ ::Myco.find_constant(:SymbolLiteral)
88
+ )) {param.value.value.__send__(
89
+ :==,
90
+ :*
91
+ )}) {required_kwargs.push(param)}) {optional_kwargs.push(param)})}
92
+ ret = [
93
+ required_kwargs,
94
+ optional_kwargs
95
+ ]
96
+ )}
97
+ declare_meme(:keyword_entries, [], nil, ::Myco.cscope.dup) { |*| (
98
+ entries = self.required_and_optional_kwargs
99
+ entries.first.__send__(:map!) { |x| ([
100
+ x.name,
101
+ true
102
+ ])}
103
+ entries.last.__send__(:map!) { |x| ([
104
+ x.name,
105
+ false
106
+ ])}
107
+ entries = entries.flatten(2)
108
+ ::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", entries.__send__(:empty?)) {nil}) {entries}
109
+ )}
110
+ declare_meme(:arity, [], nil, ::Myco.cscope.dup) { |*| (
111
+ arity = self.required.size.__send__(
112
+ :+,
113
+ self.post.size
114
+ )
115
+ kwargs_are_required = self.kwargs.select { |param| (::Myco.branch_op(:"&&", param.value.__send__(
116
+ :kind_of?,
117
+ ::Myco.find_constant(:SymbolLiteral)
118
+ )) {param.value.value.__send__(
119
+ :==,
120
+ :*
121
+ )})}
122
+ ::Myco.branch_op(:"&&", kwargs_are_required) {arity = arity.__send__(
123
+ :+,
124
+ 1
125
+ )}
126
+ ::Myco.branch_op(:"&&", ::Myco.branch_op(:"||", ::Myco.branch_op(:"||", self.splat) {self.optional.__send__(:any?)}) {::Myco.branch_op(:"&&", self.kwargs.__send__(:any?)) {kwargs_are_required.__send__(:!)}}) {(
127
+ arity = arity.__send__(
128
+ :+,
129
+ 1
130
+ )
131
+ arity = arity.__send__(
132
+ :*,
133
+ -1
134
+ )
135
+ )}
136
+ arity
137
+ )}
138
+ declare_meme(:names, [], nil, ::Myco.cscope.dup) { |*| ([
139
+ *self.required,
140
+ *self.optional.map(&:name),
141
+ *::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", self.splat.__send__(
142
+ :is_a?,
143
+ ::Myco.find_constant(:Symbol)
144
+ )) {[self.splat]}) {[]},
145
+ *self.post,
146
+ *self.kwargs.map(&:name),
147
+ *::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", self.kwrest.__send__(
148
+ :is_a?,
149
+ ::Myco.find_constant(:Symbol)
150
+ )) {[self.kwrest]}) {[]},
151
+ *::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", self.block) {[self.block.name]}) {[]}
152
+ ])}
153
+ declare_meme(:map_locals, [], nil, ::Myco.cscope.dup) { |scope| (
154
+ self.required.each { |name| (scope.new_local(name))}
155
+ self.optional.each { |var| (scope.assign_local_reference(var))}
156
+ ::Myco.branch_op(:"&&", self.splat) {::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", self.splat.__send__(
157
+ :is_a?,
158
+ ::Myco.find_constant(:Symbol)
159
+ )) {scope.new_local(self.splat)}) {scope.new_local(:*)}}
160
+ self.post.each { |name| (scope.new_local(name))}
161
+ ::Myco.branch_op(:"&&", ::Myco.branch_op(:"||", self.kwargs.__send__(:any?)) {self.kwrest}) {scope.new_local(:__myco_kwargs_value__)}
162
+ self.kwargs.each { |var| (scope.assign_local_reference(var))}
163
+ ::Myco.branch_op(:"&&", self.kwrest) {::Myco.branch_op(:"&&", self.kwrest.__send__(
164
+ :is_a?,
165
+ ::Myco.find_constant(:Symbol)
166
+ )) {scope.new_local(self.kwrest)}}
167
+ ::Myco.branch_op(:"&&", self.block) {scope.assign_local_reference(self.block)}
168
+ )}
169
+ declare_meme(:bytecode, [], nil, ::Myco.cscope.dup) { |g| (
170
+ g.state.__send__(
171
+ :check_for_locals=,
172
+ false
173
+ )
174
+ self.map_locals(g.state.scope)
175
+ self.optional.each { |param| (
176
+ done = g.new_label
177
+ param.variable.get_bytecode(g)
178
+ g.goto_if_not_undefined(done)
179
+ param.bytecode(g)
180
+ g.pop
181
+ done.__send__(:set!)
182
+ )}
183
+ ::Myco.branch_op(:"&&", ::Myco.branch_op(:"||", self.kwargs.__send__(:any?)) {self.kwrest}) {(
184
+ kw_done = g.new_label
185
+ assignments_label = g.new_label
186
+ missing_value_label = g.new_label
187
+ defaults_label = g.new_label
188
+ kwargs_value_var = g.state.scope.search_local(:__myco_kwargs_value__)
189
+ kwargs_value_var.get_bytecode(g)
190
+ g.dup
191
+ g.goto_if_not_nil(assignments_label)
192
+ g.pop
193
+ g.push_cpath_top
194
+ g.find_const(:Hash)
195
+ g.send(
196
+ :allocate,
197
+ 0,
198
+ true
199
+ )
200
+ assignments_label.__send__(:set!)
201
+ entries = self.required_and_optional_kwargs
202
+ required_kwargs = entries.first
203
+ optional_kwargs = entries.last
204
+ required_kwargs.each { |param| (
205
+ g.dup
206
+ g.push_literal(param.name)
207
+ g.send(
208
+ :find_item,
209
+ 1,
210
+ true
211
+ )
212
+ g.dup
213
+ g.goto_if_false(missing_value_label)
214
+ g.send(
215
+ :value,
216
+ 0,
217
+ true
218
+ )
219
+ param.variable.set_bytecode(g)
220
+ g.pop
221
+ )}
222
+ g.goto(defaults_label)
223
+ missing_value_label.__send__(:set!)
224
+ g.pop
225
+ g.push_rubinius
226
+ g.find_const(:Runtime)
227
+ g.swap
228
+ g.send(
229
+ :keywords_missing,
230
+ 1,
231
+ true
232
+ )
233
+ g.goto(kw_done)
234
+ defaults_label.__send__(:set!)
235
+ extra_keys_label = g.new_label
236
+ ::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", optional_kwargs.__send__(:empty?)) {(
237
+ g.dup
238
+ g.send(
239
+ :size,
240
+ 0,
241
+ true
242
+ )
243
+ g.push(required_kwargs.size)
244
+ g.goto_if_not_equal(extra_keys_label)
245
+ ::Myco.branch_op(:"&&", self.kwrest.__send__(
246
+ :is_a?,
247
+ ::Myco.find_constant(:Symbol)
248
+ )) {(
249
+ g.push_cpath_top
250
+ g.find_const(:Hash)
251
+ g.send(
252
+ :allocate,
253
+ 0,
254
+ true
255
+ )
256
+ kwrest_asgn = g.state.scope.search_local(self.kwrest)
257
+ kwrest_asgn.set_bytecode(g)
258
+ g.pop
259
+ )}
260
+ g.goto(kw_done)
261
+ )}) {optional_kwargs.each { |arg| (
262
+ next_value_label = g.new_label
263
+ default_value_label = g.new_label
264
+ g.dup
265
+ g.push_literal(arg.name)
266
+ g.send(
267
+ :find_item,
268
+ 1,
269
+ true
270
+ )
271
+ g.dup
272
+ g.goto_if_false(default_value_label)
273
+ g.send(
274
+ :value,
275
+ 0,
276
+ true
277
+ )
278
+ arg.variable.set_bytecode(g)
279
+ g.goto(next_value_label)
280
+ default_value_label.__send__(:set!)
281
+ g.pop
282
+ arg.bytecode(g)
283
+ next_value_label.__send__(:set!)
284
+ g.pop
285
+ )}}
286
+ extra_keys_label.__send__(:set!)
287
+ g.dup
288
+ g.push_rubinius
289
+ g.find_const(:Runtime)
290
+ g.swap
291
+ ::Myco.branch_op(:"??", ::Myco.branch_op(:"&?", self.kwrest) {g.push(:true)}) {g.push(:false)}
292
+ g.send(
293
+ :keywords_extra,
294
+ 2,
295
+ true
296
+ )
297
+ ::Myco.branch_op(:"&&", self.kwrest.__send__(
298
+ :is_a?,
299
+ ::Myco.find_constant(:Symbol)
300
+ )) {(
301
+ kwrest_asgn = g.state.scope.search_local(self.kwrest)
302
+ kwrest_asgn.set_bytecode(g)
303
+ )}
304
+ g.pop
305
+ kw_done.__send__(:set!)
306
+ )}
307
+ ::Myco.branch_op(:"&&", self.block) {self.block.bytecode(g)}
308
+ g.state.__send__(
309
+ :check_for_locals=,
310
+ true
311
+ )
312
+ )}
313
+ )}})
314
+ .tap { |__c__| __c__.__name__ = :ParameterAssembly })})}}.instance
@@ -0,0 +1,61 @@
1
+
2
+ CodeTools::AST << {
3
+
4
+ Quest < Node {
5
+ var receiver, var questable
6
+
7
+ Form: [:quest, :receiver, :questable]
8
+
9
+ setter questable: |given| {
10
+ given.receiver = FakeReceiver.new(line: self.line)
11
+ given
12
+ }
13
+
14
+ bytecode: |g| {
15
+ pos(g)
16
+
17
+ ##
18
+ # unless self.receiver.respond_to?(self.questable.name).false?
19
+ # execute_statement self.questable
20
+ # else
21
+ # return void
22
+ # end
23
+
24
+ else_label = g.new_label
25
+ end_label = g.new_label
26
+
27
+ self.receiver.bytecode(g)
28
+ g.dup_top # dup the receiver to save it for later
29
+ g.push_literal(self.questable.name)
30
+ g.send(:"respond_to?", 1)
31
+ g.send(:"false?", 0)
32
+ g.goto_if_true(else_label)
33
+
34
+ # The duped receiver is still at the top of the stack,
35
+ # and self.questable.receiver has been set to an instance of FakeReceiver
36
+ # to let the true receiver pass through instead.
37
+ self.questable.bytecode(g)
38
+ g.goto(end_label)
39
+
40
+ else_label.set!
41
+ g.pop # pop the duped receiver - it won't be used after all
42
+ g.push_cpath_top
43
+ g.find_const(:"Myco")
44
+ g.find_const(:"Void")
45
+
46
+ end_label.set!
47
+ }
48
+
49
+
50
+ FakeReceiver < Node {
51
+ Form: [:qrcvr]
52
+
53
+ # Do nothing here - this would normally be ill-advised,
54
+ # because Nodes are expected to push an item onto the stack,
55
+ # but here we are intentionally not doing so because
56
+ # the real receiver should already at the top of the stack
57
+ bytecode: |g| pos(g)
58
+ }
59
+ }
60
+
61
+ }
@@ -0,0 +1,51 @@
1
+
2
+ ::Myco::Component.new([::Myco::FileToplevel], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
3
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(::Myco.find_constant(:CodeTools)::AST.component_eval {(::Myco.cscope.for_method_definition.const_set(:Quest, ::Myco::Component.new([::Myco.find_constant(:Node)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
4
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(
5
+ declare_meme(:receiver, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
6
+ declare_meme(:questable, [[:var, []]], nil, ::Myco.cscope.dup) { |*| nil}
7
+ ::Myco.cscope.for_method_definition.const_set(:Form, ([
8
+ :quest,
9
+ :receiver,
10
+ :questable
11
+ ]))
12
+ declare_meme(:questable, [[:setter, []]], nil, ::Myco.cscope.dup) { |given| (
13
+ given.__send__(
14
+ :receiver=,
15
+ ::Myco.find_constant(:FakeReceiver).new({:line => self.line})
16
+ )
17
+ given
18
+ )}
19
+ declare_meme(:bytecode, [], nil, ::Myco.cscope.dup) { |g| (
20
+ self.pos(g)
21
+ else_label = g.new_label
22
+ end_label = g.new_label
23
+ self.receiver.bytecode(g)
24
+ g.dup_top
25
+ g.push_literal(self.questable.name)
26
+ g.send(
27
+ :respond_to?,
28
+ 1
29
+ )
30
+ g.send(
31
+ :false?,
32
+ 0
33
+ )
34
+ g.goto_if_true(else_label)
35
+ self.questable.bytecode(g)
36
+ g.goto(end_label)
37
+ else_label.__send__(:set!)
38
+ g.pop
39
+ g.push_cpath_top
40
+ g.find_const(:Myco)
41
+ g.find_const(:Void)
42
+ end_label.__send__(:set!)
43
+ )}
44
+ ::Myco.cscope.for_method_definition.const_set(:FakeReceiver, ::Myco::Component.new([::Myco.find_constant(:Node)], ::Myco.cscope.for_method_definition, __FILE__, __LINE__)
45
+ .tap { |__c__| __c__.__last__ = __c__.component_eval {(
46
+ ::Myco.cscope.for_method_definition.const_set(:Form, ([:qrcvr]))
47
+ declare_meme(:bytecode, [], nil, ::Myco.cscope.dup) { |g| (self.pos(g))}
48
+ )}})
49
+ .tap { |__c__| __c__.__name__ = :FakeReceiver }
50
+ )}})
51
+ .tap { |__c__| __c__.__name__ = :Quest })})}}.instance
@@ -0,0 +1,27 @@
1
+
2
+ CodeTools::AST << {
3
+
4
+ # TODO: consider moving out of the AST namespace - or maybe collapse into FileToplevel
5
+ Script < Node {
6
+ var file, var body
7
+ var variable_scope # TODO: remove?
8
+
9
+ Form: [:script, :file, :body]
10
+
11
+ nest_scope: |scope| scope.parent = self
12
+ search_local: null # TODO: revisit and possibly implement for nested evals
13
+
14
+ bytecode: |g| {
15
+ g.name = :"__script__"
16
+ g.file = self.file.to_sym
17
+
18
+ g.push_state(self)
19
+
20
+ self.body.bytecode(g)
21
+ g.ret
22
+
23
+ g.pop_state
24
+ }
25
+ }
26
+
27
+ }