compiler_test.go 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478
  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, 39),
  100. tengo.MakeInstruction(parser.OpPop),
  101. tengo.MakeInstruction(parser.OpSuspend)),
  102. objectsArray(
  103. intObject(2),
  104. intObject(1))))
  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, 44),
  122. tengo.MakeInstruction(parser.OpPop),
  123. tengo.MakeInstruction(parser.OpSuspend)),
  124. objectsArray(
  125. intObject(2),
  126. intObject(1))))
  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, 8), // 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, 11), // 0001
  202. tengo.MakeInstruction(parser.OpConstant, 0), // 0004
  203. tengo.MakeInstruction(parser.OpPop), // 0007
  204. tengo.MakeInstruction(parser.OpJump, 15), // 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, 9), // 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, 15), // 0005
  559. tengo.MakeInstruction(parser.OpConstant, 1), // 0008
  560. tengo.MakeInstruction(parser.OpPop), // 0011
  561. tengo.MakeInstruction(parser.OpJump, 19), // 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.OpConstant, 1),
  868. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  869. tengo.MakeInstruction(parser.OpBinaryOp, 39),
  870. tengo.MakeInstruction(parser.OpJumpFalsy, 31),
  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, 37),
  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, 23),
  910. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  911. tengo.MakeInstruction(parser.OpConstant, 1),
  912. tengo.MakeInstruction(parser.OpNotEqual),
  913. tengo.MakeInstruction(parser.OpOrJump, 34),
  914. tengo.MakeInstruction(parser.OpConstant, 1),
  915. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  916. tengo.MakeInstruction(parser.OpBinaryOp, 39),
  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, b := 1, 2`,
  954. "Compile Error: tuple assignment not allowed\n\tat test:1:1")
  955. expectCompileError(t, `a.b := 1`,
  956. "not allowed with selector")
  957. expectCompileError(t, `a:=1; a:=3`,
  958. "Compile Error: 'a' redeclared in this block\n\tat test:1:7")
  959. expectCompileError(t, `return 5`,
  960. "Compile Error: return not allowed outside function\n\tat test:1:1")
  961. expectCompileError(t, `func() { break }`,
  962. "Compile Error: break not allowed outside loop\n\tat test:1:10")
  963. expectCompileError(t, `func() { continue }`,
  964. "Compile Error: continue not allowed outside loop\n\tat test:1:10")
  965. expectCompileError(t, `func() { export 5 }`,
  966. "Compile Error: export not allowed inside function\n\tat test:1:10")
  967. }
  968. func TestCompilerDeadCode(t *testing.T) {
  969. expectCompile(t, `
  970. func() {
  971. a := 4
  972. return a
  973. b := 5 // dead code from here
  974. c := a
  975. return b
  976. }`,
  977. bytecode(
  978. concatInsts(
  979. tengo.MakeInstruction(parser.OpConstant, 2),
  980. tengo.MakeInstruction(parser.OpPop),
  981. tengo.MakeInstruction(parser.OpSuspend)),
  982. objectsArray(
  983. intObject(4),
  984. intObject(5),
  985. compiledFunction(0, 0,
  986. tengo.MakeInstruction(parser.OpConstant, 0),
  987. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  988. tengo.MakeInstruction(parser.OpGetLocal, 0),
  989. tengo.MakeInstruction(parser.OpReturn, 1)))))
  990. expectCompile(t, `
  991. func() {
  992. if true {
  993. return 5
  994. a := 4 // dead code from here
  995. b := a
  996. return b
  997. } else {
  998. return 4
  999. c := 5 // dead code from here
  1000. d := c
  1001. return d
  1002. }
  1003. }`, bytecode(
  1004. concatInsts(
  1005. tengo.MakeInstruction(parser.OpConstant, 2),
  1006. tengo.MakeInstruction(parser.OpPop),
  1007. tengo.MakeInstruction(parser.OpSuspend)),
  1008. objectsArray(
  1009. intObject(5),
  1010. intObject(4),
  1011. compiledFunction(0, 0,
  1012. tengo.MakeInstruction(parser.OpTrue),
  1013. tengo.MakeInstruction(parser.OpJumpFalsy, 9),
  1014. tengo.MakeInstruction(parser.OpConstant, 0),
  1015. tengo.MakeInstruction(parser.OpReturn, 1),
  1016. tengo.MakeInstruction(parser.OpConstant, 1),
  1017. tengo.MakeInstruction(parser.OpReturn, 1)))))
  1018. expectCompile(t, `
  1019. func() {
  1020. a := 1
  1021. for {
  1022. if a == 5 {
  1023. return 10
  1024. }
  1025. 5 + 5
  1026. return 20
  1027. b := a
  1028. return b
  1029. }
  1030. }`, bytecode(
  1031. concatInsts(
  1032. tengo.MakeInstruction(parser.OpConstant, 4),
  1033. tengo.MakeInstruction(parser.OpPop),
  1034. tengo.MakeInstruction(parser.OpSuspend)),
  1035. objectsArray(
  1036. intObject(1),
  1037. intObject(5),
  1038. intObject(10),
  1039. intObject(20),
  1040. compiledFunction(0, 0,
  1041. tengo.MakeInstruction(parser.OpConstant, 0),
  1042. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  1043. tengo.MakeInstruction(parser.OpGetLocal, 0),
  1044. tengo.MakeInstruction(parser.OpConstant, 1),
  1045. tengo.MakeInstruction(parser.OpEqual),
  1046. tengo.MakeInstruction(parser.OpJumpFalsy, 19),
  1047. tengo.MakeInstruction(parser.OpConstant, 2),
  1048. tengo.MakeInstruction(parser.OpReturn, 1),
  1049. tengo.MakeInstruction(parser.OpConstant, 1),
  1050. tengo.MakeInstruction(parser.OpConstant, 1),
  1051. tengo.MakeInstruction(parser.OpBinaryOp, 11),
  1052. tengo.MakeInstruction(parser.OpPop),
  1053. tengo.MakeInstruction(parser.OpConstant, 3),
  1054. tengo.MakeInstruction(parser.OpReturn, 1)))))
  1055. expectCompile(t, `
  1056. func() {
  1057. if true {
  1058. return 5
  1059. a := 4 // dead code from here
  1060. b := a
  1061. return b
  1062. } else {
  1063. return 4
  1064. c := 5 // dead code from here
  1065. d := c
  1066. return d
  1067. }
  1068. }`, bytecode(
  1069. concatInsts(
  1070. tengo.MakeInstruction(parser.OpConstant, 2),
  1071. tengo.MakeInstruction(parser.OpPop),
  1072. tengo.MakeInstruction(parser.OpSuspend)),
  1073. objectsArray(
  1074. intObject(5),
  1075. intObject(4),
  1076. compiledFunction(0, 0,
  1077. tengo.MakeInstruction(parser.OpTrue),
  1078. tengo.MakeInstruction(parser.OpJumpFalsy, 9),
  1079. tengo.MakeInstruction(parser.OpConstant, 0),
  1080. tengo.MakeInstruction(parser.OpReturn, 1),
  1081. tengo.MakeInstruction(parser.OpConstant, 1),
  1082. tengo.MakeInstruction(parser.OpReturn, 1)))))
  1083. expectCompile(t, `
  1084. func() {
  1085. if true {
  1086. return
  1087. }
  1088. return
  1089. return 123
  1090. }`, bytecode(
  1091. concatInsts(
  1092. tengo.MakeInstruction(parser.OpConstant, 1),
  1093. tengo.MakeInstruction(parser.OpPop),
  1094. tengo.MakeInstruction(parser.OpSuspend)),
  1095. objectsArray(
  1096. intObject(123),
  1097. compiledFunction(0, 0,
  1098. tengo.MakeInstruction(parser.OpTrue),
  1099. tengo.MakeInstruction(parser.OpJumpFalsy, 6),
  1100. tengo.MakeInstruction(parser.OpReturn, 0),
  1101. tengo.MakeInstruction(parser.OpReturn, 0),
  1102. tengo.MakeInstruction(parser.OpConstant, 0),
  1103. tengo.MakeInstruction(parser.OpReturn, 1)))))
  1104. }
  1105. func TestCompilerScopes(t *testing.T) {
  1106. expectCompile(t, `
  1107. if a := 1; a {
  1108. a = 2
  1109. b := a
  1110. } else {
  1111. a = 3
  1112. b := a
  1113. }`, bytecode(
  1114. concatInsts(
  1115. tengo.MakeInstruction(parser.OpConstant, 0),
  1116. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  1117. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  1118. tengo.MakeInstruction(parser.OpJumpFalsy, 27),
  1119. tengo.MakeInstruction(parser.OpConstant, 1),
  1120. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  1121. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  1122. tengo.MakeInstruction(parser.OpSetGlobal, 1),
  1123. tengo.MakeInstruction(parser.OpJump, 39),
  1124. tengo.MakeInstruction(parser.OpConstant, 2),
  1125. tengo.MakeInstruction(parser.OpSetGlobal, 0),
  1126. tengo.MakeInstruction(parser.OpGetGlobal, 0),
  1127. tengo.MakeInstruction(parser.OpSetGlobal, 2),
  1128. tengo.MakeInstruction(parser.OpSuspend)),
  1129. objectsArray(
  1130. intObject(1),
  1131. intObject(2),
  1132. intObject(3))))
  1133. expectCompile(t, `
  1134. func() {
  1135. if a := 1; a {
  1136. a = 2
  1137. b := a
  1138. } else {
  1139. a = 3
  1140. b := a
  1141. }
  1142. }`, bytecode(
  1143. concatInsts(
  1144. tengo.MakeInstruction(parser.OpConstant, 3),
  1145. tengo.MakeInstruction(parser.OpPop),
  1146. tengo.MakeInstruction(parser.OpSuspend)),
  1147. objectsArray(
  1148. intObject(1),
  1149. intObject(2),
  1150. intObject(3),
  1151. compiledFunction(0, 0,
  1152. tengo.MakeInstruction(parser.OpConstant, 0),
  1153. tengo.MakeInstruction(parser.OpDefineLocal, 0),
  1154. tengo.MakeInstruction(parser.OpGetLocal, 0),
  1155. tengo.MakeInstruction(parser.OpJumpFalsy, 22),
  1156. tengo.MakeInstruction(parser.OpConstant, 1),
  1157. tengo.MakeInstruction(parser.OpSetLocal, 0),
  1158. tengo.MakeInstruction(parser.OpGetLocal, 0),
  1159. tengo.MakeInstruction(parser.OpDefineLocal, 1),
  1160. tengo.MakeInstruction(parser.OpJump, 31),
  1161. tengo.MakeInstruction(parser.OpConstant, 2),
  1162. tengo.MakeInstruction(parser.OpSetLocal, 0),
  1163. tengo.MakeInstruction(parser.OpGetLocal, 0),
  1164. tengo.MakeInstruction(parser.OpDefineLocal, 1),
  1165. tengo.MakeInstruction(parser.OpReturn, 0)))))
  1166. }
  1167. func TestCompiler_custom_extension(t *testing.T) {
  1168. pathFileSource := "./testdata/issue286/test.mshk"
  1169. modules := stdlib.GetModuleMap(stdlib.AllModuleNames()...)
  1170. src, err := ioutil.ReadFile(pathFileSource)
  1171. require.NoError(t, err)
  1172. // Escape shegang
  1173. if len(src) > 1 && string(src[:2]) == "#!" {
  1174. copy(src, "//")
  1175. }
  1176. fileSet := parser.NewFileSet()
  1177. srcFile := fileSet.AddFile(filepath.Base(pathFileSource), -1, len(src))
  1178. p := parser.NewParser(srcFile, src, nil)
  1179. file, err := p.ParseFile()
  1180. require.NoError(t, err)
  1181. c := tengo.NewCompiler(srcFile, nil, nil, modules, nil)
  1182. c.EnableFileImport(true)
  1183. c.SetImportDir(filepath.Dir(pathFileSource))
  1184. // Search for "*.tengo" and ".mshk"(custom extension)
  1185. c.SetImportFileExt(".tengo", ".mshk")
  1186. err = c.Compile(file)
  1187. require.NoError(t, err)
  1188. }
  1189. func TestCompilerNewCompiler_default_file_extension(t *testing.T) {
  1190. modules := stdlib.GetModuleMap(stdlib.AllModuleNames()...)
  1191. input := "{}"
  1192. fileSet := parser.NewFileSet()
  1193. file := fileSet.AddFile("test", -1, len(input))
  1194. c := tengo.NewCompiler(file, nil, nil, modules, nil)
  1195. c.EnableFileImport(true)
  1196. require.Equal(t, []string{".tengo"}, c.GetImportFileExt(),
  1197. "newly created compiler object must contain the default extension")
  1198. }
  1199. func TestCompilerSetImportExt_extension_name_validation(t *testing.T) {
  1200. c := new(tengo.Compiler) // Instantiate a new compiler object with no initialization
  1201. // Test of empty arg
  1202. err := c.SetImportFileExt()
  1203. require.Error(t, err, "empty arg should return an error")
  1204. // Test of various arg types
  1205. for _, test := range []struct {
  1206. extensions []string
  1207. expect []string
  1208. requireErr bool
  1209. msgFail string
  1210. }{
  1211. {[]string{".tengo"}, []string{".tengo"}, false,
  1212. "well-formed extension should not return an error"},
  1213. {[]string{""}, []string{".tengo"}, true,
  1214. "empty extension name should return an error"},
  1215. {[]string{"foo"}, []string{".tengo"}, true,
  1216. "name without dot prefix should return an error"},
  1217. {[]string{"foo.bar"}, []string{".tengo"}, true,
  1218. "malformed extension should return an error"},
  1219. {[]string{"foo."}, []string{".tengo"}, true,
  1220. "malformed extension should return an error"},
  1221. {[]string{".mshk"}, []string{".mshk"}, false,
  1222. "name with dot prefix should be added"},
  1223. {[]string{".foo", ".bar"}, []string{".foo", ".bar"}, false,
  1224. "it should replace instead of appending"},
  1225. } {
  1226. err := c.SetImportFileExt(test.extensions...)
  1227. if test.requireErr {
  1228. require.Error(t, err, test.msgFail)
  1229. }
  1230. expect := test.expect
  1231. actual := c.GetImportFileExt()
  1232. require.Equal(t, expect, actual, test.msgFail)
  1233. }
  1234. }
  1235. func concatInsts(instructions ...[]byte) []byte {
  1236. var concat []byte
  1237. for _, i := range instructions {
  1238. concat = append(concat, i...)
  1239. }
  1240. return concat
  1241. }
  1242. func bytecode(
  1243. instructions []byte,
  1244. constants []tengo.Object,
  1245. ) *tengo.Bytecode {
  1246. return &tengo.Bytecode{
  1247. FileSet: parser.NewFileSet(),
  1248. MainFunction: &tengo.CompiledFunction{Instructions: instructions},
  1249. Constants: constants,
  1250. }
  1251. }
  1252. func expectCompile(
  1253. t *testing.T,
  1254. input string,
  1255. expected *tengo.Bytecode,
  1256. ) {
  1257. actual, trace, err := traceCompile(input, nil)
  1258. var ok bool
  1259. defer func() {
  1260. if !ok {
  1261. for _, tr := range trace {
  1262. t.Log(tr)
  1263. }
  1264. }
  1265. }()
  1266. require.NoError(t, err)
  1267. equalBytecode(t, expected, actual)
  1268. ok = true
  1269. }
  1270. func expectCompileError(t *testing.T, input, expected string) {
  1271. _, trace, err := traceCompile(input, nil)
  1272. var ok bool
  1273. defer func() {
  1274. if !ok {
  1275. for _, tr := range trace {
  1276. t.Log(tr)
  1277. }
  1278. }
  1279. }()
  1280. require.Error(t, err)
  1281. require.True(t, strings.Contains(err.Error(), expected),
  1282. "expected error string: %s, got: %s", expected, err.Error())
  1283. ok = true
  1284. }
  1285. func equalBytecode(t *testing.T, expected, actual *tengo.Bytecode) {
  1286. require.Equal(t, expected.MainFunction, actual.MainFunction)
  1287. equalConstants(t, expected.Constants, actual.Constants)
  1288. }
  1289. func equalConstants(t *testing.T, expected, actual []tengo.Object) {
  1290. require.Equal(t, len(expected), len(actual))
  1291. for i := 0; i < len(expected); i++ {
  1292. require.Equal(t, expected[i], actual[i])
  1293. }
  1294. }
  1295. type compileTracer struct {
  1296. Out []string
  1297. }
  1298. func (o *compileTracer) Write(p []byte) (n int, err error) {
  1299. o.Out = append(o.Out, string(p))
  1300. return len(p), nil
  1301. }
  1302. func traceCompile(
  1303. input string,
  1304. symbols map[string]tengo.Object,
  1305. ) (res *tengo.Bytecode, trace []string, err error) {
  1306. fileSet := parser.NewFileSet()
  1307. file := fileSet.AddFile("test", -1, len(input))
  1308. p := parser.NewParser(file, []byte(input), nil)
  1309. symTable := tengo.NewSymbolTable()
  1310. for name := range symbols {
  1311. symTable.Define(name)
  1312. }
  1313. for idx, fn := range tengo.GetAllBuiltinFunctions() {
  1314. symTable.DefineBuiltin(idx, fn.Name)
  1315. }
  1316. tr := &compileTracer{}
  1317. c := tengo.NewCompiler(file, symTable, nil, nil, tr)
  1318. parsed, err := p.ParseFile()
  1319. if err != nil {
  1320. return
  1321. }
  1322. err = c.Compile(parsed)
  1323. res = c.Bytecode()
  1324. res.RemoveDuplicates()
  1325. {
  1326. trace = append(trace, fmt.Sprintf("Compiler Trace:\n%s",
  1327. strings.Join(tr.Out, "")))
  1328. trace = append(trace, fmt.Sprintf("Compiled Constants:\n%s",
  1329. strings.Join(res.FormatConstants(), "\n")))
  1330. trace = append(trace, fmt.Sprintf("Compiled Instructions:\n%s\n",
  1331. strings.Join(res.FormatInstructions(), "\n")))
  1332. }
  1333. if err != nil {
  1334. return
  1335. }
  1336. return
  1337. }
  1338. func objectsArray(o ...tengo.Object) []tengo.Object {
  1339. return o
  1340. }
  1341. func intObject(v int64) tengo.Int {
  1342. return tengo.Int{Value: v}
  1343. }
  1344. func stringObject(v string) *tengo.String {
  1345. return &tengo.String{Value: v}
  1346. }
  1347. func compiledFunction(
  1348. numLocals, numParams int,
  1349. insts ...[]byte,
  1350. ) *tengo.CompiledFunction {
  1351. return &tengo.CompiledFunction{
  1352. Instructions: concatInsts(insts...),
  1353. NumLocals: numLocals,
  1354. NumParameters: numParams,
  1355. }
  1356. }