diff --git a/tests/base.py b/tests/base.py index 826218f74..731b78cf9 100644 --- a/tests/base.py +++ b/tests/base.py @@ -5,7 +5,7 @@ from topaz.error import RubyError from topaz.objects.arrayobject import W_ArrayObject from topaz.objects.bignumobject import W_BignumObject -from topaz.objects.boolobject import W_TrueObject, W_FalseObject +from topaz.objects.boolobject import W_BoolObject from topaz.objects.floatobject import W_FloatObject from topaz.objects.intobject import W_FixnumObject from topaz.objects.moduleobject import W_ModuleObject @@ -32,10 +32,8 @@ def unwrap(self, space, w_obj): return space.bigint_w(w_obj) elif isinstance(w_obj, W_FloatObject): return space.float_w(w_obj) - elif isinstance(w_obj, W_TrueObject): - return True - elif isinstance(w_obj, W_FalseObject): - return False + elif isinstance(w_obj, W_BoolObject): + return w_obj.boolvalue elif isinstance(w_obj, W_StringObject): return space.str_w(w_obj) elif isinstance(w_obj, W_SymbolObject): @@ -44,10 +42,6 @@ def unwrap(self, space, w_obj): return [self.unwrap(space, w_x) for w_x in space.listview(w_obj)] elif isinstance(w_obj, W_ModuleObject): return w_obj - elif w_obj is space.w_true: - return True - elif w_obj is space.w_false: - return False elif w_obj is space.w_nil: return None raise NotImplementedError(type(w_obj)) diff --git a/tests/jit/test_basic.py b/tests/jit/test_basic.py index 1c60e8af0..580e192ad 100644 --- a/tests/jit/test_basic.py +++ b/tests/jit/test_basic.py @@ -125,3 +125,34 @@ def test_method_missing(self, topaz, tmpdir): setfield_gc(p1, p73, descr=) jump(p0, p1, p3, p4, p5, p7, p10, i75, p19, p22, p24, p30, descr=TargetToken(4310782288)) """) + + def test_unroll(self, topaz, tmpdir): + traces = self.run(topaz, tmpdir, """ + i = 0 + while i < 10000 + i += [0, 1].reduce(:+) + end + """) + self.assert_matches(traces[0].loop, """ + label(p0, p1, p3, p4, p5, p6, p7, p10, i35, p20, p22, p28, descr=TargetToken(4310781936)) + debug_merge_point(0, 0, '
at LOAD_DEREF') + debug_merge_point(0, 0, '
at LOAD_CONST') + debug_merge_point(0, 0, '
at SEND') + setfield_gc(p22, 21, descr=) + guard_not_invalidated(descr=) + p37 = force_token() + i38 = int_lt(i35, 10000) + guard_true(i38, descr=) + debug_merge_point(0, 0, '
at JUMP_IF_FALSE') + debug_merge_point(0, 0, '
at LOAD_DEREF') + debug_merge_point(0, 0, '
at LOAD_CONST') + debug_merge_point(0, 0, '
at SEND') + p39 = force_token() + i40 = int_add(i35, 1) + debug_merge_point(0, 0, '
at STORE_DEREF') + debug_merge_point(0, 0, '
at DISCARD_TOP') + debug_merge_point(0, 0, '
at JUMP') + debug_merge_point(0, 0, '
at LOAD_DEREF') + setfield_gc(p22, 35, descr=) + jump(p0, p1, p3, p4, p5, p6, p7, p10, i40, p20, p22, p28, descr=TargetToken(4310781936)) + """) diff --git a/tests/modules/test_comparable.py b/tests/modules/test_comparable.py index a942f864d..a17294f70 100644 --- a/tests/modules/test_comparable.py +++ b/tests/modules/test_comparable.py @@ -1,49 +1,52 @@ -class TestComparable(object): +from ..base import BaseTopazTest + + +class TestComparable(BaseTopazTest): def test_name(self, space): space.execute("Comparable") def test_gt(self, space): w_res = space.execute("return 'a' > 'b'") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_lt(self, space): w_res = space.execute("return 'a' < 'b'") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_le(self, space): w_res = space.execute("return 'b' <= 'b'") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return 'a' <= 'b'") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return 'c' <= 'b'") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_ge(self, space): w_res = space.execute("return 'c' >= 'b'") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_eqeq(self, space): w_res = space.execute("return 'a' == 'a'") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_not_eqeq(self, space): w_res = space.execute("return 'a' == 'b'") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_between_true(self, space): w_res = space.execute("return 'c'.between?('b', 'd')") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_between_false_low(self, space): w_res = space.execute("return 'a'.between?('b', 'd')") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_between_false_high(self, space): w_res = space.execute("return 'e'.between?('b', 'd')") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_between_equal(self, space): w_res = space.execute("return 'e'.between?('e', 'z')") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return 'e'.between?('a', 'e')") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True diff --git a/tests/modules/test_enumerable.py b/tests/modules/test_enumerable.py index 03e80cca5..1eb36b222 100644 --- a/tests/modules/test_enumerable.py +++ b/tests/modules/test_enumerable.py @@ -41,7 +41,7 @@ def test_all(self, space): word.length > 2 end """) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_all_false(self, space): w_res = space.execute(""" @@ -49,19 +49,19 @@ def test_all_false(self, space): word.length > 3 end """) - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_all_empty(self, space): w_res = space.execute(""" return [].all? """) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_all_no_block(self, space): w_res = space.execute(""" return [1, 2, 3].all? """) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_any(self, space): w_res = space.execute(""" @@ -69,13 +69,13 @@ def test_any(self, space): word.length > 2 end """) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_any_false(self, space): w_res = space.execute(""" return [nil, nil, nil].any? """) - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_select(self, space): w_res = space.execute(""" @@ -87,12 +87,12 @@ def test_include(self, space): w_res = space.execute(""" return (2..5).include? 12 """) - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute(""" return (2..3).include? 2 """) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_drop(self, space): w_res = space.execute("""return [0, 1, 2, 3, 4, 5, 6, 7].drop 3""") diff --git a/tests/modules/test_kernel.py b/tests/modules/test_kernel.py index 6ac76d4bd..33b5df220 100644 --- a/tests/modules/test_kernel.py +++ b/tests/modules/test_kernel.py @@ -29,7 +29,7 @@ def test_lambda(self, space): """) w_cls, w_lambda = space.listview(w_res) assert w_cls is space.w_proc - assert w_lambda is space.w_true + assert self.unwrap(space, w_lambda) is True def test_proc(self, space): w_res = space.execute(""" @@ -38,7 +38,7 @@ def test_proc(self, space): """) w_cls, w_lambda = space.listview(w_res) assert w_cls is space.w_proc - assert w_lambda is space.w_false + assert self.unwrap(space, w_lambda) is False def test_singleton_methods(self, space): w_res = space.execute(""" @@ -137,9 +137,14 @@ def test_exit(self, space): space.execute("exit") def test_block_given_p(self, space): - assert space.execute("return block_given?") is space.w_false - assert space.execute("return iterator?") is space.w_false - assert space.execute("return (proc { block_given? })[]") is space.w_false + w_res = space.execute("return block_given?") + assert self.unwrap(space, w_res) is False + + w_res = space.execute("return iterator?") + assert self.unwrap(space, w_res) is False + + w_res = space.execute("return (proc { block_given? })[]") + assert self.unwrap(space, w_res) is False w_res = space.execute(""" def foo block_given? @@ -304,7 +309,7 @@ def t(a, b) assert space.int_w(w_res) == -9 def test_load_path(self, space, tmpdir): - f = tmpdir.join("t.rb") + f = tmpdir.join("abc.rb") f.write(""" def t(a, b) a - b @@ -312,7 +317,7 @@ def t(a, b) """) w_res = space.execute(""" $LOAD_PATH[0..-1] = ['%s'] - require 't.rb' + require 'abc.rb' return t(2, 5) """ % tmpdir) @@ -322,7 +327,7 @@ def test_stdlib_default_load_path(self, space): w_res = space.execute(""" return require 'prettyprint' """) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_nonexistance(self, space): with self.raises(space, "LoadError"): @@ -396,7 +401,7 @@ def to_path require 't' return $success """ % tmpdir) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_path_ambigious_directory_file(self, space, tmpdir): f = tmpdir.join("t.rb") @@ -409,7 +414,7 @@ def test_path_ambigious_directory_file(self, space, tmpdir): require '%s' return $success """ % (tmpdir, tmpdir.join("t"))) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True class TestExec(BaseTopazTest): diff --git a/tests/modules/test_objectspace.py b/tests/modules/test_objectspace.py index 29c9727ab..ae4c3a93f 100644 --- a/tests/modules/test_objectspace.py +++ b/tests/modules/test_objectspace.py @@ -1,7 +1,9 @@ from rpython.rlib import rgc +from ..base import BaseTopazTest -class TestObjectSpace(object): + +class TestObjectSpace(BaseTopazTest): def test_name(self, space): space.execute("ObjectSpace") @@ -18,4 +20,4 @@ class X end return names.include? "X" """) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True diff --git a/tests/objects/test_arrayobject.py b/tests/objects/test_arrayobject.py index 4473319b3..c1df4b6e3 100644 --- a/tests/objects/test_arrayobject.py +++ b/tests/objects/test_arrayobject.py @@ -79,9 +79,9 @@ def test_length(self, space): def test_emptyp(self, space): w_res = space.execute("return [].empty?") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return [1].empty?") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_plus(self, space): w_res = space.execute("return [1, 2] + [3]") @@ -321,11 +321,11 @@ def test_eq(self, space): def test_eqlp(self, space): w_res = space.execute("return [].eql? 2") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return [0].eql? [0.0]") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return [0].eql? [0]") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_clear(self, space): w_res = space.execute(""" diff --git a/tests/objects/test_bignumobject.py b/tests/objects/test_bignumobject.py index 8a9b70879..fd3885829 100644 --- a/tests/objects/test_bignumobject.py +++ b/tests/objects/test_bignumobject.py @@ -29,9 +29,9 @@ def test_xor(self, space): def test_eq(self, space): w_res = space.execute("return 18446744073709551628 == 18446744073709551628") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return 18446744073709551628 == 18446744073709551629") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_comparator(self, space): w_res = space.execute("return 18446744073709551628 <=> 2") @@ -39,9 +39,9 @@ def test_comparator(self, space): def test_hash(self, space): w_res = space.execute("return 18446744073709551628.hash == 18446744073709551628.hash") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return 18446744073709551628.hash == 18446744073709551658.hash") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_coerce(self, space): w_res = space.execute("return 18446744073709551628.coerce 12") diff --git a/tests/objects/test_boolobject.py b/tests/objects/test_boolobject.py index d856a4c7f..ae9c2cf15 100644 --- a/tests/objects/test_boolobject.py +++ b/tests/objects/test_boolobject.py @@ -22,9 +22,9 @@ def test_eql(self, space): def test_and(self, space): w_res = space.execute("return true & 3") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return true & false") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_or(self, space): w_res = space.execute("return true | 3") @@ -33,14 +33,18 @@ def test_or(self, space): assert w_res is space.w_true def test_xor(self, space): - assert space.execute("return true ^ nil") is space.w_true - assert space.execute("return true ^ false") is space.w_true - assert space.execute("return true ^ true") is space.w_false - assert space.execute("return true ^ 1") is space.w_false + w_res = space.execute("return true ^ nil") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return true ^ false") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return true ^ true") + assert self.unwrap(space, w_res) is False + w_res = space.execute("return true ^ 1") + assert self.unwrap(space, w_res) is False def test_singleton_class(self, space): w_res = space.execute("return true.singleton_class == TrueClass") - assert w_res is space.w_true + assert self.unwrap(space, w_res) class TestFalseObject(BaseTopazTest): @@ -64,22 +68,26 @@ def test_eql(self, space): def test_and(self, space): w_res = space.execute("return false & 3") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return false & false") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_or(self, space): w_res = space.execute("return false | 3") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return false | nil") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_xor(self, space): - assert space.execute("return false ^ nil") is space.w_false - assert space.execute("return false ^ false") is space.w_false - assert space.execute("return false ^ true") is space.w_true - assert space.execute("return false ^ 1") is space.w_true + w_res = space.execute("return false ^ nil") + assert self.unwrap(space, w_res) is False + w_res = space.execute("return false ^ false") + assert self.unwrap(space, w_res) is False + w_res = space.execute("return false ^ true") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return false ^ 1") + assert self.unwrap(space, w_res) is True def test_singleton_class(self, space): w_res = space.execute("return false.singleton_class == FalseClass") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True diff --git a/tests/objects/test_fileobject.py b/tests/objects/test_fileobject.py index a163a503a..55bdf21a8 100644 --- a/tests/objects/test_fileobject.py +++ b/tests/objects/test_fileobject.py @@ -185,30 +185,30 @@ def test_existp(self, space, tmpdir): f = tmpdir.join("test.rb") f.write("") w_res = space.execute("return File.exist?('%s')" % f) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return File.exist?('%s')" % tmpdir) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return File.exist?('no way this exists')") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_filep(self, space, tmpdir): f = tmpdir.join("test.rb") f.write("") w_res = space.execute("return File.file?('%s')" % f) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return File.file?('%s')" % tmpdir) - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return File.file?('no way this exists')") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_executablep(self, space, tmpdir): f = tmpdir.join("test.rb") f.write("") w_res = space.execute("return File.executable?('%s')" % f) - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False os.chmod(str(f), stat.S_IEXEC) w_res = space.execute("return File.executable?('%s')" % f) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_directoryp(self, space, tmpdir): w_res = space.execute("return File.directory?('%s')" % tmpdir) diff --git a/tests/objects/test_floatobject.py b/tests/objects/test_floatobject.py index 50589ea62..9972dca01 100644 --- a/tests/objects/test_floatobject.py +++ b/tests/objects/test_floatobject.py @@ -45,19 +45,19 @@ def test_neg(self, space): def test_equal(self, space): w_res = space.execute("return 2.3 == 2.3") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return 2.4 == 2.3") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_equal_method(self, space): w_res = space.execute("return 2.3.equal?(2.3)") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return Float::NAN.equal?(Float::NAN)") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_hashability(self, space): w_res = space.execute("return 1.0.hash == 1.0.hash") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_to_s(self, space): w_res = space.execute("return 1.5.to_s") @@ -80,28 +80,42 @@ def test_to_i(self, space): space.execute("(-1.0 / 0.0).to_i") def test_lt(self, space): - assert space.execute("return 1.1 < 1.2") is space.w_true - assert space.execute("return 1.2 < 0") is space.w_false + w_res = space.execute("return 1.1 < 1.2") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 1.2 < 0") + assert self.unwrap(space, w_res) is False def test_lte(self, space): - assert space.execute("return 1.1 <= 2") is space.w_true - assert space.execute("return 1.0 <= 1") is space.w_true - assert space.execute("return 1.1 <= 1.1") is space.w_true - assert space.execute("return 1.1 <= 0.9") is space.w_false - assert space.execute("return 1.0 <= '1.1'") is space.w_true + w_res = space.execute("return 1.1 <= 2") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 1.0 <= 1") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 1.1 <= 1.1") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 1.1 <= 0.9") + assert self.unwrap(space, w_res) is False + w_res = space.execute("return 1.0 <= '1.1'") + assert self.unwrap(space, w_res) is True with self.raises(space, "ArgumentError", "comparison of Float with String failed"): space.execute("1.0 <= 'a'") def test_gt(self, space): - assert space.execute("return 1.1 > 1.2") is space.w_false - assert space.execute("return 1.2 > 0") is space.w_true + w_res = space.execute("return 1.1 > 1.2") + assert self.unwrap(space, w_res) is False + w_res = space.execute("return 1.2 > 0") + assert self.unwrap(space, w_res) is True def test_gte(self, space): - assert space.execute("return 1.1 >= 2") is space.w_false - assert space.execute("return 1.0 >= 1") is space.w_true - assert space.execute("return 1.1 >= 1.1") is space.w_true - assert space.execute("return 1.1 >= 0.9") is space.w_true - assert space.execute("return 1.0 >= '1.1'") is space.w_false + w_res = space.execute("return 1.1 >= 2") + assert self.unwrap(space, w_res) is False + w_res = space.execute("return 1.0 >= 1") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 1.1 >= 1.1") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 1.1 >= 0.9") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 1.0 >= '1.1'") + assert self.unwrap(space, w_res) is False with self.raises(space, "ArgumentError", "comparison of Float with String failed"): space.execute("1.0 >= 'a'") @@ -210,6 +224,6 @@ def test_infinite(self, space): def test_nan(self, space): w_res = space.execute("return 1.0.nan?") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return Float::NAN.nan?") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True diff --git a/tests/objects/test_hashobject.py b/tests/objects/test_hashobject.py index b49cd46ed..ae4d85d4a 100644 --- a/tests/objects/test_hashobject.py +++ b/tests/objects/test_hashobject.py @@ -173,24 +173,24 @@ def test_size(self, space): def test_emptyp(self, space): w_res = space.execute("return {}.empty?") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return {1 => 2}.empty?") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_equal(self, space): w_res = space.execute("return {} == nil") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return {1 => 2, 2 => 3} == {2 => 3, 1 => 2}") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return {} == {}") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return {} == {1 => 2}") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute(""" h = {} return h == h """) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_shift(self, space): w_res = space.execute("return {}.shift") diff --git a/tests/objects/test_intobject.py b/tests/objects/test_intobject.py index 69d15340e..e6fd1357e 100644 --- a/tests/objects/test_intobject.py +++ b/tests/objects/test_intobject.py @@ -106,7 +106,7 @@ def test_or(self, space): def test_equal(self, space): w_res = space.execute("return 1 == 1") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute(""" class A def ==(o); 'hi'; end @@ -115,43 +115,48 @@ def ==(o); 'hi'; end """) assert space.str_w(w_res) == 'hi' w_res = space.execute("return 1 == '1'") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_not_equal(self, space): w_res = space.execute("return 1 != 1") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return 1 != '1'") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute(""" class A def ==(o); 'hi'; end end return 1 != A.new """) - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_less(self, space): w_res = space.execute("return 1 < 2") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return 1 < 1.2") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_less_equal(self, space): - assert space.execute("return 1 <= 2") is space.w_true - assert space.execute("return 1 <= 1") is space.w_true - assert space.execute("return 1 <= 1.1") is space.w_true - assert space.execute("return 1 <= 0.9") is space.w_false - assert space.execute("return 1 <= '1.1'") is space.w_true + w_res = space.execute("return 1 <= 2") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 1 <= 1") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 1 <= 1.1") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 1 <= 0.9") + assert self.unwrap(space, w_res) is False + w_res = space.execute("return 1 <= '1.1'") + assert self.unwrap(space, w_res) is True with self.raises(space, "ArgumentError", "comparison of Fixnum with String failed"): space.execute("1 <= 'a'") def test_greater(self, space): w_res = space.execute("return 1 > 2") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_greater_equal(self, space): w_res = space.execute("return 5 >= 4") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_times(self, space): w_res = space.execute(""" @@ -195,9 +200,9 @@ def test_comparator_other_type(self, space): def test_eqlp(self, space): w_res = space.execute("return 1.eql? 1.0") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return 1.eql? 1") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_to_i(self, space): w_res = space.execute("return [1.to_i, 1.to_int]") diff --git a/tests/objects/test_ioobject.py b/tests/objects/test_ioobject.py index 54010bf86..77296ec07 100644 --- a/tests/objects/test_ioobject.py +++ b/tests/objects/test_ioobject.py @@ -244,7 +244,7 @@ def test_to_io(self, space, tmpdir): f = File.new '%s' return f.eql? f.to_io """ % f) - assert w_res == space.w_true + assert self.unwrap(space, w_res) is True def test_to_i(self, space, tmpdir): f1 = tmpdir.join("file1.txt") diff --git a/tests/objects/test_nilobject.py b/tests/objects/test_nilobject.py index 6b57d0aab..43f922057 100644 --- a/tests/objects/test_nilobject.py +++ b/tests/objects/test_nilobject.py @@ -33,20 +33,20 @@ def test_to_a(self, space): def test_and(self, space): w_res = space.execute("return nil & true") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_or(self, space): w_res = space.execute("return nil | 4") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return nil | false") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_xor(self, space): w_res = space.execute("return nil ^ 4") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return nil ^ false") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_singleton_class(self, space): w_res = space.execute("return nil.singleton_class == NilClass") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True diff --git a/tests/objects/test_numericobject.py b/tests/objects/test_numericobject.py index 5102598d0..be686a79a 100644 --- a/tests/objects/test_numericobject.py +++ b/tests/objects/test_numericobject.py @@ -31,13 +31,13 @@ def test_less_equal(self, space): class A < Numeric; end return A.new <= A.new """) - assert w_res == space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute(""" class A < Numeric; end a = A.new return a <= a """) - assert w_res == space.w_true + assert self.unwrap(space, w_res) is True def test_coerce(self, space): w_res = space.execute("return 1.coerce(1)") diff --git a/tests/objects/test_objectobject.py b/tests/objects/test_objectobject.py index 92a594e99..bedbbee1a 100644 --- a/tests/objects/test_objectobject.py +++ b/tests/objects/test_objectobject.py @@ -83,13 +83,13 @@ def test_neq(self, space): def test_not(self, space): w_res = space.execute("return !BasicObject.new") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return !true") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return !false") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return !nil") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test___send__(self, space): w_res = space.execute(""" @@ -232,7 +232,7 @@ def test_inspect(self, space): obj = Object.new return obj.to_s == obj.inspect """) - assert w_res == space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute(""" class A def to_s @@ -242,7 +242,7 @@ def to_s obj = A.new return obj.to_s == obj.inspect """) - assert w_res == space.w_true + assert self.unwrap(space, w_res) is True def test_send(self, space): w_res = space.execute("return [1.send(:to_s), 1.send('+', 2)]") @@ -266,8 +266,8 @@ def test_hash(self, space): """) w_int, w_self_hash, w_other_hash = space.listview(w_res) assert isinstance(w_int, W_FixnumObject) - assert w_self_hash is space.w_true - assert w_other_hash is space.w_true + assert self.unwrap(space, w_self_hash) is True + assert self.unwrap(space, w_other_hash) is True def test_is_kind_ofp(self, space): w_res = space.execute(""" diff --git a/tests/objects/test_procobject.py b/tests/objects/test_procobject.py index 71f576560..dd66949d0 100644 --- a/tests/objects/test_procobject.py +++ b/tests/objects/test_procobject.py @@ -9,7 +9,7 @@ def test_new(self, space): """) w_cls, w_proc = space.listview(w_res) assert w_cls is space.w_proc - assert w_proc is space.w_false + assert self.unwrap(space, w_proc) is False def test_call(self, space): w_res = space.execute(""" diff --git a/tests/objects/test_rangeobject.py b/tests/objects/test_rangeobject.py index 8bd4ac225..460221b87 100644 --- a/tests/objects/test_rangeobject.py +++ b/tests/objects/test_rangeobject.py @@ -46,9 +46,9 @@ def test_exclude_end(self, space): def test_eqeqeq(self, space): w_res = space.execute("return (1..10) === 5") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return (1..10) === -1") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_begin(self, space): w_res = space.execute("return (1..10).begin") @@ -83,4 +83,4 @@ def test_each_returns_self(self, space): r = (1...3) return r.each {}.equal?(r) """) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True diff --git a/tests/objects/test_regexpobject.py b/tests/objects/test_regexpobject.py index 19e61fe6c..5d0c3ada1 100644 --- a/tests/objects/test_regexpobject.py +++ b/tests/objects/test_regexpobject.py @@ -136,7 +136,7 @@ def test_match_end(self, space): def test_new_regexp(self, space): w_res = space.execute("return Regexp.new('..abc..') == Regexp.compile('..abc..')") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return Regexp.new(/abc/).source") assert space.str_w(w_res) == "abc" @@ -221,15 +221,15 @@ def test_repeated_quantification(self, space): def test_casefoldp(self, space): w_res = space.execute("return /a/.casefold?") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return /a/i.casefold?") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_eqeqeq(self, space): w_res = space.execute("return /abc/ === 'defabc'") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return /abc/ === 'ddddddd'") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_escape(self, space): w_res = space.execute(""" diff --git a/tests/objects/test_stringobject.py b/tests/objects/test_stringobject.py index 894afa9e9..6c4a10292 100644 --- a/tests/objects/test_stringobject.py +++ b/tests/objects/test_stringobject.py @@ -54,9 +54,9 @@ def test_length(self, space): def test_emptyp(self, space): w_res = space.execute("return ''.empty?") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute("return 'a'.empty?") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False def test_subscript_constant(self, space): w_res = space.execute(""" @@ -118,9 +118,9 @@ def <=>(other); other <=> self.to_str; end def test_eqlp(self, space): w_res = space.execute("return 'abc'.eql? 2") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return 'abc'.eql? 'abc'") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_hash(self, space): w_res = space.execute(""" @@ -465,9 +465,12 @@ def test_reverse(self, space): assert self.unwrap(space, w_res) == ["desserts", "stressed"] def test_includep(self, space): - assert space.execute("return 'abc'.include? 'ab'") is space.w_true - assert space.execute("return 'abc'.include? 'bc'") is space.w_true - assert space.execute("return 'abc'.include? 'cd'") is space.w_false + w_res = space.execute("return 'abc'.include? 'ab'") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 'abc'.include? 'bc'") + assert self.unwrap(space, w_res) is True + w_res = space.execute("return 'abc'.include? 'cd'") + assert self.unwrap(space, w_res) is False def test_gsub(self, space): w_res = space.execute(""" diff --git a/tests/test_compiler.py b/tests/test_compiler.py index 41c3843f9..d0fe61450 100644 --- a/tests/test_compiler.py +++ b/tests/test_compiler.py @@ -1,7 +1,9 @@ from topaz import consts +from .base import BaseTopazTest -class TestCompiler(object): + +class TestCompiler(BaseTopazTest): def assert_compiles(self, space, source, expected_bytecode_str): bc = space.compile(source, None) self.assert_compiled(bc, expected_bytecode_str) @@ -207,7 +209,10 @@ def test_named_constants(self, space): RETURN """) - assert bc.consts_w == [space.w_false, space.w_true, space.w_nil] + assert len(bc.consts_w) == 3 + assert self.unwrap(space, bc.consts_w[0]) is False + assert self.unwrap(space, bc.consts_w[1]) is True + assert self.unwrap(space, bc.consts_w[2]) is None def test_comparison(self, space): self.assert_compiles(space, "1 == 1", """ diff --git a/tests/test_interpreter.py b/tests/test_interpreter.py index 15d650b67..654e46061 100644 --- a/tests/test_interpreter.py +++ b/tests/test_interpreter.py @@ -748,9 +748,9 @@ def test_or(self, space): def test_not(self, space): w_res = space.execute("return !3") - assert w_res is space.w_false + assert self.unwrap(space, w_res) is False w_res = space.execute("return !!3") - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True def test_subscript_assignment(self, space): w_res = space.execute(""" @@ -794,7 +794,7 @@ def to_a a = *x return a == [x] """) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True w_res = space.execute(""" *a = nil return a @@ -1917,4 +1917,4 @@ def test_bang_method_call_without_parens(self, space): w_res = space.execute(""" ! respond_to? :asdf """) - assert w_res is space.w_true + assert self.unwrap(space, w_res) is True diff --git a/topaz/interpreter.py b/topaz/interpreter.py index adba9fdc1..b9b4df563 100644 --- a/topaz/interpreter.py +++ b/topaz/interpreter.py @@ -146,8 +146,8 @@ def handle_throw(self, space, pc, frame, bytecode, e): unroller = ThrowValue(e.name, e.w_value) return block.handle(space, frame, unroller) - def jump(self, space, bytecode, frame, cur_pc, target_pc): - if target_pc < cur_pc: + def jump(self, space, bytecode, frame, cur_pc, target_pc, unroll=False): + if target_pc < cur_pc and not unroll: self.jitdriver.can_enter_jit( self=self, bytecode=bytecode, frame=frame, pc=target_pc, block_bytecode=self.get_block_bytecode(frame.block), @@ -644,16 +644,24 @@ def JUMP(self, space, bytecode, frame, pc, target_pc): return self.jump(space, bytecode, frame, pc, target_pc) def JUMP_IF_TRUE(self, space, bytecode, frame, pc, target_pc): - if space.is_true(frame.pop()): - return self.jump(space, bytecode, frame, pc, target_pc) + should_jump = space.is_true(frame.pop()) + is_const = jit.isconstant(should_jump) + if should_jump: + return self.jump( + space, bytecode, frame, pc, target_pc, unroll=is_const + ) else: return pc def JUMP_IF_FALSE(self, space, bytecode, frame, pc, target_pc): - if space.is_true(frame.pop()): + should_jump = space.is_true(frame.pop()) + is_const = jit.isconstant(should_jump) + if should_jump: return pc else: - return self.jump(space, bytecode, frame, pc, target_pc) + return self.jump( + space, bytecode, frame, pc, target_pc, unroll=is_const + ) def DISCARD_TOP(self, space, bytecode, frame, pc): frame.pop() diff --git a/topaz/modules/kernel.py b/topaz/modules/kernel.py index 0c70bbd46..9785bcaa8 100644 --- a/topaz/modules/kernel.py +++ b/topaz/modules/kernel.py @@ -314,9 +314,12 @@ def method_respond_to_missingp(self, space, w_name, w_include_private): @moduledef.method("dup") def method_dup(self, space): - if (self is space.w_nil or self is space.w_true or - self is space.w_false or space.is_kind_of(self, space.w_symbol) or - space.is_kind_of(self, space.w_fixnum)): + if ( + self is space.w_nil or space.is_true_object(self) or + space.is_false_object(self) or + space.is_kind_of(self, space.w_symbol) or + space.is_kind_of(self, space.w_fixnum) + ): raise space.error(space.w_TypeError, "can't dup %s" % space.getclass(self).name) w_dup = space.send(space.getnonsingletonclass(self), "allocate") w_dup.copy_instance_vars(space, self) @@ -326,9 +329,12 @@ def method_dup(self, space): @moduledef.method("clone") def method_clone(self, space): - if (self is space.w_nil or self is space.w_true or - self is space.w_false or space.is_kind_of(self, space.w_symbol) or - space.is_kind_of(self, space.w_fixnum)): + if ( + self is space.w_nil or space.is_true_object(self) or + space.is_false_object(self) or + space.is_kind_of(self, space.w_symbol) or + space.is_kind_of(self, space.w_fixnum) + ): raise space.error(space.w_TypeError, "can't dup %s" % space.getclass(self).name) w_dup = space.send(space.getnonsingletonclass(self), "allocate") w_dup.copy_instance_vars(space, self) diff --git a/topaz/objects/boolobject.py b/topaz/objects/boolobject.py index 57517d7bb..1d062fd7d 100644 --- a/topaz/objects/boolobject.py +++ b/topaz/objects/boolobject.py @@ -2,60 +2,90 @@ from topaz.objects.objectobject import W_Object -class W_TrueObject(W_Object): - classdef = ClassDef("TrueClass", W_Object.classdef) +class W_BoolObject(W_Object): + _attrs_ = ["boolvalue"] + _immutable_fields_ = ["boolvalue"] + + def __init__(self, space, boolvalue): + W_Object.__init__(self, space) + self.boolvalue = boolvalue + + def __deepcopy__(self, memo): + obj = super(W_BoolObject, self).__deepcopy__(memo) + obj.boolvalue = self.boolvalue + return obj + + def is_true(self, space): + return self.boolvalue + + def getclass(self, space): + if self.boolvalue: + return space.getclassobject(true_classdef) + else: + return space.getclassobject(false_classdef) def getsingletonclass(self, space): - return space.getclassfor(W_TrueObject) + return self.getclass(space) - @classdef.method("inspect") - @classdef.method("to_s") - def method_to_s(self, space): - return space.newstr_fromstr("true") - @classdef.method("==") - def method_eq(self, space, w_other): - return space.newbool(self is w_other) +true_classdef = ClassDef("TrueClass", W_Object.classdef) +true_classdef.cls = W_BoolObject - @classdef.method("&") - def methof_and(self, space, w_other): - return space.newbool(space.is_true(w_other)) +false_classdef = ClassDef("FalseClass", W_Object.classdef) +false_classdef.cls = W_BoolObject - @classdef.method("|") - def method_or(self, space, w_other): - return space.w_true - @classdef.method("^") - def method_xor(self, space, w_other): - return space.newbool(not space.is_true(w_other)) +@true_classdef.method("inspect") +@true_classdef.method("to_s") +def true_method_to_s(self, space): + return space.newstr_fromstr("true") -class W_FalseObject(W_Object): - classdef = ClassDef("FalseClass", W_Object.classdef) +@false_classdef.method("inspect") +@false_classdef.method("to_s") +def false_method_to_s(self, space): + return space.newstr_fromstr("false") - def is_true(self, space): - return False - def getsingletonclass(self, space): - return space.getclassfor(W_FalseObject) +@true_classdef.method("==") +def true_method_eq(self, space, w_other): + return space.newbool( + isinstance(w_other, W_BoolObject) and self.boolvalue == w_other.boolvalue + ) + + +@false_classdef.method("==") +def false_method_eq(self, space, w_other): + return space.newbool( + isinstance(w_other, W_BoolObject) and self.boolvalue == w_other.boolvalue + ) + + +@true_classdef.method("&") +def true_methof_and(self, space, w_other): + return space.newbool(space.is_true(w_other)) + + +@false_classdef.method("&") +def false_methof_and(self, space, w_other): + return space.w_false + + +@true_classdef.method("|") +def true_method_or(self, space, w_other): + return space.w_true + - @classdef.method("inspect") - @classdef.method("to_s") - def method_to_s(self, space): - return space.newstr_fromstr("false") +@false_classdef.method("|") +def false_method_or(self, space, w_other): + return space.newbool(space.is_true(w_other)) - @classdef.method("==") - def method_eq(self, space, w_other): - return space.newbool(self is w_other) - @classdef.method("&") - def methof_and(self, space, w_other): - return space.w_false +@true_classdef.method("^") +def true_method_xor(self, space, w_other): + return space.newbool(not space.is_true(w_other)) - @classdef.method("|") - def method_or(self, space, w_other): - return space.newbool(space.is_true(w_other)) - @classdef.method("^") - def method_xor(self, space, w_other): - return space.newbool(space.is_true(w_other)) +@false_classdef.method("^") +def false_method_xor(self, space, w_other): + return space.newbool(space.is_true(w_other)) diff --git a/topaz/objects/intobject.py b/topaz/objects/intobject.py index 01605b8ea..f54bcaa86 100644 --- a/topaz/objects/intobject.py +++ b/topaz/objects/intobject.py @@ -325,7 +325,9 @@ def method_eq(self, space, w_other): @classdef.method("!=") def method_ne(self, space, w_other): - return space.newbool(space.send(self, "==", [w_other]) is space.w_false) + return space.newbool( + not space.is_true(space.send(self, "==", [w_other])) + ) def new_bool_op(classdef, name, func): @classdef.method(name) diff --git a/topaz/objects/moduleobject.py b/topaz/objects/moduleobject.py index 6f0c7e99d..baaa7ef17 100644 --- a/topaz/objects/moduleobject.py +++ b/topaz/objects/moduleobject.py @@ -473,7 +473,12 @@ def method_attr_writer(self, space, args_w): @classdef.method("attr") def method_attr(self, space, args_w): - if len(args_w) == 2 and (args_w[1] is space.w_true or args_w[1] is space.w_false): + if ( + len(args_w) == 2 and ( + space.is_true_object(args_w[1]) or + space.is_false_object(args_w[1]) + ) + ): [w_name, w_writable] = args_w if space.is_true(w_writable): self.method_attr_accessor(space, [w_name]) diff --git a/topaz/objspace.py b/topaz/objspace.py index ba0d7a624..46b48d21c 100644 --- a/topaz/objspace.py +++ b/topaz/objspace.py @@ -36,7 +36,9 @@ from topaz.objects.arrayobject import W_ArrayObject from topaz.objects.bignumobject import W_BignumObject from topaz.objects.bindingobject import W_BindingObject -from topaz.objects.boolobject import W_TrueObject, W_FalseObject +from topaz.objects.boolobject import ( + W_BoolObject, true_classdef, false_classdef +) from topaz.objects.classobject import W_ClassObject from topaz.objects.codeobject import W_CodeObject from topaz.objects.dirobject import W_DirObject @@ -94,8 +96,8 @@ def __init__(self, config): self.bootstrap = True self.exit_handlers_w = [] - self.w_true = W_TrueObject(self) - self.w_false = W_FalseObject(self) + self.w_true = W_BoolObject(self, True) + self.w_false = W_BoolObject(self, False) self.w_nil = W_NilObject(self) # Force the setup of a few key classes, we create a fake "Class" class @@ -173,8 +175,8 @@ def __init__(self, config): self.w_kernel, self.w_topaz, self.getclassfor(W_NilObject), - self.getclassfor(W_TrueObject), - self.getclassfor(W_FalseObject), + self.getclassobject(true_classdef), + self.getclassobject(false_classdef), self.getclassfor(W_RangeObject), self.getclassfor(W_FileObject), self.getclassfor(W_DirObject), @@ -344,10 +346,7 @@ def execute_frame(self, frame, bc): @signature(types.any(), types.bool(), returns=types.instance(W_Root)) def newbool(self, boolvalue): - if boolvalue: - return self.w_true - else: - return self.w_false + return W_BoolObject(self, boolvalue) @signature(types.any(), types.int(), returns=types.instance(W_FixnumObject)) def newint(self, intvalue): @@ -489,6 +488,12 @@ def listview(self, w_obj): def is_true(self, w_obj): return w_obj.is_true(self) + def is_true_object(self, w_obj): + return isinstance(w_obj, W_BoolObject) and w_obj.is_true(self) + + def is_false_object(self, w_obj): + return isinstance(w_obj, W_BoolObject) and not w_obj.is_true(self) + def getclass(self, w_receiver): return w_receiver.getclass(self)