Sha256: 3e1135ac9d8e9487dd6656efd12caade6e339769dec99a2ffb07a52a25eb6692

Contents?: true

Size: 1.19 KB

Versions: 2

Compression:

Stored size: 1.19 KB

Contents

require "rubype/rubype"

# Builtin Contracts
class  Any;     end
module Boolean; end
TrueClass.send(:include, Boolean)
FalseClass.send(:include, Boolean)

class Module
  private
  def __rubype__
    prepend (@__rubype__ = Module.new) unless @__rubype__
    @__rubype__
  end

  def typesig(hash)
    meth = hash.keys.first
    *arg_types, type_pair = hash.values.first

    __rubype__.send(:define_method, meth) do |*args, &block|
      ::Rubype.assert_arg_type(meth, args, arg_types << type_pair.keys.first)
      rtn = super(*args, &block)
      ::Rubype.assert_trn_type(meth, rtn, type_pair.values.first)
      rtn
    end
    self
  end
end

module Rubype
  class << self
    def assert_arg_type(meth, args, klasses)
      args.each_with_index do |arg, i|
        if wrong_type?(arg, klasses[i])
          raise ArgumentError, "Wrong type of argument, type of #{arg.inspect} should be #{klasses[i]}"
        end
      end
    end

    def assert_trn_type(meth, rtn, klass)
      if wrong_type?(rtn, klass)
        raise TypeError, "Expected #{meth} to return #{klass} but got #{rtn.inspect} instead"
      end
    end

    def wrong_type?(obj, klass)
      !(obj.is_a?(klass) || klass == Any)
    end
  end
end

Version data entries

2 entries across 2 versions & 2 rubygems

Version Path
haskell-0.2.0 lib/rubype.rb
rubype-0.2.0 lib/rubype.rb