atomy 0.1.1 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +13 -0
  3. data/LICENSE.md +201 -0
  4. data/bin/atomy +16 -133
  5. data/kernel/array.ay +6 -0
  6. data/kernel/atomy.ay +18 -0
  7. data/kernel/condition.ay +171 -271
  8. data/kernel/control-flow.ay +197 -192
  9. data/kernel/core.ay +120 -0
  10. data/kernel/data.ay +83 -39
  11. data/kernel/define.ay +84 -93
  12. data/kernel/doc.ay +282 -449
  13. data/kernel/dynamic.ay +25 -29
  14. data/kernel/file.ay +9 -0
  15. data/kernel/grammar.ay +267 -0
  16. data/kernel/hash.ay +17 -0
  17. data/kernel/interpolation.ay +59 -0
  18. data/kernel/io.ay +70 -244
  19. data/kernel/let-macro.ay +24 -0
  20. data/kernel/let-pattern.ay +24 -0
  21. data/kernel/loop.ay +80 -0
  22. data/kernel/mutation.ay +53 -0
  23. data/kernel/particles.ay +176 -39
  24. data/kernel/patterns.ay +527 -191
  25. data/kernel/pretty.ay +311 -277
  26. data/kernel/quotes.ay +29 -0
  27. data/kernel/range.ay +4 -0
  28. data/kernel/regexp.ay +23 -0
  29. data/kernel/repl.ay +83 -109
  30. data/kernel/stack-local.ay +21 -0
  31. data/lib/atomy.rb +37 -0
  32. data/lib/atomy/bootstrap.rb +256 -0
  33. data/lib/atomy/code/assign.rb +64 -0
  34. data/lib/atomy/code/block.rb +98 -0
  35. data/lib/atomy/code/class_variable.rb +17 -0
  36. data/lib/atomy/code/constant.rb +21 -0
  37. data/lib/atomy/code/define.rb +242 -0
  38. data/lib/atomy/code/define_function.rb +51 -0
  39. data/lib/atomy/code/define_method.rb +20 -0
  40. data/lib/atomy/code/false.rb +9 -0
  41. data/lib/atomy/code/instance_variable.rb +15 -0
  42. data/lib/atomy/code/integer.rb +13 -0
  43. data/lib/atomy/code/list.rb +17 -0
  44. data/lib/atomy/code/nil.rb +9 -0
  45. data/lib/atomy/code/pattern.rb +23 -0
  46. data/lib/atomy/code/pattern/and.rb +61 -0
  47. data/lib/atomy/code/pattern/quasi_quote.rb +185 -0
  48. data/lib/atomy/code/pattern/splat.rb +29 -0
  49. data/lib/atomy/code/pattern/wildcard.rb +37 -0
  50. data/lib/atomy/code/quasi_quote.rb +118 -0
  51. data/lib/atomy/code/quote.rb +13 -0
  52. data/lib/atomy/code/self.rb +9 -0
  53. data/lib/atomy/code/send.rb +110 -0
  54. data/lib/atomy/code/sequence.rb +23 -0
  55. data/lib/atomy/code/string_literal.rb +53 -0
  56. data/lib/atomy/code/symbol.rb +13 -0
  57. data/lib/atomy/code/true.rb +9 -0
  58. data/lib/atomy/code/undefined.rb +9 -0
  59. data/lib/atomy/code/variable.rb +17 -0
  60. data/lib/atomy/codeloader.rb +218 -0
  61. data/lib/atomy/compiler.rb +57 -0
  62. data/lib/atomy/errors.rb +54 -0
  63. data/lib/atomy/grammar.rb +2278 -0
  64. data/lib/atomy/locals.rb +75 -0
  65. data/lib/atomy/message_structure.rb +277 -0
  66. data/lib/atomy/method.rb +343 -0
  67. data/lib/atomy/module.rb +144 -0
  68. data/lib/atomy/node/constructable.rb +169 -0
  69. data/lib/atomy/node/equality.rb +113 -0
  70. data/lib/atomy/node/meta.rb +206 -0
  71. data/lib/atomy/node/pretty.rb +108 -0
  72. data/lib/atomy/parser.rb +21 -0
  73. data/lib/atomy/pattern.rb +26 -0
  74. data/lib/atomy/pattern/and.rb +59 -0
  75. data/lib/atomy/pattern/attribute.rb +16 -0
  76. data/lib/atomy/pattern/class_variable.rb +15 -0
  77. data/lib/atomy/pattern/equality.rb +42 -0
  78. data/lib/atomy/pattern/instance_variable.rb +15 -0
  79. data/lib/atomy/pattern/kind_of.rb +20 -0
  80. data/lib/atomy/pattern/or.rb +48 -0
  81. data/lib/atomy/pattern/quasi_quote.rb +164 -0
  82. data/lib/atomy/pattern/splat.rb +15 -0
  83. data/lib/atomy/pattern/wildcard.rb +18 -0
  84. data/lib/atomy/rubygems.rb +48 -0
  85. data/lib/atomy/version.rb +3 -0
  86. metadata +169 -134
  87. data/COPYING +0 -30
  88. data/README.md +0 -1
  89. data/kernel/block.ay +0 -30
  90. data/kernel/boot.ay +0 -10
  91. data/kernel/comparison.ay +0 -61
  92. data/kernel/concurrency.ay +0 -84
  93. data/kernel/cosmetics.ay +0 -3
  94. data/kernel/data-delta.ay +0 -105
  95. data/kernel/documentation.ay +0 -135
  96. data/kernel/errors.ay +0 -6
  97. data/kernel/format.ay +0 -13
  98. data/kernel/format/data.ay +0 -89
  99. data/kernel/format/formatter.ay +0 -345
  100. data/kernel/format/parser.ay +0 -13
  101. data/kernel/hashes.ay +0 -39
  102. data/kernel/namespaces.ay +0 -63
  103. data/kernel/node.ay +0 -48
  104. data/kernel/operators.ay +0 -28
  105. data/kernel/precision.ay +0 -148
  106. data/kernel/therie.ay +0 -204
  107. data/lib/ast/binary_send.rb +0 -44
  108. data/lib/ast/block.rb +0 -268
  109. data/lib/ast/constant.rb +0 -88
  110. data/lib/ast/internal/assign.rb +0 -19
  111. data/lib/ast/internal/block_pass.rb +0 -21
  112. data/lib/ast/internal/catch.rb +0 -247
  113. data/lib/ast/internal/class.rb +0 -30
  114. data/lib/ast/internal/class_variable.rb +0 -23
  115. data/lib/ast/internal/define.rb +0 -174
  116. data/lib/ast/internal/ensure.rb +0 -135
  117. data/lib/ast/internal/file.rb +0 -14
  118. data/lib/ast/internal/global_variable.rb +0 -20
  119. data/lib/ast/internal/if_then_else.rb +0 -24
  120. data/lib/ast/internal/instance_variable.rb +0 -17
  121. data/lib/ast/internal/let_macro.rb +0 -35
  122. data/lib/ast/internal/macro_quote.rb +0 -23
  123. data/lib/ast/internal/match.rb +0 -53
  124. data/lib/ast/internal/module.rb +0 -30
  125. data/lib/ast/internal/pattern.rb +0 -17
  126. data/lib/ast/internal/return.rb +0 -29
  127. data/lib/ast/internal/set.rb +0 -19
  128. data/lib/ast/internal/singleton_class.rb +0 -18
  129. data/lib/ast/internal/splat.rb +0 -14
  130. data/lib/ast/internal/when.rb +0 -24
  131. data/lib/ast/list.rb +0 -25
  132. data/lib/ast/macro.rb +0 -37
  133. data/lib/ast/node.rb +0 -599
  134. data/lib/ast/operator.rb +0 -21
  135. data/lib/ast/particle.rb +0 -13
  136. data/lib/ast/primitive.rb +0 -20
  137. data/lib/ast/quasi_quote.rb +0 -20
  138. data/lib/ast/quote.rb +0 -13
  139. data/lib/ast/send.rb +0 -104
  140. data/lib/ast/splice.rb +0 -32
  141. data/lib/ast/string.rb +0 -23
  142. data/lib/ast/unary.rb +0 -44
  143. data/lib/ast/unquote.rb +0 -45
  144. data/lib/ast/variable.rb +0 -64
  145. data/lib/atomy.kpeg.rb +0 -3995
  146. data/lib/code_loader.rb +0 -137
  147. data/lib/compiler/compiler.rb +0 -155
  148. data/lib/compiler/stages.rb +0 -81
  149. data/lib/formatter.kpeg.rb +0 -1394
  150. data/lib/macros.rb +0 -317
  151. data/lib/method.rb +0 -261
  152. data/lib/namespace.rb +0 -236
  153. data/lib/parser.rb +0 -28
  154. data/lib/patterns.rb +0 -276
  155. data/lib/patterns/any.rb +0 -21
  156. data/lib/patterns/attribute.rb +0 -59
  157. data/lib/patterns/block_pass.rb +0 -54
  158. data/lib/patterns/constant.rb +0 -33
  159. data/lib/patterns/default.rb +0 -44
  160. data/lib/patterns/head_tail.rb +0 -63
  161. data/lib/patterns/list.rb +0 -77
  162. data/lib/patterns/match.rb +0 -45
  163. data/lib/patterns/named.rb +0 -55
  164. data/lib/patterns/named_class.rb +0 -46
  165. data/lib/patterns/named_global.rb +0 -46
  166. data/lib/patterns/named_instance.rb +0 -46
  167. data/lib/patterns/particle.rb +0 -29
  168. data/lib/patterns/quasi_quote.rb +0 -184
  169. data/lib/patterns/quote.rb +0 -33
  170. data/lib/patterns/singleton_class.rb +0 -31
  171. data/lib/patterns/splat.rb +0 -57
  172. data/lib/util.rb +0 -37
@@ -0,0 +1,75 @@
1
+ require "rubinius/compiler"
2
+
3
+ module Atomy
4
+ class LocalState
5
+ include CodeTools::Compiler::LocalVariables
6
+
7
+ attr_accessor :parent
8
+
9
+ def search_local(name)
10
+ if variable = variables[name]
11
+ variable.nested_reference
12
+ elsif @parent && reference = @parent.search_local(name)
13
+ reference.depth += 1
14
+ reference
15
+ end
16
+ end
17
+
18
+ def new_local(name)
19
+ variable = CodeTools::Compiler::LocalVariable.new(allocate_slot)
20
+ variables[name] = variable
21
+ end
22
+ end
23
+
24
+ class EvalLocalState < LocalState
25
+ def initialize(variable_scope)
26
+ @variable_scope = variable_scope
27
+ end
28
+
29
+ # Returns a cached reference to a variable or searches all
30
+ # surrounding scopes for a variable. If no variable is found,
31
+ # it returns nil and a nested scope will create the variable
32
+ # in itself.
33
+ def search_local(name)
34
+ if variable = variables[name]
35
+ return variable.nested_reference
36
+ end
37
+
38
+ if variable = search_scopes(name)
39
+ variables[name] = variable
40
+ return variable.nested_reference
41
+ end
42
+ end
43
+
44
+ def new_local(name)
45
+ variable = CodeTools::Compiler::EvalLocalVariable.new(name)
46
+ variables[name] = variable
47
+ end
48
+
49
+ def local_count
50
+ 0
51
+ end
52
+
53
+ def local_names
54
+ []
55
+ end
56
+
57
+ private
58
+
59
+ def search_scopes(name)
60
+ depth = 1
61
+ scope = @variable_scope
62
+
63
+ while scope
64
+ if !scope.method.for_eval? && (slot = scope.method.local_slot(name))
65
+ return CodeTools::Compiler::NestedLocalVariable.new(depth, slot)
66
+ elsif scope.eval_local_defined?(name, false)
67
+ return CodeTools::Compiler::EvalLocalVariable.new(name)
68
+ end
69
+
70
+ depth += 1
71
+ scope = scope.parent
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,277 @@
1
+ module Atomy
2
+ class MessageStructure
3
+ class DefaultArgument
4
+ attr_reader :node, :default
5
+
6
+ def initialize(node, default)
7
+ @node = node
8
+ @default = default
9
+ end
10
+
11
+ def ==(other)
12
+ other.is_a?(self.class) && \
13
+ other.node == @node && \
14
+ other.default == @default
15
+ end
16
+ end
17
+
18
+ class BlockArgument
19
+ attr_reader :body, :arguments, :proc_argument
20
+
21
+ def initialize(body, arguments = [], proc_argument = nil)
22
+ @body = body
23
+ @arguments = arguments
24
+ @proc_argument = proc_argument
25
+ end
26
+
27
+ def ==(other)
28
+ other.is_a?(self.class) && \
29
+ other.body == @body && \
30
+ other.arguments == @arguments && \
31
+ other.proc_argument == @proc_argument
32
+ end
33
+ end
34
+
35
+ class UnknownMessageStructure < RuntimeError
36
+ def initialize(node)
37
+ @node = node
38
+ end
39
+
40
+ def to_s
41
+ "unknown message structure: #{@node}"
42
+ end
43
+ end
44
+
45
+ def initialize(node)
46
+ @node = node
47
+ end
48
+
49
+ def name
50
+ # don't treat sole constant as message send
51
+ raise unknown_message if @node.is_a?(Atomy::Grammar::AST::Constant)
52
+
53
+ name_from(@node)
54
+ end
55
+
56
+ def arguments
57
+ pre, defaults, post, splat = arguments_from(argument_list_from(@node))
58
+ pre
59
+ end
60
+
61
+ def splat_argument
62
+ pre, defaults, post, splat = arguments_from(argument_list_from(@node))
63
+ splat
64
+ end
65
+
66
+ def receiver
67
+ receiver_from(@node)
68
+ end
69
+
70
+ def proc_argument
71
+ proc_argument_from(@node)
72
+ end
73
+
74
+ def block
75
+ block_from(@node)
76
+ end
77
+
78
+ def default_arguments
79
+ pre, defaults, post, splat = arguments_from(argument_list_from(@node))
80
+ defaults
81
+ end
82
+
83
+ def post_arguments
84
+ pre, defaults, post, splat = arguments_from(argument_list_from(@node))
85
+ post
86
+ end
87
+
88
+ private
89
+
90
+ def unknown_message
91
+ UnknownMessageStructure.new(@node)
92
+ end
93
+
94
+ def name_from(node)
95
+ case node
96
+ when Grammar::AST::Word, Grammar::AST::Constant
97
+ return node.text
98
+ when Grammar::AST::Apply
99
+ return name_from(node.node)
100
+ when Grammar::AST::Infix
101
+ return node.operator
102
+ when Grammar::AST::Postfix
103
+ case node.operator
104
+ when :"!", :"?"
105
+ case node.node
106
+ when Grammar::AST::Word, Grammar::AST::Constant
107
+ return :"#{node.node.text}#{node.operator}"
108
+ end
109
+ end
110
+ when Grammar::AST::Prefix
111
+ return :"#{node.operator}@"
112
+ when Grammar::AST::Compose
113
+ case node.right
114
+ when Grammar::AST::Prefix # proc argument
115
+ return name_from(node.left)
116
+ when Grammar::AST::Word, Grammar::AST::Constant, Grammar::AST::Apply # has a receiver
117
+ return name_from(node.right)
118
+ when Grammar::AST::Postfix
119
+ case node.right.operator
120
+ when :"!", :"?"
121
+ return name_from(node.right)
122
+ end
123
+ when Grammar::AST::Block # block literal argument
124
+ case node.left
125
+ when Grammar::AST::Compose
126
+ case node.left.right
127
+ when Grammar::AST::List # block args; skip
128
+ return name_from(node.left.left)
129
+ else
130
+ return name_from(node.left)
131
+ end
132
+ else
133
+ return name_from(node.left)
134
+ end
135
+ when Grammar::AST::List # foo[bar]
136
+ return :[]
137
+ end
138
+ end
139
+
140
+ raise unknown_message
141
+ end
142
+
143
+ def arguments_from(list)
144
+ pre = []
145
+ defaults = []
146
+ post = []
147
+ splat = nil
148
+
149
+ list.each do |a|
150
+ if a.is_a?(Grammar::AST::Infix) && a.operator == :"="
151
+ if splat || !post.empty?
152
+ raise unknown_message
153
+ end
154
+
155
+ defaults << DefaultArgument.new(a.left, a.right)
156
+ elsif a.is_a?(Grammar::AST::Prefix) && a.operator == :"*"
157
+ if splat || !post.empty?
158
+ raise unknown_message
159
+ end
160
+
161
+ splat = a.node
162
+ elsif splat || !defaults.empty?
163
+ post << a
164
+ else
165
+ pre << a
166
+ end
167
+ end
168
+
169
+ [pre, defaults, post, splat]
170
+ end
171
+
172
+ def argument_list_from(node)
173
+ case node
174
+ when Grammar::AST::Apply
175
+ return node.arguments
176
+ when Grammar::AST::Infix
177
+ return [node.right]
178
+ when Grammar::AST::Compose
179
+ case node.right
180
+ when Grammar::AST::Prefix # proc argument
181
+ return argument_list_from(node.left)
182
+ when Grammar::AST::Word, Grammar::AST::Constant, Grammar::AST::Apply # has a receiver
183
+ return argument_list_from(node.right)
184
+ when Grammar::AST::Block # block literal argument
185
+ case node.left
186
+ when Grammar::AST::Compose
187
+ case node.left.right
188
+ when Grammar::AST::List # block args; skip
189
+ return argument_list_from(node.left.left)
190
+ else
191
+ return argument_list_from(node.left)
192
+ end
193
+ else
194
+ return argument_list_from(node.left)
195
+ end
196
+ when Grammar::AST::List # foo[bar]
197
+ return node.right.nodes
198
+ end
199
+ end
200
+
201
+ []
202
+ end
203
+
204
+ def proc_argument_from(node)
205
+ case node
206
+ when Grammar::AST::Compose
207
+ case node.right
208
+ when Grammar::AST::Prefix
209
+ if node.right.operator == :"&" # proc argument
210
+ return node.right.node
211
+ end
212
+ end
213
+ end
214
+ end
215
+
216
+ def receiver_from(node)
217
+ case node
218
+ when Grammar::AST::Infix
219
+ return node.left
220
+ when Grammar::AST::Compose
221
+ case node.right
222
+ when Grammar::AST::Word, Grammar::AST::Constant, Grammar::AST::Apply
223
+ return node.left
224
+ when Grammar::AST::Postfix
225
+ case node.right.operator
226
+ when :"!", :"?"
227
+ return node.left
228
+ end
229
+ when Grammar::AST::Block # block literal argument
230
+ case node.left
231
+ when Grammar::AST::Compose
232
+ case node.left.right
233
+ when Grammar::AST::List # block args; skip
234
+ return receiver_from(node.left.left)
235
+ else
236
+ return receiver_from(node.left)
237
+ end
238
+ else
239
+ return receiver_from(node.left)
240
+ end
241
+ when Grammar::AST::List
242
+ return node.left
243
+ when Grammar::AST::Prefix
244
+ if node.right.operator == :"&" # proc argument
245
+ return receiver_from(node.left)
246
+ end
247
+ end
248
+ when Grammar::AST::Prefix
249
+ return node.node
250
+ end
251
+ end
252
+
253
+ def block_from(node)
254
+ case node
255
+ when Grammar::AST::Compose
256
+ blk = nil
257
+
258
+ case node.right
259
+ when Grammar::AST::Block
260
+ blk = BlockArgument.new(node.right.nodes)
261
+ else
262
+ return
263
+ end
264
+
265
+ case node.left
266
+ when Grammar::AST::Compose
267
+ case node.left.right
268
+ when Grammar::AST::List
269
+ return BlockArgument.new(blk.body, node.left.right.nodes)
270
+ end
271
+ end
272
+
273
+ return blk
274
+ end
275
+ end
276
+ end
277
+ end
@@ -0,0 +1,343 @@
1
+ # dispatch strategy:
2
+ #
3
+ # 1 foo([a, b]) := a + 1
4
+ # 2 foo([c]) := 4
5
+ #
6
+ # defines:
7
+ #
8
+ # Integer#foo (arity 1) : 1 concrete arg
9
+ # Integer#foo-branch-1 (arity 2) : 2 bindings
10
+ # Integer#foo-branch-2 (arity 1) : 1 binding
11
+ #
12
+ # so, doing 1.foo([1, 2]) will execute:
13
+ #
14
+ # Integer#foo:
15
+ # - locals tuple: [arg:0]
16
+ # - invoke Pattern#matches? with var scope
17
+ # - if true, invoke Integer#foo-match-1(*Pattern#bindings(scope))
18
+ # - if false, invoke Pattern#matches? with var scope
19
+ # - if true, invoke Integer#foo-match-2(*Pattern#bindings(scope))
20
+ # - if false, raise Atomy::MessageMismatch
21
+ #
22
+
23
+ require "atomy/compiler"
24
+ require "atomy/locals"
25
+
26
+ module Atomy
27
+ class InconsistentArgumentForms < RuntimeError
28
+ def to_s
29
+ "inconsistent method argument forms"
30
+ end
31
+ end
32
+
33
+ class Method
34
+ class Branch
35
+ attr_reader :body, :receiver, :arguments, :default_arguments,
36
+ :splat_argument, :post_arguments, :proc_argument
37
+
38
+ attr_accessor :name
39
+
40
+ def initialize(receiver = nil, arguments = [], default_arguments = [],
41
+ splat_argument = nil, post_arguments = [],
42
+ proc_argument = nil, &body)
43
+ @body = body.block
44
+ @receiver = receiver
45
+ @arguments = arguments
46
+ @default_arguments = default_arguments
47
+ @splat_argument = splat_argument
48
+ @post_arguments = post_arguments
49
+ @proc_argument = proc_argument
50
+ end
51
+
52
+ def pre_arguments_count
53
+ @arguments.size
54
+ end
55
+
56
+ def default_arguments_count
57
+ @default_arguments.size
58
+ end
59
+
60
+ def post_arguments_count
61
+ @post_arguments.size
62
+ end
63
+
64
+ def splat_index
65
+ @arguments.size + @default_arguments.size if @splat_argument
66
+ end
67
+
68
+ def for_method!
69
+ @method = true
70
+ self
71
+ end
72
+
73
+ def method?
74
+ @method
75
+ end
76
+
77
+ def as_method
78
+ Rubinius::BlockEnvironment::AsMethod.new(@body)
79
+ end
80
+ end
81
+
82
+ attr_reader :name, :branches
83
+
84
+ def initialize(name)
85
+ @name = name
86
+ @branches = []
87
+ end
88
+
89
+ @@tick = 0
90
+
91
+ def add_branch(branch)
92
+ @branches << branch
93
+
94
+ if branch.method?
95
+ @@tick += 1
96
+ branch.name = :"#{@name}:branch:#{@@tick}"
97
+ end
98
+
99
+ branch
100
+ end
101
+
102
+ def build
103
+ Atomy::Compiler.package(:__wrapper__) do |gen|
104
+ gen.name = @name
105
+
106
+ pre, default, splat, post = argument_form
107
+ gen.total_args = pre + default + post
108
+ gen.required_args = pre + post
109
+ gen.splat_index = splat
110
+ gen.post_args = post
111
+
112
+ arg = 0
113
+ pre.times do
114
+ gen.state.scope.new_local(:"arg:#{arg}")
115
+ arg += 1
116
+ end
117
+
118
+ default.times do
119
+ gen.state.scope.new_local(:"arg:#{arg}")
120
+ arg += 1
121
+ end
122
+
123
+ if gen.splat_index
124
+ gen.state.scope.new_local(:"arg:splat")
125
+ end
126
+
127
+ post.times do
128
+ gen.state.scope.new_local(:"arg:#{arg}")
129
+ arg += 1
130
+ end
131
+
132
+ done = gen.new_label
133
+
134
+ build_branches(gen, done)
135
+
136
+ try_super(gen, done) unless @name == :initialize
137
+ raise_mismatch(gen)
138
+
139
+ gen.push_nil
140
+
141
+ done.set!
142
+ end.tap do |cm|
143
+ cm.scope = Rubinius::ConstantScope.new(Object)
144
+ end
145
+ end
146
+
147
+ private
148
+
149
+ def uniform_argument_forms?
150
+ return true if @branches.empty?
151
+
152
+ return false unless @branches.collect(&:pre_arguments_count).uniq.size == 1
153
+ return false unless @branches.collect(&:splat_index).uniq.size == 1
154
+ return false unless @branches.collect(&:post_arguments_count).uniq.size == 1
155
+
156
+ # permit varying default argument counts; as long as the rest are the
157
+ # same it's unambiguous
158
+
159
+ true
160
+ end
161
+
162
+ def argument_form
163
+ return [0, 0, nil, 0] if @branches.empty?
164
+
165
+ raise InconsistentArgumentForms unless uniform_argument_forms?
166
+
167
+ [
168
+ @branches.collect(&:pre_arguments_count).first,
169
+ @branches.collect(&:default_arguments_count).max,
170
+ @branches.collect(&:splat_index).first,
171
+ @branches.collect(&:post_arguments_count).first,
172
+ ]
173
+ end
174
+
175
+ def build_branches(gen, done)
176
+ @branches.each do |b|
177
+ skip = gen.new_label
178
+
179
+ # check for too few arguments
180
+ gen.passed_arg(b.pre_arguments_count - 1)
181
+ gen.gif(skip)
182
+
183
+ # check for too many arguments
184
+ unless b.splat_index
185
+ gen.passed_arg(b.pre_arguments_count + b.default_arguments_count + b.post_arguments_count)
186
+ gen.git(skip)
187
+ end
188
+
189
+ if b.receiver
190
+ gen.push_self
191
+ b.receiver.inline_matches?(gen)
192
+ gen.gif(skip)
193
+ end
194
+
195
+ arg = 0
196
+ b.arguments.each do |pat|
197
+ gen.push_local(arg)
198
+ pat.inline_matches?(gen)
199
+ gen.gif(skip)
200
+
201
+ arg += 1
202
+ end
203
+
204
+ b.default_arguments.each do |pat|
205
+ skip_check = gen.new_label
206
+
207
+ gen.push_local(arg)
208
+ gen.goto_if_undefined(skip_check)
209
+
210
+ gen.push_local(arg)
211
+ pat.inline_matches?(gen)
212
+ gen.gif(skip)
213
+
214
+ skip_check.set!
215
+
216
+ arg += 1
217
+ end
218
+
219
+ if b.splat_argument
220
+ gen.push_local(b.splat_index)
221
+ b.splat_argument.inline_matches?(gen)
222
+ gen.gif(skip)
223
+
224
+ arg += 1
225
+ end
226
+
227
+ b.post_arguments.each do |pat|
228
+ gen.push_local(arg)
229
+ pat.inline_matches?(gen)
230
+ gen.gif(skip)
231
+
232
+ arg += 1
233
+ end
234
+
235
+ if b.proc_argument
236
+ gen.push_proc
237
+ b.proc_argument.inline_matches?(gen)
238
+ gen.gif(skip)
239
+ end
240
+
241
+ branch_args = 0
242
+ method_arg = 0
243
+
244
+ if pat = b.receiver
245
+ gen.push_literal(pat)
246
+ gen.push_self
247
+ branch_args += 2
248
+ end
249
+
250
+ b.arguments.each do |pat|
251
+ gen.push_literal(pat)
252
+ gen.push_local(method_arg)
253
+ method_arg += 1
254
+ branch_args += 2
255
+ end
256
+
257
+ b.default_arguments.each do |pat|
258
+ gen.push_literal(pat)
259
+ gen.push_local(method_arg)
260
+ method_arg += 1
261
+ branch_args += 2
262
+ end
263
+
264
+ if pat = b.splat_argument
265
+ gen.push_literal(pat)
266
+ gen.push_local(b.splat_index)
267
+ method_arg += 1
268
+ branch_args += 2
269
+ end
270
+
271
+ b.post_arguments.each do |pat|
272
+ gen.push_literal(pat)
273
+ gen.push_local(method_arg)
274
+ method_arg += 1
275
+ branch_args += 2
276
+ end
277
+
278
+ if pat = b.proc_argument
279
+ gen.push_literal(pat)
280
+ gen.push_proc
281
+ branch_args += 2
282
+ end
283
+
284
+ if b.name
285
+ gen.push_self
286
+ gen.move_down(branch_args)
287
+
288
+ gen.send(b.name, branch_args, true)
289
+ else
290
+ gen.push_literal(b.as_method)
291
+ gen.move_down(branch_args)
292
+
293
+ gen.push_literal(@name)
294
+ gen.move_down(branch_args)
295
+
296
+ gen.push_literal(b.body.constant_scope.module)
297
+ gen.move_down(branch_args)
298
+
299
+ gen.push_self
300
+ gen.move_down(branch_args)
301
+
302
+ gen.make_array(branch_args)
303
+
304
+ gen.push_nil
305
+
306
+ gen.send(:invoke, 5)
307
+ end
308
+
309
+ gen.goto(done)
310
+
311
+ skip.set!
312
+ end
313
+ end
314
+
315
+ def try_super(gen, done)
316
+ no_super = gen.new_label
317
+
318
+ gen.invoke_primitive(:vm_check_super_callable, 0)
319
+ gen.gif(no_super)
320
+
321
+ gen.push_proc
322
+ if gen.state.super?
323
+ gen.zsuper(g.state.super.name)
324
+ else
325
+ gen.zsuper(nil)
326
+ end
327
+
328
+ gen.goto(done)
329
+
330
+ no_super.set!
331
+ end
332
+
333
+ def raise_mismatch(gen)
334
+ gen.push_cpath_top
335
+ gen.find_const(:Atomy)
336
+ gen.find_const(:MessageMismatch)
337
+ gen.push_literal(@name)
338
+ gen.push_self
339
+ gen.send(:new, 2)
340
+ gen.raise_exc
341
+ end
342
+ end
343
+ end