Class: RDL::Wrap
- Inherits:
-
Object
- Object
- RDL::Wrap
- Defined in:
- lib/rdl/wrap.rb
Class Method Summary collapse
- .get_type_params(klass) ⇒ Object
-
.process_pre_post_args(default_class, name, *args, &blk) ⇒ Object
default_class-
should be a class [
name] is the name to give the block as a contract.
-
.process_type_args(default_class, *args) ⇒ Object
default_class-
should be a class.
- .resolve_alias(klass, meth) ⇒ Object
-
.wrap(klass_str, meth) ⇒ Object
klass-
may be a Class, String, or Symbol [
meth] may be a String or Symbol.
- .wrapped?(klass, meth) ⇒ Boolean
Class Method Details
.get_type_params(klass) ⇒ Object
18 19 20 21 |
# File 'lib/rdl/wrap.rb', line 18 def self.get_type_params(klass) klass = klass.to_s RDL::Globals.type_params[klass] end |
.process_pre_post_args(default_class, name, *args, &blk) ⇒ Object
default_class-
should be a class
name-
is the name to give the block as a contract
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/rdl/wrap.rb', line 89 def self.process_pre_post_args(default_class, name, *args, &blk) klass = slf = meth = contract = nil default_class = "Object" if (default_class.is_a? Object) && (default_class.to_s == "main") # special case for main if args.size == 3 klass = class_to_string args[0] slf, meth = meth_to_sym args[1] contract = args[2] elsif args.size == 2 && blk klass = class_to_string args[0] slf, meth = meth_to_sym args[1] contract = RDL::Contract::FlatContract.new(name, &blk) elsif args.size == 2 klass = default_class.to_s slf, meth = meth_to_sym args[0] contract = args[1] elsif args.size == 1 && blk klass = default_class.to_s slf, meth = meth_to_sym args[0] contract = RDL::Contract::FlatContract.new(name, &blk) elsif args.size == 1 klass = default_class.to_s contract = args[0] elsif blk klass = default_class.to_s contract = RDL::Contract::FlatContract.new(name, &blk) else raise ArgumentError, "Invalid arguments to `pre` or `post`" end raise ArgumentError, "#{contract.class} received where Contract expected" unless contract.class < RDL::Contract::Contract # meth = :initialize if meth && meth.to_sym == :new # actually wrap constructor klass = RDL::Util.add_singleton_marker(klass) if slf # && (meth != :initialize) return [klass, meth, contract] end |
.process_type_args(default_class, *args) ⇒ Object
default_class-
should be a class
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/rdl/wrap.rb', line 124 def self.process_type_args(default_class, *args) klass = meth = type = nil default_class = "Object" if (default_class.is_a? Object) && (default_class.to_s == "main") # special case for main if args.size == 3 klass = class_to_string args[0] slf, meth = meth_to_sym args[1] type = type_to_type args[2] elsif args.size == 2 klass = default_class.to_s slf, meth = meth_to_sym args[0] type = type_to_type args[1] elsif args.size == 1 klass = default_class.to_s type = type_to_type args[0] else raise ArgumentError, "Invalid arguments to `type`" end raise ArgumentError, "Excepting method type, got #{type.class} instead" if type.class != RDL::Type::MethodType # meth = :initialize if meth && slf && meth.to_sym == :new # actually wrap constructor klass = RDL::Util.add_singleton_marker(klass) if slf return [klass, meth, type] end |
.resolve_alias(klass, meth) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 |
# File 'lib/rdl/wrap.rb', line 6 def self.resolve_alias(klass, meth) klass = klass.to_s meth = meth.to_sym while RDL::Globals.aliases[klass] && RDL::Globals.aliases[klass][meth] if RDL::Globals.info.has_any?(klass, meth, [:pre, :post, :type]) raise RuntimeError, "Alias #{RDL::Util.pp_klass_method(klass, meth)} has contracts. Contracts are only allowed on methods, not aliases." end meth = RDL::Globals.aliases[klass][meth] end return meth end |
.wrap(klass_str, meth) ⇒ Object
klass-
may be a Class, String, or Symbol
meth-
may be a String or Symbol
Wraps klass#method to check contracts and types. Does not rewrap if already wrapped. Also records source location of method.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/rdl/wrap.rb', line 28 def self.wrap(klass_str, meth) RDL::Globals.wrap_switch.off { klass_str = klass_str.to_s klass = RDL::Util.to_class klass_str return if wrapped? klass, meth return if RDL::Config.instance.nowrap.member? klass_str.to_sym raise ArgumentError, "Attempt to wrap #{RDL::Util.pp_klass_method(klass, meth)}" if klass.to_s =~ /^RDL::/ meth_old = wrapped_name(klass, meth) # meth_old is a symbol # return if (klass.method_defined? meth_old) # now checked above by wrapped? call is_singleton_method = RDL::Util.has_singleton_marker(klass_str) full_method_name = RDL::Util.pp_klass_method(klass_str, meth) klass_str_without_singleton = if is_singleton_method then RDL::Util.remove_singleton_marker(klass_str) else klass_str end klass.class_eval <<-RUBY, __FILE__, __LINE__ alias_method meth_old, meth def #{meth}(*args, &blk) klass = "#{klass_str}" meth = types = matches = nil bind = binding inst = nil RDL::Globals.wrap_switch.off { RDL::Globals.wrapped_calls["#{full_method_name}"] += 1 if RDL::Config.instance.gather_stats inst = nil inst = @__rdl_type.to_inst if ((defined? @__rdl_type) && @__rdl_type.is_a?(RDL::Type::GenericType)) inst = Hash[RDL::Globals.type_params[klass][0].zip []] if (not(inst) && RDL::Globals.type_params[klass]) inst = {} if not inst #{if not(is_singleton_method) then "inst[:self] = RDL::Type::NominalType.new(self.class)" end} # puts "Intercepted #{full_method_name}(\#{args.join(", ")}) { \#{blk} }, inst = \#{inst.inspect}" meth = RDL::Wrap.resolve_alias(klass, #{meth.inspect}) RDL::Typecheck.typecheck(klass, meth) if RDL::Globals.info.get(klass, meth, :typecheck) == :call pres = RDL::Globals.info.get(klass, meth, :pre) RDL::Contract::AndContract.check_array(pres, self, *args, &blk) if pres types = RDL::Globals.info.get(klass, meth, :type) if types matches, args, blk, bind = RDL::Type::MethodType.check_arg_types("#{full_method_name}", self, bind, types, inst, *args, &blk) end } ret = send(#{meth_old.inspect}, *args, &blk) RDL::Globals.wrap_switch.off { posts = RDL::Globals.info.get(klass, meth, :post) RDL::Contract::AndContract.check_array(posts, self, ret, *args, &blk) if posts if matches ret = RDL::Type::MethodType.check_ret_types(self, "#{full_method_name}", types, inst, matches, ret, bind, *args, &blk) end if RDL::Config.instance.guess_types.include?("#{klass_str_without_singleton}".to_sym) RDL::Globals.info.add(klass, meth, :otype, { args: (args.map { |arg| arg.class }), ret: ret.class, block: block_given? }) end return ret } end if (public_method_defined? meth_old) then public meth elsif (protected_method_defined? meth_old) then protected meth elsif (private_method_defined? meth_old) then private meth end RUBY } end |
.wrapped?(klass, meth) ⇒ Boolean
2 3 4 |
# File 'lib/rdl/wrap.rb', line 2 def self.wrapped?(klass, meth) RDL::Util.method_defined?(klass, wrapped_name(klass, meth)) end |