Class: Typecheck::SignatureCompiler
- Inherits:
-
Object
- Object
- Typecheck::SignatureCompiler
- Defined in:
- lib/typecheck.rb
Instance Method Summary collapse
- #call(signature, method) ⇒ Object
- #check_array(type, array) ⇒ Object
- #check_class(klz, value) ⇒ Object
- #check_respond_to(method, value) ⇒ Object
- #parse_sig(sig) ⇒ Object
- #parse_type(subtype, check_or_raise) ⇒ Object
- #parse_type_list(choices) ⇒ Object
- #pred_and(preds) ⇒ Object
- #pred_or(preds) ⇒ Object
- #raise_array(type, array) ⇒ Object
- #raise_class(klz, value) ⇒ Object
- #raise_respond_to(method, value) ⇒ Object
Instance Method Details
#call(signature, method) ⇒ Object
10 11 12 13 14 15 16 17 18 19 |
# File 'lib/typecheck.rb', line 10 def call(signature, method) unchecked_method = "#{method}_unchecked" check_args, check_out = parse_sig(signature) ->(*args) do check_args.(*args) __send__(unchecked_method, *args).tap do |result| check_out.(result) end end end |
#check_array(type, array) ⇒ Object
78 79 80 |
# File 'lib/typecheck.rb', line 78 def check_array(type, array) array.all? {|element| check_class(type, element) } end |
#check_class(klz, value) ⇒ Object
87 88 89 |
# File 'lib/typecheck.rb', line 87 def check_class(klz, value) value.is_a? klz end |
#check_respond_to(method, value) ⇒ Object
69 70 71 |
# File 'lib/typecheck.rb', line 69 def check_respond_to(method, value) value.respond_to?(method) end |
#parse_sig(sig) ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/typecheck.rb', line 21 def parse_sig(sig) in_t, out_t = sig.split('->').map(&:strip) in_ts = in_t.split(',') in_checks = in_ts.map(&method(:parse_type_list)) out_check = parse_type_list(out_t) args_checker = ->(*args) { args.each.with_index do |arg, idx| in_checks[idx].(arg) end } [args_checker, out_check] end |
#parse_type(subtype, check_or_raise) ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/typecheck.rb', line 56 def parse_type(subtype, check_or_raise) pred_and subtype.split(';').map(&:strip).map { |type| case type when /#(.*)/ method("#{check_or_raise}_respond_to").to_proc.curry.(type[1..-1]) when /\[(.*)\]/ method("#{check_or_raise}_array").to_proc.curry.(eval(type[1..-2])) else method("#{check_or_raise}_class").to_proc.curry.(eval(type)) end } end |
#parse_type_list(choices) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/typecheck.rb', line 44 def parse_type_list(choices) types = choices.split('|') pred_or [ pred_or(types.map {|choice| parse_type(choice, :check) }), pred_or(types.map {|choice| parse_type(choice, :raise) }) ] end |
#pred_and(preds) ⇒ Object
40 41 42 |
# File 'lib/typecheck.rb', line 40 def pred_and(preds) ->(value) { preds.all?{|pred| pred.(value) } } end |
#pred_or(preds) ⇒ Object
36 37 38 |
# File 'lib/typecheck.rb', line 36 def pred_or(preds) ->(value) { preds.any?{|pred| pred.(value) } } end |
#raise_array(type, array) ⇒ Object
82 83 84 85 |
# File 'lib/typecheck.rb', line 82 def raise_array(type, array) raise TypeError, "Bad type: expected #{array} to only contain #{type}" unless check_array(type, array) true end |
#raise_class(klz, value) ⇒ Object
91 92 93 94 |
# File 'lib/typecheck.rb', line 91 def raise_class(klz, value) raise TypeError, "Bad type: #{value.inspect}, expected #{klz}" unless check_class(klz, value) true end |
#raise_respond_to(method, value) ⇒ Object
73 74 75 76 |
# File 'lib/typecheck.rb', line 73 def raise_respond_to(method, value) raise TypeError, "Expected #{value.inspect}, to respond_to #{method}" unless check_respond_to(method, value) true end |