Chervil is a toy Lisp interpreter written in Ruby
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

core.rb 2.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. module Chervil
  2. module Core
  3. def self.compare_pairs(ary, method)
  4. pairs = Array.new
  5. ary.each_with_index do |el, i|
  6. unless ary[i + 1].nil?
  7. pairs.push([el, ary[i + 1]])
  8. end
  9. end
  10. !(pairs.map { |pair| pair[0].send(method, pair[1]) }.any?(false))
  11. end
  12. def self.display_class_name(cls)
  13. case cls.inspect
  14. when "Float"
  15. "number"
  16. when "String"
  17. "string"
  18. end
  19. end
  20. def self.type_check(args, cls)
  21. args_with_wrong_type = args.select { |arg| !arg.is_a?(cls) }
  22. if args_with_wrong_type.length.zero?
  23. nil
  24. else
  25. expected_type = display_class_name(cls)
  26. received_type = display_class_name(args_with_wrong_type.first.class)
  27. ::Chervil::Error.new("Expected an argument of type #{expected_type} but got #{received_type}")
  28. end
  29. end
  30. def self.arity_check(args, expected_count)
  31. if args.size != expected_count
  32. s = expected_count == 1 ? '' : 's'
  33. Error.new("Expected #{expected_count} argument#{s} but received #{args.size}")
  34. else
  35. nil
  36. end
  37. end
  38. CORE = {
  39. "+" => Proc.new { |args| type_check(args, Float) || args.inject(:+) },
  40. "-" => Proc.new { |args| type_check(args, Float) || args.inject(:-) },
  41. "*" => Proc.new { |args| type_check(args, Float) || args.inject(:*) },
  42. "/" => Proc.new { |args| type_check(args, Float) || args.inject(:/) },
  43. "=" => Proc.new { |args| compare_pairs(args, :==) },
  44. "<" => Proc.new { |args| type_check(args, Float) || compare_pairs(args, :<) },
  45. ">" => Proc.new { |args| type_check(args, Float) || compare_pairs(args, :>) },
  46. "<=" => Proc.new { |args| type_check(args, Float) || compare_pairs(args, :<=) },
  47. ">=" => Proc.new { |args| type_check(args, Float) || compare_pairs(args, :>=) },
  48. "and" => Proc.new { |args| !(args.include?(false)) },
  49. "or" => Proc.new { |args| args.any? { |arg| !!arg == true } },
  50. "not" => Proc.new do |args|
  51. error = arity_check(args, 1)
  52. if error.nil?
  53. args.first == false ? true : false
  54. else
  55. error
  56. end
  57. end,
  58. }
  59. end
  60. end