gecoder 0.8.2 → 0.8.3

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 (38) hide show
  1. data/CHANGES +14 -0
  2. data/ext/gecoder.cpp +181 -0
  3. data/ext/gecoder.h +94 -0
  4. data/ext/vararray.cpp +3 -3
  5. data/lib/gecoder/bindings/bindings.rb +104 -46
  6. data/lib/gecoder/interface/binding_changes.rb +1 -301
  7. data/lib/gecoder/interface/branch.rb +15 -11
  8. data/lib/gecoder/interface/constraints/bool/boolean.rb +56 -52
  9. data/lib/gecoder/interface/constraints/bool/channel.rb +1 -16
  10. data/lib/gecoder/interface/constraints/bool_enum/channel.rb +13 -8
  11. data/lib/gecoder/interface/constraints/bool_enum/extensional.rb +48 -0
  12. data/lib/gecoder/interface/constraints/extensional_regexp.rb +101 -0
  13. data/lib/gecoder/interface/constraints/int/channel.rb +1 -13
  14. data/lib/gecoder/interface/constraints/int_enum/channel.rb +15 -35
  15. data/lib/gecoder/interface/constraints/int_enum/extensional.rb +130 -0
  16. data/lib/gecoder/interface/constraints/set/channel.rb +54 -0
  17. data/lib/gecoder/interface/constraints/set_enum/channel.rb +37 -6
  18. data/lib/gecoder/interface/constraints/set_var_constraints.rb +1 -0
  19. data/lib/gecoder/interface/constraints.rb +38 -0
  20. data/lib/gecoder/interface/model.rb +110 -85
  21. data/lib/gecoder/interface/variables.rb +3 -21
  22. data/lib/gecoder/version.rb +1 -1
  23. data/specs/branch.rb +16 -1
  24. data/specs/constraints/bool_enum_relation.rb +6 -6
  25. data/specs/constraints/boolean.rb +31 -25
  26. data/specs/constraints/channel.rb +102 -4
  27. data/specs/constraints/extensional.rb +185 -2
  28. data/specs/constraints/reification_sugar.rb +2 -46
  29. data/specs/model.rb +85 -7
  30. data/tasks/dependencies.txt +1 -0
  31. data/vendor/rust/rust/class.rb +33 -35
  32. data/vendor/rust/rust/templates/ClassDeclarations.rusttpl +1 -1
  33. data/vendor/rust/rust/templates/CxxClassDefinitions.rusttpl +10 -1
  34. metadata +185 -184
  35. data/example/raw_bindings.rb +0 -44
  36. data/ext/missing.cpp +0 -328
  37. data/ext/missing.h +0 -120
  38. data/specs/binding_changes.rb +0 -76
@@ -26,10 +26,23 @@ class BoolChannelSampleProblem < Gecode::Model
26
26
  @int = int_var(0..3)
27
27
  @bool = bool_var
28
28
 
29
- branch_on wrap_enum([@int])
29
+ branch_on @int
30
30
  end
31
31
  end
32
32
 
33
+ class SetChannelSampleProblem < Gecode::Model
34
+ attr :bool_enum
35
+ attr :set
36
+
37
+ def initialize
38
+ @bool_enum = bool_var_array(4)
39
+ @set = set_var([], 0..3)
40
+
41
+ branch_on @bool_enum
42
+ end
43
+ end
44
+
45
+
33
46
  describe Gecode::Constraints::IntEnum::Channel, ' (two int enums)' do
34
47
  before do
35
48
  @model = ChannelSampleProblem.new
@@ -73,10 +86,10 @@ describe Gecode::Constraints::IntEnum::Channel, ' (two int enums)' do
73
86
  lambda{ @elements.must.channel 'hello' }.should raise_error(TypeError)
74
87
  end
75
88
 
76
- it_should_behave_like 'reifiable constraint'
89
+ it_should_behave_like 'non-reifiable constraint'
77
90
  end
78
91
 
79
- describe Gecode::Constraints::IntEnum::Channel, ' (one int enum and one set enum)' do
92
+ describe Gecode::Constraints::SetEnum::Channel::IntChannelConstraint, ' (channel with set as right hand side)' do
80
93
  before do
81
94
  @model = ChannelSampleProblem.new
82
95
  @positions = @model.positions
@@ -113,7 +126,7 @@ describe Gecode::Constraints::IntEnum::Channel, ' (one int enum and one set enum
113
126
  it_should_behave_like 'non-reifiable set constraint'
114
127
  end
115
128
 
116
- describe Gecode::Constraints::SetEnum, ' (channel with set as left hand side)' do
129
+ describe Gecode::Constraints::SetEnum::Channel::IntChannelConstraint, ' (channel with set as left hand side)' do
117
130
  before do
118
131
  @model = ChannelSampleProblem.new
119
132
  @positions = @model.positions
@@ -354,3 +367,88 @@ describe Gecode::Constraints::BoolEnum::Channel, ' (int variable as lhs with boo
354
367
 
355
368
  it_should_behave_like 'channel constraint between bool enum and int variable'
356
369
  end
370
+
371
+ # Requires @model, @bool_enum and @set. Also requires @place_constraint which
372
+ # is a method that takes four variables: a boolean enum, a set variable,
373
+ # whether or not the constraint should be negated and a hash of options, and
374
+ # places the channel constraint on them.
375
+ describe 'channel constraint between set variable and bool enum', :shared => true do
376
+ before do
377
+ @invoke_options = lambda do |hash|
378
+ @place_constraint.call(@bools, @set, false, hash)
379
+ @model.solve!
380
+ end
381
+ @expect_options = option_expectation do |strength, kind, reif_var|
382
+ Gecode::Raw.should_receive(:channel).once.with(
383
+ an_instance_of(Gecode::Raw::Space),
384
+ an_instance_of(Gecode::Raw::BoolVarArray),
385
+ an_instance_of(Gecode::Raw::SetVar))
386
+ end
387
+ end
388
+
389
+ it 'should channel the bool enum with the set variable' do
390
+ @set.must_be.superset_of [0, 2]
391
+ @place_constraint.call(@bools, @set, false, {})
392
+ @model.solve!.should_not be_nil
393
+ set_values = @set.value
394
+ @bools.values.each_with_index do |bool, index|
395
+ bool.should == set_values.include?(index)
396
+ end
397
+ end
398
+
399
+ it 'should not allow negation' do
400
+ lambda do
401
+ @place_constraint.call(@bools, @set, true, {})
402
+ end.should raise_error(Gecode::MissingConstraintError)
403
+ end
404
+
405
+ it_should_behave_like 'non-reifiable set constraint'
406
+ end
407
+
408
+ describe Gecode::Constraints::Set::Channel, ' (set variable as lhs with bool enum)' do
409
+ before do
410
+ @model = SetChannelSampleProblem.new
411
+ @bools = @model.bool_enum
412
+ @set = @model.set
413
+
414
+ @place_constraint = lambda do |bools, set, negate, options|
415
+ unless negate
416
+ set.must.channel(bools, options)
417
+ else
418
+ set.must_not.channel(bools, options)
419
+ end
420
+ end
421
+ end
422
+
423
+ it 'should raise error if a boolean enum is not given as right hand side' do
424
+ lambda do
425
+ @set.must.channel 'hello'
426
+ end.should raise_error(TypeError)
427
+ end
428
+
429
+ it_should_behave_like 'channel constraint between set variable and bool enum'
430
+ end
431
+
432
+ describe Gecode::Constraints::Set::Channel, ' (bool enum as lhs with set variable)' do
433
+ before do
434
+ @model = SetChannelSampleProblem.new
435
+ @bools = @model.bool_enum
436
+ @set = @model.set
437
+
438
+ @place_constraint = lambda do |bools, set, negate, options|
439
+ unless negate
440
+ bools.must.channel(set, options)
441
+ else
442
+ bools.must_not.channel(set, options)
443
+ end
444
+ end
445
+ end
446
+
447
+ it 'should raise error if an integer variable is not given as right hand side' do
448
+ lambda do
449
+ @bools.must.channel 'hello'
450
+ end.should raise_error(TypeError)
451
+ end
452
+
453
+ it_should_behave_like 'channel constraint between set variable and bool enum'
454
+ end
@@ -44,7 +44,7 @@ describe 'tuple constraint', :shared => true do
44
44
  it_should_behave_like 'non-reifiable constraint'
45
45
  end
46
46
 
47
- describe Gecode::Constraints::IntEnum::Extensional do
47
+ describe Gecode::Constraints::IntEnum::Extensional, ' (tuple constraint)' do
48
48
  before do
49
49
  @model = Gecode::Model.new
50
50
  @tuples = [[1,7], [5,1]]
@@ -77,7 +77,7 @@ describe Gecode::Constraints::IntEnum::Extensional do
77
77
  it_should_behave_like 'tuple constraint'
78
78
  end
79
79
 
80
- describe Gecode::Constraints::BoolEnum::Extensional do
80
+ describe Gecode::Constraints::BoolEnum::Extensional, ' (tuple constraint)' do
81
81
  before do
82
82
  @model = Gecode::Model.new
83
83
  @tuples = [[true, false, true], [false, false, true]]
@@ -109,3 +109,186 @@ describe Gecode::Constraints::BoolEnum::Extensional do
109
109
 
110
110
  it_should_behave_like 'tuple constraint'
111
111
  end
112
+
113
+ # Assumes that @variables, @expected_array, @value1, @value2 (must not
114
+ # equal @value1) and @regexp are defined.
115
+ describe 'regular expression constraint', :shared => true do
116
+ before do
117
+ @invoke_options = lambda do |hash|
118
+ @variables.must.match(@regexp, hash)
119
+ @model.solve!
120
+ end
121
+ @expect_options = option_expectation do |strength, kind, reif_var|
122
+ Gecode::Raw.should_receive(:extensional).once.with(
123
+ an_instance_of(Gecode::Raw::Space),
124
+ @expected_array,
125
+ an_instance_of(Gecode::Raw::REG), strength, kind)
126
+ end
127
+ end
128
+
129
+ it 'should handle values grouped in a single array' do
130
+ @variables.must.match [@value1, @value2, @value1]
131
+ @model.solve!.should_not be_nil
132
+ @variables.values.should == [@value1, @value2, @value1]
133
+ end
134
+
135
+ it 'should allow nested groups of values' do
136
+ @variables.must.match [@value1, [@value2, [@value1]]]
137
+ @model.solve!.should_not be_nil
138
+ @variables.values.should == [@value1, @value2, @value1]
139
+ end
140
+
141
+ it 'should handle the repeat operation' do
142
+ @variables.must.match [@value1, @model.repeat([@value2], 1, 2)]
143
+ @model.solve!.should_not be_nil
144
+ @variables.values.should == [@value1, @value2, @value2]
145
+ end
146
+
147
+ it 'should handle repeat operations that do not encase constant values in arrays' do
148
+ @variables.must.match [@value1, @model.repeat(@value2, 1, 2)]
149
+ @model.solve!.should_not be_nil
150
+ @variables.values.should == [@value1, @value2, @value2]
151
+ end
152
+
153
+ it 'should handle nested repeat operations' do
154
+ @variables.must.match [[@model.repeat(@model.repeat([@value2], 1, 3), 1, 2)]]
155
+ @model.solve!.should_not be_nil
156
+ @variables.values.should == [@value2, @value2, @value2]
157
+ end
158
+
159
+ it 'should handle nested repeat operations (2)' do
160
+ @variables.must.match [[@model.repeat([@model.repeat(@value2, 1, 3)], 1, 2)]]
161
+ @model.solve!.should_not be_nil
162
+ @variables.values.should == [@value2, @value2, @value2]
163
+ end
164
+
165
+ it 'should interpret the repeat operation with the last argument omitted as only giving a lower bound' do
166
+ @variables.must.match [@value1, @model.repeat([@value2], 1)]
167
+ @model.solve!.should_not be_nil
168
+ @variables.values.should == [@value1, @value2, @value2]
169
+ end
170
+
171
+ it 'should interpret the repeat operation with all but the first argument omitted as not giving any bound' do
172
+ @variables.must.match [@model.repeat(@value2), @value1, @value1, @value1]
173
+ @model.solve!.should_not be_nil
174
+ @variables.values.should == [@value1, @value1, @value1]
175
+ end
176
+
177
+ it 'should interpret the repeat operation with all but the first argument omitted as not giving any bound (2)' do
178
+ @variables.must.match [@model.repeat(@value2)]
179
+ @model.solve!.should_not be_nil
180
+ @variables.values.should == [@value2, @value2, @value2]
181
+ end
182
+
183
+ it 'should translate at_most_once(reg) to repeat(reg, 0, 1)' do
184
+ @model.should_receive(:repeat).once.with([@value1], 0, 1)
185
+ @model.at_most_once [@value1]
186
+ end
187
+
188
+ it 'should translate at_least_once(reg) to repeat(reg, 1)' do
189
+ @model.should_receive(:repeat).once.with([@value1], 1)
190
+ @model.at_least_once [@value1]
191
+ end
192
+
193
+ it 'should raise error if the right hand side is not an enumeration' do
194
+ lambda do
195
+ @variables.must.match Object.new
196
+ end.should raise_error(TypeError)
197
+ end
198
+
199
+ it 'should raise error if the right hand side does not a regexp of the right type' do
200
+ lambda do
201
+ @variables.must.match [@value1, 'foo']
202
+ end.should raise_error(TypeError)
203
+ end
204
+
205
+ it 'should raise error if the right hand side contains a nested element of an incorrect type' do
206
+ lambda do
207
+ @variables.must.match [@value1, [@value2, 'foo']]
208
+ end.should raise_error(TypeError)
209
+ end
210
+
211
+ it 'should raise error if the repeat operation is given arguments of incorrect type (2)' do
212
+ lambda do
213
+ @variables.must.match @model.repeat(@value1, [0], 1)
214
+ end.should raise_error(TypeError)
215
+ end
216
+
217
+ it 'should raise error if the repeat operation is given arguments of incorrect type (3)' do
218
+ lambda do
219
+ @variables.must.match @model.repeat(@value1, 0, [1])
220
+ end.should raise_error(TypeError)
221
+ end
222
+
223
+ it 'should raise error if the repeat operation is given arguments of incorrect type' do
224
+ lambda do
225
+ @variables.must.match @model.repeat('foo', 0, 1)
226
+ end.should raise_error(TypeError)
227
+ end
228
+
229
+ it 'should not allow negation' do
230
+ lambda do
231
+ @variables.must_not.match @regexp
232
+ end.should raise_error(Gecode::MissingConstraintError)
233
+ end
234
+
235
+ it_should_behave_like 'non-reifiable constraint'
236
+ end
237
+
238
+ describe Gecode::Constraints::IntEnum::Extensional, ' (regexp constraint)' do
239
+ before do
240
+ @model = Gecode::Model.new
241
+ @variables = @digits = @model.int_var_array(3, 0..9)
242
+ @model.branch_on @digits
243
+ @expected_array = an_instance_of Gecode::Raw::IntVarArray
244
+ @value1 = 3
245
+ @value2 = 5
246
+ @regexp = [1, @model.any(3, 4), @model.at_most_once(5)]
247
+ end
248
+
249
+ it 'should handle the any operation' do
250
+ @digits.must.match [1, @model.any(1, 2, 3), 3]
251
+ @model.solve!.should_not be_nil
252
+ values = @digits.values
253
+ values.size.should == 3
254
+ values.should == values.sort
255
+ end
256
+
257
+ it 'should handle the any operator with nested expressions' do
258
+ @digits.must.match [1, @model.any(@model.at_least_once(2), [3, 5])]
259
+ @digits[2].must < 4
260
+ @model.solve!.should_not be_nil
261
+ @digits.values.should == [1,2,2]
262
+ end
263
+
264
+ it_should_behave_like 'regular expression constraint'
265
+ end
266
+
267
+ describe Gecode::Constraints::BoolEnum::Extensional, ' (regexp constraint)' do
268
+ before do
269
+ @model = Gecode::Model.new
270
+ @variables = @bools = @model.bool_var_array(3)
271
+ @model.branch_on @bools
272
+ @expected_array = an_instance_of Gecode::Raw::BoolVarArray
273
+ @value1 = true
274
+ @value2 = false
275
+ @regexp = [true, @model.any(true, false), @model.at_most_once(true)]
276
+ end
277
+
278
+ it 'should handle the any operation' do
279
+ @bools.must.match [@model.repeat(@model.any(true, false))]
280
+ @bools[0].must_be.true
281
+ @bools[1].must_be.false
282
+ @model.solve!.should_not be_nil
283
+ @bools[0].value.should be_true
284
+ @bools[1].value.should be_false
285
+ end
286
+
287
+ it 'should handle the any operator with nested expressions' do
288
+ @bools.must.match [@model.any(@model.at_least_once(true), [false])]
289
+ @model.solve!.should_not be_nil
290
+ @bools.values.should == [true, true, true]
291
+ end
292
+
293
+ it_should_behave_like 'regular expression constraint'
294
+ end
@@ -26,28 +26,6 @@ describe Gecode::Constraints::ReifiableConstraint do
26
26
  @model.solve!.should be_nil
27
27
  end
28
28
 
29
- it 'should translate disjunctions' do
30
- Gecode::Raw.should_receive(:rel).once.with(
31
- an_instance_of(Gecode::Raw::Space),
32
- an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::BOT_OR,
33
- an_instance_of(Gecode::Raw::BoolVar),
34
- an_instance_of(Gecode::Raw::BoolVar),
35
- Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF
36
- )
37
- Gecode::Raw.should_receive(:rel).once.with(
38
- an_instance_of(Gecode::Raw::Space),
39
- an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR, 0,
40
- an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF,
41
- Gecode::Raw::PK_DEF)
42
- Gecode::Raw.should_receive(:rel).once.with(
43
- an_instance_of(Gecode::Raw::Space),
44
- an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_EQ, 3,
45
- an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF,
46
- Gecode::Raw::PK_DEF)
47
- (@x.must > 0) | (@y.must == 3)
48
- sol = @model.solve!
49
- end
50
-
51
29
  it 'should solve disjunctions' do
52
30
  (@x.must > 0) | (@y.must == 3)
53
31
  sol = @model.solve!
@@ -59,29 +37,7 @@ describe Gecode::Constraints::ReifiableConstraint do
59
37
  (@x.must > 3) & (@y.must == 3)
60
38
  @model.solve!.should be_nil
61
39
  end
62
-
63
- it 'should translate conjunctions' do
64
- Gecode::Raw.should_receive(:rel).once.with(
65
- an_instance_of(Gecode::Raw::Space),
66
- an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::BOT_AND,
67
- an_instance_of(Gecode::Raw::BoolVar),
68
- an_instance_of(Gecode::Raw::BoolVar),
69
- Gecode::Raw::ICL_DEF, Gecode::Raw::PK_DEF
70
- )
71
- Gecode::Raw.should_receive(:rel).once.with(
72
- an_instance_of(Gecode::Raw::Space),
73
- an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_GR, 0,
74
- an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF,
75
- Gecode::Raw::PK_DEF)
76
- Gecode::Raw.should_receive(:rel).once.with(
77
- an_instance_of(Gecode::Raw::Space),
78
- an_instance_of(Gecode::Raw::IntVar), Gecode::Raw::IRT_EQ, 2,
79
- an_instance_of(Gecode::Raw::BoolVar), Gecode::Raw::ICL_DEF,
80
- Gecode::Raw::PK_DEF)
81
- (@x.must > 0) & (@y.must == 2)
82
- sol = @model.solve!
83
- end
84
-
40
+
85
41
  it 'should solve conjunctions' do
86
42
  (@x.must > 0) & (@y.must == 2)
87
43
  sol = @model.solve!
@@ -111,4 +67,4 @@ describe Gecode::Constraints::ReifiableConstraint do
111
67
  sol = @model.solve!
112
68
  sol.should be_nil
113
69
  end
114
- end
70
+ end
data/specs/model.rb CHANGED
@@ -9,7 +9,7 @@ describe Gecode::Model, ' (integer creation)' do
9
9
  range = 0..3
10
10
  @model.int_var(range).should have_domain(range)
11
11
  end
12
-
12
+
13
13
  it 'should allow the creation of int variables without specified domain' do
14
14
  var = @model.int_var
15
15
  var.should be_range
@@ -43,6 +43,17 @@ describe Gecode::Model, ' (integer creation)' do
43
43
  vars.each{ |var| var.should have_domain(domain) }
44
44
  end
45
45
 
46
+ it 'should allow the creation of int-var arrays without specified domain' do
47
+ count = 5
48
+ vars = @model.int_var_array(count)
49
+ vars.size.should equal(count)
50
+ vars.each do |var|
51
+ var.should be_range
52
+ var.min.should == Gecode::Raw::IntLimits::MIN
53
+ var.max.should == Gecode::Raw::IntLimits::MAX
54
+ end
55
+ end
56
+
46
57
  it 'should allow the creation of int-var matrices with range domains' do
47
58
  range = 0..3
48
59
  rows = 5
@@ -62,6 +73,32 @@ describe Gecode::Model, ' (integer creation)' do
62
73
  vars.column_size.should equal(columns)
63
74
  vars.each{ |var| var.should have_domain(domain) }
64
75
  end
76
+
77
+ it 'should allow the creation of int-var matrices without specified domain' do
78
+ rows = 5
79
+ columns = 4
80
+ vars = @model.int_var_matrix(rows, columns)
81
+ vars.row_size.should equal(rows)
82
+ vars.column_size.should equal(columns)
83
+ vars.each do |var|
84
+ var.should be_range
85
+ var.min.should == Gecode::Raw::IntLimits::MIN
86
+ var.max.should == Gecode::Raw::IntLimits::MAX
87
+ end
88
+ end
89
+
90
+ it 'should raise error if the domain is of incorrect type' do
91
+ lambda do
92
+ @model.int_var(nil)
93
+ end.should raise_error(TypeError)
94
+ end
95
+
96
+ it 'should gracefully GC a variable that was never accessed' do
97
+ lambda do
98
+ @model.int_var 0
99
+ GC.start
100
+ end.should_not raise_error
101
+ end
65
102
  end
66
103
 
67
104
  describe Gecode::Model, ' (bool creation)' do
@@ -82,6 +119,13 @@ describe Gecode::Model, ' (bool creation)' do
82
119
  matrix.row_size.should equal(3)
83
120
  matrix.column_size.should equal(4)
84
121
  end
122
+
123
+ it 'should gracefully GC a variable that was never accessed' do
124
+ lambda do
125
+ @model.bool_var
126
+ GC.start
127
+ end.should_not raise_error
128
+ end
85
129
  end
86
130
 
87
131
  describe Gecode::Model, ' (set creation)' do
@@ -143,6 +187,15 @@ describe Gecode::Model, ' (set creation)' do
143
187
  end
144
188
  end
145
189
 
190
+ it 'should allow the creation of arrays of set variables without specified bounds' do
191
+ vars = @model.set_var_array(3)
192
+ vars.each do |var|
193
+ var.lower_bound.size.should == 0
194
+ var.upper_bound.min.should == Gecode::Raw::SetLimits::MIN
195
+ var.upper_bound.max.should == Gecode::Raw::SetLimits::MAX
196
+ end
197
+ end
198
+
146
199
  it 'should allow the creation of matrices of set variables' do
147
200
  matrix = @model.set_var_matrix(4, 5, @glb_enum, @lub_enum,
148
201
  @lower_card..@upper_card)
@@ -154,20 +207,45 @@ describe Gecode::Model, ' (set creation)' do
154
207
  var.cardinality.begin.should >= @lower_card
155
208
  end
156
209
  end
210
+
211
+ it 'should allow the creation of matrices of set variables without specified bounds' do
212
+ matrix = @model.set_var_matrix(4, 5)
213
+ matrix.each do |var|
214
+ var.lower_bound.size.should == 0
215
+ var.upper_bound.min.should == Gecode::Raw::SetLimits::MIN
216
+ var.upper_bound.max.should == Gecode::Raw::SetLimits::MAX
217
+ end
218
+ end
157
219
 
158
220
  it 'should raise error if glb and lub are not valid when they are given as range' do
159
- lambda{ @model.set_var(@lub_range, @glb_range).should }.should raise_error(
160
- ArgumentError)
221
+ lambda do
222
+ @model.set_var(@lub_range, @glb_range)
223
+ end.should raise_error(ArgumentError)
161
224
  end
162
225
 
163
226
  it 'should raise error if glb and lub are not valid when one is given as enum' do
164
- lambda{ @model.set_var(@lub_range, @glb_enum).should }.should raise_error(
165
- ArgumentError)
227
+ lambda do
228
+ @model.set_var(@lub_range, @glb_enum)
229
+ end.should raise_error(ArgumentError)
166
230
  end
167
231
 
168
232
  it 'should raise error if glb and lub are not valid when both are given as enums' do
169
- lambda{ @model.set_var(@lub_enum, @glb_enum).should }.should raise_error(
170
- ArgumentError)
233
+ lambda do
234
+ @model.set_var(@lub_enum, @glb_enum)
235
+ end.should raise_error(ArgumentError)
236
+ end
237
+
238
+ it 'should raise error if the glb and lub are of incorrect type' do
239
+ lambda do
240
+ @model.set_var("foo\n", "foo\ns")
241
+ end.should raise_error(TypeError)
242
+ end
243
+
244
+ it 'should gracefully GC a variable that was never accessed' do
245
+ lambda do
246
+ @model.set_var(@glb_range, @lub_range)
247
+ GC.start
248
+ end.should_not raise_error
171
249
  end
172
250
  end
173
251
 
@@ -9,6 +9,7 @@ coderay
9
9
 
10
10
  # To run the specs and produce a report for the website.
11
11
  rspec
12
+ rcov
12
13
 
13
14
  # To release files to RubyForge.
14
15
  meta_project
@@ -260,7 +260,7 @@ module Rust
260
260
 
261
261
  private
262
262
  def raw_call(nparam = nil)
263
- case @position
263
+ case position(@parameters.size)
264
264
  when 1 # pre
265
265
  "#{@name} (*tmp)"
266
266
  when 2 # mid
@@ -272,43 +272,41 @@ module Rust
272
272
  end
273
273
  end
274
274
 
275
+ # 1: pre 2: mid 3: post 4: mixed
276
+ def position(nparam)
277
+ case @name
278
+ when "+": (nparam.zero? ? 1 : 3)
279
+ when "-": 3
280
+ when "*": (nparam.zero? ? 1 : 3)
281
+ when "/": 3
282
+ when /\[\s*\]=/: 4
283
+ when /\[\s*\]/: 2
284
+ when "==": 3
285
+ when "!=": 3
286
+ when "<<": 3
287
+ when ">>": 3
288
+ when "!": 1
289
+ when "()": 2
290
+ else
291
+ 3
292
+ end
293
+ end
294
+
275
295
  def valid_name
276
296
  case @name
277
- when "+"
278
- @position = 3
279
- "plusop"
280
- when "-"
281
- @position = 3
282
- "minusop"
283
- when "*"
284
- @position = 3
285
- "multop"
286
- when "/"
287
- @position = 3
288
- "divop"
289
- when /\[\s*\]=/
290
- @position = 4
291
- "ateqop"
292
- when /\[\s*\]/
293
- @position = 2
294
- "atop"
295
- when "=="
296
- @position = 3
297
- "equalop"
298
- when "!="
299
- @position = 3
300
- "notequalop"
301
- when "<<"
302
- @position = 3
303
- "outstream"
304
- when ">>"
305
- @position = 3
306
- "intstream"
307
- when "!"
308
- @position = 1
309
- "notop"
297
+ when "+": "plusop"
298
+ when "-": "minusop"
299
+ when "*": "multop"
300
+ when "/": "divop"
301
+ when /\[\s*\]=/: "ateqop"
302
+ when /\[\s*\]/: "atop"
303
+ when "==": "equalop"
304
+ when "!=": "notequalop"
305
+ when "<<": "outstream"
306
+ when ">>": "intstream"
307
+ when "!": "notop"
308
+ when "()": "parenthesisop"
310
309
  else
311
- @position = 3
312
310
  "undefop_#{@name[0].chr.to_i}#{rand(1024)}"
313
311
  end
314
312
  end
@@ -1,7 +1,7 @@
1
1
  //-*-c++-*-
2
2
 
3
3
  extern VALUE r!class_varname!;
4
- VALUE cxx2ruby(!c_class_name!* instance, bool free = false);
4
+ VALUE cxx2ruby(!c_class_name!* instance, bool free = false, bool create_new_if_needed = true);
5
5
  bool is_!class_varname!(VALUE val);
6
6
  !c_class_name!* ruby2!class_varcname!Ptr(VALUE rval, int argn = -1);
7
7
  !c_class_name!& ruby2!class_varcname!(VALUE rval, int argn = -1);
@@ -51,17 +51,26 @@ bool is_!class_varname!(VALUE val)
51
51
  return *ruby2!class_varcname!Ptr(rval, argn);
52
52
  }
53
53
 
54
- VALUE cxx2ruby(!c_class_name!* instance, bool free) {
54
+ VALUE cxx2ruby(!c_class_name!* instance, bool free, bool create_new_if_needed) {
55
55
  if ( instance == NULL ) return Qnil;
56
56
 
57
57
  T!class_ptrmap!::iterator it, eend = !class_ptrmap!.end();
58
58
 
59
+ #ifdef DEBUG
60
+ fprintf(stderr, "rust: searching for !c_class_name! %p\n", instance);
61
+ #endif
62
+
59
63
  for(it = !class_ptrmap!.begin(); it != eend; it++)
60
64
  if ( (*it).second == (!c_class_name!*)instance ) break;
61
65
 
62
66
  if ( it != !class_ptrmap!.end() )
63
67
  return (*it).first;
64
68
  else {
69
+ #ifdef DEBUG
70
+ fprintf(stderr, "rust: failed to find match for %p\n", instance);
71
+ #endif
72
+ if(!create_new_if_needed) return Qnil;
73
+
65
74
  VALUE klass = r!class_varname!;
66
75
 
67
76
  !test_children!