Chervil is a toy Lisp interpreter written in Ruby
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

core.rb 2.0KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  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. ::Chervil::Error.new("Expected #{expected_count} arguments but received #{args.size}")
  33. else
  34. nil
  35. end
  36. end
  37. CORE = {
  38. "+" => Proc.new { |args| type_check(args, Float) || args.inject(:+) },
  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| compare_pairs(args, :==) },
  43. "<" => Proc.new { |args| type_check(args, Float) || 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. "and" => Proc.new { |args| !(args.include?(false)) },
  48. "or" => Proc.new { |args| args.any? { |arg| !!arg == true } },
  49. "not" => Proc.new { |args| arity_check(args, 1) || args.first == false ? true : false },
  50. }
  51. end
  52. end