module TypedRb::Runtime::Normalization
Public Instance Methods
build_class_methods_info(klass, all_instance_methods, all_methods)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 104 def build_class_methods_info(klass, all_instance_methods, all_methods) { :class => klass, :instance_methods => all_instance_methods, :all_methods => all_methods } end
build_generic_singleton_object(type_info)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 39 def build_generic_singleton_object(type_info) type_class, info = type_info TypedRb.log(binding, :debug, "Normalising generic type: #{type_class}") info[:type] = Class.for_name(type_class) info[:parameters] = info[:parameters].map do |parameter| ::TypedRb::Runtime::TypeParser.parse(parameter, info[:type]) end ::TypedRb::Types::TyGenericSingletonObject.new(info[:type], info[:parameters]) end
build_generic_super_type(type, super_type)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 56 def build_generic_super_type(type, super_type) valid_super_type?(type, super_type) TypedRb.log(binding, :debug, "Normalising generic super type: #{super_type[:type]} for #{type}") build_generic_singleton_object([super_type[:type], super_type]) end
check_generic_super_type(type_info)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 49 def check_generic_super_type(type_info) _, info = type_info @generic_types_registry[info[:type]].super_type = (info[:super_type] || []).map do |super_type_spec| build_generic_super_type(info[:type], super_type_spec) end end
check_super_type_annotations()
click to toggle source
# File lib/typed/runtime/normalization.rb, line 29 def check_super_type_annotations @generic_types_registry.values.each do |type| if type.super_type type.super_type.each do |super_type| super_type.self_materialize end end end end
collect_methods(object, options)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 81 def collect_methods(object, options) messages = if options[:instance] [:public_instance_methods, :protected_instance_methods, :private_instance_methods] else [:public_methods, :protected_methods, :private_methods] end messages.inject([]) do |acc, message| acc + object.send(message) end end
compute_parameters_info(method_type, klass, method, normalized_method, signature)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 139 def compute_parameters_info(method_type, klass, method, normalized_method, signature) return if method_type == :instance_variable || method_type == :class_variable ruby_params = if method_type == :instance if klass == :main TOPLEVEL_BINDING.receiver.method(method).parameters else klass.instance_method(method).parameters end else if klass == :main TOPLEVEL_BINDING.receiver.class.method(method).parameters else klass.method(method).parameters end end ruby_params_clean = ruby_params.reject { |(kind, _)| kind == :block } min, max = ruby_params_clean.each_with_object([0, 0]) do |(kind, _), acc| acc[1] += 1 acc[1] = Float::INFINITY if kind == :rest acc[0] += 1 if kind == :req end signature_clean = signature.reject { |acc| acc.is_a?(Hash) && acc[:kind] == :block_arg } if signature_clean.count < min || signature_clean.count > max fail ::TypedRb::Types::TypeParsingError, "Type signature declaration for method '#{klass}.#{method}': '#{signature_clean}' inconsistent with method parameters #{ruby_params.inspect}" end count = 0 parameters_info = signature_clean.map do |signature_value| type, name = if count > ruby_params_clean.count ruby_params_clean.last else ruby_params_clean[count] end count += 1 if signature_value.is_a?(Hash) && signature_value[:kind] == :rest [:rest, name] elsif type == :rest [:opt, name] else [type, name] end end normalized_method.parameters_info = parameters_info end
find_methods(klass)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 76 def find_methods(klass) return find_methods_for_top_level_object if klass == :main find_methods_for_class(klass) end
find_methods_for_class(klass)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 98 def find_methods_for_class(klass) all_instance_methods = collect_methods(klass, instance: true) all_methods = collect_methods(klass, instance: false) build_class_methods_info(klass, all_instance_methods, all_methods) end
find_methods_for_top_level_object()
click to toggle source
# File lib/typed/runtime/normalization.rb, line 92 def find_methods_for_top_level_object all_instance_methods = collect_methods(TOPLEVEL_BINDING, instance: false) all_methods = collect_methods(TOPLEVEL_BINDING.receiver.class, instance: false) build_class_methods_info(:main, all_instance_methods, all_methods) end
normalize_generic_types!()
click to toggle source
# File lib/typed/runtime/normalization.rb, line 7 def normalize_generic_types! initial_value = @generic_types_registry || Hash.call(Class, TypedRb::Types::TyGenericSingletonObject).new @generic_types_registry = generic_types_parser_registry.each_with_object(initial_value) do |type_info, acc| generic_singleton_object = build_generic_singleton_object(type_info) acc[generic_singleton_object.ruby_type] = generic_singleton_object end generic_types_parser_registry.each do |type_info| check_generic_super_type(type_info) end end
normalize_method_signatures(method_signatures, klass, method_type)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 118 def normalize_method_signatures(method_signatures, klass, method_type) method_signatures.each_with_object({}) do |method_info, signatures_acc| method, signatures = method_info validate_method(find_methods(klass), klass, method, method_type) normalized_signatures = signatures.map do |signature| validate_function_signature(klass, method, signature, method_type) normalized_method = normalize_signature!(klass, signature) validate_signature(method_type, normalized_method) compute_parameters_info(method_type, klass, method, normalized_method, signature) normalized_method end if method_type == :instance_variable || method_type == :class_variable # TODO: print a warning if the declaration of the variable is duplicated signatures_acc[method] = normalized_signatures.first else validate_signatures(normalized_signatures, klass, method) signatures_acc[method] = normalized_signatures.sort { |fa, fb| fa.arity <=> fb.arity } end end end
normalize_methods!()
click to toggle source
# File lib/typed/runtime/normalization.rb, line 19 def normalize_methods! @registry = @registry || {} parser_registry.each_pair do |object_key, method_signatures| method_type, class_name = parse_object_key(object_key) klass = parse_class(class_name) @registry[[method_type, klass]] = normalize_method_signatures(method_signatures, klass, method_type) end end
normalize_signature!(klass, type)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 113 def normalize_signature!(klass, type) normalized_signature = ::TypedRb::Runtime::TypeParser.parse(type, klass) ::TypedRb::Model::TmFun.with_fresh_bindings(klass, normalized_signature) end
object_key(kind, receiver)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 189 def object_key(kind, receiver) "#{kind}|#{receiver}" end
parse_class(class_name)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 71 def parse_class(class_name) return :main if class_name == :main Class.for_name(class_name.to_s) end
parse_object_key(object_key)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 194 def parse_object_key(object_key) object_key.split('|').map(&:to_sym) end
valid_super_type?(base_class, super_type_info)
click to toggle source
# File lib/typed/runtime/normalization.rb, line 62 def valid_super_type?(base_class, super_type_info) return false if super_type_info.nil? valid = base_class.ancestors.map(&:name).detect { |klass_name| klass_name == super_type_info[:type].to_s } valid = valid || base_class.meta_ancestors.map(&:name).detect { |klass_name| klass_name == super_type_info[:type].to_s } return true if valid fail ::TypedRb::Types::TypeParsingError, "Super type annotation '#{super_type_info[:type]}' not a super class of '#{base_class}'" end