module Chervil RSpec.describe Core do it 'does arithmetic' do expect(Core::CORE['+'].call([1.0, 2.0])).to eq(3.0) expect(Core::CORE['-'].call([3.0, 1.0])).to eq(2.0) expect(Core::CORE['*'].call([2.0, 3.0])).to eq(6.0) expect(Core::CORE['/'].call([6.0, 2.0])).to eq(3.0) end it 'compares values' do expect(Core::CORE['='].call([1.0, 2.0])).to eq(false) expect(Core::CORE['='].call([1.0, 1.0])).to eq(true) expect(Core::CORE['<'].call([2.0, 1.0])).to eq(false) expect(Core::CORE['<'].call([2.0, 3.0])).to eq(true) expect(Core::CORE['>'].call([2.0, 1.0])).to eq(true) expect(Core::CORE['>'].call([2.0, 3.0])).to eq(false) expect(Core::CORE['<='].call([2.0, 1.0])).to eq(false) expect(Core::CORE['<='].call([2.0, 2.0])).to eq(true) expect(Core::CORE['>='].call([2.0, 2.0])).to eq(true) expect(Core::CORE['>='].call([2.0, 3.0])).to eq(false) expect(Core::CORE['and'].call([2.0, 3.0])).to eq(true) expect(Core::CORE['and'].call([2.0, 3.0, false])).to eq(false) expect(Core::CORE['or'].call([2.0, 3.0, false])).to eq(true) expect(Core::CORE['or'].call([false, false])).to eq(false) expect(Core::CORE['not'].call([1.0])).to eq(false) expect(Core::CORE['not'].call([false])).to eq(true) end it 'returns an error if argument has the wrong type' do expect(Core::CORE['+'].call([1.0, "hello"])).to eq( Error.new("Expected an argument of type number but got string") ) end it 'returns an error if given the wrong number of arguments' do expect(Core::CORE['not'].call([1.0, 2.0])).to eq( Error.new("Expected 1 argument but received 2") ) end it 'can do car and cdr' do expect(Core::CORE['car'].call([[1, 2, 3]])).to eq(1) expect(Core::CORE['cdr'].call([[1, 2, 3]])).to eq([2, 3]) expect(Core::CORE['car'].call([1.0])).to eq( Error.new("Expected an argument of type list but got number") ) expect(Core::CORE['cdr'].call([1.0])).to eq( Error.new("Expected an argument of type list but got number") ) expect(Core::CORE['car'].call([[1, 2, 3], [4, 5, 6]])).to eq( Error.new("Expected 1 argument but received 2") ) expect(Core::CORE['cdr'].call([[1, 2, 3], [4, 5, 6]])).to eq( Error.new("Expected 1 argument but received 2") ) expect(Core::CORE['car'].call([Array.new])).to eq( Error.new("`car` expects a non-empty list") ) end it 'implements cons' do expect(Core::CORE['cons'].call([1.0, [2.0, 3.0]])).to eq( [1.0, 2.0, 3.0] ) end it 'implements map' do env = Env.new Core.eval("(define (plus-one x) (+ x 1))", env) expect(Core.eval("(map plus-one '(1 2 3))", env)).to eq( [2.0, 3.0, 4.0] ) end end end