Skip to content

Commit f8f99bd

Browse files
chrisseatonegonSchiele
authored andcommitted
Don't use exceptions for control flow
1 parent 78be9e2 commit f8f99bd

File tree

2 files changed

+27
-29
lines changed

2 files changed

+27
-29
lines changed

lib/contracts/call_with.rb

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
module Contracts
22
module CallWith
33
def call_with(this, *args, &blk)
4+
call_with_inner(false, this, *args, &blk)
5+
end
6+
7+
def call_with_inner(returns, this, *args, &blk)
48
args << blk if blk
59

610
# Explicitly append blk=nil if nil != Proc contract violation anticipated
@@ -16,14 +20,16 @@ def call_with(this, *args, &blk)
1620
validator = @args_validators[i]
1721

1822
unless validator && validator[arg]
19-
return unless Contract.failure_callback(:arg => arg,
20-
:contract => contract,
21-
:class => klass,
22-
:method => method,
23-
:contracts => self,
24-
:arg_pos => i+1,
25-
:total_args => args.size,
26-
:return_value => false)
23+
data = {:arg => arg,
24+
:contract => contract,
25+
:class => klass,
26+
:method => method,
27+
:contracts => self,
28+
:arg_pos => i+1,
29+
:total_args => args.size,
30+
:return_value => false}
31+
return ParamContractError.new("as return value", data) if returns
32+
return unless Contract.failure_callback(data)
2733
end
2834

2935
if contract.is_a?(Contracts::Func) && blk && !nil_block_appended

lib/contracts/method_handler.rb

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -125,31 +125,23 @@ def redefine_method
125125
# function. Otherwise we return the result.
126126
# If we run out of functions, we raise the last error, but
127127
# convert it to_contract_error.
128-
success = false
129-
i = 0
130-
result = nil
128+
131129
expected_error = decorated_methods[0].failure_exception
130+
last_error = nil
132131

133-
until success
134-
decorated_method = decorated_methods[i]
135-
i += 1
136-
begin
137-
success = true
138-
result = decorated_method.call_with(self, *args, &blk)
139-
rescue expected_error => error
140-
success = false
141-
unless decorated_methods[i]
142-
begin
143-
::Contract.failure_callback(error.data, false)
144-
rescue expected_error => final_error
145-
raise final_error.to_contract_error
146-
end
147-
end
148-
end
132+
decorated_methods.each do |decorated_method|
133+
result = decorated_method.call_with_inner(true, self, *args, &blk)
134+
return result unless result.is_a?(ParamContractError)
135+
last_error = result
149136
end
150137

151-
# Return the result of successfully called method
152-
result
138+
begin
139+
if ::Contract.failure_callback(last_error.data, false)
140+
decorated_methods.last.call_with_inner(false, self, *args, &blk)
141+
end
142+
rescue expected_error => final_error
143+
raise final_error.to_contract_error
144+
end
153145
end
154146
end
155147

0 commit comments

Comments
 (0)