compiler_test.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. package compiler
  2. import (
  3. "fmt"
  4. "github/runnignwater/monkey/ast"
  5. "github/runnignwater/monkey/code"
  6. "github/runnignwater/monkey/lexer"
  7. "github/runnignwater/monkey/object"
  8. "github/runnignwater/monkey/parser"
  9. "testing"
  10. )
  11. type compilerTestCase struct {
  12. input string
  13. expectedConstants []interface{}
  14. expectedInstructions []code.Instructions
  15. }
  16. func TestIntegerArithmetic(t *testing.T) {
  17. tests := []compilerTestCase{
  18. {
  19. input: "1 + 2",
  20. expectedConstants: []interface{}{1, 2},
  21. expectedInstructions: []code.Instructions{
  22. code.Make(code.OpConstant, 0),
  23. code.Make(code.OpConstant, 1),
  24. code.Make(code.OpAdd),
  25. code.Make(code.OpPop),
  26. },
  27. },
  28. {
  29. input: "1;2",
  30. expectedConstants: []interface{}{1, 2},
  31. expectedInstructions: []code.Instructions{
  32. code.Make(code.OpConstant, 0),
  33. code.Make(code.OpPop),
  34. code.Make(code.OpConstant, 1),
  35. code.Make(code.OpPop),
  36. },
  37. },
  38. {
  39. input: "1 - 2",
  40. expectedConstants: []interface{}{1, 2},
  41. expectedInstructions: []code.Instructions{
  42. code.Make(code.OpConstant, 0),
  43. code.Make(code.OpConstant, 1),
  44. code.Make(code.OpSub),
  45. code.Make(code.OpPop),
  46. },
  47. },
  48. {
  49. input: "1 * 2",
  50. expectedConstants: []interface{}{1, 2},
  51. expectedInstructions: []code.Instructions{
  52. code.Make(code.OpConstant, 0),
  53. code.Make(code.OpConstant, 1),
  54. code.Make(code.OpMul),
  55. code.Make(code.OpPop),
  56. },
  57. },
  58. {
  59. input: "2 / 1",
  60. expectedConstants: []interface{}{2, 1},
  61. expectedInstructions: []code.Instructions{
  62. code.Make(code.OpConstant, 0),
  63. code.Make(code.OpConstant, 1),
  64. code.Make(code.OpDiv),
  65. code.Make(code.OpPop),
  66. },
  67. },
  68. {
  69. input: "5 * (2 + 10)",
  70. expectedConstants: []interface{}{5, 2, 10},
  71. expectedInstructions: []code.Instructions{
  72. code.Make(code.OpConstant, 0),
  73. code.Make(code.OpConstant, 1),
  74. code.Make(code.OpConstant, 2),
  75. code.Make(code.OpAdd),
  76. code.Make(code.OpMul),
  77. code.Make(code.OpPop),
  78. },
  79. },
  80. {
  81. input: "-1",
  82. expectedConstants: []interface{}{1},
  83. expectedInstructions: []code.Instructions{
  84. code.Make(code.OpConstant, 0),
  85. code.Make(code.OpMinus),
  86. code.Make(code.OpPop),
  87. },
  88. },
  89. }
  90. runCompilerTests(t, tests)
  91. }
  92. func TestBooleanExpression(t *testing.T) {
  93. tests := []compilerTestCase{
  94. {
  95. input: "true",
  96. expectedConstants: []interface{}{},
  97. expectedInstructions: []code.Instructions{
  98. code.Make(code.OpTrue),
  99. code.Make(code.OpPop),
  100. },
  101. },
  102. {
  103. input: "false",
  104. expectedConstants: []interface{}{},
  105. expectedInstructions: []code.Instructions{
  106. code.Make(code.OpFalse),
  107. code.Make(code.OpPop),
  108. },
  109. },
  110. {
  111. input: "1 > 2",
  112. expectedConstants: []interface{}{1, 2},
  113. expectedInstructions: []code.Instructions{
  114. code.Make(code.OpConstant, 0),
  115. code.Make(code.OpConstant, 1),
  116. code.Make(code.OpGreaterThan),
  117. code.Make(code.OpPop),
  118. },
  119. },
  120. {
  121. input: "1 < 2",
  122. expectedConstants: []interface{}{2, 1},
  123. expectedInstructions: []code.Instructions{
  124. code.Make(code.OpConstant, 0),
  125. code.Make(code.OpConstant, 1),
  126. code.Make(code.OpGreaterThan),
  127. code.Make(code.OpPop),
  128. },
  129. },
  130. {
  131. input: "1 == 2",
  132. expectedConstants: []interface{}{1, 2},
  133. expectedInstructions: []code.Instructions{
  134. code.Make(code.OpConstant, 0),
  135. code.Make(code.OpConstant, 1),
  136. code.Make(code.OpEqual),
  137. code.Make(code.OpPop),
  138. },
  139. },
  140. {
  141. input: "1 != 2",
  142. expectedConstants: []interface{}{1, 2},
  143. expectedInstructions: []code.Instructions{
  144. code.Make(code.OpConstant, 0),
  145. code.Make(code.OpConstant, 1),
  146. code.Make(code.OpNotEqual),
  147. code.Make(code.OpPop),
  148. },
  149. },
  150. {
  151. input: "true == false",
  152. expectedConstants: []interface{}{},
  153. expectedInstructions: []code.Instructions{
  154. code.Make(code.OpTrue),
  155. code.Make(code.OpFalse),
  156. code.Make(code.OpEqual),
  157. code.Make(code.OpPop),
  158. },
  159. },
  160. {
  161. input: "true != false",
  162. expectedConstants: []interface{}{},
  163. expectedInstructions: []code.Instructions{
  164. code.Make(code.OpTrue),
  165. code.Make(code.OpFalse),
  166. code.Make(code.OpNotEqual),
  167. code.Make(code.OpPop),
  168. },
  169. },
  170. {
  171. input: "!true",
  172. expectedConstants: []interface{}{},
  173. expectedInstructions: []code.Instructions{
  174. code.Make(code.OpTrue),
  175. code.Make(code.OpBang),
  176. code.Make(code.OpPop),
  177. },
  178. },
  179. }
  180. runCompilerTests(t, tests)
  181. }
  182. func TestConditionals(t *testing.T) {
  183. tests := []compilerTestCase{
  184. {
  185. input: "if (true) {10} ; 3333;",
  186. expectedConstants: []interface{}{10, 3333},
  187. expectedInstructions: []code.Instructions{
  188. // 0000
  189. code.Make(code.OpTrue),
  190. // 0001
  191. code.Make(code.OpJumpNotTruthy, 10),
  192. // 0004
  193. code.Make(code.OpConstant, 0),
  194. // 0007
  195. code.Make(code.OpJump, 11),
  196. // 0010
  197. code.Make(code.OpNull),
  198. // 0011
  199. code.Make(code.OpPop),
  200. // 0012
  201. code.Make(code.OpConstant, 1),
  202. // 0015
  203. code.Make(code.OpPop),
  204. },
  205. },
  206. {
  207. input: "if(true) {10} else {20}; 3333",
  208. expectedConstants: []interface{}{10, 20, 3333},
  209. expectedInstructions: []code.Instructions{
  210. // 0000
  211. code.Make(code.OpTrue),
  212. // 0001
  213. code.Make(code.OpJumpNotTruthy, 10),
  214. // 0004
  215. code.Make(code.OpConstant, 0),
  216. // 0007
  217. code.Make(code.OpJump, 13),
  218. // 0010
  219. code.Make(code.OpConstant, 1),
  220. // 0013
  221. code.Make(code.OpPop),
  222. // 0014
  223. code.Make(code.OpConstant, 2),
  224. // 0017
  225. code.Make(code.OpPop),
  226. },
  227. },
  228. }
  229. runCompilerTests(t, tests)
  230. }
  231. func TestGlobalLetStatements(t *testing.T) {
  232. tests := []compilerTestCase{
  233. {
  234. input: `let one = 1; let two = 2;`,
  235. expectedConstants: []interface{}{1, 2},
  236. expectedInstructions: []code.Instructions{
  237. code.Make(code.OpConstant, 0),
  238. code.Make(code.OpSetGlobal, 0),
  239. code.Make(code.OpConstant, 1),
  240. code.Make(code.OpSetGlobal, 1),
  241. },
  242. },
  243. {
  244. input: `let one = 1; one;`,
  245. expectedConstants: []interface{}{1},
  246. expectedInstructions: []code.Instructions{
  247. code.Make(code.OpConstant, 0),
  248. code.Make(code.OpSetGlobal, 0),
  249. code.Make(code.OpGetGlobal, 0),
  250. code.Make(code.OpPop),
  251. },
  252. },
  253. }
  254. runCompilerTests(t, tests)
  255. }
  256. func TestLetStatement(t *testing.T) {
  257. tests := []compilerTestCase{
  258. {
  259. input: `let num = 55; fn(){num};`,
  260. expectedConstants: []interface{}{
  261. 55,
  262. []code.Instructions{
  263. code.Make(code.OpGetGlobal, 0),
  264. code.Make(code.OpReturnValue),
  265. },
  266. },
  267. expectedInstructions: []code.Instructions{
  268. code.Make(code.OpConstant, 0),
  269. code.Make(code.OpSetGlobal, 0),
  270. code.Make(code.OpConstant, 1),
  271. code.Make(code.OpPop),
  272. },
  273. },
  274. {
  275. input: `
  276. fn () {
  277. let num = 55;
  278. num;
  279. }
  280. `,
  281. expectedConstants: []interface{}{
  282. 55,
  283. []code.Instructions{
  284. code.Make(code.OpConstant, 0),
  285. code.Make(code.OpSetLocal, 0),
  286. code.Make(code.OpGetLocal, 0),
  287. code.Make(code.OpReturnValue),
  288. },
  289. },
  290. expectedInstructions: []code.Instructions{
  291. code.Make(code.OpConstant, 1),
  292. code.Make(code.OpPop),
  293. },
  294. },
  295. {
  296. input: `
  297. fn () {
  298. let a = 55;
  299. let b = 77;
  300. a + b;
  301. }
  302. `,
  303. expectedConstants: []interface{}{
  304. 55, 77,
  305. []code.Instructions{
  306. code.Make(code.OpConstant, 0),
  307. code.Make(code.OpSetLocal, 0),
  308. code.Make(code.OpConstant, 1),
  309. code.Make(code.OpSetLocal, 1),
  310. code.Make(code.OpGetLocal, 0),
  311. code.Make(code.OpGetLocal, 1),
  312. code.Make(code.OpAdd),
  313. code.Make(code.OpReturnValue),
  314. },
  315. },
  316. expectedInstructions: []code.Instructions{
  317. code.Make(code.OpConstant, 2),
  318. code.Make(code.OpPop),
  319. },
  320. },
  321. }
  322. runCompilerTests(t, tests)
  323. }
  324. func TestStringExpression(t *testing.T) {
  325. tests := []compilerTestCase{
  326. {
  327. input: `"monkey"`,
  328. expectedConstants: []interface{}{"monkey"},
  329. expectedInstructions: []code.Instructions{
  330. code.Make(code.OpConstant, 0),
  331. code.Make(code.OpPop),
  332. },
  333. },
  334. {
  335. input: `"monkey" + "language"`,
  336. expectedConstants: []interface{}{"monkey", "language"},
  337. expectedInstructions: []code.Instructions{
  338. code.Make(code.OpConstant, 0),
  339. code.Make(code.OpConstant, 1),
  340. code.Make(code.OpAdd),
  341. code.Make(code.OpPop),
  342. },
  343. },
  344. }
  345. runCompilerTests(t, tests)
  346. }
  347. func TestArrayLiteral(t *testing.T) {
  348. tests := []compilerTestCase{
  349. {
  350. input: "[]",
  351. expectedConstants: []interface{}{},
  352. expectedInstructions: []code.Instructions{
  353. code.Make(code.OpArray, 0),
  354. code.Make(code.OpPop),
  355. },
  356. },
  357. {
  358. input: "[1, 2, 3]",
  359. expectedConstants: []interface{}{1, 2, 3},
  360. expectedInstructions: []code.Instructions{
  361. code.Make(code.OpConstant, 0),
  362. code.Make(code.OpConstant, 1),
  363. code.Make(code.OpConstant, 2),
  364. code.Make(code.OpArray, 3),
  365. code.Make(code.OpPop),
  366. },
  367. },
  368. {
  369. input: "[1+2, 3 - 4, 5 *6]",
  370. expectedConstants: []interface{}{1, 2, 3, 4, 5, 6},
  371. expectedInstructions: []code.Instructions{
  372. code.Make(code.OpConstant, 0),
  373. code.Make(code.OpConstant, 1),
  374. code.Make(code.OpAdd),
  375. code.Make(code.OpConstant, 2),
  376. code.Make(code.OpConstant, 3),
  377. code.Make(code.OpSub),
  378. code.Make(code.OpConstant, 4),
  379. code.Make(code.OpConstant, 5),
  380. code.Make(code.OpMul),
  381. code.Make(code.OpArray, 3),
  382. code.Make(code.OpPop),
  383. },
  384. },
  385. }
  386. runCompilerTests(t, tests)
  387. }
  388. func TestHashLiterals(t *testing.T) {
  389. tests := []compilerTestCase{
  390. {
  391. input: "{}",
  392. expectedConstants: []interface{}{},
  393. expectedInstructions: []code.Instructions{
  394. code.Make(code.OpHash, 0),
  395. code.Make(code.OpPop),
  396. },
  397. },
  398. {
  399. input: "{1:2, 3:4, 5:6}",
  400. expectedConstants: []interface{}{1, 2, 3, 4, 5, 6},
  401. expectedInstructions: []code.Instructions{
  402. code.Make(code.OpConstant, 0),
  403. code.Make(code.OpConstant, 1),
  404. code.Make(code.OpConstant, 2),
  405. code.Make(code.OpConstant, 3),
  406. code.Make(code.OpConstant, 4),
  407. code.Make(code.OpConstant, 5),
  408. code.Make(code.OpHash, 6),
  409. code.Make(code.OpPop),
  410. },
  411. },
  412. {
  413. input: "{1:2+3, 4:5*6}",
  414. expectedConstants: []interface{}{1, 2, 3, 4, 5, 6},
  415. expectedInstructions: []code.Instructions{
  416. code.Make(code.OpConstant, 0),
  417. code.Make(code.OpConstant, 1),
  418. code.Make(code.OpConstant, 2),
  419. code.Make(code.OpAdd),
  420. code.Make(code.OpConstant, 3),
  421. code.Make(code.OpConstant, 4),
  422. code.Make(code.OpConstant, 5),
  423. code.Make(code.OpMul),
  424. code.Make(code.OpHash, 4),
  425. code.Make(code.OpPop),
  426. },
  427. },
  428. }
  429. runCompilerTests(t, tests)
  430. }
  431. func TestIndexExpressions(t *testing.T) {
  432. tests := []compilerTestCase{
  433. {
  434. input: "[1,2,3][1+1]",
  435. expectedConstants: []interface{}{1, 2, 3, 1, 1},
  436. expectedInstructions: []code.Instructions{
  437. code.Make(code.OpConstant, 0),
  438. code.Make(code.OpConstant, 1),
  439. code.Make(code.OpConstant, 2),
  440. code.Make(code.OpArray, 3),
  441. code.Make(code.OpConstant, 3),
  442. code.Make(code.OpConstant, 4),
  443. code.Make(code.OpAdd),
  444. code.Make(code.OpIndex),
  445. code.Make(code.OpPop),
  446. },
  447. },
  448. {
  449. input: "{1:2}[2-1]",
  450. expectedConstants: []interface{}{1, 2, 2, 1},
  451. expectedInstructions: []code.Instructions{
  452. code.Make(code.OpConstant, 0),
  453. code.Make(code.OpConstant, 1),
  454. code.Make(code.OpHash, 2),
  455. code.Make(code.OpConstant, 2),
  456. code.Make(code.OpConstant, 3),
  457. code.Make(code.OpSub),
  458. code.Make(code.OpIndex),
  459. code.Make(code.OpPop),
  460. },
  461. },
  462. }
  463. runCompilerTests(t, tests)
  464. }
  465. func TestFunctions(t *testing.T) {
  466. tests := []compilerTestCase{
  467. {
  468. input: `fn() {return 5 + 10; }`,
  469. expectedConstants: []interface{}{
  470. 5,
  471. 10,
  472. []code.Instructions{
  473. code.Make(code.OpConstant, 0),
  474. code.Make(code.OpConstant, 1),
  475. code.Make(code.OpAdd),
  476. code.Make(code.OpReturnValue),
  477. },
  478. },
  479. expectedInstructions: []code.Instructions{
  480. code.Make(code.OpConstant, 2),
  481. code.Make(code.OpPop),
  482. },
  483. },
  484. {
  485. input: `fn(){5+10}`,
  486. expectedConstants: []interface{}{
  487. 5, 10,
  488. []code.Instructions{
  489. code.Make(code.OpConstant, 0),
  490. code.Make(code.OpConstant, 1),
  491. code.Make(code.OpAdd),
  492. code.Make(code.OpReturnValue),
  493. },
  494. },
  495. expectedInstructions: []code.Instructions{
  496. code.Make(code.OpConstant, 2),
  497. code.Make(code.OpPop),
  498. },
  499. },
  500. {
  501. input: `fn(){1;2}`,
  502. expectedConstants: []interface{}{
  503. 1, 2,
  504. []code.Instructions{
  505. code.Make(code.OpConstant, 0),
  506. code.Make(code.OpPop),
  507. code.Make(code.OpConstant, 1),
  508. code.Make(code.OpReturnValue),
  509. },
  510. },
  511. expectedInstructions: []code.Instructions{
  512. code.Make(code.OpConstant, 2),
  513. code.Make(code.OpPop),
  514. },
  515. },
  516. }
  517. runCompilerTests(t, tests)
  518. }
  519. func TestCompilerScopes(t *testing.T) {
  520. compiler := New()
  521. if compiler.scopeIndex != 0 {
  522. t.Errorf("scopeIndex wrong. got=%d, want=%d", compiler.scopeIndex, 0)
  523. }
  524. globalSymbolTable := compiler.symbolTable
  525. compiler.emit(code.OpMul)
  526. // enterScope ======================================================================================================
  527. compiler.enterScope()
  528. if compiler.scopeIndex != 1 {
  529. t.Errorf("scopeIndex wrong. got=%d, want=%d", compiler.scopeIndex, 0)
  530. }
  531. compiler.emit(code.OpSub)
  532. if len(compiler.scopes[compiler.scopeIndex].instructions) != 1 {
  533. t.Errorf("instructions length wrong. got=%d, want = 1",
  534. len(compiler.scopes[compiler.scopeIndex].instructions))
  535. }
  536. last := compiler.scopes[compiler.scopeIndex].lastInstruction
  537. if last.Opcode != code.OpSub {
  538. t.Errorf("lastInstruction.Opcde wrong. got=%d, want=%d", last.Opcode, code.OpSub)
  539. }
  540. if compiler.symbolTable.Outer != globalSymbolTable {
  541. t.Errorf("compiler did not enclose symboTable")
  542. }
  543. compiler.leaveScope()
  544. if compiler.scopeIndex != 0 {
  545. t.Errorf("scopeIndex wrong. got=%d, want=%d", compiler.scopeIndex, 0)
  546. }
  547. // leaveScope ======================================================================================================
  548. if compiler.symbolTable != globalSymbolTable {
  549. t.Errorf("compiler did not restore global symbol table")
  550. }
  551. if compiler.symbolTable.Outer != nil {
  552. t.Errorf("compiler modified global symbol table incorrectly")
  553. }
  554. compiler.emit(code.OpAdd)
  555. if len(compiler.scopes[compiler.scopeIndex].instructions) != 2 {
  556. t.Errorf("instructions length wrong. got=%d",
  557. len(compiler.scopes[compiler.scopeIndex].instructions))
  558. }
  559. last = compiler.scopes[compiler.scopeIndex].lastInstruction
  560. if last.Opcode != code.OpAdd {
  561. t.Errorf("lastInstruction.Opcode wrong. got=%d, want=%d", last.Opcode, code.OpAdd)
  562. }
  563. previous := compiler.scopes[compiler.scopeIndex].previousInstruction
  564. if previous.Opcode != code.OpMul {
  565. t.Errorf("previousInstruction.Opcode wrong. got=%d, want=%d", previous.Opcode, code.OpMul)
  566. }
  567. }
  568. func TestFunctionWithoutReturnValue(t *testing.T) {
  569. tests := []compilerTestCase{
  570. {input: `fn() {}`,
  571. expectedConstants: []interface{}{
  572. []code.Instructions{code.Make(code.OpReturn)},
  573. },
  574. expectedInstructions: []code.Instructions{
  575. code.Make(code.OpConstant, 0),
  576. code.Make(code.OpPop),
  577. },
  578. },
  579. }
  580. runCompilerTests(t, tests)
  581. }
  582. func TestFunctionCalls(t *testing.T) {
  583. tests := []compilerTestCase{
  584. {
  585. input: `fn () { 24 } ()`,
  586. expectedConstants: []interface{}{
  587. 24,
  588. []code.Instructions{
  589. code.Make(code.OpConstant, 0), // The literal "24"
  590. code.Make(code.OpReturnValue),
  591. },
  592. },
  593. expectedInstructions: []code.Instructions{
  594. code.Make(code.OpConstant, 1), // The compiled function
  595. code.Make(code.OpCall),
  596. code.Make(code.OpPop),
  597. },
  598. },
  599. {
  600. input: `let noArg = fn(){24};noArg();`,
  601. expectedConstants: []interface{}{
  602. 24,
  603. []code.Instructions{
  604. code.Make(code.OpConstant, 0),
  605. code.Make(code.OpReturnValue)},
  606. },
  607. expectedInstructions: []code.Instructions{
  608. code.Make(code.OpConstant, 1), // The compiled function
  609. code.Make(code.OpSetGlobal, 0),
  610. code.Make(code.OpGetGlobal, 0),
  611. code.Make(code.OpCall),
  612. code.Make(code.OpPop),
  613. },
  614. },
  615. }
  616. runCompilerTests(t, tests)
  617. }
  618. func runCompilerTests(t *testing.T, tests []compilerTestCase) {
  619. t.Helper()
  620. for _, tt := range tests {
  621. program := parse(tt.input)
  622. compiler := New()
  623. err := compiler.Compile(program)
  624. if err != nil {
  625. t.Fatalf("compiler error: %s", err)
  626. }
  627. bytecode := compiler.ByteCode()
  628. err = testInstructions(tt.expectedInstructions, bytecode.Instructions)
  629. if err != nil {
  630. t.Fatalf("testInstructions failed: %s", err)
  631. }
  632. err = testConstants(t, tt.expectedConstants, bytecode.Constants)
  633. if err != nil {
  634. t.Fatalf("testConstants failed: %s", err)
  635. }
  636. }
  637. }
  638. func testConstants(
  639. t *testing.T,
  640. expected []interface{},
  641. actual []object.Object,
  642. ) error {
  643. t.Helper()
  644. if len(expected) != len(actual) {
  645. return fmt.Errorf("wrong number of constants. got=%d, want=%d", len(actual), len(expected))
  646. }
  647. for i, constant := range expected {
  648. switch constant := constant.(type) {
  649. case int:
  650. err := testIntegerObject(int64(constant), actual[i])
  651. if err != nil {
  652. return fmt.Errorf("constant %d -- testIntegerObject failed: %s",
  653. i, err)
  654. }
  655. case string:
  656. err := testStringObject(constant, actual[i])
  657. if err != nil {
  658. return fmt.Errorf("constant %d - testStringObject failed: %s", i, err)
  659. }
  660. case []code.Instructions:
  661. fn, ok := actual[i].(*object.CompileFunction)
  662. if !ok {
  663. return fmt.Errorf("constant %d -- not a function: %T", i, actual[i])
  664. }
  665. err := testInstructions(constant, fn.Instructions)
  666. if err != nil {
  667. return fmt.Errorf("constant %d -- testInstructions failed: %s", i, err)
  668. }
  669. }
  670. }
  671. return nil
  672. }
  673. func testStringObject(expected string, actual object.Object) error {
  674. result, ok := actual.(*object.String)
  675. if !ok {
  676. return fmt.Errorf("object is not String. got=%T (%+v)", actual, actual)
  677. }
  678. if result.Value != expected {
  679. return fmt.Errorf("object has wrong value. got=%s, want=%q", result.Value, expected)
  680. }
  681. return nil
  682. }
  683. func testIntegerObject(expected int64, actual object.Object) error {
  684. result, ok := actual.(*object.Integer)
  685. if !ok {
  686. return fmt.Errorf("object is not Integer. got=%T (%+v)", actual, actual)
  687. }
  688. if result.Value != expected {
  689. return fmt.Errorf("object has wrong value. got=%d, want=%d",
  690. result.Value, expected)
  691. }
  692. return nil
  693. }
  694. func testInstructions(
  695. expected []code.Instructions,
  696. actual code.Instructions,
  697. ) error {
  698. concatted := concatInstructions(expected)
  699. if len(actual) != len(concatted) {
  700. return fmt.Errorf("wrong instructions length.\nwant=%q\n got=%q", concatted, actual)
  701. }
  702. for i, ins := range concatted {
  703. if actual[i] != ins {
  704. return fmt.Errorf("wrong instructions at %d.\nwant=%q\n got=%q", i, concatted, actual)
  705. }
  706. }
  707. return nil
  708. }
  709. func concatInstructions(s []code.Instructions) code.Instructions {
  710. out := code.Instructions{}
  711. for _, ins := range s {
  712. out = append(out, ins...)
  713. }
  714. return out
  715. }
  716. func parse(input string) *ast.Program {
  717. l := lexer.New(input)
  718. p := parser.New(l)
  719. return p.ParseProgram()
  720. }