Runtime assertions for Ruby literal.fun
ruby
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 189 lines 4.4 kB view raw
1# frozen_string_literal: true 2 3require "zeitwerk" 4require_relative "literal/version" 5 6module Literal 7 Loader = Zeitwerk::Loader.for_gem.tap do |loader| 8 loader.ignore("#{__dir__}/literal/rails") 9 loader.ignore("#{__dir__}/literal/railtie.rb") 10 loader.ignore("#{__dir__}/ruby_lsp") 11 12 loader.inflector.inflect( 13 "json_data_type" => "JSONDataType" 14 ) 15 16 loader.collapse("#{__dir__}/literal/flags") 17 loader.collapse("#{__dir__}/literal/errors") 18 loader.collapse("#{__dir__}/literal/serializers") 19 20 loader.setup 21 end 22 23 def self.Value(*args, **kwargs, &block) 24 value_class = Class.new(Literal::Value) 25 26 type = Literal::Types._Constraint(*args, **kwargs) 27 value_class.define_method(:__type__) { type } 28 29 if subtype?(type, Integer) 30 value_class.alias_method :to_i, :value 31 elsif subtype?(type, String) 32 value_class.alias_method :to_s, :value 33 value_class.alias_method :to_str, :value 34 elsif subtype?(type, Array) 35 value_class.alias_method :to_a, :value 36 value_class.alias_method :to_ary, :value 37 elsif subtype?(type, Hash) 38 value_class.alias_method :to_h, :value 39 elsif subtype?(type, Float) 40 value_class.alias_method :to_f, :value 41 elsif subtype?(type, Set) 42 value_class.alias_method :to_set, :value 43 end 44 45 value_class.class_eval(&block) if block 46 value_class.freeze 47 end 48 49 def self.Delegator(*args, **kwargs, &block) 50 delegator_class = Class.new(Literal::Delegator) 51 52 type = Literal::Types._Constraint(*args, **kwargs) 53 delegator_class.define_method(:__type__) { type } 54 55 delegator_class.class_eval(&block) if block 56 delegator_class.freeze 57 end 58 59 def self.Enum(type) 60 Class.new(Literal::Enum) do 61 prop :value, type, :positional, reader: :public 62 end 63 end 64 65 def self.Array(type) 66 Literal::Array::Generic.new(type) 67 end 68 69 def self.Set(type) 70 Literal::Set::Generic.new(type) 71 end 72 73 def self.Hash(key_type, value_type) 74 Literal::Hash::Generic.new(key_type, value_type) 75 end 76 77 def self.Tuple(*types) 78 Literal::Tuple::Generic.new(*types) 79 end 80 81 def self.Brand(...) 82 Literal::Brand.new(...) 83 end 84 85 def self.Result(success_type, failure_type, &) 86 result_type = Result::Generic.new(success_type, failure_type) 87 88 if block_given? 89 result_type.try(&) 90 else 91 result_type 92 end 93 end 94 95 def self.Success(type) 96 Success::Generic.new(type) 97 end 98 99 def self.Failure(type) 100 Failure::Generic.new(type) 101 end 102 103 def self.check(value, type) 104 if type === value 105 true 106 else 107 context = Literal::TypeError::Context.new(expected: type, actual: value) 108 type.record_literal_type_errors(context) if type.respond_to?(:record_literal_type_errors) 109 yield context if block_given? 110 raise Literal::TypeError.new(context:) 111 end 112 end 113 114 def self.subtype?(type, supertype, context: nil) 115 context ||= SubtypeContext.new 116 raw_key = [type.object_id, supertype.object_id] 117 raw_acquired = false 118 resolved_key = nil 119 resolved_acquired = false 120 121 return context.fetch(raw_key) if context.memoized?(raw_key) 122 return false unless context.acquire(raw_key) 123 124 raw_acquired = true 125 126 subtype = type 127 128 subtype = subtype.block.call if Types::DeferredType === subtype 129 supertype = supertype.block.call if Types::DeferredType === supertype 130 resolved_key = [subtype.object_id, supertype.object_id] 131 132 if resolved_key != raw_key 133 if context.memoized?(resolved_key) 134 result = context.fetch(resolved_key) 135 context.store(raw_key, result) 136 return result 137 end 138 139 return false unless context.acquire(resolved_key) 140 141 resolved_acquired = true 142 end 143 144 result = if subtype == Types::NeverType::Instance 145 true 146 elsif supertype == subtype 147 true 148 else 149 case supertype 150 when Literal::Type 151 supertype.>=(subtype, context:) 152 when Module 153 case subtype 154 when Module 155 supertype >= subtype 156 when Numeric 157 Numeric >= supertype 158 when String 159 String >= supertype 160 when Symbol 161 Symbol >= supertype 162 when ::Array 163 ::Array >= supertype 164 when ::Hash 165 ::Hash >= supertype 166 when Literal::Type 167 subtype.<=(supertype, context:) 168 else 169 false 170 end 171 when Range 172 supertype.cover?(subtype) 173 else 174 false 175 end 176 end 177 178 context.store(resolved_key, result) 179 context.store(raw_key, result) 180 result 181 ensure 182 if context 183 context.release(resolved_key) if resolved_acquired 184 context.release(raw_key) if raw_acquired 185 end 186 end 187end 188 189require_relative "literal/railtie" if defined?(Rails)