evaluator_test.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. package evaluator
  2. import (
  3. "github/runnignwater/monkey/lexer"
  4. "github/runnignwater/monkey/object"
  5. "github/runnignwater/monkey/parser"
  6. "log"
  7. "testing"
  8. )
  9. func TestEvalIntegerExpression(t *testing.T) {
  10. tests := []struct {
  11. input string
  12. expected int64
  13. }{
  14. {"5", 5},
  15. {"10", 10},
  16. {"-5", -5},
  17. {"-10", -10},
  18. {"5+5+5+5-10", 10},
  19. {"2*2*2*2*2", 32},
  20. {"-50+100+-50", 0},
  21. }
  22. for _, tt := range tests {
  23. evaluated := testEval(tt.input)
  24. testIntegerObject(t, evaluated, tt.expected)
  25. }
  26. }
  27. func TestEvalBooleanExpression(t *testing.T) {
  28. tests := []struct {
  29. input string
  30. expected bool
  31. }{
  32. {"true", true},
  33. {"false", false},
  34. {"1 < 2", true},
  35. {"1 > 2", false},
  36. {"1 == 1", true},
  37. {"1 != 1", false},
  38. {"1 == 2", false},
  39. {"1 != 2", true},
  40. {"true == true", true},
  41. {"false == false", true},
  42. {"(1 < 2) == true", true},
  43. }
  44. for _, tt := range tests {
  45. evaluated := testEval(tt.input)
  46. testBooleanObject(t, evaluated, tt.expected)
  47. }
  48. }
  49. func TestBangOperator(t *testing.T) {
  50. tests := []struct {
  51. input string
  52. expected bool
  53. }{
  54. {"!true", false},
  55. {"!false", true},
  56. {"!5", false},
  57. {"!!true", true},
  58. {"!!false", false},
  59. {"!!5", true},
  60. }
  61. for _, tt := range tests {
  62. evaluated := testEval(tt.input)
  63. testBooleanObject(t, evaluated, tt.expected)
  64. }
  65. }
  66. func TestIfElseExpression(t *testing.T) {
  67. tests := []struct {
  68. input string
  69. expected interface{}
  70. }{
  71. {"if (true) {10}", 10},
  72. {"if(false) {10}", nil},
  73. {"if (1) {10}", 10},
  74. {"if(1<2){10}", 10},
  75. {"if(1>2){10}", nil},
  76. {"if(1<2){10} else {20}", 10},
  77. {"if(1>2){10} else {20}", 20},
  78. }
  79. for _, tt := range tests {
  80. evaluated := testEval(tt.input)
  81. integer, ok := tt.expected.(int)
  82. if ok {
  83. testIntegerObject(t, evaluated, int64(integer))
  84. } else {
  85. testNullObject(t, evaluated)
  86. }
  87. }
  88. }
  89. func TestReturnStatements(t *testing.T) {
  90. tests := []struct {
  91. input string
  92. expected int64
  93. }{
  94. {"return 10;", 10},
  95. {"return 10;9", 10},
  96. {"return 2*5;9;", 10},
  97. {"9;return 3 *5; 9;", 15},
  98. {
  99. `if ( 10 > 1) {
  100. if( 10 > 1) {
  101. return 10;
  102. }
  103. return 1;
  104. }
  105. `,
  106. 10,
  107. },
  108. }
  109. for _, tt := range tests {
  110. evaluated := testEval(tt.input)
  111. testIntegerObject(t, evaluated, tt.expected)
  112. }
  113. }
  114. func TestErrorHandling(t *testing.T) {
  115. tests := []struct {
  116. input string
  117. expectedMsg string
  118. }{
  119. {
  120. "5 + true",
  121. "type mismatch: INTEGER + BOOLEAN",
  122. },
  123. {
  124. "5 + true; 5;",
  125. "type mismatch: INTEGER + BOOLEAN",
  126. },
  127. {
  128. "-true",
  129. "unknown operator: -BOOLEAN",
  130. },
  131. {
  132. "true + false",
  133. "unknown operator: BOOLEAN + BOOLEAN",
  134. },
  135. {
  136. "5;true + false;5",
  137. "unknown operator: BOOLEAN + BOOLEAN",
  138. },
  139. {
  140. "if ( 10 > 1) { true + false; }",
  141. "unknown operator: BOOLEAN + BOOLEAN",
  142. },
  143. {
  144. `
  145. if (10 > 1) {
  146. if (10 > 1) {
  147. return true + false;
  148. }
  149. return 1;
  150. }
  151. `,
  152. "unknown operator: BOOLEAN + BOOLEAN",
  153. },
  154. {
  155. "foobar",
  156. "identifier not found: foobar",
  157. },
  158. {
  159. `"Hello" - "World"`,
  160. "unknown operator: STRING - STRING",
  161. },
  162. }
  163. for _, tt := range tests {
  164. evaluated := testEval(tt.input)
  165. errObj, ok := evaluated.(*object.Error)
  166. if !ok {
  167. t.Errorf("no error object returned. got=%T (%+v)", evaluated, evaluated)
  168. continue
  169. }
  170. if errObj.Msg != tt.expectedMsg {
  171. t.Errorf("wrong error message. expected=%q, got=%q", tt.expectedMsg, errObj.Msg)
  172. }
  173. }
  174. }
  175. func TestLetStatement(t *testing.T) {
  176. tests := []struct {
  177. input string
  178. expected int64
  179. }{
  180. {"let a = 5;a;", 5},
  181. {"let a = 5 * 5;a;", 25},
  182. {"let a = 5;let b = a;b;", 5},
  183. {"let a = 5; let b = a;let c = a + b + 5;c;", 15},
  184. }
  185. for _, tt := range tests {
  186. testIntegerObject(t, testEval(tt.input), tt.expected)
  187. }
  188. }
  189. func TestFunctionObject(t *testing.T) {
  190. input := "fn(x) {x + 2;};"
  191. evaluated := testEval(input)
  192. fn, ok := evaluated.(*object.Function)
  193. if !ok {
  194. t.Fatalf("object is not Function. got=%T (%+v)", evaluated, evaluated)
  195. }
  196. if len(fn.Parameters) != 1 {
  197. t.Fatalf("function has wrong parameters. Parameters=%+v", fn.Parameters)
  198. }
  199. if fn.Parameters[0].String() != "x" {
  200. t.Fatalf("parameter is not 'x'. got=%q", fn.Parameters[0])
  201. }
  202. expectedBody := "(x + 2)"
  203. if fn.Body.String() != expectedBody {
  204. t.Fatalf("body is not %q. got=%q", expectedBody, fn.Body.String())
  205. }
  206. }
  207. func TestFunctionApplication(t *testing.T) {
  208. tests := []struct {
  209. input string
  210. expected int64
  211. }{
  212. {"let identity = fn(x) {x;};identity(5);", 5},
  213. {"let identify = fn(x){return x;};identify(5);", 5},
  214. {"let double = fn(x) { x * 2; };double(5);", 10},
  215. {"let add = fn(x,y){x+y;};add(5,5);", 10},
  216. {"let add = fn(x,y){x+y;};add(5+5,add(5,5));", 20},
  217. {"fn(x){x;}(5)", 5},
  218. }
  219. for _, tt := range tests {
  220. testIntegerObject(t, testEval(tt.input), tt.expected)
  221. }
  222. }
  223. // --------------------------------------------------------------------------------------------------------------------
  224. func testNullObject(t *testing.T, obj object.Object) bool {
  225. if obj != NULL {
  226. t.Errorf("object is not NULL. got=%T (%+v)", obj, obj)
  227. return false
  228. }
  229. return true
  230. }
  231. func testIntegerObject(t *testing.T, obj object.Object, expected int64) bool {
  232. result, ok := obj.(*object.Integer)
  233. if !ok {
  234. t.Errorf("object is not Integer. got=%T (%+v)", obj, obj)
  235. return false
  236. }
  237. if result.Value != expected {
  238. t.Errorf("object has wrong value. got=%d, want=%d", result.Value, expected)
  239. return false
  240. }
  241. return true
  242. }
  243. func testBooleanObject(t *testing.T, obj object.Object, expected bool) bool {
  244. result, ok := obj.(*object.Boolean)
  245. if !ok {
  246. t.Errorf("object is not Boolean. got=%T (%+v)", obj, obj)
  247. return false
  248. }
  249. if result.Value != expected {
  250. t.Errorf("object has wrong value. got=%t, want=%t", result.Value, expected)
  251. return false
  252. }
  253. return true
  254. }
  255. func testEval(input string) object.Object {
  256. l := lexer.New(input)
  257. p := parser.New(l)
  258. program := p.ParseProgram()
  259. env := object.NewEnvironment()
  260. return Eval(program, env)
  261. }
  262. func TestClosures(t *testing.T) {
  263. input := `
  264. let newAdder = fn(x) {
  265. fn (y) { x + y };
  266. };
  267. let addTwo = newAdder(2); addTwo(2);
  268. `
  269. testIntegerObject(t, testEval(input), 4)
  270. }
  271. func TestStringLiteral(t *testing.T) {
  272. input := `"Hello World!"`
  273. evaluated := testEval(input)
  274. str, ok := evaluated.(*object.String)
  275. if !ok {
  276. t.Fatalf("object is not String. got=%T (%+v)", evaluated, evaluated)
  277. }
  278. if str.Value != "Hello World!" {
  279. t.Errorf("String has wrong value. got=%q", str.Value)
  280. }
  281. }
  282. func TestStringConcatenation(t *testing.T) {
  283. input := `"Hello" + " " + "World!"`
  284. evaluated := testEval(input)
  285. str, ok := evaluated.(*object.String)
  286. if !ok {
  287. t.Fatalf("object is not String. got=%T (%+v)", evaluated, evaluated)
  288. }
  289. if str.Value != "Hello World!" {
  290. t.Errorf("String has wrong value. got=%q", str.Value)
  291. }
  292. }
  293. // ------------------------------------------------------------------------Built-in Function
  294. func TestBuiltinFunctions(t *testing.T) {
  295. tests := []struct {
  296. input string
  297. expected interface{}
  298. }{
  299. {`len("")`, 0},
  300. {`len("four")`, 4},
  301. {`len("hello world")`, 11},
  302. {`len(1)`, "argument to `len` not supported, got INTEGER"},
  303. {`len("one", "two")`, "wrong number of arguments. got=2, want=1"},
  304. }
  305. for _, tt := range tests {
  306. evaluated := testEval(tt.input)
  307. switch expected := tt.expected.(type) {
  308. case int:
  309. testIntegerObject(t, evaluated, int64(expected))
  310. case string:
  311. errObj, ok := evaluated.(*object.Error)
  312. if !ok {
  313. t.Errorf("object is not Error. got=%T (%+v)", evaluated, evaluated)
  314. }
  315. if errObj.Msg != expected {
  316. t.Errorf("wrong error message. expected=%q, got=%q", expected, errObj.Msg)
  317. }
  318. }
  319. }
  320. }
  321. func TestArrayLiterals(t *testing.T) {
  322. input := "[1, 2 * 2, 3 + 5]"
  323. evaluated := testEval(input)
  324. result, ok := evaluated.(*object.Array)
  325. if !ok {
  326. t.Fatalf("object is not Array. got=%T (%+v)", evaluated, evaluated)
  327. }
  328. if len(result.Elements) != 3 {
  329. log.Fatalf("array has wrong num of elements. got=%d",
  330. len(result.Elements))
  331. }
  332. testIntegerObject(t, result.Elements[0], 1)
  333. testIntegerObject(t, result.Elements[1], 4)
  334. testIntegerObject(t, result.Elements[2], 8)
  335. }
  336. func TestArrayIndexExpression(t *testing.T) {
  337. tests := []struct {
  338. input string
  339. expected interface{}
  340. }{
  341. {
  342. "[1, 2, 3][0]",
  343. 1,
  344. },
  345. {
  346. "[1, 2, 3][1]",
  347. 2,
  348. },
  349. {
  350. "[1, 2, 3][2]",
  351. 3,
  352. },
  353. {
  354. "let i = 0; [1][i];",
  355. 1,
  356. },
  357. {
  358. "[1, 2, 3][1 + 1]",
  359. 3,
  360. },
  361. {
  362. "let myArray = [1, 2, 3];myArray[2]",
  363. 3,
  364. },
  365. {
  366. "let myArray = [1, 2, 3];myArray[0]+myArray[1]+myArray[2]",
  367. 6,
  368. },
  369. {
  370. "let myArray = [1, 2, 3]; let i = myArray[0];myArray[i];",
  371. 2,
  372. },
  373. {
  374. "[1, 2, 3][3]",
  375. nil,
  376. },
  377. {
  378. "[1, 2, 3][-1]",
  379. nil,
  380. },
  381. }
  382. for _, tt := range tests {
  383. evaluated := testEval(tt.input)
  384. integer, ok := tt.expected.(int)
  385. if ok {
  386. testIntegerObject(t, evaluated, int64(integer))
  387. } else {
  388. testNullObject(t, evaluated)
  389. }
  390. }
  391. }
  392. func TestHashLiterals(t *testing.T) {
  393. input := `let two = "two";
  394. {
  395. "one" : 10 -9,
  396. "two" : 1 + 1,
  397. "thr"+"ee" : 6 / 2,
  398. 4 : 4,
  399. true: 5,
  400. false :6
  401. }
  402. `
  403. evaluated := testEval(input)
  404. result, ok := evaluated.(*object.Hash)
  405. if !ok {
  406. t.Fatalf("Eval didn't return Hash. got=%T (%+v)", evaluated, evaluated)
  407. }
  408. expected := map[object.HashKey]int64{
  409. (&object.String{Value: "one"}).HashKey(): 1,
  410. (&object.String{Value: "two"}).HashKey(): 2,
  411. (&object.String{Value: "three"}).HashKey(): 3,
  412. (&object.Integer{Value: 4}).HashKey(): 4,
  413. TRUE.HashKey(): 5,
  414. FALSE.HashKey(): 6,
  415. }
  416. if len(result.Pairs) != len(expected) {
  417. t.Fatalf("Hash has wrong num of pairs. got=%d", len(result.Pairs))
  418. }
  419. for expectedKey, expectedValue := range expected {
  420. pair, ok := result.Pairs[expectedKey]
  421. if !ok {
  422. t.Errorf("no pair for given key in Pairs")
  423. }
  424. testIntegerObject(t, pair.Value, expectedValue)
  425. }
  426. }