~ubuntu-branches/ubuntu/intrepid/ruby1.9/intrepid-updates

« back to all changes in this revision

Viewing changes to test/ruby/test_yield.rb

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-09-04 16:01:17 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20070904160117-i15zckg2nhxe9fyw
Tags: 1.9.0+20070830-2ubuntu1
* Sync from Debian; remaining changes:
  - Add -g to CFLAGS.
* Fixes build failure on ia64.
* Fixes build failure with gcc-4.2 on lpia.
* Robustify check for target_os, fixing build failure on lpia.
* Set Ubuntu maintainer address.

Show diffs side-by-side

added added

removed removed

Lines of Context:
65
65
  end
66
66
 
67
67
end
 
68
 
 
69
require 'sentence'
 
70
class TestRubyYieldGen < Test::Unit::TestCase
 
71
  Syntax = {
 
72
    :exp => [["0"],
 
73
             ["nil"],
 
74
             ["false"],
 
75
             ["[]"],
 
76
             ["[",:exps,"]"]],
 
77
    :exps => [[:exp],
 
78
              [:exp,",",:exps]],
 
79
    :opt_block_param => [[],
 
80
                         [:block_param_def]],
 
81
    :block_param_def => [['|', '|'],
 
82
                         ['|', :block_param, '|']],
 
83
    :block_param => [[:f_arg, ",", :f_rest_arg, :opt_f_block_arg],
 
84
                     [:f_arg, ","],
 
85
                     [:f_arg, ',', :f_rest_arg, ",", :f_arg, :opt_f_block_arg],
 
86
                     [:f_arg, :opt_f_block_arg],
 
87
                     [:f_rest_arg, :opt_f_block_arg],
 
88
                     [:f_rest_arg, ',', :f_arg, :opt_f_block_arg],
 
89
                     [:f_block_arg]],
 
90
    :f_arg => [[:f_arg_item],
 
91
               [:f_arg, ',', :f_arg_item]],
 
92
    :f_rest_arg => [['*', "var"],
 
93
                    ['*']],
 
94
    :opt_f_block_arg => [[',', :f_block_arg],
 
95
                         []],
 
96
    :f_block_arg => [['&', 'var']],
 
97
    :f_arg_item => [[:f_norm_arg],
 
98
                    ['(', :f_margs, ')']],
 
99
    :f_margs => [[:f_marg_list],
 
100
                 [:f_marg_list, ',', '*', :f_norm_arg],
 
101
                 [:f_marg_list, ',', '*', :f_norm_arg, ',', :f_marg_list],
 
102
                 [:f_marg_list, ',', '*'],
 
103
                 [:f_marg_list, ',', '*',              ',', :f_marg_list],
 
104
                 [                   '*', :f_norm_arg],
 
105
                 [                   '*', :f_norm_arg, ',', :f_marg_list],
 
106
                 [                   '*'],
 
107
                 [                   '*',              ',', :f_marg_list]],
 
108
    :f_marg_list => [[:f_marg],
 
109
                     [:f_marg_list, ',', :f_marg]],
 
110
    :f_marg => [[:f_norm_arg],
 
111
                ['(', :f_margs, ')']],
 
112
    :f_norm_arg => [['var']],
 
113
 
 
114
    :command_args => [[:open_args]],
 
115
    :open_args => [[' ',:call_args],
 
116
                   ['(', ')'],
 
117
                   ['(', :call_args2, ')']],
 
118
    :call_args =>  [[:command],
 
119
                    [           :args,               :opt_block_arg],
 
120
                    [                       :assocs, :opt_block_arg],
 
121
                    [           :args, ',', :assocs, :opt_block_arg],
 
122
                    [                                    :block_arg]],
 
123
    :call_args2 => [[:arg, ',', :args,               :opt_block_arg],
 
124
                    [:arg, ',',                          :block_arg],
 
125
                    [                       :assocs, :opt_block_arg],
 
126
                    [:arg, ',',             :assocs, :opt_block_arg],
 
127
                    [:arg, ',', :args, ',', :assocs, :opt_block_arg],
 
128
                    [                                    :block_arg]],
 
129
 
 
130
    :command_args_noblock => [[:open_args_noblock]],
 
131
    :open_args_noblock => [[' ',:call_args_noblock],
 
132
                   ['(', ')'],
 
133
                   ['(', :call_args2_noblock, ')']],
 
134
    :call_args_noblock =>  [[:command],
 
135
                    [           :args],
 
136
                    [                       :assocs],
 
137
                    [           :args, ',', :assocs]],
 
138
    :call_args2_noblock => [[:arg, ',', :args],
 
139
                            [                       :assocs],
 
140
                            [:arg, ',',             :assocs],
 
141
                            [:arg, ',', :args, ',', :assocs]],
 
142
 
 
143
    :command => [],
 
144
    :args => [[:arg],
 
145
              ["*",:arg],
 
146
              [:args,",",:arg],
 
147
              [:args,",","*",:arg]],
 
148
    :arg => [[:exp]],
 
149
    :assocs => [[:assoc],
 
150
                [:assocs, ',', :assoc]],
 
151
    :assoc => [[:arg, '=>', :arg],
 
152
               ['label', ':', :arg]],
 
153
    :opt_block_arg => [[',', :block_arg],
 
154
                       []],
 
155
    :block_arg => [['&', :arg]],
 
156
    #:test => [['def m() yield', :command_args_noblock, ' end; r = m {', :block_param_def, 'vars', '}; undef m; r']]
 
157
    :test_proc => [['def m() yield', :command_args_noblock, ' end; r = m {', :block_param_def, 'vars', '}; undef m; r']],
 
158
    :test_lambda => [['def m() yield', :command_args_noblock, ' end; r = m(&lambda {', :block_param_def, 'vars', '}); undef m; r']]
 
159
  }
 
160
 
 
161
  def rename_var(obj)
 
162
    vars = []
 
163
    r = obj.subst('var') {
 
164
      var = "v#{vars.length}"
 
165
      vars << var
 
166
      var
 
167
    }
 
168
    return r, vars
 
169
  end
 
170
 
 
171
  def split_by_comma(ary)
 
172
    return [] if ary.empty?
 
173
    result = [[]]
 
174
    ary.each {|e|
 
175
      if e == ','
 
176
        result << []
 
177
      else
 
178
        result.last << e
 
179
      end
 
180
    }
 
181
    result
 
182
  end
 
183
 
 
184
  def emu_return_args(*vs)
 
185
    vs
 
186
  end
 
187
 
 
188
  def emu_eval_args(args)
 
189
    if args.last == []
 
190
      args = args[0...-1]
 
191
    end
 
192
    code = "emu_return_args #{args.map {|a| a.join('') }.join(",")}"
 
193
    eval code
 
194
  end
 
195
 
 
196
  def emu_bind_single(arg, param, result_binding)
 
197
    #p [:emu_bind_single, arg, param]
 
198
    if param.length == 1 && String === param[0] && /\A[a-z0-9]+\z/ =~ param[0]
 
199
      result_binding[param[0]] = arg
 
200
    elsif param.length == 1 && Array === param[0] && param[0][0] == '(' && param[0][-1] == ')'
 
201
      arg = [arg] unless Array === arg
 
202
      emu_bind_params(arg, split_by_comma(param[0][1...-1]), false, result_binding)
 
203
    else
 
204
      raise "unexpected param: #{param.inspect}"
 
205
    end
 
206
    result_binding
 
207
  end
 
208
 
 
209
  def emu_bind_params(args, params, islambda, result_binding={})
 
210
    #p [:emu_bind_params, args, params]
 
211
    if params.last == [] # extra comma
 
212
      params.pop
 
213
    end
 
214
 
 
215
    star_index = nil
 
216
    params.each_with_index {|par, i|
 
217
      star_index = i if par[0] == '*'
 
218
    }
 
219
 
 
220
    if islambda
 
221
      if star_index
 
222
        if args.length < params.length - 1
 
223
          throw :emuerror, ArgumentError
 
224
        end
 
225
      else
 
226
        if args.length != params.length
 
227
          throw :emuerror, ArgumentError
 
228
        end
 
229
      end
 
230
    end
 
231
 
 
232
    # TRICK #2 : adjust mismatch on number of arguments
 
233
    if star_index
 
234
      pre_params = params[0...star_index]
 
235
      rest_param = params[star_index]
 
236
      post_params = params[(star_index+1)..-1]
 
237
      pre_params.each {|par| emu_bind_single(args.shift, par, result_binding) }
 
238
      if post_params.length <= args.length
 
239
        post_params.reverse_each {|par| emu_bind_single(args.pop, par, result_binding) }
 
240
      else
 
241
        post_params.each {|par| emu_bind_single(args.shift, par, result_binding) }
 
242
      end
 
243
      if rest_param != ['*']
 
244
        emu_bind_single(args, rest_param[1..-1], result_binding)
 
245
      end
 
246
    else
 
247
      params.each_with_index {|par, i|
 
248
        emu_bind_single(args[i], par, result_binding)
 
249
      }
 
250
    end
 
251
 
 
252
    #p [args, params, result_binding]
 
253
 
 
254
    result_binding
 
255
  end
 
256
 
 
257
  def emu_bind(t, islambda)
 
258
    #puts
 
259
    #p t
 
260
    command_args_noblock = t[1]
 
261
    block_param_def = t[3]
 
262
    command_args_noblock = command_args_noblock.expand {|a| !(a[0] == '[' && a[-1] == ']') }
 
263
    block_param_def = block_param_def.expand {|a| !(a[0] == '(' && a[-1] == ')') }
 
264
 
 
265
    if command_args_noblock.to_a[0] == ' '
 
266
      args = command_args_noblock.to_a[1..-1]
 
267
    elsif command_args_noblock.to_a[0] == '(' && command_args_noblock.to_a[-1] == ')'
 
268
      args = command_args_noblock.to_a[1...-1]
 
269
    else
 
270
      raise "unexpected command_args_noblock: #{command_args_noblock.inspect}"
 
271
    end
 
272
    args = emu_eval_args(split_by_comma(args))
 
273
 
 
274
    params = block_param_def.to_a[1...-1]
 
275
    params = split_by_comma(params)
 
276
 
 
277
    #p [:emu0, args, params]
 
278
 
 
279
    result_binding = {}
 
280
 
 
281
    if params.last && params.last[0] == '&'
 
282
      result_binding[params.last[1]] = nil
 
283
      params.pop
 
284
    end
 
285
 
 
286
    if !islambda
 
287
      # TRICK #1 : single array argument is expanded if there are two or more params.
 
288
      # * block parameter is not counted.
 
289
      # * extra comma after single param forces the expansion.
 
290
      if args.length == 1 && Array === args[0] && 1 < params.length
 
291
        args = args[0]
 
292
      end
 
293
    end
 
294
 
 
295
    emu_bind_params(args, params, islambda, result_binding)
 
296
    #p result_binding
 
297
    result_binding
 
298
  end
 
299
 
 
300
  def emu(t, vars, islambda)
 
301
    catch(:emuerror) {
 
302
      emu_binding = emu_bind(t, islambda)
 
303
      vars.map {|var| emu_binding.fetch(var, "NOVAL") }
 
304
    }
 
305
  end
 
306
 
 
307
  def check_nofork(t, islambda=false)
 
308
    t, vars = rename_var(t)
 
309
    t = t.subst('vars') { " [#{vars.join(",")}]" }
 
310
    emu_values = emu(t, vars, islambda)
 
311
    s = t.to_s
 
312
    #print "#{s}\t\t"
 
313
    #STDOUT.flush
 
314
    begin
 
315
      eval_values = eval(s)
 
316
    rescue ArgumentError
 
317
      eval_values = ArgumentError
 
318
    end
 
319
    #success = emu_values == eval_values ? 'succ' : 'fail'
 
320
    #puts "eval:#{vs_ev.inspect[1...-1].delete(' ')}\temu:#{vs_emu.inspect[1...-1].delete(' ')}\t#{success}"
 
321
    assert_equal(emu_values, eval_values, s)
 
322
  end
 
323
 
 
324
  def test_yield
 
325
    syntax = Sentence.expand_syntax(Syntax)
 
326
    Sentence.each(syntax, :test_proc, 4) {|t|
 
327
      check_nofork(t)
 
328
    }
 
329
  end
 
330
 
 
331
  def test_yield_lambda
 
332
    syntax = Sentence.expand_syntax(Syntax)
 
333
    Sentence.each(syntax, :test_lambda, 4) {|t|
 
334
      check_nofork(t, true)
 
335
    }
 
336
  end
 
337
 
 
338
end