@@ -50,14 +50,20 @@ def call(args)
5050
5151 module TypeChecker
5252 def get_type ( value )
53- case value
54- when String then STRING_TYPE
55- when true , false then BOOLEAN_TYPE
56- when nil then NULL_TYPE
57- when Numeric then NUMBER_TYPE
58- when Hash , Struct then OBJECT_TYPE
59- when Array then ARRAY_TYPE
60- when Expression then EXPRESSION_TYPE
53+ if value . respond_to? ( :to_str )
54+ STRING_TYPE
55+ elsif value == true || value == false
56+ BOOLEAN_TYPE
57+ elsif value == nil
58+ NULL_TYPE
59+ elsif value . is_a? ( Numeric )
60+ NUMBER_TYPE
61+ elsif value . respond_to? ( :to_hash ) || value . is_a? ( Struct )
62+ OBJECT_TYPE
63+ elsif value . respond_to? ( :to_ary )
64+ ARRAY_TYPE
65+ elsif value . is_a? ( Expression )
66+ EXPRESSION_TYPE
6167 end
6268 end
6369
@@ -106,7 +112,8 @@ def call(args)
106112 else
107113 return maybe_raise Errors ::InvalidArityError , "function avg() expects one argument"
108114 end
109- if Array === values
115+ if values . respond_to? ( :to_ary )
116+ values = values . to_ary
110117 return nil if values . empty?
111118 values . inject ( 0 ) do |total , n |
112119 if Numeric === n
@@ -145,8 +152,10 @@ def call(args)
145152 if args . count == 2
146153 haystack = args [ 0 ]
147154 needle = args [ 1 ]
148- if String === haystack || Array === haystack
149- haystack . include? ( needle )
155+ if haystack . respond_to? ( :to_str )
156+ haystack . to_str . include? ( needle )
157+ elsif haystack . respond_to? ( :to_ary )
158+ haystack . to_ary . include? ( needle )
150159 else
151160 return maybe_raise Errors ::InvalidTypeError , "contains expects 2nd arg to be a list"
152161 end
@@ -182,9 +191,10 @@ def call(args)
182191 else
183192 return maybe_raise Errors ::InvalidArityError , "function length() expects one argument"
184193 end
185- case value
186- when Hash , Array , String then value . size
187- else return maybe_raise Errors ::InvalidTypeError , "function length() expects string, array or object"
194+ if value . respond_to? ( :to_hash ) || value . respond_to? ( :to_ary ) || value . respond_to? ( :to_str )
195+ value . size
196+ else
197+ return maybe_raise Errors ::InvalidTypeError , "function length() expects string, array or object"
188198 end
189199 end
190200 end
@@ -202,8 +212,8 @@ def call(args)
202212 else
203213 return maybe_raise Errors ::InvalidTypeError , "function map() expects the first argument to be an expression"
204214 end
205- if Array === args [ 1 ]
206- list = args [ 1 ]
215+ if args [ 1 ] . respond_to? ( :to_ary )
216+ list = args [ 1 ] . to_ary
207217 else
208218 return maybe_raise Errors ::InvalidTypeError , "function map() expects the second argument to be an list"
209219 end
@@ -223,7 +233,8 @@ def call(args)
223233 else
224234 return maybe_raise Errors ::InvalidArityError , "function max() expects one argument"
225235 end
226- if Array === values
236+ if values . respond_to? ( :to_ary )
237+ values = values . to_ary
227238 return nil if values . empty?
228239 first = values . first
229240 first_type = get_type ( first )
@@ -258,7 +269,8 @@ def call(args)
258269 else
259270 return maybe_raise Errors ::InvalidArityError , "function min() expects one argument"
260271 end
261- if Array === values
272+ if values . respond_to? ( :to_ary )
273+ values = values . to_ary
262274 return nil if values . empty?
263275 first = values . first
264276 first_type = get_type ( first )
@@ -302,12 +314,10 @@ class KeysFunction < Function
302314 def call ( args )
303315 if args . count == 1
304316 value = args . first
305- if hash_like? ( value )
306- case value
307- when Hash then value . keys . map ( &:to_s )
308- when Struct then value . members . map ( &:to_s )
309- else raise NotImplementedError
310- end
317+ if value . respond_to? ( :to_hash )
318+ value . to_hash . keys . map ( &:to_s )
319+ elsif value . is_a? ( Struct )
320+ value . members . map ( &:to_s )
311321 else
312322 return maybe_raise Errors ::InvalidTypeError , "function keys() expects a hash"
313323 end
@@ -323,10 +333,12 @@ class ValuesFunction < Function
323333 def call ( args )
324334 if args . count == 1
325335 value = args . first
326- if hash_like? ( value )
327- value . values
328- elsif Array === value
329- value
336+ if value . respond_to? ( :to_hash )
337+ value . to_hash . values
338+ elsif value . is_a? ( Struct )
339+ value . to_h . values
340+ elsif value . respond_to? ( :to_ary )
341+ value . to_ary
330342 else
331343 return maybe_raise Errors ::InvalidTypeError , "function values() expects an array or a hash"
332344 end
@@ -345,8 +357,8 @@ def call(args)
345357 values = args [ 1 ]
346358 if !( String === glue )
347359 return maybe_raise Errors ::InvalidTypeError , "function join() expects the first argument to be a string"
348- elsif Array === values && values . all? { |v | String === v }
349- values . join ( glue )
360+ elsif values . respond_to? ( :to_ary ) && values . to_ary . all? { |v | String === v }
361+ values . to_ary . join ( glue )
350362 else
351363 return maybe_raise Errors ::InvalidTypeError , "function join() expects values to be an array of strings"
352364 end
@@ -390,8 +402,8 @@ class SumFunction < Function
390402 FUNCTIONS [ 'sum' ] = self
391403
392404 def call ( args )
393- if args . count == 1 && Array === args . first
394- args . first . inject ( 0 ) do |sum , n |
405+ if args . count == 1 && args . first . respond_to? ( :to_ary )
406+ args . first . to_ary . inject ( 0 ) do |sum , n |
395407 if Numeric === n
396408 sum + n
397409 else
@@ -424,7 +436,8 @@ class SortFunction < Function
424436 def call ( args )
425437 if args . count == 1
426438 value = args . first
427- if Array === value
439+ if value . respond_to? ( :to_ary )
440+ value = value . to_ary
428441 # every element in the list must be of the same type
429442 array_type = get_type ( value [ 0 ] )
430443 if array_type == STRING_TYPE || array_type == NUMBER_TYPE || value . size == 0
@@ -616,7 +629,9 @@ def call(args)
616629 return maybe_raise Errors ::InvalidArityError , msg
617630 end
618631 value = args . first
619- if Array === value || String === value
632+ if value . respond_to? ( :to_ary )
633+ value . to_ary . reverse
634+ elsif String === value
620635 value . reverse
621636 else
622637 msg = "function reverse() expects an array or string"
@@ -630,7 +645,7 @@ class ToArrayFunction < Function
630645
631646 def call ( args )
632647 value = args . first
633- Array === value ? value : [ value ]
648+ value . respond_to? ( :to_ary ) ? value . to_ary : [ value ]
634649 end
635650 end
636651 end
0 commit comments