Skip to content

Commit

Permalink
Merge pull request crystal-lang#6890 from bcardiff/feature/amp-int-ops
Browse files Browse the repository at this point in the history
Add wrapping arithmetics operators
  • Loading branch information
ysbaddaden authored Sep 29, 2018
2 parents 738394f + 5d42333 commit 07f91d7
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 4 deletions.
57 changes: 57 additions & 0 deletions spec/compiler/codegen/arithmetics_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
require "../../spec_helper"

describe "Code gen: arithmetics primitives" do
describe "&+ addition" do
{% for type in [UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64] %}
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 [UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64] %}
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 [UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64] %}
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
end
14 changes: 13 additions & 1 deletion spec/compiler/codegen/primitives_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,26 @@ describe "Code gen: primitives" do
run(%(1 + 2)).to_i.should eq(3)
end

it "codegens 1 + 2" do
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(%(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(%(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
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/crystal/codegen/primitives.cr
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ class Crystal::CodeGenVisitor
p1, p2 = codegen_binary_extend_int(t1, t2, p1, p2)

case op
when "+" then codegen_trunc_binary_op_result(t1, t2, builder.add(p1, p2))
when "-" then codegen_trunc_binary_op_result(t1, t2, builder.sub(p1, p2))
when "*" then codegen_trunc_binary_op_result(t1, t2, builder.mul(p1, p2))
when "+", "&+" then codegen_trunc_binary_op_result(t1, t2, builder.add(p1, p2))
when "-", "&-" then codegen_trunc_binary_op_result(t1, t2, builder.sub(p1, p2))
when "*", "&*" then codegen_trunc_binary_op_result(t1, t2, builder.mul(p1, p2))
when "/", "unsafe_div" then codegen_trunc_binary_op_result(t1, t2, t1.signed? ? builder.sdiv(p1, p2) : builder.udiv(p1, p2))
when "%", "unsafe_mod" then codegen_trunc_binary_op_result(t1, t2, t1.signed? ? builder.srem(p1, p2) : builder.urem(p1, p2))
when "unsafe_shl" then codegen_trunc_binary_op_result(t1, t2, builder.shl(p1, p2))
Expand Down
6 changes: 6 additions & 0 deletions src/primitives.cr
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,12 @@ end
@[Primitive(:binary)]
def {{op.id}}(other : {{int2.id}}) : self
end

# Returns the result of {{desc.id}} `self` and *other*.
# In case of overflow a wrapping is performed.
@[Primitive(:binary)]
def &{{op.id}}(other : {{int2.id}}) : self
end
{% end %}
{% end %}

Expand Down

0 comments on commit 07f91d7

Please sign in to comment.