Chervil is a toy Lisp interpreter written in Ruby
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

core_spec.rb 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. module Chervil
  2. RSpec.describe Core do
  3. it 'does arithmetic' do
  4. expect(Core::CORE['+'].call([1.0, 2.0])).to eq(3.0)
  5. expect(Core::CORE['-'].call([3.0, 1.0])).to eq(2.0)
  6. expect(Core::CORE['*'].call([2.0, 3.0])).to eq(6.0)
  7. expect(Core::CORE['/'].call([6.0, 2.0])).to eq(3.0)
  8. end
  9. it 'compares values' do
  10. expect(Core::CORE['='].call([1.0, 2.0])).to eq(false)
  11. expect(Core::CORE['='].call([1.0, 1.0])).to eq(true)
  12. expect(Core::CORE['<'].call([2.0, 1.0])).to eq(false)
  13. expect(Core::CORE['<'].call([2.0, 3.0])).to eq(true)
  14. expect(Core::CORE['>'].call([2.0, 1.0])).to eq(true)
  15. expect(Core::CORE['>'].call([2.0, 3.0])).to eq(false)
  16. expect(Core::CORE['<='].call([2.0, 1.0])).to eq(false)
  17. expect(Core::CORE['<='].call([2.0, 2.0])).to eq(true)
  18. expect(Core::CORE['>='].call([2.0, 2.0])).to eq(true)
  19. expect(Core::CORE['>='].call([2.0, 3.0])).to eq(false)
  20. expect(Core::CORE['and'].call([2.0, 3.0])).to eq(true)
  21. expect(Core::CORE['and'].call([2.0, 3.0, false])).to eq(false)
  22. expect(Core::CORE['or'].call([2.0, 3.0, false])).to eq(true)
  23. expect(Core::CORE['or'].call([false, false])).to eq(false)
  24. expect(Core::CORE['not'].call([1.0])).to eq(false)
  25. expect(Core::CORE['not'].call([false])).to eq(true)
  26. end
  27. it 'returns an error if argument has the wrong type' do
  28. expect(Core::CORE['+'].call([1.0, "hello"])).to eq(
  29. Error.new("Expected an argument of type number but got string")
  30. )
  31. end
  32. it 'returns an error if given the wrong number of arguments' do
  33. expect(Core::CORE['not'].call([1.0, 2.0])).to eq(
  34. Error.new("Expected 1 argument but received 2")
  35. )
  36. end
  37. it 'can do car and cdr' do
  38. expect(Core::CORE['car'].call([[1, 2, 3]])).to eq(1)
  39. expect(Core::CORE['cdr'].call([[1, 2, 3]])).to eq([2, 3])
  40. expect(Core::CORE['car'].call([1.0])).to eq(
  41. Error.new("Expected an argument of type list but got number")
  42. )
  43. expect(Core::CORE['cdr'].call([1.0])).to eq(
  44. Error.new("Expected an argument of type list but got number")
  45. )
  46. expect(Core::CORE['car'].call([[1, 2, 3], [4, 5, 6]])).to eq(
  47. Error.new("Expected 1 argument but received 2")
  48. )
  49. expect(Core::CORE['cdr'].call([[1, 2, 3], [4, 5, 6]])).to eq(
  50. Error.new("Expected 1 argument but received 2")
  51. )
  52. expect(Core::CORE['car'].call([Array.new])).to eq(
  53. Error.new("`car` expects a non-empty list")
  54. )
  55. end
  56. it 'implements cons' do
  57. expect(Core::CORE['cons'].call([1.0, [2.0, 3.0]])).to eq(
  58. [1.0, 2.0, 3.0]
  59. )
  60. end
  61. it 'implements map' do
  62. env = Env.new
  63. Core.eval("(define (plus-one x) (+ x 1))", env)
  64. expect(Core.eval("(map plus-one '(1 2 3))", env)).to eq(
  65. [2.0, 3.0, 4.0]
  66. )
  67. end
  68. end
  69. end