compiler_test.go 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480
  1. package tengo_test
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "path/filepath"
  6. "strings"
  7. "testing"
  8. "github.com/d5/tengo/v2"
  9. "github.com/d5/tengo/v2/parser"
  10. "github.com/d5/tengo/v2/require"
  11. "github.com/d5/tengo/v2/stdlib"
  12. )
  13. func TestCompiler_Compile(t *testing.T) {
  14. expectCompile(t, `1 + 2`,
  15. bytecode(
  16. concatInsts(
  17. tengo.MakeInstruction(parser.OpConstant, 0),
  18. tengo.MakeInstruction(parser.OpConstant, 1),
  19. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  20. tengo.MakeInstruction(parser.OpPop),
  21. tengo.MakeInstruction(parser.OpSuspend)),
  22. objectsArray(
  23. intObject(1),
  24. intObject(2))))
  25. expectCompile(t, `1; 2`,
  26. bytecode(
  27. concatInsts(
  28. tengo.MakeInstruction(parser.OpConstant, 0),
  29. tengo.MakeInstruction(parser.OpPop),
  30. tengo.MakeInstruction(parser.OpConstant, 1),
  31. tengo.MakeInstruction(parser.OpPop),
  32. tengo.MakeInstruction(parser.OpSuspend)),
  33. objectsArray(
  34. intObject(1),
  35. intObject(2))))
  36. expectCompile(t, `1 - 2`,
  37. bytecode(
  38. concatInsts(
  39. tengo.MakeInstruction(parser.OpConstant, 0),
  40. tengo.MakeInstruction(parser.OpConstant, 1),
  41. tengo.MakeInstruction(parser.OpBinaryOp, 12),
  42. tengo.MakeInstruction(parser.OpPop),
  43. tengo.MakeInstruction(parser.OpSuspend)),
  44. objectsArray(
  45. intObject(1),
  46. intObject(2))))
  47. expectCompile(t, `1 * 2`,
  48. bytecode(
  49. concatInsts(
  50. tengo.MakeInstruction(parser.OpConstant, 0),
  51. tengo.MakeInstruction(parser.OpConstant, 1),
  52. tengo.MakeInstruction(parser.OpBinaryOp, 13),
  53. tengo.MakeInstruction(parser.OpPop),
  54. tengo.MakeInstruction(parser.OpSuspend)),
  55. objectsArray(
  56. intObject(1),
  57. intObject(2))))
  58. expectCompile(t, `2 / 1`,
  59. bytecode(
  60. concatInsts(
  61. tengo.MakeInstruction(parser.OpConstant, 0),
  62. tengo.MakeInstruction(parser.OpConstant, 1),
  63. tengo.MakeInstruction(parser.OpBinaryOp, 14),
  64. tengo.MakeInstruction(parser.OpPop),
  65. tengo.MakeInstruction(parser.OpSuspend)),
  66. objectsArray(
  67. intObject(2),
  68. intObject(1))))
  69. expectCompile(t, `true`,
  70. bytecode(
  71. concatInsts(
  72. tengo.MakeInstruction(parser.OpTrue),
  73. tengo.MakeInstruction(parser.OpPop),
  74. tengo.MakeInstruction(parser.OpSuspend)),
  75. objectsArray()))
  76. expectCompile(t, `false`,
  77. bytecode(
  78. concatInsts(
  79. tengo.MakeInstruction(parser.OpFalse),
  80. tengo.MakeInstruction(parser.OpPop),
  81. tengo.MakeInstruction(parser.OpSuspend)),
  82. objectsArray()))
  83. expectCompile(t, `1 > 2`,
  84. bytecode(
  85. concatInsts(
  86. tengo.MakeInstruction(parser.OpConstant, 0),
  87. tengo.MakeInstruction(parser.OpConstant, 1),
  88. tengo.MakeInstruction(parser.OpBinaryOp, 39),
  89. tengo.MakeInstruction(parser.OpPop),
  90. tengo.MakeInstruction(parser.OpSuspend)),
  91. objectsArray(
  92. intObject(1),
  93. intObject(2))))
  94. expectCompile(t, `1 < 2`,
  95. bytecode(
  96. concatInsts(
  97. tengo.MakeInstruction(parser.OpConstant, 0),
  98. tengo.MakeInstruction(parser.OpConstant, 1),
  99. tengo.MakeInstruction(parser.OpBinaryOp, 38),
  100. tengo.MakeInstruction(parser.OpPop),
  101. tengo.MakeInstruction(parser.OpSuspend)),
  102. objectsArray(
  103. intObject(1),
  104. intObject(2))))
  105. expectCompile(t, `1 >= 2`,
  106. bytecode(
  107. concatInsts(
  108. tengo.MakeInstruction(parser.OpConstant, 0),
  109. tengo.MakeInstruction(parser.OpConstant, 1),
  110. tengo.MakeInstruction(parser.OpBinaryOp, 44),
  111. tengo.MakeInstruction(parser.OpPop),
  112. tengo.MakeInstruction(parser.OpSuspend)),
  113. objectsArray(
  114. intObject(1),
  115. intObject(2))))
  116. expectCompile(t, `1 <= 2`,
  117. bytecode(
  118. concatInsts(
  119. tengo.MakeInstruction(parser.OpConstant, 0),
  120. tengo.MakeInstruction(parser.OpConstant, 1),
  121. tengo.MakeInstruction(parser.OpBinaryOp, 43),
  122. tengo.MakeInstruction(parser.OpPop),
  123. tengo.MakeInstruction(parser.OpSuspend)),
  124. objectsArray(
  125. intObject(1),
  126. intObject(2))))
  127. expectCompile(t, `1 == 2`,
  128. bytecode(
  129. concatInsts(
  130. tengo.MakeInstruction(parser.OpConstant, 0),
  131. tengo.MakeInstruction(parser.OpConstant, 1),
  132. tengo.MakeInstruction(parser.OpEqual),
  133. tengo.MakeInstruction(parser.OpPop),
  134. tengo.MakeInstruction(parser.OpSuspend)),
  135. objectsArray(
  136. intObject(1),
  137. intObject(2))))
  138. expectCompile(t, `1 != 2`,
  139. bytecode(
  140. concatInsts(
  141. tengo.MakeInstruction(parser.OpConstant, 0),
  142. tengo.MakeInstruction(parser.OpConstant, 1),
  143. tengo.MakeInstruction(parser.OpNotEqual),
  144. tengo.MakeInstruction(parser.OpPop),
  145. tengo.MakeInstruction(parser.OpSuspend)),
  146. objectsArray(
  147. intObject(1),
  148. intObject(2))))
  149. expectCompile(t, `true == false`,
  150. bytecode(
  151. concatInsts(
  152. tengo.MakeInstruction(parser.OpTrue),
  153. tengo.MakeInstruction(parser.OpFalse),
  154. tengo.MakeInstruction(parser.OpEqual),
  155. tengo.MakeInstruction(parser.OpPop),
  156. tengo.MakeInstruction(parser.OpSuspend)),
  157. objectsArray()))
  158. expectCompile(t, `true != false`,
  159. bytecode(
  160. concatInsts(
  161. tengo.MakeInstruction(parser.OpTrue),
  162. tengo.MakeInstruction(parser.OpFalse),
  163. tengo.MakeInstruction(parser.OpNotEqual),
  164. tengo.MakeInstruction(parser.OpPop),
  165. tengo.MakeInstruction(parser.OpSuspend)),
  166. objectsArray()))
  167. expectCompile(t, `-1`,
  168. bytecode(
  169. concatInsts(
  170. tengo.MakeInstruction(parser.OpConstant, 0),
  171. tengo.MakeInstruction(parser.OpMinus),
  172. tengo.MakeInstruction(parser.OpPop),
  173. tengo.MakeInstruction(parser.OpSuspend)),
  174. objectsArray(
  175. intObject(1))))
  176. expectCompile(t, `!true`,
  177. bytecode(
  178. concatInsts(
  179. tengo.MakeInstruction(parser.OpTrue),
  180. tengo.MakeInstruction(parser.OpLNot),
  181. tengo.MakeInstruction(parser.OpPop),
  182. tengo.MakeInstruction(parser.OpSuspend)),
  183. objectsArray()))
  184. expectCompile(t, `if true { 10 }; 3333`,
  185. bytecode(
  186. concatInsts(
  187. tengo.MakeInstruction(parser.OpTrue), // 0000
  188. tengo.MakeInstruction(parser.OpJumpFalsy, 10), // 0001
  189. tengo.MakeInstruction(parser.OpConstant, 0), // 0004
  190. tengo.MakeInstruction(parser.OpPop), // 0007
  191. tengo.MakeInstruction(parser.OpConstant, 1), // 0008
  192. tengo.MakeInstruction(parser.OpPop),
  193. tengo.MakeInstruction(parser.OpSuspend)), // 0011
  194. objectsArray(
  195. intObject(10),
  196. intObject(3333))))
  197. expectCompile(t, `if (true) { 10 } else { 20 }; 3333;`,
  198. bytecode(
  199. concatInsts(
  200. tengo.MakeInstruction(parser.OpTrue), // 0000
  201. tengo.MakeInstruction(parser.OpJumpFalsy, 15), // 0001
  202. tengo.MakeInstruction(parser.OpConstant, 0), // 0004
  203. tengo.MakeInstruction(parser.OpPop), // 0007
  204. tengo.MakeInstruction(parser.OpJump, 19), // 0008
  205. tengo.MakeInstruction(parser.OpConstant, 1), // 0011
  206. tengo.MakeInstruction(parser.OpPop), // 0014
  207. tengo.MakeInstruction(parser.OpConstant, 2), // 0015
  208. tengo.MakeInstruction(parser.OpPop),
  209. tengo.MakeInstruction(parser.OpSuspend)), // 0018
  210. objectsArray(
  211. intObject(10),
  212. intObject(20),
  213. intObject(3333))))
  214. expectCompile(t, `"kami"`,
  215. bytecode(
  216. concatInsts(
  217. tengo.MakeInstruction(parser.OpConstant, 0),
  218. tengo.MakeInstruction(parser.OpPop),
  219. tengo.MakeInstruction(parser.OpSuspend)),
  220. objectsArray(
  221. stringObject("kami"))))
  222. expectCompile(t, `"ka" + "mi"`,
  223. bytecode(
  224. concatInsts(
  225. tengo.MakeInstruction(parser.OpConstant, 0),
  226. tengo.MakeInstruction(parser.OpConstant, 1),
  227. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  228. tengo.MakeInstruction(parser.OpPop),
  229. tengo.MakeInstruction(parser.OpSuspend)),
  230. objectsArray(
  231. stringObject("ka"),
  232. stringObject("mi"))))
  233. expectCompile(t, `a := 1; b := 2; a += b`,
  234. bytecode(
  235. concatInsts(
  236. tengo.MakeInstruction(parser.OpConstant, 0),
  237. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  238. tengo.MakeInstruction(parser.OpConstant, 1),
  239. tengo.MakeInstruction(parser.OpSetGlobal, 1),
  240. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  241. tengo.MakeInstruction(parser.OpGetGlobal, 1),
  242. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  243. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  244. tengo.MakeInstruction(parser.OpSuspend)),
  245. objectsArray(
  246. intObject(1),
  247. intObject(2))))
  248. expectCompile(t, `a := 1; b := 2; a /= b`,
  249. bytecode(
  250. concatInsts(
  251. tengo.MakeInstruction(parser.OpConstant, 0),
  252. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  253. tengo.MakeInstruction(parser.OpConstant, 1),
  254. tengo.MakeInstruction(parser.OpSetGlobal, 1),
  255. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  256. tengo.MakeInstruction(parser.OpGetGlobal, 1),
  257. tengo.MakeInstruction(parser.OpBinaryOp, 14),
  258. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  259. tengo.MakeInstruction(parser.OpSuspend)),
  260. objectsArray(
  261. intObject(1),
  262. intObject(2))))
  263. expectCompile(t, `[]`,
  264. bytecode(
  265. concatInsts(
  266. tengo.MakeInstruction(parser.OpArray, 0),
  267. tengo.MakeInstruction(parser.OpPop),
  268. tengo.MakeInstruction(parser.OpSuspend)),
  269. objectsArray()))
  270. expectCompile(t, `[1, 2, 3]`,
  271. bytecode(
  272. concatInsts(
  273. tengo.MakeInstruction(parser.OpConstant, 0),
  274. tengo.MakeInstruction(parser.OpConstant, 1),
  275. tengo.MakeInstruction(parser.OpConstant, 2),
  276. tengo.MakeInstruction(parser.OpArray, 3),
  277. tengo.MakeInstruction(parser.OpPop),
  278. tengo.MakeInstruction(parser.OpSuspend)),
  279. objectsArray(
  280. intObject(1),
  281. intObject(2),
  282. intObject(3))))
  283. expectCompile(t, `[1 + 2, 3 - 4, 5 * 6]`,
  284. bytecode(
  285. concatInsts(
  286. tengo.MakeInstruction(parser.OpConstant, 0),
  287. tengo.MakeInstruction(parser.OpConstant, 1),
  288. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  289. tengo.MakeInstruction(parser.OpConstant, 2),
  290. tengo.MakeInstruction(parser.OpConstant, 3),
  291. tengo.MakeInstruction(parser.OpBinaryOp, 12),
  292. tengo.MakeInstruction(parser.OpConstant, 4),
  293. tengo.MakeInstruction(parser.OpConstant, 5),
  294. tengo.MakeInstruction(parser.OpBinaryOp, 13),
  295. tengo.MakeInstruction(parser.OpArray, 3),
  296. tengo.MakeInstruction(parser.OpPop),
  297. tengo.MakeInstruction(parser.OpSuspend)),
  298. objectsArray(
  299. intObject(1),
  300. intObject(2),
  301. intObject(3),
  302. intObject(4),
  303. intObject(5),
  304. intObject(6))))
  305. expectCompile(t, `{}`,
  306. bytecode(
  307. concatInsts(
  308. tengo.MakeInstruction(parser.OpMap, 0),
  309. tengo.MakeInstruction(parser.OpPop),
  310. tengo.MakeInstruction(parser.OpSuspend)),
  311. objectsArray()))
  312. expectCompile(t, `{a: 2, b: 4, c: 6}`,
  313. bytecode(
  314. concatInsts(
  315. tengo.MakeInstruction(parser.OpConstant, 0),
  316. tengo.MakeInstruction(parser.OpConstant, 1),
  317. tengo.MakeInstruction(parser.OpConstant, 2),
  318. tengo.MakeInstruction(parser.OpConstant, 3),
  319. tengo.MakeInstruction(parser.OpConstant, 4),
  320. tengo.MakeInstruction(parser.OpConstant, 5),
  321. tengo.MakeInstruction(parser.OpMap, 6),
  322. tengo.MakeInstruction(parser.OpPop),
  323. tengo.MakeInstruction(parser.OpSuspend)),
  324. objectsArray(
  325. stringObject("a"),
  326. intObject(2),
  327. stringObject("b"),
  328. intObject(4),
  329. stringObject("c"),
  330. intObject(6))))
  331. expectCompile(t, `{a: 2 + 3, b: 5 * 6}`,
  332. bytecode(
  333. concatInsts(
  334. tengo.MakeInstruction(parser.OpConstant, 0),
  335. tengo.MakeInstruction(parser.OpConstant, 1),
  336. tengo.MakeInstruction(parser.OpConstant, 2),
  337. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  338. tengo.MakeInstruction(parser.OpConstant, 3),
  339. tengo.MakeInstruction(parser.OpConstant, 4),
  340. tengo.MakeInstruction(parser.OpConstant, 5),
  341. tengo.MakeInstruction(parser.OpBinaryOp, 13),
  342. tengo.MakeInstruction(parser.OpMap, 4),
  343. tengo.MakeInstruction(parser.OpPop),
  344. tengo.MakeInstruction(parser.OpSuspend)),
  345. objectsArray(
  346. stringObject("a"),
  347. intObject(2),
  348. intObject(3),
  349. stringObject("b"),
  350. intObject(5),
  351. intObject(6))))
  352. expectCompile(t, `[1, 2, 3][1 + 1]`,
  353. bytecode(
  354. concatInsts(
  355. tengo.MakeInstruction(parser.OpConstant, 0),
  356. tengo.MakeInstruction(parser.OpConstant, 1),
  357. tengo.MakeInstruction(parser.OpConstant, 2),
  358. tengo.MakeInstruction(parser.OpArray, 3),
  359. tengo.MakeInstruction(parser.OpConstant, 0),
  360. tengo.MakeInstruction(parser.OpConstant, 0),
  361. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  362. tengo.MakeInstruction(parser.OpIndex),
  363. tengo.MakeInstruction(parser.OpPop),
  364. tengo.MakeInstruction(parser.OpSuspend)),
  365. objectsArray(
  366. intObject(1),
  367. intObject(2),
  368. intObject(3))))
  369. expectCompile(t, `{a: 2}[2 - 1]`,
  370. bytecode(
  371. concatInsts(
  372. tengo.MakeInstruction(parser.OpConstant, 0),
  373. tengo.MakeInstruction(parser.OpConstant, 1),
  374. tengo.MakeInstruction(parser.OpMap, 2),
  375. tengo.MakeInstruction(parser.OpConstant, 1),
  376. tengo.MakeInstruction(parser.OpConstant, 2),
  377. tengo.MakeInstruction(parser.OpBinaryOp, 12),
  378. tengo.MakeInstruction(parser.OpIndex),
  379. tengo.MakeInstruction(parser.OpPop),
  380. tengo.MakeInstruction(parser.OpSuspend)),
  381. objectsArray(
  382. stringObject("a"),
  383. intObject(2),
  384. intObject(1))))
  385. expectCompile(t, `[1, 2, 3][:]`,
  386. bytecode(
  387. concatInsts(
  388. tengo.MakeInstruction(parser.OpConstant, 0),
  389. tengo.MakeInstruction(parser.OpConstant, 1),
  390. tengo.MakeInstruction(parser.OpConstant, 2),
  391. tengo.MakeInstruction(parser.OpArray, 3),
  392. tengo.MakeInstruction(parser.OpNull),
  393. tengo.MakeInstruction(parser.OpNull),
  394. tengo.MakeInstruction(parser.OpSliceIndex),
  395. tengo.MakeInstruction(parser.OpPop),
  396. tengo.MakeInstruction(parser.OpSuspend)),
  397. objectsArray(
  398. intObject(1),
  399. intObject(2),
  400. intObject(3))))
  401. expectCompile(t, `[1, 2, 3][0 : 2]`,
  402. bytecode(
  403. concatInsts(
  404. tengo.MakeInstruction(parser.OpConstant, 0),
  405. tengo.MakeInstruction(parser.OpConstant, 1),
  406. tengo.MakeInstruction(parser.OpConstant, 2),
  407. tengo.MakeInstruction(parser.OpArray, 3),
  408. tengo.MakeInstruction(parser.OpConstant, 3),
  409. tengo.MakeInstruction(parser.OpConstant, 1),
  410. tengo.MakeInstruction(parser.OpSliceIndex),
  411. tengo.MakeInstruction(parser.OpPop),
  412. tengo.MakeInstruction(parser.OpSuspend)),
  413. objectsArray(
  414. intObject(1),
  415. intObject(2),
  416. intObject(3),
  417. intObject(0))))
  418. expectCompile(t, `[1, 2, 3][:2]`,
  419. bytecode(
  420. concatInsts(
  421. tengo.MakeInstruction(parser.OpConstant, 0),
  422. tengo.MakeInstruction(parser.OpConstant, 1),
  423. tengo.MakeInstruction(parser.OpConstant, 2),
  424. tengo.MakeInstruction(parser.OpArray, 3),
  425. tengo.MakeInstruction(parser.OpNull),
  426. tengo.MakeInstruction(parser.OpConstant, 1),
  427. tengo.MakeInstruction(parser.OpSliceIndex),
  428. tengo.MakeInstruction(parser.OpPop),
  429. tengo.MakeInstruction(parser.OpSuspend)),
  430. objectsArray(
  431. intObject(1),
  432. intObject(2),
  433. intObject(3))))
  434. expectCompile(t, `[1, 2, 3][0:]`,
  435. bytecode(
  436. concatInsts(
  437. tengo.MakeInstruction(parser.OpConstant, 0),
  438. tengo.MakeInstruction(parser.OpConstant, 1),
  439. tengo.MakeInstruction(parser.OpConstant, 2),
  440. tengo.MakeInstruction(parser.OpArray, 3),
  441. tengo.MakeInstruction(parser.OpConstant, 3),
  442. tengo.MakeInstruction(parser.OpNull),
  443. tengo.MakeInstruction(parser.OpSliceIndex),
  444. tengo.MakeInstruction(parser.OpPop),
  445. tengo.MakeInstruction(parser.OpSuspend)),
  446. objectsArray(
  447. intObject(1),
  448. intObject(2),
  449. intObject(3),
  450. intObject(0))))
  451. expectCompile(t, `f1 := func(a) { return a }; f1([1, 2]...);`,
  452. bytecode(
  453. concatInsts(
  454. tengo.MakeInstruction(parser.OpConstant, 0),
  455. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  456. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  457. tengo.MakeInstruction(parser.OpConstant, 1),
  458. tengo.MakeInstruction(parser.OpConstant, 2),
  459. tengo.MakeInstruction(parser.OpArray, 2),
  460. tengo.MakeInstruction(parser.OpCall, 1, 1),
  461. tengo.MakeInstruction(parser.OpPop),
  462. tengo.MakeInstruction(parser.OpSuspend)),
  463. objectsArray(
  464. compiledFunction(1, 1,
  465. tengo.MakeInstruction(parser.OpGetLocal, 0),
  466. tengo.MakeInstruction(parser.OpReturn, 1)),
  467. intObject(1),
  468. intObject(2))))
  469. expectCompile(t, `func() { return 5 + 10 }`,
  470. bytecode(
  471. concatInsts(
  472. tengo.MakeInstruction(parser.OpConstant, 2),
  473. tengo.MakeInstruction(parser.OpPop),
  474. tengo.MakeInstruction(parser.OpSuspend)),
  475. objectsArray(
  476. intObject(5),
  477. intObject(10),
  478. compiledFunction(0, 0,
  479. tengo.MakeInstruction(parser.OpConstant, 0),
  480. tengo.MakeInstruction(parser.OpConstant, 1),
  481. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  482. tengo.MakeInstruction(parser.OpReturn, 1)))))
  483. expectCompile(t, `func() { 5 + 10 }`,
  484. bytecode(
  485. concatInsts(
  486. tengo.MakeInstruction(parser.OpConstant, 2),
  487. tengo.MakeInstruction(parser.OpPop),
  488. tengo.MakeInstruction(parser.OpSuspend)),
  489. objectsArray(
  490. intObject(5),
  491. intObject(10),
  492. compiledFunction(0, 0,
  493. tengo.MakeInstruction(parser.OpConstant, 0),
  494. tengo.MakeInstruction(parser.OpConstant, 1),
  495. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  496. tengo.MakeInstruction(parser.OpPop),
  497. tengo.MakeInstruction(parser.OpReturn, 0)))))
  498. expectCompile(t, `func() { 1; 2 }`,
  499. bytecode(
  500. concatInsts(
  501. tengo.MakeInstruction(parser.OpConstant, 2),
  502. tengo.MakeInstruction(parser.OpPop),
  503. tengo.MakeInstruction(parser.OpSuspend)),
  504. objectsArray(
  505. intObject(1),
  506. intObject(2),
  507. compiledFunction(0, 0,
  508. tengo.MakeInstruction(parser.OpConstant, 0),
  509. tengo.MakeInstruction(parser.OpPop),
  510. tengo.MakeInstruction(parser.OpConstant, 1),
  511. tengo.MakeInstruction(parser.OpPop),
  512. tengo.MakeInstruction(parser.OpReturn, 0)))))
  513. expectCompile(t, `func() { 1; return 2 }`,
  514. bytecode(
  515. concatInsts(
  516. tengo.MakeInstruction(parser.OpConstant, 2),
  517. tengo.MakeInstruction(parser.OpPop),
  518. tengo.MakeInstruction(parser.OpSuspend)),
  519. objectsArray(
  520. intObject(1),
  521. intObject(2),
  522. compiledFunction(0, 0,
  523. tengo.MakeInstruction(parser.OpConstant, 0),
  524. tengo.MakeInstruction(parser.OpPop),
  525. tengo.MakeInstruction(parser.OpConstant, 1),
  526. tengo.MakeInstruction(parser.OpReturn, 1)))))
  527. expectCompile(t, `func() { if(true) { return 1 } else { return 2 } }`,
  528. bytecode(
  529. concatInsts(
  530. tengo.MakeInstruction(parser.OpConstant, 2),
  531. tengo.MakeInstruction(parser.OpPop),
  532. tengo.MakeInstruction(parser.OpSuspend)),
  533. objectsArray(
  534. intObject(1),
  535. intObject(2),
  536. compiledFunction(0, 0,
  537. tengo.MakeInstruction(parser.OpTrue), // 0000
  538. tengo.MakeInstruction(parser.OpJumpFalsy, 11), // 0001
  539. tengo.MakeInstruction(parser.OpConstant, 0), // 0004
  540. tengo.MakeInstruction(parser.OpReturn, 1), // 0007
  541. tengo.MakeInstruction(parser.OpConstant, 1), // 0009
  542. tengo.MakeInstruction(parser.OpReturn, 1))))) // 0012
  543. expectCompile(t, `func() { 1; if(true) { 2 } else { 3 }; 4 }`,
  544. bytecode(
  545. concatInsts(
  546. tengo.MakeInstruction(parser.OpConstant, 4),
  547. tengo.MakeInstruction(parser.OpPop),
  548. tengo.MakeInstruction(parser.OpSuspend)),
  549. objectsArray(
  550. intObject(1),
  551. intObject(2),
  552. intObject(3),
  553. intObject(4),
  554. compiledFunction(0, 0,
  555. tengo.MakeInstruction(parser.OpConstant, 0), // 0000
  556. tengo.MakeInstruction(parser.OpPop), // 0003
  557. tengo.MakeInstruction(parser.OpTrue), // 0004
  558. tengo.MakeInstruction(parser.OpJumpFalsy, 19), // 0005
  559. tengo.MakeInstruction(parser.OpConstant, 1), // 0008
  560. tengo.MakeInstruction(parser.OpPop), // 0011
  561. tengo.MakeInstruction(parser.OpJump, 23), // 0012
  562. tengo.MakeInstruction(parser.OpConstant, 2), // 0015
  563. tengo.MakeInstruction(parser.OpPop), // 0018
  564. tengo.MakeInstruction(parser.OpConstant, 3), // 0019
  565. tengo.MakeInstruction(parser.OpPop), // 0022
  566. tengo.MakeInstruction(parser.OpReturn, 0))))) // 0023
  567. expectCompile(t, `func() { }`,
  568. bytecode(
  569. concatInsts(
  570. tengo.MakeInstruction(parser.OpConstant, 0),
  571. tengo.MakeInstruction(parser.OpPop),
  572. tengo.MakeInstruction(parser.OpSuspend)),
  573. objectsArray(
  574. compiledFunction(0, 0,
  575. tengo.MakeInstruction(parser.OpReturn, 0)))))
  576. expectCompile(t, `func() { 24 }()`,
  577. bytecode(
  578. concatInsts(
  579. tengo.MakeInstruction(parser.OpConstant, 1),
  580. tengo.MakeInstruction(parser.OpCall, 0, 0),
  581. tengo.MakeInstruction(parser.OpPop),
  582. tengo.MakeInstruction(parser.OpSuspend)),
  583. objectsArray(
  584. intObject(24),
  585. compiledFunction(0, 0,
  586. tengo.MakeInstruction(parser.OpConstant, 0),
  587. tengo.MakeInstruction(parser.OpPop),
  588. tengo.MakeInstruction(parser.OpReturn, 0)))))
  589. expectCompile(t, `func() { return 24 }()`,
  590. bytecode(
  591. concatInsts(
  592. tengo.MakeInstruction(parser.OpConstant, 1),
  593. tengo.MakeInstruction(parser.OpCall, 0, 0),
  594. tengo.MakeInstruction(parser.OpPop),
  595. tengo.MakeInstruction(parser.OpSuspend)),
  596. objectsArray(
  597. intObject(24),
  598. compiledFunction(0, 0,
  599. tengo.MakeInstruction(parser.OpConstant, 0),
  600. tengo.MakeInstruction(parser.OpReturn, 1)))))
  601. expectCompile(t, `noArg := func() { 24 }; noArg();`,
  602. bytecode(
  603. concatInsts(
  604. tengo.MakeInstruction(parser.OpConstant, 1),
  605. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  606. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  607. tengo.MakeInstruction(parser.OpCall, 0, 0),
  608. tengo.MakeInstruction(parser.OpPop),
  609. tengo.MakeInstruction(parser.OpSuspend)),
  610. objectsArray(
  611. intObject(24),
  612. compiledFunction(0, 0,
  613. tengo.MakeInstruction(parser.OpConstant, 0),
  614. tengo.MakeInstruction(parser.OpPop),
  615. tengo.MakeInstruction(parser.OpReturn, 0)))))
  616. expectCompile(t, `noArg := func() { return 24 }; noArg();`,
  617. bytecode(
  618. concatInsts(
  619. tengo.MakeInstruction(parser.OpConstant, 1),
  620. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  621. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  622. tengo.MakeInstruction(parser.OpCall, 0, 0),
  623. tengo.MakeInstruction(parser.OpPop),
  624. tengo.MakeInstruction(parser.OpSuspend)),
  625. objectsArray(
  626. intObject(24),
  627. compiledFunction(0, 0,
  628. tengo.MakeInstruction(parser.OpConstant, 0),
  629. tengo.MakeInstruction(parser.OpReturn, 1)))))
  630. expectCompile(t, `n := 55; func() { n };`,
  631. bytecode(
  632. concatInsts(
  633. tengo.MakeInstruction(parser.OpConstant, 0),
  634. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  635. tengo.MakeInstruction(parser.OpConstant, 1),
  636. tengo.MakeInstruction(parser.OpPop),
  637. tengo.MakeInstruction(parser.OpSuspend)),
  638. objectsArray(
  639. intObject(55),
  640. compiledFunction(0, 0,
  641. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  642. tengo.MakeInstruction(parser.OpPop),
  643. tengo.MakeInstruction(parser.OpReturn, 0)))))
  644. expectCompile(t, `func() { n := 55; return n }`,
  645. bytecode(
  646. concatInsts(
  647. tengo.MakeInstruction(parser.OpConstant, 1),
  648. tengo.MakeInstruction(parser.OpPop),
  649. tengo.MakeInstruction(parser.OpSuspend)),
  650. objectsArray(
  651. intObject(55),
  652. compiledFunction(1, 0,
  653. tengo.MakeInstruction(parser.OpConstant, 0),
  654. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  655. tengo.MakeInstruction(parser.OpGetLocal, 0),
  656. tengo.MakeInstruction(parser.OpReturn, 1)))))
  657. expectCompile(t, `func() { a := 55; b := 77; return a + b }`,
  658. bytecode(
  659. concatInsts(
  660. tengo.MakeInstruction(parser.OpConstant, 2),
  661. tengo.MakeInstruction(parser.OpPop),
  662. tengo.MakeInstruction(parser.OpSuspend)),
  663. objectsArray(
  664. intObject(55),
  665. intObject(77),
  666. compiledFunction(2, 0,
  667. tengo.MakeInstruction(parser.OpConstant, 0),
  668. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  669. tengo.MakeInstruction(parser.OpConstant, 1),
  670. tengo.MakeInstruction(parser.OpDefineLocal, 1),
  671. tengo.MakeInstruction(parser.OpGetLocal, 0),
  672. tengo.MakeInstruction(parser.OpGetLocal, 1),
  673. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  674. tengo.MakeInstruction(parser.OpReturn, 1)))))
  675. expectCompile(t, `f1 := func(a) { return a }; f1(24);`,
  676. bytecode(
  677. concatInsts(
  678. tengo.MakeInstruction(parser.OpConstant, 0),
  679. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  680. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  681. tengo.MakeInstruction(parser.OpConstant, 1),
  682. tengo.MakeInstruction(parser.OpCall, 1, 0),
  683. tengo.MakeInstruction(parser.OpPop),
  684. tengo.MakeInstruction(parser.OpSuspend)),
  685. objectsArray(
  686. compiledFunction(1, 1,
  687. tengo.MakeInstruction(parser.OpGetLocal, 0),
  688. tengo.MakeInstruction(parser.OpReturn, 1)),
  689. intObject(24))))
  690. expectCompile(t, `varTest := func(...a) { return a }; varTest(1,2,3);`,
  691. bytecode(
  692. concatInsts(
  693. tengo.MakeInstruction(parser.OpConstant, 0),
  694. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  695. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  696. tengo.MakeInstruction(parser.OpConstant, 1),
  697. tengo.MakeInstruction(parser.OpConstant, 2),
  698. tengo.MakeInstruction(parser.OpConstant, 3),
  699. tengo.MakeInstruction(parser.OpCall, 3, 0),
  700. tengo.MakeInstruction(parser.OpPop),
  701. tengo.MakeInstruction(parser.OpSuspend)),
  702. objectsArray(
  703. compiledFunction(1, 1,
  704. tengo.MakeInstruction(parser.OpGetLocal, 0),
  705. tengo.MakeInstruction(parser.OpReturn, 1)),
  706. intObject(1), intObject(2), intObject(3))))
  707. expectCompile(t, `f1 := func(a, b, c) { a; b; return c; }; f1(24, 25, 26);`,
  708. bytecode(
  709. concatInsts(
  710. tengo.MakeInstruction(parser.OpConstant, 0),
  711. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  712. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  713. tengo.MakeInstruction(parser.OpConstant, 1),
  714. tengo.MakeInstruction(parser.OpConstant, 2),
  715. tengo.MakeInstruction(parser.OpConstant, 3),
  716. tengo.MakeInstruction(parser.OpCall, 3, 0),
  717. tengo.MakeInstruction(parser.OpPop),
  718. tengo.MakeInstruction(parser.OpSuspend)),
  719. objectsArray(
  720. compiledFunction(3, 3,
  721. tengo.MakeInstruction(parser.OpGetLocal, 0),
  722. tengo.MakeInstruction(parser.OpPop),
  723. tengo.MakeInstruction(parser.OpGetLocal, 1),
  724. tengo.MakeInstruction(parser.OpPop),
  725. tengo.MakeInstruction(parser.OpGetLocal, 2),
  726. tengo.MakeInstruction(parser.OpReturn, 1)),
  727. intObject(24),
  728. intObject(25),
  729. intObject(26))))
  730. expectCompile(t, `func() { n := 55; n = 23; return n }`,
  731. bytecode(
  732. concatInsts(
  733. tengo.MakeInstruction(parser.OpConstant, 2),
  734. tengo.MakeInstruction(parser.OpPop),
  735. tengo.MakeInstruction(parser.OpSuspend)),
  736. objectsArray(
  737. intObject(55),
  738. intObject(23),
  739. compiledFunction(1, 0,
  740. tengo.MakeInstruction(parser.OpConstant, 0),
  741. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  742. tengo.MakeInstruction(parser.OpConstant, 1),
  743. tengo.MakeInstruction(parser.OpSetLocal, 0),
  744. tengo.MakeInstruction(parser.OpGetLocal, 0),
  745. tengo.MakeInstruction(parser.OpReturn, 1)))))
  746. expectCompile(t, `len([]);`,
  747. bytecode(
  748. concatInsts(
  749. tengo.MakeInstruction(parser.OpGetBuiltin, 0),
  750. tengo.MakeInstruction(parser.OpArray, 0),
  751. tengo.MakeInstruction(parser.OpCall, 1, 0),
  752. tengo.MakeInstruction(parser.OpPop),
  753. tengo.MakeInstruction(parser.OpSuspend)),
  754. objectsArray()))
  755. expectCompile(t, `func() { return len([]) }`,
  756. bytecode(
  757. concatInsts(
  758. tengo.MakeInstruction(parser.OpConstant, 0),
  759. tengo.MakeInstruction(parser.OpPop),
  760. tengo.MakeInstruction(parser.OpSuspend)),
  761. objectsArray(
  762. compiledFunction(0, 0,
  763. tengo.MakeInstruction(parser.OpGetBuiltin, 0),
  764. tengo.MakeInstruction(parser.OpArray, 0),
  765. tengo.MakeInstruction(parser.OpCall, 1, 0),
  766. tengo.MakeInstruction(parser.OpReturn, 1)))))
  767. expectCompile(t, `func(a) { func(b) { return a + b } }`,
  768. bytecode(
  769. concatInsts(
  770. tengo.MakeInstruction(parser.OpConstant, 1),
  771. tengo.MakeInstruction(parser.OpPop),
  772. tengo.MakeInstruction(parser.OpSuspend)),
  773. objectsArray(
  774. compiledFunction(1, 1,
  775. tengo.MakeInstruction(parser.OpGetFree, 0),
  776. tengo.MakeInstruction(parser.OpGetLocal, 0),
  777. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  778. tengo.MakeInstruction(parser.OpReturn, 1)),
  779. compiledFunction(1, 1,
  780. tengo.MakeInstruction(parser.OpGetLocalPtr, 0),
  781. tengo.MakeInstruction(parser.OpClosure, 0, 1),
  782. tengo.MakeInstruction(parser.OpPop),
  783. tengo.MakeInstruction(parser.OpReturn, 0)))))
  784. expectCompile(t, `
  785. func(a) {
  786. return func(b) {
  787. return func(c) {
  788. return a + b + c
  789. }
  790. }
  791. }`,
  792. bytecode(
  793. concatInsts(
  794. tengo.MakeInstruction(parser.OpConstant, 2),
  795. tengo.MakeInstruction(parser.OpPop),
  796. tengo.MakeInstruction(parser.OpSuspend)),
  797. objectsArray(
  798. compiledFunction(1, 1,
  799. tengo.MakeInstruction(parser.OpGetFree, 0),
  800. tengo.MakeInstruction(parser.OpGetFree, 1),
  801. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  802. tengo.MakeInstruction(parser.OpGetLocal, 0),
  803. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  804. tengo.MakeInstruction(parser.OpReturn, 1)),
  805. compiledFunction(1, 1,
  806. tengo.MakeInstruction(parser.OpGetFreePtr, 0),
  807. tengo.MakeInstruction(parser.OpGetLocalPtr, 0),
  808. tengo.MakeInstruction(parser.OpClosure, 0, 2),
  809. tengo.MakeInstruction(parser.OpReturn, 1)),
  810. compiledFunction(1, 1,
  811. tengo.MakeInstruction(parser.OpGetLocalPtr, 0),
  812. tengo.MakeInstruction(parser.OpClosure, 1, 1),
  813. tengo.MakeInstruction(parser.OpReturn, 1)))))
  814. expectCompile(t, `
  815. g := 55;
  816. func() {
  817. a := 66;
  818. return func() {
  819. b := 77;
  820. return func() {
  821. c := 88;
  822. return g + a + b + c;
  823. }
  824. }
  825. }`,
  826. bytecode(
  827. concatInsts(
  828. tengo.MakeInstruction(parser.OpConstant, 0),
  829. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  830. tengo.MakeInstruction(parser.OpConstant, 6),
  831. tengo.MakeInstruction(parser.OpPop),
  832. tengo.MakeInstruction(parser.OpSuspend)),
  833. objectsArray(
  834. intObject(55),
  835. intObject(66),
  836. intObject(77),
  837. intObject(88),
  838. compiledFunction(1, 0,
  839. tengo.MakeInstruction(parser.OpConstant, 3),
  840. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  841. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  842. tengo.MakeInstruction(parser.OpGetFree, 0),
  843. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  844. tengo.MakeInstruction(parser.OpGetFree, 1),
  845. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  846. tengo.MakeInstruction(parser.OpGetLocal, 0),
  847. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  848. tengo.MakeInstruction(parser.OpReturn, 1)),
  849. compiledFunction(1, 0,
  850. tengo.MakeInstruction(parser.OpConstant, 2),
  851. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  852. tengo.MakeInstruction(parser.OpGetFreePtr, 0),
  853. tengo.MakeInstruction(parser.OpGetLocalPtr, 0),
  854. tengo.MakeInstruction(parser.OpClosure, 4, 2),
  855. tengo.MakeInstruction(parser.OpReturn, 1)),
  856. compiledFunction(1, 0,
  857. tengo.MakeInstruction(parser.OpConstant, 1),
  858. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  859. tengo.MakeInstruction(parser.OpGetLocalPtr, 0),
  860. tengo.MakeInstruction(parser.OpClosure, 5, 1),
  861. tengo.MakeInstruction(parser.OpReturn, 1)))))
  862. expectCompile(t, `for i:=0; i<10; i++ {}`,
  863. bytecode(
  864. concatInsts(
  865. tengo.MakeInstruction(parser.OpConstant, 0),
  866. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  867. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  868. tengo.MakeInstruction(parser.OpConstant, 1),
  869. tengo.MakeInstruction(parser.OpBinaryOp, 38),
  870. tengo.MakeInstruction(parser.OpJumpFalsy, 35),
  871. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  872. tengo.MakeInstruction(parser.OpConstant, 2),
  873. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  874. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  875. tengo.MakeInstruction(parser.OpJump, 6),
  876. tengo.MakeInstruction(parser.OpSuspend)),
  877. objectsArray(
  878. intObject(0),
  879. intObject(10),
  880. intObject(1))))
  881. expectCompile(t, `m := {}; for k, v in m {}`,
  882. bytecode(
  883. concatInsts(
  884. tengo.MakeInstruction(parser.OpMap, 0),
  885. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  886. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  887. tengo.MakeInstruction(parser.OpIteratorInit),
  888. tengo.MakeInstruction(parser.OpSetGlobal, 1),
  889. tengo.MakeInstruction(parser.OpGetGlobal, 1),
  890. tengo.MakeInstruction(parser.OpIteratorNext),
  891. tengo.MakeInstruction(parser.OpJumpFalsy, 41),
  892. tengo.MakeInstruction(parser.OpGetGlobal, 1),
  893. tengo.MakeInstruction(parser.OpIteratorKey),
  894. tengo.MakeInstruction(parser.OpSetGlobal, 2),
  895. tengo.MakeInstruction(parser.OpGetGlobal, 1),
  896. tengo.MakeInstruction(parser.OpIteratorValue),
  897. tengo.MakeInstruction(parser.OpSetGlobal, 3),
  898. tengo.MakeInstruction(parser.OpJump, 13),
  899. tengo.MakeInstruction(parser.OpSuspend)),
  900. objectsArray()))
  901. expectCompile(t, `a := 0; a == 0 && a != 1 || a < 1`,
  902. bytecode(
  903. concatInsts(
  904. tengo.MakeInstruction(parser.OpConstant, 0),
  905. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  906. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  907. tengo.MakeInstruction(parser.OpConstant, 0),
  908. tengo.MakeInstruction(parser.OpEqual),
  909. tengo.MakeInstruction(parser.OpAndJump, 25),
  910. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  911. tengo.MakeInstruction(parser.OpConstant, 1),
  912. tengo.MakeInstruction(parser.OpNotEqual),
  913. tengo.MakeInstruction(parser.OpOrJump, 38),
  914. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  915. tengo.MakeInstruction(parser.OpConstant, 1),
  916. tengo.MakeInstruction(parser.OpBinaryOp, 38),
  917. tengo.MakeInstruction(parser.OpPop),
  918. tengo.MakeInstruction(parser.OpSuspend)),
  919. objectsArray(
  920. intObject(0),
  921. intObject(1))))
  922. // unknown module name
  923. expectCompileError(t, `import("user1")`, "module 'user1' not found")
  924. // too many errors
  925. expectCompileError(t, `
  926. r["x"] = {
  927. @a:1,
  928. @b:1,
  929. @c:1,
  930. @d:1,
  931. @e:1,
  932. @f:1,
  933. @g:1,
  934. @h:1,
  935. @i:1,
  936. @j:1,
  937. @k:1
  938. }
  939. `, "Parse Error: illegal character U+0040 '@'\n\tat test:3:5 (and 10 more errors)")
  940. expectCompileError(t, `import("")`, "empty module name")
  941. // https://github.com/d5/tengo/issues/314
  942. expectCompileError(t, `
  943. (func() {
  944. fn := fn()
  945. })()
  946. `, "unresolved reference 'fn")
  947. }
  948. func TestCompilerErrorReport(t *testing.T) {
  949. expectCompileError(t, `import("user1")`,
  950. "Compile Error: module 'user1' not found\n\tat test:1:1")
  951. expectCompileError(t, `a = 1`,
  952. "Compile Error: unresolved reference 'a'\n\tat test:1:1")
  953. expectCompileError(t, `a := a`,
  954. "Compile Error: unresolved reference 'a'\n\tat test:1:6")
  955. expectCompileError(t, `a, b := 1, 2`,
  956. "Compile Error: tuple assignment not allowed\n\tat test:1:1")
  957. expectCompileError(t, `a.b := 1`,
  958. "not allowed with selector")
  959. expectCompileError(t, `a:=1; a:=3`,
  960. "Compile Error: 'a' redeclared in this block\n\tat test:1:7")
  961. expectCompileError(t, `return 5`,
  962. "Compile Error: return not allowed outside function\n\tat test:1:1")
  963. expectCompileError(t, `func() { break }`,
  964. "Compile Error: break not allowed outside loop\n\tat test:1:10")
  965. expectCompileError(t, `func() { continue }`,
  966. "Compile Error: continue not allowed outside loop\n\tat test:1:10")
  967. expectCompileError(t, `func() { export 5 }`,
  968. "Compile Error: export not allowed inside function\n\tat test:1:10")
  969. }
  970. func TestCompilerDeadCode(t *testing.T) {
  971. expectCompile(t, `
  972. func() {
  973. a := 4
  974. return a
  975. b := 5 // dead code from here
  976. c := a
  977. return b
  978. }`,
  979. bytecode(
  980. concatInsts(
  981. tengo.MakeInstruction(parser.OpConstant, 2),
  982. tengo.MakeInstruction(parser.OpPop),
  983. tengo.MakeInstruction(parser.OpSuspend)),
  984. objectsArray(
  985. intObject(4),
  986. intObject(5),
  987. compiledFunction(0, 0,
  988. tengo.MakeInstruction(parser.OpConstant, 0),
  989. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  990. tengo.MakeInstruction(parser.OpGetLocal, 0),
  991. tengo.MakeInstruction(parser.OpReturn, 1)))))
  992. expectCompile(t, `
  993. func() {
  994. if true {
  995. return 5
  996. a := 4 // dead code from here
  997. b := a
  998. return b
  999. } else {
  1000. return 4
  1001. c := 5 // dead code from here
  1002. d := c
  1003. return d
  1004. }
  1005. }`, bytecode(
  1006. concatInsts(
  1007. tengo.MakeInstruction(parser.OpConstant, 2),
  1008. tengo.MakeInstruction(parser.OpPop),
  1009. tengo.MakeInstruction(parser.OpSuspend)),
  1010. objectsArray(
  1011. intObject(5),
  1012. intObject(4),
  1013. compiledFunction(0, 0,
  1014. tengo.MakeInstruction(parser.OpTrue),
  1015. tengo.MakeInstruction(parser.OpJumpFalsy, 11),
  1016. tengo.MakeInstruction(parser.OpConstant, 0),
  1017. tengo.MakeInstruction(parser.OpReturn, 1),
  1018. tengo.MakeInstruction(parser.OpConstant, 1),
  1019. tengo.MakeInstruction(parser.OpReturn, 1)))))
  1020. expectCompile(t, `
  1021. func() {
  1022. a := 1
  1023. for {
  1024. if a == 5 {
  1025. return 10
  1026. }
  1027. 5 + 5
  1028. return 20
  1029. b := a
  1030. return b
  1031. }
  1032. }`, bytecode(
  1033. concatInsts(
  1034. tengo.MakeInstruction(parser.OpConstant, 4),
  1035. tengo.MakeInstruction(parser.OpPop),
  1036. tengo.MakeInstruction(parser.OpSuspend)),
  1037. objectsArray(
  1038. intObject(1),
  1039. intObject(5),
  1040. intObject(10),
  1041. intObject(20),
  1042. compiledFunction(0, 0,
  1043. tengo.MakeInstruction(parser.OpConstant, 0),
  1044. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  1045. tengo.MakeInstruction(parser.OpGetLocal, 0),
  1046. tengo.MakeInstruction(parser.OpConstant, 1),
  1047. tengo.MakeInstruction(parser.OpEqual),
  1048. tengo.MakeInstruction(parser.OpJumpFalsy, 21),
  1049. tengo.MakeInstruction(parser.OpConstant, 2),
  1050. tengo.MakeInstruction(parser.OpReturn, 1),
  1051. tengo.MakeInstruction(parser.OpConstant, 1),
  1052. tengo.MakeInstruction(parser.OpConstant, 1),
  1053. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  1054. tengo.MakeInstruction(parser.OpPop),
  1055. tengo.MakeInstruction(parser.OpConstant, 3),
  1056. tengo.MakeInstruction(parser.OpReturn, 1)))))
  1057. expectCompile(t, `
  1058. func() {
  1059. if true {
  1060. return 5
  1061. a := 4 // dead code from here
  1062. b := a
  1063. return b
  1064. } else {
  1065. return 4
  1066. c := 5 // dead code from here
  1067. d := c
  1068. return d
  1069. }
  1070. }`, bytecode(
  1071. concatInsts(
  1072. tengo.MakeInstruction(parser.OpConstant, 2),
  1073. tengo.MakeInstruction(parser.OpPop),
  1074. tengo.MakeInstruction(parser.OpSuspend)),
  1075. objectsArray(
  1076. intObject(5),
  1077. intObject(4),
  1078. compiledFunction(0, 0,
  1079. tengo.MakeInstruction(parser.OpTrue),
  1080. tengo.MakeInstruction(parser.OpJumpFalsy, 11),
  1081. tengo.MakeInstruction(parser.OpConstant, 0),
  1082. tengo.MakeInstruction(parser.OpReturn, 1),
  1083. tengo.MakeInstruction(parser.OpConstant, 1),
  1084. tengo.MakeInstruction(parser.OpReturn, 1)))))
  1085. expectCompile(t, `
  1086. func() {
  1087. if true {
  1088. return
  1089. }
  1090. return
  1091. return 123
  1092. }`, bytecode(
  1093. concatInsts(
  1094. tengo.MakeInstruction(parser.OpConstant, 1),
  1095. tengo.MakeInstruction(parser.OpPop),
  1096. tengo.MakeInstruction(parser.OpSuspend)),
  1097. objectsArray(
  1098. intObject(123),
  1099. compiledFunction(0, 0,
  1100. tengo.MakeInstruction(parser.OpTrue),
  1101. tengo.MakeInstruction(parser.OpJumpFalsy, 8),
  1102. tengo.MakeInstruction(parser.OpReturn, 0),
  1103. tengo.MakeInstruction(parser.OpReturn, 0),
  1104. tengo.MakeInstruction(parser.OpConstant, 0),
  1105. tengo.MakeInstruction(parser.OpReturn, 1)))))
  1106. }
  1107. func TestCompilerScopes(t *testing.T) {
  1108. expectCompile(t, `
  1109. if a := 1; a {
  1110. a = 2
  1111. b := a
  1112. } else {
  1113. a = 3
  1114. b := a
  1115. }`, bytecode(
  1116. concatInsts(
  1117. tengo.MakeInstruction(parser.OpConstant, 0),
  1118. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  1119. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  1120. tengo.MakeInstruction(parser.OpJumpFalsy, 31),
  1121. tengo.MakeInstruction(parser.OpConstant, 1),
  1122. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  1123. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  1124. tengo.MakeInstruction(parser.OpSetGlobal, 1),
  1125. tengo.MakeInstruction(parser.OpJump, 43),
  1126. tengo.MakeInstruction(parser.OpConstant, 2),
  1127. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  1128. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  1129. tengo.MakeInstruction(parser.OpSetGlobal, 2),
  1130. tengo.MakeInstruction(parser.OpSuspend)),
  1131. objectsArray(
  1132. intObject(1),
  1133. intObject(2),
  1134. intObject(3))))
  1135. expectCompile(t, `
  1136. func() {
  1137. if a := 1; a {
  1138. a = 2
  1139. b := a
  1140. } else {
  1141. a = 3
  1142. b := a
  1143. }
  1144. }`, bytecode(
  1145. concatInsts(
  1146. tengo.MakeInstruction(parser.OpConstant, 3),
  1147. tengo.MakeInstruction(parser.OpPop),
  1148. tengo.MakeInstruction(parser.OpSuspend)),
  1149. objectsArray(
  1150. intObject(1),
  1151. intObject(2),
  1152. intObject(3),
  1153. compiledFunction(0, 0,
  1154. tengo.MakeInstruction(parser.OpConstant, 0),
  1155. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  1156. tengo.MakeInstruction(parser.OpGetLocal, 0),
  1157. tengo.MakeInstruction(parser.OpJumpFalsy, 26),
  1158. tengo.MakeInstruction(parser.OpConstant, 1),
  1159. tengo.MakeInstruction(parser.OpSetLocal, 0),
  1160. tengo.MakeInstruction(parser.OpGetLocal, 0),
  1161. tengo.MakeInstruction(parser.OpDefineLocal, 1),
  1162. tengo.MakeInstruction(parser.OpJump, 35),
  1163. tengo.MakeInstruction(parser.OpConstant, 2),
  1164. tengo.MakeInstruction(parser.OpSetLocal, 0),
  1165. tengo.MakeInstruction(parser.OpGetLocal, 0),
  1166. tengo.MakeInstruction(parser.OpDefineLocal, 1),
  1167. tengo.MakeInstruction(parser.OpReturn, 0)))))
  1168. }
  1169. func TestCompiler_custom_extension(t *testing.T) {
  1170. pathFileSource := "./testdata/issue286/test.mshk"
  1171. modules := stdlib.GetModuleMap(stdlib.AllModuleNames()...)
  1172. src, err := ioutil.ReadFile(pathFileSource)
  1173. require.NoError(t, err)
  1174. // Escape shegang
  1175. if len(src) > 1 && string(src[:2]) == "#!" {
  1176. copy(src, "//")
  1177. }
  1178. fileSet := parser.NewFileSet()
  1179. srcFile := fileSet.AddFile(filepath.Base(pathFileSource), -1, len(src))
  1180. p := parser.NewParser(srcFile, src, nil)
  1181. file, err := p.ParseFile()
  1182. require.NoError(t, err)
  1183. c := tengo.NewCompiler(srcFile, nil, nil, modules, nil)
  1184. c.EnableFileImport(true)
  1185. c.SetImportDir(filepath.Dir(pathFileSource))
  1186. // Search for "*.tengo" and ".mshk"(custom extension)
  1187. c.SetImportFileExt(".tengo", ".mshk")
  1188. err = c.Compile(file)
  1189. require.NoError(t, err)
  1190. }
  1191. func TestCompilerNewCompiler_default_file_extension(t *testing.T) {
  1192. modules := stdlib.GetModuleMap(stdlib.AllModuleNames()...)
  1193. input := "{}"
  1194. fileSet := parser.NewFileSet()
  1195. file := fileSet.AddFile("test", -1, len(input))
  1196. c := tengo.NewCompiler(file, nil, nil, modules, nil)
  1197. c.EnableFileImport(true)
  1198. require.Equal(t, []string{".tengo"}, c.GetImportFileExt(),
  1199. "newly created compiler object must contain the default extension")
  1200. }
  1201. func TestCompilerSetImportExt_extension_name_validation(t *testing.T) {
  1202. c := new(tengo.Compiler) // Instantiate a new compiler object with no initialization
  1203. // Test of empty arg
  1204. err := c.SetImportFileExt()
  1205. require.Error(t, err, "empty arg should return an error")
  1206. // Test of various arg types
  1207. for _, test := range []struct {
  1208. extensions []string
  1209. expect []string
  1210. requireErr bool
  1211. msgFail string
  1212. }{
  1213. {[]string{".tengo"}, []string{".tengo"}, false,
  1214. "well-formed extension should not return an error"},
  1215. {[]string{""}, []string{".tengo"}, true,
  1216. "empty extension name should return an error"},
  1217. {[]string{"foo"}, []string{".tengo"}, true,
  1218. "name without dot prefix should return an error"},
  1219. {[]string{"foo.bar"}, []string{".tengo"}, true,
  1220. "malformed extension should return an error"},
  1221. {[]string{"foo."}, []string{".tengo"}, true,
  1222. "malformed extension should return an error"},
  1223. {[]string{".mshk"}, []string{".mshk"}, false,
  1224. "name with dot prefix should be added"},
  1225. {[]string{".foo", ".bar"}, []string{".foo", ".bar"}, false,
  1226. "it should replace instead of appending"},
  1227. } {
  1228. err := c.SetImportFileExt(test.extensions...)
  1229. if test.requireErr {
  1230. require.Error(t, err, test.msgFail)
  1231. }
  1232. expect := test.expect
  1233. actual := c.GetImportFileExt()
  1234. require.Equal(t, expect, actual, test.msgFail)
  1235. }
  1236. }
  1237. func concatInsts(instructions ...[]byte) []byte {
  1238. var concat []byte
  1239. for _, i := range instructions {
  1240. concat = append(concat, i...)
  1241. }
  1242. return concat
  1243. }
  1244. func bytecode(
  1245. instructions []byte,
  1246. constants []tengo.Object,
  1247. ) *tengo.Bytecode {
  1248. return &tengo.Bytecode{
  1249. FileSet: parser.NewFileSet(),
  1250. MainFunction: &tengo.CompiledFunction{Instructions: instructions},
  1251. Constants: constants,
  1252. }
  1253. }
  1254. func expectCompile(
  1255. t *testing.T,
  1256. input string,
  1257. expected *tengo.Bytecode,
  1258. ) {
  1259. actual, trace, err := traceCompile(input, nil)
  1260. var ok bool
  1261. defer func() {
  1262. if !ok {
  1263. for _, tr := range trace {
  1264. t.Log(tr)
  1265. }
  1266. }
  1267. }()
  1268. require.NoError(t, err)
  1269. equalBytecode(t, expected, actual)
  1270. ok = true
  1271. }
  1272. func expectCompileError(t *testing.T, input, expected string) {
  1273. _, trace, err := traceCompile(input, nil)
  1274. var ok bool
  1275. defer func() {
  1276. if !ok {
  1277. for _, tr := range trace {
  1278. t.Log(tr)
  1279. }
  1280. }
  1281. }()
  1282. require.Error(t, err)
  1283. require.True(t, strings.Contains(err.Error(), expected),
  1284. "expected error string: %s, got: %s", expected, err.Error())
  1285. ok = true
  1286. }
  1287. func equalBytecode(t *testing.T, expected, actual *tengo.Bytecode) {
  1288. require.Equal(t, expected.MainFunction, actual.MainFunction)
  1289. equalConstants(t, expected.Constants, actual.Constants)
  1290. }
  1291. func equalConstants(t *testing.T, expected, actual []tengo.Object) {
  1292. require.Equal(t, len(expected), len(actual))
  1293. for i := 0; i < len(expected); i++ {
  1294. require.Equal(t, expected[i], actual[i])
  1295. }
  1296. }
  1297. type compileTracer struct {
  1298. Out []string
  1299. }
  1300. func (o *compileTracer) Write(p []byte) (n int, err error) {
  1301. o.Out = append(o.Out, string(p))
  1302. return len(p), nil
  1303. }
  1304. func traceCompile(
  1305. input string,
  1306. symbols map[string]tengo.Object,
  1307. ) (res *tengo.Bytecode, trace []string, err error) {
  1308. fileSet := parser.NewFileSet()
  1309. file := fileSet.AddFile("test", -1, len(input))
  1310. p := parser.NewParser(file, []byte(input), nil)
  1311. symTable := tengo.NewSymbolTable()
  1312. for name := range symbols {
  1313. symTable.Define(name)
  1314. }
  1315. for idx, fn := range tengo.GetAllBuiltinFunctions() {
  1316. symTable.DefineBuiltin(idx, fn.Name)
  1317. }
  1318. tr := &compileTracer{}
  1319. c := tengo.NewCompiler(file, symTable, nil, nil, tr)
  1320. parsed, err := p.ParseFile()
  1321. if err != nil {
  1322. return
  1323. }
  1324. err = c.Compile(parsed)
  1325. res = c.Bytecode()
  1326. res.RemoveDuplicates()
  1327. {
  1328. trace = append(trace, fmt.Sprintf("Compiler Trace:\n%s",
  1329. strings.Join(tr.Out, "")))
  1330. trace = append(trace, fmt.Sprintf("Compiled Constants:\n%s",
  1331. strings.Join(res.FormatConstants(), "\n")))
  1332. trace = append(trace, fmt.Sprintf("Compiled Instructions:\n%s\n",
  1333. strings.Join(res.FormatInstructions(), "\n")))
  1334. }
  1335. if err != nil {
  1336. return
  1337. }
  1338. return
  1339. }
  1340. func objectsArray(o ...tengo.Object) []tengo.Object {
  1341. return o
  1342. }
  1343. func intObject(v int64) *tengo.Int {
  1344. return &tengo.Int{Value: v}
  1345. }
  1346. func stringObject(v string) *tengo.String {
  1347. return &tengo.String{Value: v}
  1348. }
  1349. func compiledFunction(
  1350. numLocals, numParams int,
  1351. insts ...[]byte,
  1352. ) *tengo.CompiledFunction {
  1353. return &tengo.CompiledFunction{
  1354. Instructions: concatInsts(insts...),
  1355. NumLocals: numLocals,
  1356. NumParameters: numParams,
  1357. }
  1358. }