From a121f29cd97d02857761b9da58f82a6888767dae Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Fri, 8 Oct 2021 13:19:17 +0800 Subject: [PATCH 01/16] Move specs for arithmetic primitives to `primitives_spec` --- .github/workflows/aarch64.yml | 8 + .github/workflows/smoke.yml | 6 +- .github/workflows/win.yml | 11 +- CONTRIBUTING.md | 1 + Makefile | 12 +- bin/check-compiler-flag | 8 +- bin/ci | 3 +- spec/all_spec.cr | 1 + spec/compiler/codegen/arithmetics_spec.cr | 330 ---------------------- spec/compiler/codegen/primitives_spec.cr | 87 +++--- spec/primitives/float_spec.cr | 58 ++++ spec/primitives/int_spec.cr | 126 +++++++++ spec/primitives_spec.cr | 2 + spec/std/overflow_spec.cr | 54 ---- spec/support/number.cr | 13 +- 15 files changed, 292 insertions(+), 428 deletions(-) delete mode 100644 spec/compiler/codegen/arithmetics_spec.cr create mode 100644 spec/primitives/float_spec.cr create mode 100644 spec/primitives/int_spec.cr create mode 100644 spec/primitives_spec.cr delete mode 100644 spec/std/overflow_spec.cr diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml index 416cc0fb0d03..6a8f98e44646 100644 --- a/.github/workflows/aarch64.yml +++ b/.github/workflows/aarch64.yml @@ -36,6 +36,10 @@ jobs: uses: docker://jhass/crystal:1.0.0-alpine-build with: args: make std_spec + - name: Run primitives specs + uses: docker://jhass/crystal:1.0.0-alpine-build + with: + args: make primitives_spec musl-test-compiler: needs: musl-build runs-on: [linux, ARM64] @@ -87,6 +91,10 @@ jobs: uses: docker://jhass/crystal:1.0.0-build with: args: make std_spec + - name: Run primitives specs + uses: docker://jhass/crystal:1.0.0-alpine-build + with: + args: make primitives_spec gnu-test-compiler: needs: gnu-build runs-on: [linux, ARM64] diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index 5c7be225ab00..a190cabcf8c3 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -1,7 +1,7 @@ # These jobs are smoke tests for platforms where we don't rund full tests. -# They ensure that std_spec, compiler_spec and the compiler itself at least -# compile for the target with --cross-compile. But the binaries are not linked -# and executed. So this does not validate correct behaviour. +# They ensure that std_spec, compiler_spec, primitives_spec, and the compiler +# itself at least compile for the target with --cross-compile. But the binaries +# are not linked and executed. So this does not validate correct behaviour. # # The list of supported platforms is extracted from the lib_c bindings: # diff --git a/.github/workflows/win.yml b/.github/workflows/win.yml index 456af8b975ca..d9d26bc72dca 100644 --- a/.github/workflows/win.yml +++ b/.github/workflows/win.yml @@ -188,7 +188,7 @@ jobs: - name: Build stdlib specs executable run: | - bin\crystal.exe build spec/std_spec.cr --exclude-warnings spec/std --exclude-warnings spec/compiler -Dwithout_openssl -Di_know_what_im_doing + bin\crystal.exe build spec/std_spec.cr --exclude-warnings spec/std -Dwithout_openssl -Di_know_what_im_doing - name: Run socket specs run: | .\std_spec.exe --verbose -e TCPSocket @@ -198,7 +198,14 @@ jobs: - name: Build compiler specs executable run: | - bin\crystal.exe build spec/compiler_spec.cr --exclude-warnings spec/std --exclude-warnings spec/compiler -Dwithout_playground -Di_know_what_im_doing + bin\crystal.exe build spec/compiler_spec.cr --exclude-warnings spec/compiler -Dwithout_playground -Di_know_what_im_doing - name: Run compiler specs run: | .\compiler_spec.exe + + - name: Build primitives specs executable + run: | + bin\crystal.exe build spec/primitives_spec.cr --exclude-warnings spec/primitives -Dwithout_playground -Di_know_what_im_doing + - name: Run primitives specs + run: | + .\primitives_spec.exe diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 73fdd426e719..735a68a908b2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -122,6 +122,7 @@ Executing `make crystal` builds the compiler into `.build/compiler` and you can The script sets up the proper environment variables that the compiler can find the standard library source files in `src/`. `make compiler_spec` runs the compiler specs. `make std_spec` runs the standard library specs. +`make primitives_spec` runs the specs for primitive methods with an up-to-date Crystal compiler. You can use `make help` for a list of available make targets. ## This guide diff --git a/Makefile b/Makefile index 99c1d03908fa..ab4025032d84 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,7 @@ O := .build SOURCES := $(shell find src -name '*.cr') SPEC_SOURCES := $(shell find spec -name '*.cr') override FLAGS += $(if $(release),--release )$(if $(stats),--stats )$(if $(progress),--progress )$(if $(threads),--threads $(threads) )$(if $(debug),-d )$(if $(static),--static )$(if $(LDFLAGS),--link-flags="$(LDFLAGS)" )$(if $(target),--cross-compile --target $(target) ) -SPEC_WARNINGS_OFF := --exclude-warnings spec/std --exclude-warnings spec/compiler +SPEC_WARNINGS_OFF := --exclude-warnings spec/std --exclude-warnings spec/compiler --exclude-warnings spec/primitives SPEC_FLAGS := $(if $(verbose),-v )$(if $(junit_output),--junit_output $(junit_output) ) CRYSTAL_CONFIG_LIBRARY_PATH := '$$ORIGIN/../lib/crystal' CRYSTAL_CONFIG_BUILD_COMMIT := $(shell git rev-parse --short HEAD 2> /dev/null) @@ -99,8 +99,12 @@ std_spec: $(O)/std_spec ## Run standard library specs compiler_spec: $(O)/compiler_spec ## Run compiler specs $(O)/compiler_spec $(SPEC_FLAGS) +.PHONY: primitives_spec +primitives_spec: $(O)/primitives_spec ## Run primitives specs + $(O)/primitives_spec $(SPEC_FLAGS) + .PHONY: smoke_test ## Build specs as a smoke test -smoke_test: $(O)/std_spec $(O)/compiler_spec $(O)/crystal +smoke_test: $(O)/std_spec $(O)/compiler_spec $(O)/primitives_spec $(O)/crystal .PHONY: docs docs: ## Generate standard library documentation @@ -163,6 +167,10 @@ $(O)/compiler_spec: $(DEPS) $(SOURCES) $(SPEC_SOURCES) @mkdir -p $(O) $(EXPORT_CC) $(EXPORTS) ./bin/crystal build $(FLAGS) $(SPEC_WARNINGS_OFF) -o $@ spec/compiler_spec.cr +$(O)/primitives_spec: $(O)/crystal $(DEPS) $(SOURCES) $(SPEC_SOURCES) + @mkdir -p $(O) + $(EXPORT_CC) ./bin/crystal build $(FLAGS) $(SPEC_WARNINGS_OFF) -o $@ spec/primitives_spec.cr + $(O)/crystal: $(DEPS) $(SOURCES) @mkdir -p $(O) $(EXPORTS) $(EXPORTS_BUILD) ./bin/crystal build $(FLAGS) -o $@ src/compiler/crystal.cr -D without_openssl -D without_zlib diff --git a/bin/check-compiler-flag b/bin/check-compiler-flag index 714b9dea04ff..d7401ad7c1f2 100755 --- a/bin/check-compiler-flag +++ b/bin/check-compiler-flag @@ -6,10 +6,10 @@ # This script will # * run the compiler_spec using the flag # * build the compiler to have the flag available (in case the flag is introduced in this version) -# * run the std_spec with and without the flag +# * run the std_spec and primitives_spec with and without the flag # * check the compiler_spec built with and without the flag (eg: the specs build with the flag can generate a compiler without the flag) # * build a 2nd generation of the compiler using the flag -# * repeat the checks for the std_spec and compiler_spec with and without the flag +# * repeat the checks for the spec suites with and without the flag set -eux @@ -27,6 +27,8 @@ md5 .build/crystal # run specs make clean_cache std_spec make clean_cache std_spec FLAGS="-D$COMPILER_FLAG" +make clean_cache primitives_spec +make clean_cache primitives_spec FLAGS="-D$COMPILER_FLAG" # test compiler_specs make clean_cache @@ -47,6 +49,8 @@ md5 .build/crystal # run specs make clean_cache std_spec make clean_cache std_spec FLAGS="-D$COMPILER_FLAG" +make clean_cache primitives_spec +make clean_cache primitives_spec FLAGS="-D$COMPILER_FLAG" # run compiler specs make clean_cache diff --git a/bin/ci b/bin/ci index d80043fb69a9..605f35a06b08 100755 --- a/bin/ci +++ b/bin/ci @@ -115,10 +115,11 @@ build() { i=$((i + 1)) done + with_build_env 'make primitives_spec threads=1 junit_output=.junit/primitives_spec.xml' with_build_env 'make docs threads=1' ;; *) - with_build_env 'make crystal std_spec compiler_spec docs threads=1 junit_output=.junit/spec.xml DOCS_OPTIONS="--json-config-url=/api/versions.json --canonical-base-url=https://crystal-lang.org/api/latest/"' + with_build_env 'make crystal std_spec compiler_spec primitives_spec docs threads=1 junit_output=.junit/spec.xml DOCS_OPTIONS="--json-config-url=/api/versions.json --canonical-base-url=https://crystal-lang.org/api/latest/"' ;; esac diff --git a/spec/all_spec.cr b/spec/all_spec.cr index 65084face8be..5c84a41846e0 100644 --- a/spec/all_spec.cr +++ b/spec/all_spec.cr @@ -1,3 +1,4 @@ require "spec" require "./compiler/**" require "./std_spec" +require "./primitives_spec" diff --git a/spec/compiler/codegen/arithmetics_spec.cr b/spec/compiler/codegen/arithmetics_spec.cr deleted file mode 100644 index 9bcf008e6b4d..000000000000 --- a/spec/compiler/codegen/arithmetics_spec.cr +++ /dev/null @@ -1,330 +0,0 @@ -require "../../spec_helper" - -# Int128 and UInt128 specs do not pass on win32 because of missing compiler-rt symbols -{% unless flag?(:win32) %} - SupportedInts = [UInt8, UInt16, UInt32, UInt64, UInt128, Int8, Int16, Int32, Int64, Int128] - SupportedIntsConversions = { - to_i8: Int8, to_i16: Int16, to_i32: Int32, to_i64: Int64, to_i128: Int128, - to_u8: UInt8, to_u16: UInt16, to_u32: UInt32, to_u64: UInt64, to_u128: UInt128, - } -{% else %} - SupportedInts = [UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64] - SupportedIntsConversions = { - to_i8: Int8, to_i16: Int16, to_i32: Int32, to_i64: Int64, - to_u8: UInt8, to_u16: UInt16, to_u32: UInt32, to_u64: UInt64, - } -{% end %} - -describe "Code gen: arithmetic primitives" do - describe "&+ addition" do - {% for type in SupportedInts %} - it "wrap around for {{type}}" do - run(%( - require "prelude" - {{type}}::MAX &+ {{type}}.new(1) == {{type}}::MIN - )).to_b.should be_true - end - - it "wrap around for {{type}} + Int64" do - run(%( - require "prelude" - {{type}}::MAX &+ 1_i64 == {{type}}::MIN - )).to_b.should be_true - end - {% end %} - end - - describe "&- subtraction" do - {% for type in SupportedInts %} - it "wrap around for {{type}}" do - run(%( - require "prelude" - {{type}}::MIN &- {{type}}.new(1) == {{type}}::MAX - )).to_b.should be_true - end - - it "wrap around for {{type}} - Int64" do - run(%( - require "prelude" - {{type}}::MIN &- 1_i64 == {{type}}::MAX - )).to_b.should be_true - end - {% end %} - end - - describe "&* multiplication" do - {% for type in SupportedInts %} - it "wrap around for {{type}}" do - run(%( - require "prelude" - ({{type}}::MAX // {{type}}.new(2) &+ {{type}}.new(1)) &* {{type}}.new(2) == {{type}}::MIN - )).to_b.should be_true - end - - it "wrap around for {{type}} + Int64" do - run(%( - require "prelude" - ({{type}}::MAX // {{type}}.new(2) &+ {{type}}.new(1)) &* 2_i64 == {{type}}::MIN - )).to_b.should be_true - end - {% end %} - end - - describe "+ addition" do - {% for type in SupportedInts %} - it "raises overflow for {{type}}" do - run(%( - require "prelude" - begin - {{type}}::MAX + {{type}}.new(1) - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - - it "raises overflow for {{type}} + Int64" do - run(%( - require "prelude" - begin - {{type}}::MAX + 1_i64 - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - {% end %} - end - - describe "- subtraction" do - {% for type in SupportedInts %} - it "raises overflow for {{type}}" do - run(%( - require "prelude" - begin - {{type}}::MIN - {{type}}.new(1) - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - - it "raises overflow for {{type}} - Int64" do - run(%( - require "prelude" - begin - {{type}}::MIN - 1_i64 - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - {% end %} - end - - describe "* multiplication" do - {% for type in SupportedInts %} - it "raises overflow for {{type}}" do - run(%( - require "prelude" - begin - ({{type}}::MAX // {{type}}.new(2) &+ {{type}}.new(1)) * {{type}}.new(2) - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - - it "raises overflow for {{type}} * Int64" do - run(%( - require "prelude" - begin - ({{type}}::MAX // {{type}}.new(2) &+ {{type}}.new(1)) * 2_i64 - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - {% end %} - end - - describe ".to_i conversions" do - {% for method, path_type in SupportedIntsConversions %} - {% type = path_type.resolve %} - - {% if ![UInt64, Int128, UInt128].includes?(type) %} - it "raises overflow if greater than {{type}}::MAX" do - run(%( - require "prelude" - - v = UInt64.new({{type}}::MAX) + 1_u64 - - begin - v.{{method}} - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - {% end %} - - {% if ![UInt128].includes?(type) && SupportedInts.includes?(UInt128) %} - it "raises overflow if greater than {{type}}::MAX (using UInt128)" do - run(%( - require "prelude" - - v = UInt128.new({{type}}::MAX) + 1_u128 - - begin - v.{{method}} - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - {% end %} - - {% if ![Int64, Int128, UInt128].includes?(type) %} - it "raises overflow if lower than {{type}}::MIN" do - run(%( - require "prelude" - - v = Int64.new({{type}}::MIN) - 1_i64 - - begin - v.{{method}} - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - {% end %} - - {% if [UInt16, UInt32, UInt64].includes?(type) %} - it "raises overflow if lower than {{type}}::MIN (#9997)" do - run(%( - require "prelude" - - v = -1_i8 - - begin - v.{{method}} - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - {% end %} - - {% if ![Int128].includes?(type) && SupportedInts.includes?(Int128) %} - it "raises overflow if lower than {{type}}::MIN (using Int128)" do - run(%( - require "prelude" - - v = Int128.new({{type}}::MIN) - 1_i128 - - begin - v.{{method}} - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - {% end %} - - {% for float_type in [Float32, Float64] %} - {% if type != UInt128 || float_type != Float32 %} - # skip for type == UInt128 && float_type == Float32 - # since Float32::MAX < UInt128::MAX - it "raises overflow if greater than {{type}}::MAX (from {{float_type}})" do - run(%( - require "prelude" - - v = {{float_type}}.new({{type}}::MAX) * {{float_type}}.new(1.5) - - begin - v.{{method}} - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - {% end %} - - it "raises overflow if lower than {{type}}::MIN (from {{float_type}})" do - run(%( - require "prelude" - - v = {{float_type}}.new({{type}}::MIN) * {{float_type}}.new(1.5) - {{float_type}}.new(1.0) - - begin - v.{{method}} - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - {% end %} - {% end %} - end - - describe ".to_f conversions" do - {% if SupportedInts.includes?(Int128) %} - it "raises overflow if greater than Float32::MAX (from UInt128)" do - run(%( - require "prelude" - - begin - UInt128::MAX.to_f32 - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - {% end %} - - it "raises overflow if greater than Float32::MAX" do - run(%( - require "prelude" - - v = Float64.new(Float32::MAX) * 1.5_f64 - - begin - v.to_f32 - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - - it "raises overflow if lower than Float32::MIN" do - run(%( - require "prelude" - - v = Float64.new(Float32::MIN) * 1.5_f64 - - begin - v.to_f32 - 0 - rescue OverflowError - 1 - end - )).to_i.should eq(1) - end - end -end diff --git a/spec/compiler/codegen/primitives_spec.cr b/spec/compiler/codegen/primitives_spec.cr index 77ce1ed8b4ee..aa44a293bd15 100644 --- a/spec/compiler/codegen/primitives_spec.cr +++ b/spec/compiler/codegen/primitives_spec.cr @@ -34,10 +34,6 @@ describe "Code gen: primitives" do )).to_i.should eq(1) end - it "skips bounds checking when to_i produces same type" do - run("1.to_i32").to_i.should eq(1) - end - it "codegens char" do run("'a'").to_i.should eq('a'.ord) end @@ -58,44 +54,69 @@ describe "Code gen: primitives" do run(%("foo")).to_string.should eq("foo") end - it "codegens 1 + 2" do - run(%(require "prelude"; 1 + 2)).to_i.should eq(3) - end + describe "arithmetic primitives" do + # more detailed tests are done through the `primitives_spec` suite on a new + # generation of the compiler - it "codegens 1 &+ 2" do - run(%(1 &+ 2)).to_i.should eq(3) - end + it "codegens 1 + 2" do + run(%(require "prelude"; 1 + 2)).to_i.should eq(3) + end - it "codegens 1 - 2" do - run(%(require "prelude"; 1 - 2)).to_i.should eq(-1) - end + it "codegens 1 &+ 2" do + run(%(1 &+ 2)).to_i.should eq(3) + end - it "codegens 1 &- 2" do - run(%(1 &- 2)).to_i.should eq(-1) - end + it "codegens 1 - 2" do + run(%(require "prelude"; 1 - 2)).to_i.should eq(-1) + end - it "codegens 2 * 3" do - run(%(require "prelude"; 2 * 3)).to_i.should eq(6) - end + it "codegens 1 &- 2" do + run(%(1 &- 2)).to_i.should eq(-1) + end - it "codegens 2 &* 3" do - run(%(2 &* 3)).to_i.should eq(6) - end + it "codegens 2 * 3" do + run(%(require "prelude"; 2 * 3)).to_i.should eq(6) + end - it "codegens 8.unsafe_div 3" do - run(%(8.unsafe_div 3)).to_i.should eq(2) - end + it "codegens 2 &* 3" do + run(%(2 &* 3)).to_i.should eq(6) + end - it "codegens 8.unsafe_mod 3" do - run(%(10.unsafe_mod 3)).to_i.should eq(1) - end + it "codegens 8.unsafe_div 3" do + run(%(8.unsafe_div 3)).to_i.should eq(2) + end - it "codegens 16.unsafe_shr 2" do - run(%(16.unsafe_shr 2)).to_i.should eq(4) - end + it "codegens 8.unsafe_mod 3" do + run(%(10.unsafe_mod 3)).to_i.should eq(1) + end + + it "codegens 16.unsafe_shr 2" do + run(%(16.unsafe_shr 2)).to_i.should eq(4) + end + + it "codegens 16.unsafe_shl 2" do + run(%(16.unsafe_shl 2)).to_i.should eq(64) + end + + it "codegens 1.to_i16!" do + run("1.to_i16!").to_i.should eq(1) + end + + it "codegens 1.to_i16" do + run(%(require "prelude"; 1.to_i16)).to_i.should eq(1) + end + + it "codegens 1.to_f!" do + run("1.to_f!").to_f64.should eq(1.0) + end + + it "codegens 1.to_f" do + run(%(require "prelude"; 1.to_f)).to_f64.should eq(1.0) + end - it "codegens 16.unsafe_shl 2" do - run(%(16.unsafe_shl 2)).to_i.should eq(64) + it "skips bounds checking when to_i produces same type" do + run("1.to_i32").to_i.should eq(1) + end end it "defined method that calls primitive (bug)" do diff --git a/spec/primitives/float_spec.cr b/spec/primitives/float_spec.cr new file mode 100644 index 000000000000..8b15aae4eae8 --- /dev/null +++ b/spec/primitives/float_spec.cr @@ -0,0 +1,58 @@ +require "spec" +require "../support/number" + +describe "Primitives: Float" do + describe "#to_i" do + {% for float in BUILTIN_FLOAT_TYPES %} + {% for method, int in BUILTIN_INT_CONVERSIONS %} + # TODO: fix this in #11230 + {{ (float.resolve == Float32 && int.resolve == UInt128 ? "pending" : "it").id }} {{ "raises on overflow for #{float}##{method}" }} do + if {{ float }}::MAX > {{ int }}::MAX + expect_raises(OverflowError) do + {{ float }}.new!({{ int }}::MAX).next_float.{{ method }} + end + end + + expect_raises(OverflowError) do + {{ float }}::INFINITY.{{ method }} + end + + if {{ int }}::MIN.zero? # unsigned + expect_raises(OverflowError) do + {{ float }}.zero.prev_float.{{ method }} + end + end + + expect_raises(OverflowError) do + (-{{ float }}::INFINITY).{{ method }} + end + end + {% end %} + {% end %} + end + + describe "#to_f" do + it "raises on overflow for Float64#to_f32" do + expect_raises(OverflowError) { Float64::MAX.to_f32 } + expect_raises(OverflowError) { Float32::MAX.to_f64!.next_float.to_f32 } + expect_raises(OverflowError) { Float32::MIN.to_f64!.prev_float.to_f32 } + expect_raises(OverflowError) { Float64::MIN.to_f32 } + end + + it "doesn't raise for infinity" do + x = Float64::INFINITY.to_f32 + x.should be_a(Float32) + x.should eq(Float32::INFINITY) + + x = (-Float64::INFINITY).to_f32 + x.should be_a(Float32) + x.should eq(-Float32::INFINITY) + end + + it "doesn't raise for NaN" do + x = Float64::NAN.to_f32 + x.should be_a(Float32) + x.nan?.should be_true + end + end +end diff --git a/spec/primitives/int_spec.cr b/spec/primitives/int_spec.cr new file mode 100644 index 000000000000..0a6ac5c1dec5 --- /dev/null +++ b/spec/primitives/int_spec.cr @@ -0,0 +1,126 @@ +require "spec" +require "../support/number" +{% unless flag?(:win32) %} + require "big" +{% end %} + +{% for i in Int::Signed.union_types %} + struct {{i}} + TEST_CASES = [MIN, MIN &+ 1, MIN &+ 2, -1, 0, 1, MAX &- 2, MAX &- 1, MAX] of {{i}} + end +{% end %} + +{% for i in Int::Unsigned.union_types %} + struct {{i}} + TEST_CASES = [MIN, MIN &+ 1, MIN &+ 2, MAX &- 2, MAX &- 1, MAX] of {{i}} + end +{% end %} + +macro run_op_tests(t, u, op) + it "overflow test #{{{t}}} #{{{op}}} #{{{u}}}" do + {{t}}::TEST_CASES.each do |lhs| + {{u}}::TEST_CASES.each do |rhs| + result = lhs.to_big_i {{op.id}} rhs.to_big_i + passes = {{t}}::MIN <= result <= {{t}}::MAX + begin + if passes + (lhs {{op.id}} rhs).should eq(lhs &{{op.id}} rhs) + else + expect_raises(OverflowError) { lhs {{op.id}} rhs } + end + rescue e : Spec::AssertionFailed + raise Spec::AssertionFailed.new("#{e.message}: #{lhs} #{{{op}}} #{rhs}", e.file, e.line) + rescue e : OverflowError + raise OverflowError.new("#{e.message}: #{lhs} #{{{op}}} #{rhs}") + end + end + end + end +end + +describe "Primitives: Int" do + describe "#&+" do + {% for int in BUILTIN_INTEGER_TYPES %} + it "wraps around for {{ int }}" do + ({{ int }}::MAX &+ {{ int }}.new(1)).should eq({{ int }}::MIN) + ({{ int }}::MAX &+ 1_i64).should eq({{ int }}::MIN) + end + {% end %} + end + + describe "#&-" do + {% for int in BUILTIN_INTEGER_TYPES %} + it "wraps around for {{ int }}" do + ({{ int }}::MIN &- {{ int }}.new(1)).should eq({{ int }}::MAX) + ({{ int }}::MIN &- 1_i64).should eq({{ int }}::MAX) + end + {% end %} + end + + describe "#&*" do + {% for int in BUILTIN_INTEGER_TYPES %} + it "wraps around for {{ int }}" do + %val{int} = {{ int }}::MAX // {{ int }}.new(2) &+ {{ int }}.new(1) + (%val{int} &* {{ int }}.new(2)).should eq({{ int }}::MIN) + (%val{int} &* 2_i64).should eq({{ int }}::MIN) + end + {% end %} + end + + {% unless flag?(:win32) %} + describe "#+" do + {% for int1 in BUILTIN_INTEGER_TYPES %} + {% for int2 in BUILTIN_INTEGER_TYPES %} + run_op_tests {{ int1 }}, {{ int2 }}, :+ + {% end %} + {% end %} + end + + describe "#-" do + {% for int1 in BUILTIN_INTEGER_TYPES %} + {% for int2 in BUILTIN_INTEGER_TYPES %} + run_op_tests {{ int1 }}, {{ int2 }}, :- + {% end %} + {% end %} + end + + describe "#*" do + {% for int1 in BUILTIN_INTEGER_TYPES %} + {% for int2 in BUILTIN_INTEGER_TYPES %} + run_op_tests {{ int1 }}, {{ int2 }}, :* + {% end %} + {% end %} + end + {% end %} + + describe "#to_i" do + {% for int1 in BUILTIN_INTEGER_TYPES %} + {% for method, int2 in BUILTIN_INT_CONVERSIONS %} + {% if int1 != int2 %} + it {{ "raises on overflow for #{int1}##{method}" }} do + if {{ int1 }}::MAX > {{ int2 }}::MAX + expect_raises(OverflowError) do + ({{ int1 }}.new!({{ int2 }}::MAX) &+ 1).{{ method }} + end + end + + if {{ int1 }}::MIN < {{ int2 }}::MIN + expect_raises(OverflowError) do + ({{ int1 }}.new!({{ int2 }}::MIN) &- 1).{{ method }} + end + end + end + {% end %} + {% end %} + {% end %} + end + + describe "#to_f" do + {% if BUILTIN_INTEGER_TYPES.includes?(UInt128) %} + it "raises on overflow for UInt128#to_f32" do + expect_raises(OverflowError) { UInt128::MAX.to_f32 } + expect_raises(OverflowError) { (UInt128::MAX // 2).to_f32 } + end + {% end %} + end +end diff --git a/spec/primitives_spec.cr b/spec/primitives_spec.cr new file mode 100644 index 000000000000..95b96c3476e8 --- /dev/null +++ b/spec/primitives_spec.cr @@ -0,0 +1,2 @@ +require "spec" +require "./primitives/**" diff --git a/spec/std/overflow_spec.cr b/spec/std/overflow_spec.cr deleted file mode 100644 index 460e4882a23a..000000000000 --- a/spec/std/overflow_spec.cr +++ /dev/null @@ -1,54 +0,0 @@ -{% skip_file unless compare_versions(Crystal::VERSION, "0.35.0-0") > 0 %} - -require "big" -require "spec" - -{% for i in Int::Signed.union_types %} - struct {{i}} - TEST_CASES = [MIN, MIN &+ 1, MIN &+ 2, -1, 0, 1, MAX &- 2, MAX &- 1, MAX] of {{i}} - end -{% end %} - -{% for i in Int::Unsigned.union_types %} - struct {{i}} - TEST_CASES = [MIN, MIN &+ 1, MIN &+ 2, MAX &- 2, MAX &- 1, MAX] of {{i}} - end -{% end %} - -macro run_op_tests(t, u, op) - it "overflow test #{{{t}}} #{{{op}}} #{{{u}}}" do - {{t}}::TEST_CASES.each do |lhs| - {{u}}::TEST_CASES.each do |rhs| - result = lhs.to_big_i {{op.id}} rhs.to_big_i - passes = {{t}}::MIN <= result <= {{t}}::MAX - begin - if passes - (lhs {{op.id}} rhs).should eq(lhs &{{op.id}} rhs) - else - expect_raises(OverflowError) { lhs {{op.id}} rhs } - end - rescue e : Spec::AssertionFailed - raise Spec::AssertionFailed.new("#{e.message}: #{lhs} #{{{op}}} #{rhs}", e.file, e.line) - rescue e : OverflowError - raise OverflowError.new("#{e.message}: #{lhs} #{{{op}}} #{rhs}") - end - end - end - end -end - -{% if flag?(:darwin) %} - private OVERFLOW_TEST_TYPES = [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128] -{% else %} - private OVERFLOW_TEST_TYPES = [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64] -{% end %} - -describe "overflow" do - {% for t in OVERFLOW_TEST_TYPES %} - {% for u in OVERFLOW_TEST_TYPES %} - run_op_tests {{t}}, {{u}}, :+ - run_op_tests {{t}}, {{u}}, :- - run_op_tests {{t}}, {{u}}, :* - {% end %} - {% end %} -end diff --git a/spec/support/number.cr b/spec/support/number.cr index a9132caa39aa..595d185d3836 100644 --- a/spec/support/number.cr +++ b/spec/support/number.cr @@ -1,13 +1,19 @@ require "spec/helpers/iterate" # Helper methods to describe the behavior of numbers of different types -{% if flag?(:darwin) %} +# Int128 and UInt128 are excluded from win32 because of missing compiler-rt symbols +{% unless flag?(:win32) %} BUILTIN_NUMBER_TYPES = [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, Float32, Float64] BUILTIN_INTEGER_TYPES = [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128] BUILTIN_INTEGER_TYPES_128 = [Int128, UInt128] + BUILTIN_INT_CONVERSIONS = { + to_i: Int32, to_u: UInt32, + to_i8: Int8, to_i16: Int16, to_i32: Int32, to_i64: Int64, to_i128: Int128, + to_u8: UInt8, to_u16: UInt16, to_u32: UInt32, to_u64: UInt64, to_u128: UInt128, + } {% else %} BUILTIN_NUMBER_TYPES = [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float32, Float64] @@ -15,6 +21,11 @@ require "spec/helpers/iterate" [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64] BUILTIN_INTEGER_TYPES_128 = [] of Int.class + BUILTIN_INT_CONVERSIONS = { + to_i: Int32, to_u: UInt32, + to_i8: Int8, to_i16: Int16, to_i32: Int32, to_i64: Int64, + to_u8: UInt8, to_u16: UInt16, to_u32: UInt32, to_u64: UInt64, + } {% end %} BUILTIN_NUMBER_TYPES_LTE_64 = [Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float32, Float64] From 567956c8f7939ef92cfc34122e0acd7081953c0c Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Fri, 8 Oct 2021 14:18:01 +0800 Subject: [PATCH 02/16] fixup aarch64 ci --- .github/workflows/aarch64.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml index 6a8f98e44646..90dc6868506d 100644 --- a/.github/workflows/aarch64.yml +++ b/.github/workflows/aarch64.yml @@ -35,11 +35,7 @@ jobs: - name: Run stdlib specs uses: docker://jhass/crystal:1.0.0-alpine-build with: - args: make std_spec - - name: Run primitives specs - uses: docker://jhass/crystal:1.0.0-alpine-build - with: - args: make primitives_spec + args: make std_spec primitives_spec musl-test-compiler: needs: musl-build runs-on: [linux, ARM64] @@ -90,11 +86,7 @@ jobs: - name: Run stdlib specs uses: docker://jhass/crystal:1.0.0-build with: - args: make std_spec - - name: Run primitives specs - uses: docker://jhass/crystal:1.0.0-alpine-build - with: - args: make primitives_spec + args: make std_spec primitives_spec gnu-test-compiler: needs: gnu-build runs-on: [linux, ARM64] From 0f4761c9c6c4caae2ef448c696eec2498eb8e191 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Fri, 8 Oct 2021 14:39:11 +0800 Subject: [PATCH 03/16] don't rebuild compiler for primitives_spec --- .github/workflows/aarch64.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml index 90dc6868506d..d32c090ab076 100644 --- a/.github/workflows/aarch64.yml +++ b/.github/workflows/aarch64.yml @@ -35,7 +35,15 @@ jobs: - name: Run stdlib specs uses: docker://jhass/crystal:1.0.0-alpine-build with: - args: make std_spec primitives_spec + args: make std_spec + - name: Build primitives specs + uses: docker://jhass/crystal:1.0.0-alpine-build + with: + args: ./bin/crystal build --exclude-warnings spec/primitives -o .build/primitives_spec spec/primitives_spec.cr + - name: Run primitives specs + uses: docker://jhass/crystal:1.0.0-alpine-build + with: + args: .build/primitives_spec musl-test-compiler: needs: musl-build runs-on: [linux, ARM64] @@ -87,6 +95,14 @@ jobs: uses: docker://jhass/crystal:1.0.0-build with: args: make std_spec primitives_spec + - name: Build primitives specs + uses: docker://jhass/crystal:1.0.0-build + with: + args: ./bin/crystal build --exclude-warnings spec/primitives -o .build/primitives_spec spec/primitives_spec.cr + - name: Run primitives specs + uses: docker://jhass/crystal:1.0.0-build + with: + args: .build/primitives_spec gnu-test-compiler: needs: gnu-build runs-on: [linux, ARM64] From d09f5f362e5d337a3956d454e3e7a8880f27cd53 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Fri, 8 Oct 2021 14:47:11 +0800 Subject: [PATCH 04/16] fixup 2 --- .github/workflows/aarch64.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml index d32c090ab076..3a2cc9606c0e 100644 --- a/.github/workflows/aarch64.yml +++ b/.github/workflows/aarch64.yml @@ -94,7 +94,7 @@ jobs: - name: Run stdlib specs uses: docker://jhass/crystal:1.0.0-build with: - args: make std_spec primitives_spec + args: make std_spec - name: Build primitives specs uses: docker://jhass/crystal:1.0.0-build with: From 6c3e788eafe3b0bcdb5120fd7310c89ec7e03425 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Fri, 8 Oct 2021 18:07:54 +0800 Subject: [PATCH 05/16] Update bin/ci MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johannes Müller --- bin/ci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/ci b/bin/ci index 605f35a06b08..fbdf9a3c6925 100755 --- a/bin/ci +++ b/bin/ci @@ -119,7 +119,7 @@ build() { with_build_env 'make docs threads=1' ;; *) - with_build_env 'make crystal std_spec compiler_spec primitives_spec docs threads=1 junit_output=.junit/spec.xml DOCS_OPTIONS="--json-config-url=/api/versions.json --canonical-base-url=https://crystal-lang.org/api/latest/"' + with_build_env 'make crystal primitives_spec std_spec compiler_spec docs threads=1 junit_output=.junit/spec.xml DOCS_OPTIONS="--json-config-url=/api/versions.json --canonical-base-url=https://crystal-lang.org/api/latest/"' ;; esac From e74236e1a636b80125ccd4b20cda05cf306fb73d Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Fri, 8 Oct 2021 18:13:48 +0800 Subject: [PATCH 06/16] don't do primitives specs for smoke tests --- .github/workflows/smoke.yml | 6 +++--- Makefile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index a190cabcf8c3..5c7be225ab00 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -1,7 +1,7 @@ # These jobs are smoke tests for platforms where we don't rund full tests. -# They ensure that std_spec, compiler_spec, primitives_spec, and the compiler -# itself at least compile for the target with --cross-compile. But the binaries -# are not linked and executed. So this does not validate correct behaviour. +# They ensure that std_spec, compiler_spec and the compiler itself at least +# compile for the target with --cross-compile. But the binaries are not linked +# and executed. So this does not validate correct behaviour. # # The list of supported platforms is extracted from the lib_c bindings: # diff --git a/Makefile b/Makefile index ab4025032d84..34efcbf6b231 100644 --- a/Makefile +++ b/Makefile @@ -104,7 +104,7 @@ primitives_spec: $(O)/primitives_spec ## Run primitives specs $(O)/primitives_spec $(SPEC_FLAGS) .PHONY: smoke_test ## Build specs as a smoke test -smoke_test: $(O)/std_spec $(O)/compiler_spec $(O)/primitives_spec $(O)/crystal +smoke_test: $(O)/std_spec $(O)/compiler_spec $(O)/crystal .PHONY: docs docs: ## Generate standard library documentation From 5e2b2b7e24a4f1b8fe318d2f5e2769581b7d22f2 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Sat, 23 Oct 2021 17:24:22 +0800 Subject: [PATCH 07/16] run primitives_spec in test-compiler jobs --- .github/workflows/aarch64.yml | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml index 3a2cc9606c0e..bd1b10a6125e 100644 --- a/.github/workflows/aarch64.yml +++ b/.github/workflows/aarch64.yml @@ -36,14 +36,6 @@ jobs: uses: docker://jhass/crystal:1.0.0-alpine-build with: args: make std_spec - - name: Build primitives specs - uses: docker://jhass/crystal:1.0.0-alpine-build - with: - args: ./bin/crystal build --exclude-warnings spec/primitives -o .build/primitives_spec spec/primitives_spec.cr - - name: Run primitives specs - uses: docker://jhass/crystal:1.0.0-alpine-build - with: - args: .build/primitives_spec musl-test-compiler: needs: musl-build runs-on: [linux, ARM64] @@ -61,7 +53,7 @@ jobs: - name: Run compiler specs uses: docker://jhass/crystal:1.0.0-alpine-build with: - args: make compiler_spec + args: make primitives_spec compiler_spec gnu-build: runs-on: [linux, ARM64] if: github.repository == 'crystal-lang/crystal' @@ -95,14 +87,6 @@ jobs: uses: docker://jhass/crystal:1.0.0-build with: args: make std_spec - - name: Build primitives specs - uses: docker://jhass/crystal:1.0.0-build - with: - args: ./bin/crystal build --exclude-warnings spec/primitives -o .build/primitives_spec spec/primitives_spec.cr - - name: Run primitives specs - uses: docker://jhass/crystal:1.0.0-build - with: - args: .build/primitives_spec gnu-test-compiler: needs: gnu-build runs-on: [linux, ARM64] @@ -120,4 +104,4 @@ jobs: - name: Run compiler specs uses: docker://jhass/crystal:1.0.0-build with: - args: make compiler_spec + args: make primitives_spec compiler_spec From 09b88e9d8c63e7e0257b02d51d33d59de5966888 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Sat, 23 Oct 2021 17:30:09 +0800 Subject: [PATCH 08/16] pretend *-build binaries are up-to-date --- .github/workflows/aarch64.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml index bd1b10a6125e..cad870e9a9e8 100644 --- a/.github/workflows/aarch64.yml +++ b/.github/workflows/aarch64.yml @@ -49,7 +49,7 @@ jobs: name: crystal-aarch64-musl path: .build/ - name: Mark downloaded compiler as executable - run: chmod +x .build/crystal + run: chmod +x .build/crystal && touch .build/crystal - name: Run compiler specs uses: docker://jhass/crystal:1.0.0-alpine-build with: @@ -100,7 +100,7 @@ jobs: name: crystal-aarch64-gnu path: .build/ - name: Mark downloaded compiler as executable - run: chmod +x .build/crystal + run: chmod +x .build/crystal && touch .build/crystal - name: Run compiler specs uses: docker://jhass/crystal:1.0.0-build with: From dd32e0551b8bd2c6e3bf8f98b0aa86cfaf40190b Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Sat, 23 Oct 2021 17:37:16 +0800 Subject: [PATCH 09/16] try order-only prerequisite --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 34efcbf6b231..c38f57b0346f 100644 --- a/Makefile +++ b/Makefile @@ -167,7 +167,7 @@ $(O)/compiler_spec: $(DEPS) $(SOURCES) $(SPEC_SOURCES) @mkdir -p $(O) $(EXPORT_CC) $(EXPORTS) ./bin/crystal build $(FLAGS) $(SPEC_WARNINGS_OFF) -o $@ spec/compiler_spec.cr -$(O)/primitives_spec: $(O)/crystal $(DEPS) $(SOURCES) $(SPEC_SOURCES) +$(O)/primitives_spec: $(DEPS) $(SOURCES) $(SPEC_SOURCES) | $(O)/crystal @mkdir -p $(O) $(EXPORT_CC) ./bin/crystal build $(FLAGS) $(SPEC_WARNINGS_OFF) -o $@ spec/primitives_spec.cr From 1e25b8a54f2b038d9f7a6092b23343ca11cfce0c Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Sat, 23 Oct 2021 17:48:54 +0800 Subject: [PATCH 10/16] try uploading also `llvm_ext.o` --- .github/workflows/aarch64.yml | 20 ++++++++++++-------- Makefile | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml index cad870e9a9e8..41bcab6c1da2 100644 --- a/.github/workflows/aarch64.yml +++ b/.github/workflows/aarch64.yml @@ -17,7 +17,9 @@ jobs: uses: actions/upload-artifact@v1 with: name: crystal-aarch64-musl - path: .build/crystal + path: | + .build/crystal + src/llvm/ext/llvm_ext.o musl-test-stdlib: needs: musl-build runs-on: [linux, ARM64] @@ -29,7 +31,7 @@ jobs: uses: actions/download-artifact@v1 with: name: crystal-aarch64-musl - path: .build/ + path: ./ - name: Mark downloaded compiler as executable run: chmod +x .build/crystal - name: Run stdlib specs @@ -47,9 +49,9 @@ jobs: uses: actions/download-artifact@v1 with: name: crystal-aarch64-musl - path: .build/ + path: ./ - name: Mark downloaded compiler as executable - run: chmod +x .build/crystal && touch .build/crystal + run: chmod +x .build/crystal - name: Run compiler specs uses: docker://jhass/crystal:1.0.0-alpine-build with: @@ -68,7 +70,9 @@ jobs: uses: actions/upload-artifact@v1 with: name: crystal-aarch64-gnu - path: .build/crystal + path: | + .build/crystal + src/llvm/ext/llvm_ext.o gnu-test-stdlib: needs: gnu-build runs-on: [linux, ARM64] @@ -80,7 +84,7 @@ jobs: uses: actions/download-artifact@v1 with: name: crystal-aarch64-gnu - path: .build/ + path: ./ - name: Mark downloaded compiler as executable run: chmod +x .build/crystal - name: Run stdlib specs @@ -98,9 +102,9 @@ jobs: uses: actions/download-artifact@v1 with: name: crystal-aarch64-gnu - path: .build/ + path: ./ - name: Mark downloaded compiler as executable - run: chmod +x .build/crystal && touch .build/crystal + run: chmod +x .build/crystal - name: Run compiler specs uses: docker://jhass/crystal:1.0.0-build with: diff --git a/Makefile b/Makefile index c38f57b0346f..34efcbf6b231 100644 --- a/Makefile +++ b/Makefile @@ -167,7 +167,7 @@ $(O)/compiler_spec: $(DEPS) $(SOURCES) $(SPEC_SOURCES) @mkdir -p $(O) $(EXPORT_CC) $(EXPORTS) ./bin/crystal build $(FLAGS) $(SPEC_WARNINGS_OFF) -o $@ spec/compiler_spec.cr -$(O)/primitives_spec: $(DEPS) $(SOURCES) $(SPEC_SOURCES) | $(O)/crystal +$(O)/primitives_spec: $(O)/crystal $(DEPS) $(SOURCES) $(SPEC_SOURCES) @mkdir -p $(O) $(EXPORT_CC) ./bin/crystal build $(FLAGS) $(SPEC_WARNINGS_OFF) -o $@ spec/primitives_spec.cr From 13185807f5750aa1bc6cfc7c91e767651b083fdc Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Sat, 23 Oct 2021 17:52:50 +0800 Subject: [PATCH 11/16] `upload-artifact@v2` --- .github/workflows/aarch64.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml index 41bcab6c1da2..05a9f2401661 100644 --- a/.github/workflows/aarch64.yml +++ b/.github/workflows/aarch64.yml @@ -14,7 +14,7 @@ jobs: with: args: make crystal - name: Upload Crystal executable - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v2 with: name: crystal-aarch64-musl path: | @@ -67,7 +67,7 @@ jobs: with: args: make crystal - name: Upload Crystal executable - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v2 with: name: crystal-aarch64-gnu path: | From c82e4cdd50e18b6c9e3b658041010a5fcbd089b5 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Fri, 29 Oct 2021 23:16:13 +0800 Subject: [PATCH 12/16] merge convert_spec.cr into primitives specs --- spec/compiler/codegen/convert_spec.cr | 23 ----------------------- spec/primitives/int_spec.cr | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 23 deletions(-) delete mode 100644 spec/compiler/codegen/convert_spec.cr diff --git a/spec/compiler/codegen/convert_spec.cr b/spec/compiler/codegen/convert_spec.cr deleted file mode 100644 index 69afd94b4927..000000000000 --- a/spec/compiler/codegen/convert_spec.cr +++ /dev/null @@ -1,23 +0,0 @@ -require "../../spec_helper" - -describe "Code gen: convert primitives" do - describe "to_*!" do - it "works from negative values to unsigned types" do - run(%( - -1.to_u! == 4294967295_u32 - )).to_b.should be_true - end - - it "works from greater values to smaller types" do - run(%( - 47866.to_i8! == -6_i8 - )).to_b.should be_true - end - - it "preserves negative sign" do - run(%( - -1_i8.to_i! == -1_i32 - )).to_b.should be_true - end - end -end diff --git a/spec/primitives/int_spec.cr b/spec/primitives/int_spec.cr index 0a6ac5c1dec5..95093b1a0471 100644 --- a/spec/primitives/int_spec.cr +++ b/spec/primitives/int_spec.cr @@ -115,6 +115,26 @@ describe "Primitives: Int" do {% end %} end + describe "#to_i!" do + it "works from negative values to unsigned types" do + x = (-1).to_u! + x.should be_a(UInt32) + x.should eq(4294967295_u32) + end + + it "works from greater values to smaller types" do + x = 47866.to_i8! + x.should be_a(Int8) + x.should eq(-6_i8) + end + + it "preserves negative sign" do + x = (-1_i8).to_i! + x.should be_a(Int32) + x.should eq(-1_i32) + end + end + describe "#to_f" do {% if BUILTIN_INTEGER_TYPES.includes?(UInt128) %} it "raises on overflow for UInt128#to_f32" do From 2fc92bb76c0f573ad12fc54a40aa6534093762d6 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Tue, 30 Nov 2021 00:23:24 +0800 Subject: [PATCH 13/16] fixup --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 263178460cd5..f36094dce75b 100644 --- a/Makefile +++ b/Makefile @@ -172,7 +172,7 @@ $(O)/compiler_spec: $(DEPS) $(SOURCES) $(SPEC_SOURCES) LLVM_CONFIG @mkdir -p $(O) $(EXPORT_CC) $(EXPORTS) ./bin/crystal build $(FLAGS) $(SPEC_WARNINGS_OFF) -o $@ spec/compiler_spec.cr -$(O)/primitives_spec: $(O)/crystal $(DEPS) $(SOURCES) $(SPEC_SOURCES)LLVM_CONFIG +$(O)/primitives_spec: $(O)/crystal $(DEPS) $(SOURCES) $(SPEC_SOURCES) LLVM_CONFIG @mkdir -p $(O) $(EXPORT_CC) ./bin/crystal build $(FLAGS) $(SPEC_WARNINGS_OFF) -o $@ spec/primitives_spec.cr From 63329f1d6c2000c73828e6c32439249e7a525ef8 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Wed, 1 Dec 2021 05:36:35 +0800 Subject: [PATCH 14/16] fixup --- Makefile | 2 +- spec/win32_std_spec.cr | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f36094dce75b..72b5fb9b44a0 100644 --- a/Makefile +++ b/Makefile @@ -172,7 +172,7 @@ $(O)/compiler_spec: $(DEPS) $(SOURCES) $(SPEC_SOURCES) LLVM_CONFIG @mkdir -p $(O) $(EXPORT_CC) $(EXPORTS) ./bin/crystal build $(FLAGS) $(SPEC_WARNINGS_OFF) -o $@ spec/compiler_spec.cr -$(O)/primitives_spec: $(O)/crystal $(DEPS) $(SOURCES) $(SPEC_SOURCES) LLVM_CONFIG +$(O)/primitives_spec: $(O)/crystal $(DEPS) $(SOURCES) $(SPEC_SOURCES) @mkdir -p $(O) $(EXPORT_CC) ./bin/crystal build $(FLAGS) $(SPEC_WARNINGS_OFF) -o $@ spec/primitives_spec.cr diff --git a/spec/win32_std_spec.cr b/spec/win32_std_spec.cr index daed45a6c712..1874e5eeb3d6 100644 --- a/spec/win32_std_spec.cr +++ b/spec/win32_std_spec.cr @@ -171,7 +171,6 @@ require "./std/openssl/ssl/hostname_validation_spec.cr" require "./std/openssl/x509/certificate_spec.cr" require "./std/openssl/x509/name_spec.cr" require "./std/option_parser_spec.cr" -require "./std/overflow_spec.cr" require "./std/path_spec.cr" require "./std/pointer_spec.cr" require "./std/pp_spec.cr" From 2ab3d8b244bab0d4c55e01f766931437c5fec871 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Wed, 1 Dec 2021 22:39:21 +0800 Subject: [PATCH 15/16] fixup --- .github/workflows/aarch64.yml | 12 ++++-------- spec/primitives/int_spec.cr | 4 ++-- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.github/workflows/aarch64.yml b/.github/workflows/aarch64.yml index 05a9f2401661..2b5ae6e397c5 100644 --- a/.github/workflows/aarch64.yml +++ b/.github/workflows/aarch64.yml @@ -28,10 +28,9 @@ jobs: - name: Download Crystal source uses: actions/checkout@v2 - name: Download Crystal executable - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v2 with: name: crystal-aarch64-musl - path: ./ - name: Mark downloaded compiler as executable run: chmod +x .build/crystal - name: Run stdlib specs @@ -46,10 +45,9 @@ jobs: - name: Download Crystal source uses: actions/checkout@v2 - name: Download Crystal executable - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v2 with: name: crystal-aarch64-musl - path: ./ - name: Mark downloaded compiler as executable run: chmod +x .build/crystal - name: Run compiler specs @@ -81,10 +79,9 @@ jobs: - name: Download Crystal source uses: actions/checkout@v2 - name: Download Crystal executable - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v2 with: name: crystal-aarch64-gnu - path: ./ - name: Mark downloaded compiler as executable run: chmod +x .build/crystal - name: Run stdlib specs @@ -99,10 +96,9 @@ jobs: - name: Download Crystal source uses: actions/checkout@v2 - name: Download Crystal executable - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v2 with: name: crystal-aarch64-gnu - path: ./ - name: Mark downloaded compiler as executable run: chmod +x .build/crystal - name: Run compiler specs diff --git a/spec/primitives/int_spec.cr b/spec/primitives/int_spec.cr index 95093b1a0471..e86867fdd564 100644 --- a/spec/primitives/int_spec.cr +++ b/spec/primitives/int_spec.cr @@ -6,13 +6,13 @@ require "../support/number" {% for i in Int::Signed.union_types %} struct {{i}} - TEST_CASES = [MIN, MIN &+ 1, MIN &+ 2, -1, 0, 1, MAX &- 2, MAX &- 1, MAX] of {{i}} + TEST_CASES = [MIN, MIN &+ 1, MIN &+ 2, -2, -1, 0, 1, 2, MAX &- 2, MAX &- 1, MAX] of {{i}} end {% end %} {% for i in Int::Unsigned.union_types %} struct {{i}} - TEST_CASES = [MIN, MIN &+ 1, MIN &+ 2, MAX &- 2, MAX &- 1, MAX] of {{i}} + TEST_CASES = [MIN, MIN &+ 1, MIN &+ 2, MAX // 2 &- 1, MAX // 2, MAX // 2 &+ 1, MAX &- 2, MAX &- 1, MAX] of {{i}} end {% end %} From 9ea16be70f648391f230b415bb0560e937150eb1 Mon Sep 17 00:00:00 2001 From: Quinton Miller Date: Wed, 1 Dec 2021 23:57:46 +0800 Subject: [PATCH 16/16] enable big number specs on windows --- spec/primitives/int_spec.cr | 42 +++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/spec/primitives/int_spec.cr b/spec/primitives/int_spec.cr index e86867fdd564..55368eaec91c 100644 --- a/spec/primitives/int_spec.cr +++ b/spec/primitives/int_spec.cr @@ -1,8 +1,6 @@ require "spec" require "../support/number" -{% unless flag?(:win32) %} - require "big" -{% end %} +require "big" {% for i in Int::Signed.union_types %} struct {{i}} @@ -67,31 +65,29 @@ describe "Primitives: Int" do {% end %} end - {% unless flag?(:win32) %} - describe "#+" do - {% for int1 in BUILTIN_INTEGER_TYPES %} - {% for int2 in BUILTIN_INTEGER_TYPES %} - run_op_tests {{ int1 }}, {{ int2 }}, :+ - {% end %} + describe "#+" do + {% for int1 in BUILTIN_INTEGER_TYPES %} + {% for int2 in BUILTIN_INTEGER_TYPES %} + run_op_tests {{ int1 }}, {{ int2 }}, :+ {% end %} - end + {% end %} + end - describe "#-" do - {% for int1 in BUILTIN_INTEGER_TYPES %} - {% for int2 in BUILTIN_INTEGER_TYPES %} - run_op_tests {{ int1 }}, {{ int2 }}, :- - {% end %} + describe "#-" do + {% for int1 in BUILTIN_INTEGER_TYPES %} + {% for int2 in BUILTIN_INTEGER_TYPES %} + run_op_tests {{ int1 }}, {{ int2 }}, :- {% end %} - end + {% end %} + end - describe "#*" do - {% for int1 in BUILTIN_INTEGER_TYPES %} - {% for int2 in BUILTIN_INTEGER_TYPES %} - run_op_tests {{ int1 }}, {{ int2 }}, :* - {% end %} + describe "#*" do + {% for int1 in BUILTIN_INTEGER_TYPES %} + {% for int2 in BUILTIN_INTEGER_TYPES %} + run_op_tests {{ int1 }}, {{ int2 }}, :* {% end %} - end - {% end %} + {% end %} + end describe "#to_i" do {% for int1 in BUILTIN_INTEGER_TYPES %}