1 require File.dirname(__FILE__) + '/../spec_helper'
2 require File.dirname(__FILE__) + '/fixtures/variables'
4 describe "Basic assignment" do
5 it "allows the rhs to be assigned to the lhs" do
6 a = nil; a.should == nil
9 a = [1]; a.should == [1]
10 a = [nil]; a.should == [nil]
11 a = [[]]; a.should == [[]]
12 a = [1,2]; a.should == [1,2]
13 a = [*[]]; a.should == []
14 a = [*[1]]; a.should == [1]
15 a = [*[1,2]]; a.should == [1, 2]
18 it "allows the assignment of the rhs to the lhs using the rhs splat operator" do
19 a = *nil; a.should == nil
21 a = *[]; a.should == nil
22 a = *[1]; a.should == 1
23 a = *[nil]; a.should == nil
24 a = *[[]]; a.should == []
25 a = *[1,2]; a.should == [1,2]
26 a = *[*[]]; a.should == nil
27 a = *[*[1]]; a.should == 1
28 a = *[*[1,2]]; a.should == [1,2]
31 it "allows the assignment of the rhs to the lhs using the lhs splat operator" do
32 * = 1,2 # Valid syntax, but pretty useless! Nothing to test
33 *a = nil; a.should == [nil]
34 *a = 1; a.should == [1]
35 *a = []; a.should == [[]]
36 *a = [1]; a.should == [[1]]
37 *a = [nil]; a.should == [[nil]]
38 *a = [[]]; a.should == [[[]]]
39 *a = [1,2]; a.should == [[1,2]]
40 *a = [*[]]; a.should == [[]]
41 *a = [*[1]]; a.should == [[1]]
42 *a = [*[1,2]]; a.should == [[1,2]]
45 it "allows the assignment of rhs to the lhs using the lhs and rhs splat operators simultaneously" do
46 *a = *nil; a.should == [nil]
47 *a = *1; a.should == [1]
48 *a = *[]; a.should == []
49 *a = *[1]; a.should == [1]
50 *a = *[nil]; a.should == [nil]
51 *a = *[[]]; a.should == [[]]
52 *a = *[1,2]; a.should == [1,2]
53 *a = *[*[]]; a.should == []
54 *a = *[*[1]]; a.should == [1]
55 *a = *[*[1,2]]; a.should == [1,2]
58 it "allows multiple values to be assigned" do
59 a,b,*c = nil; [a,b,c].should == [nil, nil, []]
60 a,b,*c = 1; [a,b,c].should == [1, nil, []]
61 a,b,*c = []; [a,b,c].should == [nil, nil, []]
62 a,b,*c = [1]; [a,b,c].should == [1, nil, []]
63 a,b,*c = [nil]; [a,b,c].should == [nil, nil, []]
64 a,b,*c = [[]]; [a,b,c].should == [[], nil, []]
65 a,b,*c = [1,2]; [a,b,c].should == [1,2,[]]
66 a,b,*c = [*[]]; [a,b,c].should == [nil, nil, []]
67 a,b,*c = [*[1]]; [a,b,c].should == [1, nil, []]
68 a,b,*c = [*[1,2]]; [a,b,c].should == [1, 2, []]
70 a,b,*c = *nil; [a,b,c].should == [nil, nil, []]
71 a,b,*c = *1; [a,b,c].should == [1, nil, []]
72 a,b,*c = *[]; [a,b,c].should == [nil, nil, []]
73 a,b,*c = *[1]; [a,b,c].should == [1, nil, []]
74 a,b,*c = *[nil]; [a,b,c].should == [nil, nil, []]
75 a,b,*c = *[[]]; [a,b,c].should == [[], nil, []]
76 a,b,*c = *[1,2]; [a,b,c].should == [1,2,[]]
77 a,b,*c = *[*[]]; [a,b,c].should == [nil, nil, []]
78 a,b,*c = *[*[1]]; [a,b,c].should == [1, nil, []]
79 a,b,*c = *[*[1,2]]; [a,b,c].should == [1, 2, []]
82 it "supports the {|r,| } form of block assignment" do
83 f = lambda {|r,| r.should == []}
87 f.call(42).should == 42
88 f.call([42]).should == [42]
89 f.call([[42]]).should == [[42]]
90 f.call([42,55]).should == [42,55]
93 it "allows assignment through lambda" do
94 f = lambda {|r,*l| r.should == []; l.should == [1]}
98 f.call(42).should == 42
99 f.call([42]).should == [42]
100 f.call([[42]]).should == [[42]]
101 f.call([42,55]).should == [42,55]
104 f.call(42).should == [42]
105 f.call([42]).should == [[42]]
106 f.call([[42]]).should == [[[42]]]
107 f.call([42,55]).should == [[42,55]]
108 f.call(42,55).should == [42,55]
111 it "allows chained assignment" do
112 (a = 1 + b = 2 + c = 4 + d = 8).should == 15
120 describe "Assignment using expansion" do
121 it "succeeds without conversion" do
123 x.should == [[1, 2, 3, 4, 5, 6, 7]]
127 describe "Assigning multiple values" do
128 it "allows parallel assignment" do
137 it "allows safe parallel swapping" do
144 it "evaluates rhs left-to-right" do
145 a = VariablesSpecs::ParAsgn.new
146 d,e,f = a.inc, a.inc, a.inc
152 it "supports parallel assignment to lhs args via object.method=" do
153 a = VariablesSpecs::ParAsgn.new
158 c = VariablesSpecs::ParAsgn.new
164 it "supports parallel assignment to lhs args using []=" do
167 a.should == [1,2,3,4]
171 it "bundles remaining values to an array when using the splat operator" do
177 a.should == [1, 2, 3]
193 it "calls #to_ary on rhs arg if rhs has only a single arg" do
194 x = VariablesSpecs::ParAsgn.new
235 a,(b,(*c),(*d)) = 5,x
241 a,(b,(*c),(d,*e)) = 5,x
249 it "allows complex parallel assignment" do
250 a, (b, c), d = 1, [2, 3], 4
257 [x,y,z].should == [1,2,nil]
259 [x,y,z].should == [1,2,3]
261 [x,y,z].should == [1,2,nil]
263 a,(b,c,*d),(e,f),*g = 0,[1,2,3,4],[5,6],7,8
272 x = VariablesSpecs::ParAsgn.new
273 a,(b,c,*d),(e,f),*g = 0,x,[5,6],7,8
283 it "allows a lhs arg to be used in another lhs args parallel assignment" do
297 describe "Conditional assignment" do
298 it "assigns the lhs if previously unassigned" do
305 h["foo"].should == "bar"
307 h["foo".to_sym] ||= "bar"
308 h["foo".to_sym].should == "bar"
325 it "checks for class variable definition before fetching its value" do
326 class VariableSpecCVarSpec
328 @@cvarspec.should == 5
333 describe "Operator assignment 'var op= expr'" do
334 it "is equivalent to 'var = var op expr'" do
336 (x += 5).should == 18
340 (x -= 11).should == 6
344 (x *= 5).should == 10
358 (x **= 3).should == 8
382 (x <<= 3).should == 136
387 (x >>= 1).should == 2
391 (x ||= 17).should == 17
393 (x ||= 2).should == 17
397 (x &&= true).should == false
399 (x &&= false).should == false
402 (x &&= true).should == true
404 (x &&= false).should == false
408 it "uses short-circuit arg evaluation for operators ||= and &&=" do
410 y = VariablesSpecs::OpAsgn.new
411 (x ||= y.do_side_effect).should == 8
412 y.side_effect.should == nil
415 (x &&= y.do_side_effect).should == nil
416 y.side_effect.should == nil
419 (x ||= y.do_side_effect).should == 5
420 y.side_effect.should == true
424 describe "Operator assignment 'obj.meth op= expr'" do
425 it "is equivalent to 'obj.meth = obj.meth op expr'" do
426 @x = VariablesSpecs::OpAsgn.new
428 (@x.a += 5).should == 18
432 (@x.a -= 11).should == 6
436 (@x.a *= 5).should == 10
440 (@x.a /= 9).should == 4
444 (@x.a %= 5).should == 3
446 (@x.a %= 3).should == 0
450 (@x.a **= 3).should == 8
454 (@x.a |= 3).should == 7
456 (@x.a |= 4).should == 7
460 (@x.a &= 3).should == 2
462 (@x.a &= 4).should == 0
467 (@x.a ^= 3).should == 1
469 (@x.a ^= 4).should == 5
473 (@x.a <<= 3).should == 136
477 (@x.a >>= 1).should == 2
481 (@x.a ||= 17).should == 17
483 (@x.a ||= 2).should == 17
487 (@x.a &&= true).should == false
489 (@x.a &&= false).should == false
492 (@x.a &&= true).should == true
494 (@x.a &&= false).should == false
498 it "uses short-circuit arg evaluation for operators ||= and &&=" do
500 y = VariablesSpecs::OpAsgn.new
501 (x ||= y.do_side_effect).should == 8
502 y.side_effect.should == nil
505 (x &&= y.do_side_effect).should == nil
506 y.side_effect.should == nil
509 (x ||= y.do_side_effect).should == 5
510 y.side_effect.should == true
514 describe "Operator assignment 'obj[idx] op= expr'" do
515 it "is equivalent to 'obj[idx] = obj[idx] op expr'" do
517 (x[1] += 5).should == 18
521 (x[0] -= 11).should == 6
525 (x[2] *= 2).should == 56
526 x.should == [nil,2,56]
529 (x[2] /= x[1]).should == 4
533 (x[0] %= 5).should == 3
535 (x[0] %= 3).should == 0
539 (x[1] **= 3).should == 8
543 (x[0] |= 3).should == 7
544 x.should == [7,5,nil]
545 (x[0] |= 4).should == 7
546 x.should == [7,5,nil]
549 (x[1] &= 3).should == 2
551 (x[1] &= 4).should == 0
556 (x[2] ^= 3).should == 1
558 (x[2] ^= 4).should == 5
562 (x[0] <<= 3).should == 136
566 (x[1] >>= 1).should == 2
567 x.should == [nil,2,8]
570 (x[1] ||= 17).should == 17
571 x.should == [1,17,12]
572 (x[1] ||= 2).should == 17
573 x.should == [1,17,12]
575 x = [true, false, false]
576 (x[1] &&= true).should == false
577 x.should == [true, false, false]
578 (x[1] &&= false).should == false
579 x.should == [true, false, false]
580 (x[0] &&= true).should == true
581 x.should == [true, false, false]
582 (x[0] &&= false).should == false
583 x.should == [false, false, false]
586 it "uses short-circuit arg evaluation for operators ||= and &&=" do
588 y = VariablesSpecs::OpAsgn.new
589 (x ||= y.do_side_effect).should == 8
590 y.side_effect.should == nil
593 (x &&= y.do_side_effect).should == nil
594 y.side_effect.should == nil
597 (x ||= y.do_side_effect).should == 5
598 y.side_effect.should == true
601 it "handles complex index (idx) arguments" do
603 (x[0,2] += [5]).should == [1,2,5]
604 x.should == [1,2,5,3,4]
605 (x[0,2] += [3,4]).should == [1,2,3,4]
606 x.should == [1,2,3,4,5,3,4]
608 (x[2..3] += [8]).should == [3,4,8]
609 x.should == [1,2,3,4,8,5,3,4]
611 y = VariablesSpecs::OpAsgn.new
613 (x[y.do_side_effect] *= 2).should == 4
614 x.should == [1,4,3,4,8,5,3,4]
616 h = {'key1' => 23, 'key2' => 'val'}
617 (h['key1'] %= 5).should == 3
618 (h['key2'] += 'ue').should == 'value'
619 h.should == {'key1' => 3, 'key2' => 'value'}
622 it "returns result of rhs not result of []=" do
623 a = VariablesSpecs::Hashalike.new
625 (a[123] = 2).should == 2
626 (a[123] += 2).should == 125
627 (a[123] -= 2).should == 121
628 (a[123] *= 2).should == 246
629 (a[123] /= 2).should == 61
630 (a[123] %= 2).should == 1
631 (a[123] **= 2).should == 15129
632 (a[123] |= 2).should == 123
633 (a[123] &= 2).should == 2
634 (a[123] ^= 2).should == 121
635 (a[123] <<= 2).should == 492
636 (a[123] >>= 2).should == 30
637 (a[123] ||= 2).should == 123
638 (a[nil] ||= 2).should == 2
639 (a[123] &&= 2).should == 2
640 (a[nil] &&= 2).should == nil
644 describe "Single assignment" do
645 it "Assignment does not modify the lhs, it reassigns its reference" do
650 b.should == 'Bazquux'
653 it "Assignment does not copy the object being assigned, just creates a new reference to it" do
660 it "If rhs has multiple arguments, lhs becomes an Array of them" do
662 a.should == [1, 2, 3]
666 describe "Multiple assignment without grouping or splatting" do
667 it "An equal number of arguments on lhs and rhs assigns positionally" do
668 a, b, c, d = 1, 2, 3, 4
675 it "If rhs has too few arguments, the missing ones on lhs are assigned nil" do
682 it "If rhs has too many arguments, the extra ones are silently not assigned anywhere" do
688 it "The assignments are done in parallel so that lhs and rhs are independent of eachother without copying" do
689 o_of_a, o_of_b = mock('a'), mock('b')
690 a, b = o_of_a, o_of_b
692 a.should equal(o_of_b)
693 b.should equal(o_of_a)
697 describe "Multiple assignments with splats" do
698 # TODO make this normal once rubinius eval works
699 compliant_on :ruby do
700 it "* on the lhs has to be applied to the last parameter" do
701 lambda { eval 'a, *b, c = 1, 2, 3' }.should raise_error(SyntaxError)
705 it "* on the lhs collects all parameters from its position onwards as an Array or an empty Array" do
722 i.should == [1, [2, 3]]
723 j.should == [[1,2,3]]
728 describe "Multiple assignments with grouping" do
729 it "A group on the lhs is considered one position and treats its corresponding rhs position like an Array" do
730 a, (b, c), d = 1, 2, 3, 4
731 e, (f, g), h = 1, [2, 3, 4], 5
732 i, (j, k), l = 1, 2, 3
747 it "supports multiple levels of nested groupings" do
748 a,(b,(c,d)) = 1,[2,[3,4]]
754 a,(b,(c,d)) = [1,[2,[3,4]]]
768 compliant_on :ruby do
769 it "rhs cannot use parameter grouping, it is a syntax error" do
770 lambda { eval '(a, b) = (1, 2)' }.should raise_error(SyntaxError)
775 compliant_on :ruby do
777 describe "Multiple assignment" do
778 it "has the proper return value" do
779 (a,b,*c = *[5,6,7,8,9,10]).should == [5,6,7,8,9,10]
780 (d,e = VariablesSpecs.reverse_foo(4,3)).should == [3,4]
781 (f,g,h = VariablesSpecs.reverse_foo(6,7)).should == [7,6]
782 (i,*j = *[5,6,7]).should == [5,6,7]
783 (k,*l = [5,6,7]).should == [5,6,7]
786 c.should == [7,8,9,10]
800 # For now, masgn is deliberately non-compliant with MRI wrt the return val from an masgn.
801 # Rubinius returns true as the result of the assignment, but MRI returns an array
802 # containing all the elements on the rhs. As this result is never used, the cost
803 # of creating and then discarding this array is avoided
804 describe "Multiple assignment, array-style" do
805 compliant_on :ruby do
806 it "returns an array of all rhs values" do
807 (a,b = 5,6,7).should == [5,6,7]
811 (c,d,*e = 99,8).should == [99,8]
816 (f,g,h = 99,8).should == [99,8]
823 deviates_on :rubinius do
825 (a,b = 5,6,7).should == true
829 (c,d,*e = 99,8).should == true
834 (f,g,h = 99,8).should == true