compiler.go 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387
  1. package tengo
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "io/ioutil"
  7. "os"
  8. "path/filepath"
  9. "reflect"
  10. "strings"
  11. "github.com/d5/tengo/v2/parser"
  12. "github.com/d5/tengo/v2/token"
  13. )
  14. // compilationScope represents a compiled instructions and the last two
  15. // instructions that were emitted.
  16. type compilationScope struct {
  17. Instructions []byte
  18. SymbolInit map[string]bool
  19. SourceMap map[int]parser.Pos
  20. }
  21. // loop represents a loop construct that the compiler uses to track the current
  22. // loop.
  23. type loop struct {
  24. Continues []int
  25. Breaks []int
  26. }
  27. // CompilerError represents a compiler error.
  28. type CompilerError struct {
  29. FileSet *parser.SourceFileSet
  30. Node parser.Node
  31. Err error
  32. }
  33. func (e *CompilerError) Error() string {
  34. filePos := e.FileSet.Position(e.Node.Pos())
  35. return fmt.Sprintf("Compile Error: %s\n\tat %s", e.Err.Error(), filePos)
  36. }
  37. // Compiler compiles the AST into a bytecode.
  38. type Compiler struct {
  39. file *parser.SourceFile
  40. parent *Compiler
  41. modulePath string
  42. importDir string
  43. importFileExt []string
  44. constants []Object
  45. symbolTable *SymbolTable
  46. scopes []compilationScope
  47. scopeIndex int
  48. modules ModuleGetter
  49. compiledModules map[string]*CompiledFunction
  50. allowFileImport bool
  51. loops []*loop
  52. loopIndex int
  53. trace io.Writer
  54. indent int
  55. }
  56. // NewCompiler creates a Compiler.
  57. func NewCompiler(
  58. file *parser.SourceFile,
  59. symbolTable *SymbolTable,
  60. constants []Object,
  61. modules ModuleGetter,
  62. trace io.Writer,
  63. ) *Compiler {
  64. mainScope := compilationScope{
  65. SymbolInit: make(map[string]bool),
  66. SourceMap: make(map[int]parser.Pos),
  67. }
  68. // symbol table
  69. if symbolTable == nil {
  70. symbolTable = NewSymbolTable()
  71. }
  72. // add builtin functions to the symbol table
  73. for idx, fn := range builtinFuncs {
  74. symbolTable.DefineBuiltin(idx, fn.Name)
  75. }
  76. // builtin modules
  77. if modules == nil {
  78. modules = NewModuleMap()
  79. }
  80. return &Compiler{
  81. file: file,
  82. symbolTable: symbolTable,
  83. constants: constants,
  84. scopes: []compilationScope{mainScope},
  85. scopeIndex: 0,
  86. loopIndex: -1,
  87. trace: trace,
  88. modules: modules,
  89. compiledModules: make(map[string]*CompiledFunction),
  90. importFileExt: []string{SourceFileExtDefault},
  91. }
  92. }
  93. // Compile compiles the AST node.
  94. func (c *Compiler) Compile(node parser.Node) error {
  95. if c.trace != nil {
  96. if node != nil {
  97. defer untracec(tracec(c, fmt.Sprintf("%s (%s)",
  98. node.String(), reflect.TypeOf(node).Elem().Name())))
  99. } else {
  100. defer untracec(tracec(c, "<nil>"))
  101. }
  102. }
  103. switch node := node.(type) {
  104. case *parser.File:
  105. for _, stmt := range node.Stmts {
  106. if err := c.Compile(stmt); err != nil {
  107. return err
  108. }
  109. }
  110. case *parser.ExprStmt:
  111. if err := c.Compile(node.Expr); err != nil {
  112. return err
  113. }
  114. c.emit(node, parser.OpPop)
  115. case *parser.IncDecStmt:
  116. op := token.AddAssign
  117. if node.Token == token.Dec {
  118. op = token.SubAssign
  119. }
  120. return c.compileAssign(node, []parser.Expr{node.Expr},
  121. []parser.Expr{&parser.IntLit{Value: 1}}, op)
  122. case *parser.ParenExpr:
  123. if err := c.Compile(node.Expr); err != nil {
  124. return err
  125. }
  126. case *parser.BinaryExpr:
  127. if node.Token == token.LAnd || node.Token == token.LOr {
  128. return c.compileLogical(node)
  129. }
  130. if node.Token == token.Less {
  131. if err := c.Compile(node.RHS); err != nil {
  132. return err
  133. }
  134. if err := c.Compile(node.LHS); err != nil {
  135. return err
  136. }
  137. c.emit(node, parser.OpBinaryOp, int(token.Greater))
  138. return nil
  139. } else if node.Token == token.LessEq {
  140. if err := c.Compile(node.RHS); err != nil {
  141. return err
  142. }
  143. if err := c.Compile(node.LHS); err != nil {
  144. return err
  145. }
  146. c.emit(node, parser.OpBinaryOp, int(token.GreaterEq))
  147. return nil
  148. }
  149. if err := c.Compile(node.LHS); err != nil {
  150. return err
  151. }
  152. if err := c.Compile(node.RHS); err != nil {
  153. return err
  154. }
  155. switch node.Token {
  156. case token.Add:
  157. c.emit(node, parser.OpBinaryOp, int(token.Add))
  158. case token.Sub:
  159. c.emit(node, parser.OpBinaryOp, int(token.Sub))
  160. case token.Mul:
  161. c.emit(node, parser.OpBinaryOp, int(token.Mul))
  162. case token.Quo:
  163. c.emit(node, parser.OpBinaryOp, int(token.Quo))
  164. case token.Rem:
  165. c.emit(node, parser.OpBinaryOp, int(token.Rem))
  166. case token.Greater:
  167. c.emit(node, parser.OpBinaryOp, int(token.Greater))
  168. case token.GreaterEq:
  169. c.emit(node, parser.OpBinaryOp, int(token.GreaterEq))
  170. case token.Equal:
  171. c.emit(node, parser.OpEqual)
  172. case token.NotEqual:
  173. c.emit(node, parser.OpNotEqual)
  174. case token.And:
  175. c.emit(node, parser.OpBinaryOp, int(token.And))
  176. case token.Or:
  177. c.emit(node, parser.OpBinaryOp, int(token.Or))
  178. case token.Xor:
  179. c.emit(node, parser.OpBinaryOp, int(token.Xor))
  180. case token.AndNot:
  181. c.emit(node, parser.OpBinaryOp, int(token.AndNot))
  182. case token.Shl:
  183. c.emit(node, parser.OpBinaryOp, int(token.Shl))
  184. case token.Shr:
  185. c.emit(node, parser.OpBinaryOp, int(token.Shr))
  186. default:
  187. return c.errorf(node, "invalid binary operator: %s",
  188. node.Token.String())
  189. }
  190. case *parser.IntLit:
  191. c.emit(node, parser.OpConstant,
  192. c.addConstant(Int{Value: node.Value}))
  193. case *parser.FloatLit:
  194. c.emit(node, parser.OpConstant,
  195. c.addConstant(Float{Value: node.Value}))
  196. case *parser.BoolLit:
  197. if node.Value {
  198. c.emit(node, parser.OpTrue)
  199. } else {
  200. c.emit(node, parser.OpFalse)
  201. }
  202. case *parser.StringLit:
  203. if len(node.Value) > MaxStringLen {
  204. return c.error(node, ErrStringLimit)
  205. }
  206. c.emit(node, parser.OpConstant,
  207. c.addConstant(&String{Value: node.Value}))
  208. case *parser.CharLit:
  209. c.emit(node, parser.OpConstant,
  210. c.addConstant(Char{Value: node.Value}))
  211. case *parser.UndefinedLit:
  212. c.emit(node, parser.OpNull)
  213. case *parser.UnaryExpr:
  214. if err := c.Compile(node.Expr); err != nil {
  215. return err
  216. }
  217. switch node.Token {
  218. case token.Not:
  219. c.emit(node, parser.OpLNot)
  220. case token.Sub:
  221. c.emit(node, parser.OpMinus)
  222. case token.Xor:
  223. c.emit(node, parser.OpBComplement)
  224. case token.Add:
  225. // do nothing?
  226. default:
  227. return c.errorf(node,
  228. "invalid unary operator: %s", node.Token.String())
  229. }
  230. case *parser.IfStmt:
  231. // open new symbol table for the statement
  232. c.symbolTable = c.symbolTable.Fork(true)
  233. defer func() {
  234. c.symbolTable = c.symbolTable.Parent(false)
  235. }()
  236. if node.Init != nil {
  237. if err := c.Compile(node.Init); err != nil {
  238. return err
  239. }
  240. }
  241. if err := c.Compile(node.Cond); err != nil {
  242. return err
  243. }
  244. // first jump placeholder
  245. jumpPos1 := c.emit(node, parser.OpJumpFalsy, 0)
  246. if err := c.Compile(node.Body); err != nil {
  247. return err
  248. }
  249. if node.Else != nil {
  250. // second jump placeholder
  251. jumpPos2 := c.emit(node, parser.OpJump, 0)
  252. // update first jump offset
  253. curPos := len(c.currentInstructions())
  254. c.changeOperand(jumpPos1, curPos)
  255. if err := c.Compile(node.Else); err != nil {
  256. return err
  257. }
  258. // update second jump offset
  259. curPos = len(c.currentInstructions())
  260. c.changeOperand(jumpPos2, curPos)
  261. } else {
  262. // update first jump offset
  263. curPos := len(c.currentInstructions())
  264. c.changeOperand(jumpPos1, curPos)
  265. }
  266. case *parser.ForStmt:
  267. return c.compileForStmt(node)
  268. case *parser.ForInStmt:
  269. return c.compileForInStmt(node)
  270. case *parser.BranchStmt:
  271. if node.Token == token.Break {
  272. curLoop := c.currentLoop()
  273. if curLoop == nil {
  274. return c.errorf(node, "break not allowed outside loop")
  275. }
  276. pos := c.emit(node, parser.OpJump, 0)
  277. curLoop.Breaks = append(curLoop.Breaks, pos)
  278. } else if node.Token == token.Continue {
  279. curLoop := c.currentLoop()
  280. if curLoop == nil {
  281. return c.errorf(node, "continue not allowed outside loop")
  282. }
  283. pos := c.emit(node, parser.OpJump, 0)
  284. curLoop.Continues = append(curLoop.Continues, pos)
  285. } else {
  286. panic(fmt.Errorf("invalid branch statement: %s",
  287. node.Token.String()))
  288. }
  289. case *parser.BlockStmt:
  290. if len(node.Stmts) == 0 {
  291. return nil
  292. }
  293. c.symbolTable = c.symbolTable.Fork(true)
  294. defer func() {
  295. c.symbolTable = c.symbolTable.Parent(false)
  296. }()
  297. for _, stmt := range node.Stmts {
  298. if err := c.Compile(stmt); err != nil {
  299. return err
  300. }
  301. }
  302. case *parser.AssignStmt:
  303. err := c.compileAssign(node, node.LHS, node.RHS, node.Token)
  304. if err != nil {
  305. return err
  306. }
  307. case *parser.Ident:
  308. symbol, _, ok := c.symbolTable.Resolve(node.Name, false)
  309. if !ok {
  310. return c.errorf(node, "unresolved reference '%s'", node.Name)
  311. }
  312. switch symbol.Scope {
  313. case ScopeGlobal:
  314. c.emit(node, parser.OpGetGlobal, symbol.Index)
  315. case ScopeLocal:
  316. c.emit(node, parser.OpGetLocal, symbol.Index)
  317. case ScopeBuiltin:
  318. c.emit(node, parser.OpGetBuiltin, symbol.Index)
  319. case ScopeFree:
  320. c.emit(node, parser.OpGetFree, symbol.Index)
  321. }
  322. case *parser.ArrayLit:
  323. for _, elem := range node.Elements {
  324. if err := c.Compile(elem); err != nil {
  325. return err
  326. }
  327. }
  328. c.emit(node, parser.OpArray, len(node.Elements))
  329. case *parser.MapLit:
  330. for _, elt := range node.Elements {
  331. // key
  332. if len(elt.Key) > MaxStringLen {
  333. return c.error(node, ErrStringLimit)
  334. }
  335. c.emit(node, parser.OpConstant,
  336. c.addConstant(&String{Value: elt.Key}))
  337. // value
  338. if err := c.Compile(elt.Value); err != nil {
  339. return err
  340. }
  341. }
  342. c.emit(node, parser.OpMap, len(node.Elements)*2)
  343. case *parser.SelectorExpr: // selector on RHS side
  344. if err := c.Compile(node.Expr); err != nil {
  345. return err
  346. }
  347. if err := c.Compile(node.Sel); err != nil {
  348. return err
  349. }
  350. c.emit(node, parser.OpIndex)
  351. case *parser.IndexExpr:
  352. if err := c.Compile(node.Expr); err != nil {
  353. return err
  354. }
  355. if err := c.Compile(node.Index); err != nil {
  356. return err
  357. }
  358. c.emit(node, parser.OpIndex)
  359. case *parser.SliceExpr:
  360. if err := c.Compile(node.Expr); err != nil {
  361. return err
  362. }
  363. if node.Low != nil {
  364. if err := c.Compile(node.Low); err != nil {
  365. return err
  366. }
  367. } else {
  368. c.emit(node, parser.OpNull)
  369. }
  370. if node.High != nil {
  371. if err := c.Compile(node.High); err != nil {
  372. return err
  373. }
  374. } else {
  375. c.emit(node, parser.OpNull)
  376. }
  377. c.emit(node, parser.OpSliceIndex)
  378. case *parser.FuncLit:
  379. c.enterScope()
  380. for _, p := range node.Type.Params.List {
  381. s := c.symbolTable.Define(p.Name)
  382. // function arguments is not assigned directly.
  383. s.LocalAssigned = true
  384. }
  385. if err := c.Compile(node.Body); err != nil {
  386. return err
  387. }
  388. // code optimization
  389. c.optimizeFunc(node)
  390. freeSymbols := c.symbolTable.FreeSymbols()
  391. numLocals := c.symbolTable.MaxSymbols()
  392. instructions, sourceMap := c.leaveScope()
  393. for _, s := range freeSymbols {
  394. switch s.Scope {
  395. case ScopeLocal:
  396. if !s.LocalAssigned {
  397. // Here, the closure is capturing a local variable that's
  398. // not yet assigned its value. One example is a local
  399. // recursive function:
  400. //
  401. // func() {
  402. // foo := func(x) {
  403. // // ..
  404. // return foo(x-1)
  405. // }
  406. // }
  407. //
  408. // which translate into
  409. //
  410. // 0000 GETL 0
  411. // 0002 CLOSURE ? 1
  412. // 0006 DEFL 0
  413. //
  414. // . So the local variable (0) is being captured before
  415. // it's assigned the value.
  416. //
  417. // Solution is to transform the code into something like
  418. // this:
  419. //
  420. // func() {
  421. // foo := undefined
  422. // foo = func(x) {
  423. // // ..
  424. // return foo(x-1)
  425. // }
  426. // }
  427. //
  428. // that is equivalent to
  429. //
  430. // 0000 NULL
  431. // 0001 DEFL 0
  432. // 0003 GETL 0
  433. // 0005 CLOSURE ? 1
  434. // 0009 SETL 0
  435. //
  436. c.emit(node, parser.OpNull)
  437. c.emit(node, parser.OpDefineLocal, s.Index)
  438. s.LocalAssigned = true
  439. }
  440. c.emit(node, parser.OpGetLocalPtr, s.Index)
  441. case ScopeFree:
  442. c.emit(node, parser.OpGetFreePtr, s.Index)
  443. }
  444. }
  445. compiledFunction := &CompiledFunction{
  446. Instructions: instructions,
  447. NumLocals: numLocals,
  448. NumParameters: len(node.Type.Params.List),
  449. VarArgs: node.Type.Params.VarArgs,
  450. SourceMap: sourceMap,
  451. }
  452. if len(freeSymbols) > 0 {
  453. c.emit(node, parser.OpClosure,
  454. c.addConstant(compiledFunction), len(freeSymbols))
  455. } else {
  456. c.emit(node, parser.OpConstant, c.addConstant(compiledFunction))
  457. }
  458. case *parser.ReturnStmt:
  459. if c.symbolTable.Parent(true) == nil {
  460. // outside the function
  461. return c.errorf(node, "return not allowed outside function")
  462. }
  463. if node.Result == nil {
  464. c.emit(node, parser.OpReturn, 0)
  465. } else {
  466. if err := c.Compile(node.Result); err != nil {
  467. return err
  468. }
  469. c.emit(node, parser.OpReturn, 1)
  470. }
  471. case *parser.CallExpr:
  472. if err := c.Compile(node.Func); err != nil {
  473. return err
  474. }
  475. for _, arg := range node.Args {
  476. if err := c.Compile(arg); err != nil {
  477. return err
  478. }
  479. }
  480. ellipsis := 0
  481. if node.Ellipsis.IsValid() {
  482. ellipsis = 1
  483. }
  484. c.emit(node, parser.OpCall, len(node.Args), ellipsis)
  485. case *parser.ImportExpr:
  486. if node.ModuleName == "" {
  487. return c.errorf(node, "empty module name")
  488. }
  489. if mod := c.modules.Get(node.ModuleName); mod != nil {
  490. v, err := mod.Import(node.ModuleName)
  491. if err != nil {
  492. return err
  493. }
  494. switch v := v.(type) {
  495. case []byte: // module written in Tengo
  496. compiled, err := c.compileModule(node,
  497. node.ModuleName, v, false)
  498. if err != nil {
  499. return err
  500. }
  501. c.emit(node, parser.OpConstant, c.addConstant(compiled))
  502. c.emit(node, parser.OpCall, 0, 0)
  503. case Object: // builtin module
  504. c.emit(node, parser.OpConstant, c.addConstant(v))
  505. default:
  506. panic(fmt.Errorf("invalid import value type: %T", v))
  507. }
  508. } else if c.allowFileImport {
  509. moduleName := node.ModuleName
  510. modulePath, err := c.getPathModule(moduleName)
  511. if err != nil {
  512. return c.errorf(node, "module file path error: %s",
  513. err.Error())
  514. }
  515. moduleSrc, err := ioutil.ReadFile(modulePath)
  516. if err != nil {
  517. return c.errorf(node, "module file read error: %s",
  518. err.Error())
  519. }
  520. compiled, err := c.compileModule(node, modulePath, moduleSrc, true)
  521. if err != nil {
  522. return err
  523. }
  524. c.emit(node, parser.OpConstant, c.addConstant(compiled))
  525. c.emit(node, parser.OpCall, 0, 0)
  526. } else {
  527. return c.errorf(node, "module '%s' not found", node.ModuleName)
  528. }
  529. case *parser.ExportStmt:
  530. // export statement must be in top-level scope
  531. if c.scopeIndex != 0 {
  532. return c.errorf(node, "export not allowed inside function")
  533. }
  534. // export statement is simply ignore when compiling non-module code
  535. if c.parent == nil {
  536. break
  537. }
  538. if err := c.Compile(node.Result); err != nil {
  539. return err
  540. }
  541. c.emit(node, parser.OpImmutable)
  542. c.emit(node, parser.OpReturn, 1)
  543. case *parser.ErrorExpr:
  544. if err := c.Compile(node.Expr); err != nil {
  545. return err
  546. }
  547. c.emit(node, parser.OpError)
  548. case *parser.ImmutableExpr:
  549. if err := c.Compile(node.Expr); err != nil {
  550. return err
  551. }
  552. c.emit(node, parser.OpImmutable)
  553. case *parser.CondExpr:
  554. if err := c.Compile(node.Cond); err != nil {
  555. return err
  556. }
  557. // first jump placeholder
  558. jumpPos1 := c.emit(node, parser.OpJumpFalsy, 0)
  559. if err := c.Compile(node.True); err != nil {
  560. return err
  561. }
  562. // second jump placeholder
  563. jumpPos2 := c.emit(node, parser.OpJump, 0)
  564. // update first jump offset
  565. curPos := len(c.currentInstructions())
  566. c.changeOperand(jumpPos1, curPos)
  567. if err := c.Compile(node.False); err != nil {
  568. return err
  569. }
  570. // update second jump offset
  571. curPos = len(c.currentInstructions())
  572. c.changeOperand(jumpPos2, curPos)
  573. }
  574. return nil
  575. }
  576. // Bytecode returns a compiled bytecode.
  577. func (c *Compiler) Bytecode() *Bytecode {
  578. return &Bytecode{
  579. FileSet: c.file.Set(),
  580. MainFunction: &CompiledFunction{
  581. Instructions: append(c.currentInstructions(), parser.OpSuspend),
  582. SourceMap: c.currentSourceMap(),
  583. },
  584. Constants: c.constants,
  585. }
  586. }
  587. // EnableFileImport enables or disables module loading from local files.
  588. // Local file modules are disabled by default.
  589. func (c *Compiler) EnableFileImport(enable bool) {
  590. c.allowFileImport = enable
  591. }
  592. // SetImportDir sets the initial import directory path for file imports.
  593. func (c *Compiler) SetImportDir(dir string) {
  594. c.importDir = dir
  595. }
  596. // SetImportFileExt sets the extension name of the source file for loading
  597. // local module files.
  598. //
  599. // Use this method if you want other source file extension than ".tengo".
  600. //
  601. // // this will search for *.tengo, *.foo, *.bar
  602. // err := c.SetImportFileExt(".tengo", ".foo", ".bar")
  603. //
  604. // This function requires at least one argument, since it will replace the
  605. // current list of extension name.
  606. func (c *Compiler) SetImportFileExt(exts ...string) error {
  607. if len(exts) == 0 {
  608. return fmt.Errorf("missing arg: at least one argument is required")
  609. }
  610. for _, ext := range exts {
  611. if ext != filepath.Ext(ext) || ext == "" {
  612. return fmt.Errorf("invalid file extension: %s", ext)
  613. }
  614. }
  615. c.importFileExt = exts // Replace the hole current extension list
  616. return nil
  617. }
  618. // GetImportFileExt returns the current list of extension name.
  619. // Thease are the complementary suffix of the source file to search and load
  620. // local module files.
  621. func (c *Compiler) GetImportFileExt() []string {
  622. return c.importFileExt
  623. }
  624. func (c *Compiler) compileAssign(
  625. node parser.Node,
  626. lhs, rhs []parser.Expr,
  627. op token.Token,
  628. ) error {
  629. numLHS, numRHS := len(lhs), len(rhs)
  630. if numLHS > 1 || numRHS > 1 {
  631. return c.errorf(node, "tuple assignment not allowed")
  632. }
  633. // resolve and compile left-hand side
  634. ident, selectors := resolveAssignLHS(lhs[0])
  635. numSel := len(selectors)
  636. if op == token.Define && numSel > 0 {
  637. // using selector on new variable does not make sense
  638. return c.errorf(node, "operator ':=' not allowed with selector")
  639. }
  640. symbol, depth, exists := c.symbolTable.Resolve(ident, false)
  641. if op == token.Define {
  642. if depth == 0 && exists {
  643. return c.errorf(node, "'%s' redeclared in this block", ident)
  644. }
  645. symbol = c.symbolTable.Define(ident)
  646. } else {
  647. if !exists {
  648. return c.errorf(node, "unresolved reference '%s'", ident)
  649. }
  650. }
  651. // +=, -=, *=, /=
  652. if op != token.Assign && op != token.Define {
  653. if err := c.Compile(lhs[0]); err != nil {
  654. return err
  655. }
  656. }
  657. // compile RHSs
  658. for _, expr := range rhs {
  659. if err := c.Compile(expr); err != nil {
  660. return err
  661. }
  662. }
  663. switch op {
  664. case token.AddAssign:
  665. c.emit(node, parser.OpBinaryOp, int(token.Add))
  666. case token.SubAssign:
  667. c.emit(node, parser.OpBinaryOp, int(token.Sub))
  668. case token.MulAssign:
  669. c.emit(node, parser.OpBinaryOp, int(token.Mul))
  670. case token.QuoAssign:
  671. c.emit(node, parser.OpBinaryOp, int(token.Quo))
  672. case token.RemAssign:
  673. c.emit(node, parser.OpBinaryOp, int(token.Rem))
  674. case token.AndAssign:
  675. c.emit(node, parser.OpBinaryOp, int(token.And))
  676. case token.OrAssign:
  677. c.emit(node, parser.OpBinaryOp, int(token.Or))
  678. case token.AndNotAssign:
  679. c.emit(node, parser.OpBinaryOp, int(token.AndNot))
  680. case token.XorAssign:
  681. c.emit(node, parser.OpBinaryOp, int(token.Xor))
  682. case token.ShlAssign:
  683. c.emit(node, parser.OpBinaryOp, int(token.Shl))
  684. case token.ShrAssign:
  685. c.emit(node, parser.OpBinaryOp, int(token.Shr))
  686. }
  687. // compile selector expressions (right to left)
  688. for i := numSel - 1; i >= 0; i-- {
  689. if err := c.Compile(selectors[i]); err != nil {
  690. return err
  691. }
  692. }
  693. switch symbol.Scope {
  694. case ScopeGlobal:
  695. if numSel > 0 {
  696. c.emit(node, parser.OpSetSelGlobal, symbol.Index, numSel)
  697. } else {
  698. c.emit(node, parser.OpSetGlobal, symbol.Index)
  699. }
  700. case ScopeLocal:
  701. if numSel > 0 {
  702. c.emit(node, parser.OpSetSelLocal, symbol.Index, numSel)
  703. } else {
  704. if op == token.Define && !symbol.LocalAssigned {
  705. c.emit(node, parser.OpDefineLocal, symbol.Index)
  706. } else {
  707. c.emit(node, parser.OpSetLocal, symbol.Index)
  708. }
  709. }
  710. // mark the symbol as local-assigned
  711. symbol.LocalAssigned = true
  712. case ScopeFree:
  713. if numSel > 0 {
  714. c.emit(node, parser.OpSetSelFree, symbol.Index, numSel)
  715. } else {
  716. c.emit(node, parser.OpSetFree, symbol.Index)
  717. }
  718. default:
  719. panic(fmt.Errorf("invalid assignment variable scope: %s",
  720. symbol.Scope))
  721. }
  722. return nil
  723. }
  724. func (c *Compiler) compileLogical(node *parser.BinaryExpr) error {
  725. // left side term
  726. if err := c.Compile(node.LHS); err != nil {
  727. return err
  728. }
  729. // jump position
  730. var jumpPos int
  731. if node.Token == token.LAnd {
  732. jumpPos = c.emit(node, parser.OpAndJump, 0)
  733. } else {
  734. jumpPos = c.emit(node, parser.OpOrJump, 0)
  735. }
  736. // right side term
  737. if err := c.Compile(node.RHS); err != nil {
  738. return err
  739. }
  740. c.changeOperand(jumpPos, len(c.currentInstructions()))
  741. return nil
  742. }
  743. func (c *Compiler) compileForStmt(stmt *parser.ForStmt) error {
  744. c.symbolTable = c.symbolTable.Fork(true)
  745. defer func() {
  746. c.symbolTable = c.symbolTable.Parent(false)
  747. }()
  748. // init statement
  749. if stmt.Init != nil {
  750. if err := c.Compile(stmt.Init); err != nil {
  751. return err
  752. }
  753. }
  754. // pre-condition position
  755. preCondPos := len(c.currentInstructions())
  756. // condition expression
  757. postCondPos := -1
  758. if stmt.Cond != nil {
  759. if err := c.Compile(stmt.Cond); err != nil {
  760. return err
  761. }
  762. // condition jump position
  763. postCondPos = c.emit(stmt, parser.OpJumpFalsy, 0)
  764. }
  765. // enter loop
  766. loop := c.enterLoop()
  767. // body statement
  768. if err := c.Compile(stmt.Body); err != nil {
  769. c.leaveLoop()
  770. return err
  771. }
  772. c.leaveLoop()
  773. // post-body position
  774. postBodyPos := len(c.currentInstructions())
  775. // post statement
  776. if stmt.Post != nil {
  777. if err := c.Compile(stmt.Post); err != nil {
  778. return err
  779. }
  780. }
  781. // back to condition
  782. c.emit(stmt, parser.OpJump, preCondPos)
  783. // post-statement position
  784. postStmtPos := len(c.currentInstructions())
  785. if postCondPos >= 0 {
  786. c.changeOperand(postCondPos, postStmtPos)
  787. }
  788. // update all break/continue jump positions
  789. for _, pos := range loop.Breaks {
  790. c.changeOperand(pos, postStmtPos)
  791. }
  792. for _, pos := range loop.Continues {
  793. c.changeOperand(pos, postBodyPos)
  794. }
  795. return nil
  796. }
  797. func (c *Compiler) compileForInStmt(stmt *parser.ForInStmt) error {
  798. c.symbolTable = c.symbolTable.Fork(true)
  799. defer func() {
  800. c.symbolTable = c.symbolTable.Parent(false)
  801. }()
  802. // for-in statement is compiled like following:
  803. //
  804. // for :it := iterator(iterable); :it.next(); {
  805. // k, v := :it.get() // DEFINE operator
  806. //
  807. // ... body ...
  808. // }
  809. //
  810. // ":it" is a local variable but it will not conflict with other user variables
  811. // because character ":" is not allowed in the variable names.
  812. // init
  813. // :it = iterator(iterable)
  814. itSymbol := c.symbolTable.Define(":it")
  815. if err := c.Compile(stmt.Iterable); err != nil {
  816. return err
  817. }
  818. c.emit(stmt, parser.OpIteratorInit)
  819. if itSymbol.Scope == ScopeGlobal {
  820. c.emit(stmt, parser.OpSetGlobal, itSymbol.Index)
  821. } else {
  822. c.emit(stmt, parser.OpDefineLocal, itSymbol.Index)
  823. }
  824. // pre-condition position
  825. preCondPos := len(c.currentInstructions())
  826. // condition
  827. // :it.HasMore()
  828. if itSymbol.Scope == ScopeGlobal {
  829. c.emit(stmt, parser.OpGetGlobal, itSymbol.Index)
  830. } else {
  831. c.emit(stmt, parser.OpGetLocal, itSymbol.Index)
  832. }
  833. c.emit(stmt, parser.OpIteratorNext)
  834. // condition jump position
  835. postCondPos := c.emit(stmt, parser.OpJumpFalsy, 0)
  836. // enter loop
  837. loop := c.enterLoop()
  838. // assign key variable
  839. if stmt.Key.Name != "_" {
  840. keySymbol := c.symbolTable.Define(stmt.Key.Name)
  841. if itSymbol.Scope == ScopeGlobal {
  842. c.emit(stmt, parser.OpGetGlobal, itSymbol.Index)
  843. } else {
  844. c.emit(stmt, parser.OpGetLocal, itSymbol.Index)
  845. }
  846. c.emit(stmt, parser.OpIteratorKey)
  847. if keySymbol.Scope == ScopeGlobal {
  848. c.emit(stmt, parser.OpSetGlobal, keySymbol.Index)
  849. } else {
  850. keySymbol.LocalAssigned = true
  851. c.emit(stmt, parser.OpDefineLocal, keySymbol.Index)
  852. }
  853. }
  854. // assign value variable
  855. if stmt.Value.Name != "_" {
  856. valueSymbol := c.symbolTable.Define(stmt.Value.Name)
  857. if itSymbol.Scope == ScopeGlobal {
  858. c.emit(stmt, parser.OpGetGlobal, itSymbol.Index)
  859. } else {
  860. c.emit(stmt, parser.OpGetLocal, itSymbol.Index)
  861. }
  862. c.emit(stmt, parser.OpIteratorValue)
  863. if valueSymbol.Scope == ScopeGlobal {
  864. c.emit(stmt, parser.OpSetGlobal, valueSymbol.Index)
  865. } else {
  866. valueSymbol.LocalAssigned = true
  867. c.emit(stmt, parser.OpDefineLocal, valueSymbol.Index)
  868. }
  869. }
  870. // body statement
  871. if err := c.Compile(stmt.Body); err != nil {
  872. c.leaveLoop()
  873. return err
  874. }
  875. c.leaveLoop()
  876. // post-body position
  877. postBodyPos := len(c.currentInstructions())
  878. // back to condition
  879. c.emit(stmt, parser.OpJump, preCondPos)
  880. // post-statement position
  881. postStmtPos := len(c.currentInstructions())
  882. c.changeOperand(postCondPos, postStmtPos)
  883. // update all break/continue jump positions
  884. for _, pos := range loop.Breaks {
  885. c.changeOperand(pos, postStmtPos)
  886. }
  887. for _, pos := range loop.Continues {
  888. c.changeOperand(pos, postBodyPos)
  889. }
  890. return nil
  891. }
  892. func (c *Compiler) checkCyclicImports(
  893. node parser.Node,
  894. modulePath string,
  895. ) error {
  896. if c.modulePath == modulePath {
  897. return c.errorf(node, "cyclic module import: %s", modulePath)
  898. } else if c.parent != nil {
  899. return c.parent.checkCyclicImports(node, modulePath)
  900. }
  901. return nil
  902. }
  903. func (c *Compiler) compileModule(
  904. node parser.Node,
  905. modulePath string,
  906. src []byte,
  907. isFile bool,
  908. ) (*CompiledFunction, error) {
  909. if err := c.checkCyclicImports(node, modulePath); err != nil {
  910. return nil, err
  911. }
  912. compiledModule, exists := c.loadCompiledModule(modulePath)
  913. if exists {
  914. return compiledModule, nil
  915. }
  916. modFile := c.file.Set().AddFile(modulePath, -1, len(src))
  917. p := parser.NewParser(modFile, src, nil)
  918. file, err := p.ParseFile()
  919. if err != nil {
  920. return nil, err
  921. }
  922. // inherit builtin functions
  923. symbolTable := NewSymbolTable()
  924. for _, sym := range c.symbolTable.BuiltinSymbols() {
  925. symbolTable.DefineBuiltin(sym.Index, sym.Name)
  926. }
  927. // no global scope for the module
  928. symbolTable = symbolTable.Fork(false)
  929. // compile module
  930. moduleCompiler := c.fork(modFile, modulePath, symbolTable, isFile)
  931. if err := moduleCompiler.Compile(file); err != nil {
  932. return nil, err
  933. }
  934. // code optimization
  935. moduleCompiler.optimizeFunc(node)
  936. compiledFunc := moduleCompiler.Bytecode().MainFunction
  937. compiledFunc.NumLocals = symbolTable.MaxSymbols()
  938. c.storeCompiledModule(modulePath, compiledFunc)
  939. return compiledFunc, nil
  940. }
  941. func (c *Compiler) loadCompiledModule(
  942. modulePath string,
  943. ) (mod *CompiledFunction, ok bool) {
  944. if c.parent != nil {
  945. return c.parent.loadCompiledModule(modulePath)
  946. }
  947. mod, ok = c.compiledModules[modulePath]
  948. return
  949. }
  950. func (c *Compiler) storeCompiledModule(
  951. modulePath string,
  952. module *CompiledFunction,
  953. ) {
  954. if c.parent != nil {
  955. c.parent.storeCompiledModule(modulePath, module)
  956. }
  957. c.compiledModules[modulePath] = module
  958. }
  959. func (c *Compiler) enterLoop() *loop {
  960. loop := &loop{}
  961. c.loops = append(c.loops, loop)
  962. c.loopIndex++
  963. if c.trace != nil {
  964. c.printTrace("LOOPE", c.loopIndex)
  965. }
  966. return loop
  967. }
  968. func (c *Compiler) leaveLoop() {
  969. if c.trace != nil {
  970. c.printTrace("LOOPL", c.loopIndex)
  971. }
  972. c.loops = c.loops[:len(c.loops)-1]
  973. c.loopIndex--
  974. }
  975. func (c *Compiler) currentLoop() *loop {
  976. if c.loopIndex >= 0 {
  977. return c.loops[c.loopIndex]
  978. }
  979. return nil
  980. }
  981. func (c *Compiler) currentInstructions() []byte {
  982. return c.scopes[c.scopeIndex].Instructions
  983. }
  984. func (c *Compiler) currentSourceMap() map[int]parser.Pos {
  985. return c.scopes[c.scopeIndex].SourceMap
  986. }
  987. func (c *Compiler) enterScope() {
  988. scope := compilationScope{
  989. SymbolInit: make(map[string]bool),
  990. SourceMap: make(map[int]parser.Pos),
  991. }
  992. c.scopes = append(c.scopes, scope)
  993. c.scopeIndex++
  994. c.symbolTable = c.symbolTable.Fork(false)
  995. if c.trace != nil {
  996. c.printTrace("SCOPE", c.scopeIndex)
  997. }
  998. }
  999. func (c *Compiler) leaveScope() (
  1000. instructions []byte,
  1001. sourceMap map[int]parser.Pos,
  1002. ) {
  1003. instructions = c.currentInstructions()
  1004. sourceMap = c.currentSourceMap()
  1005. c.scopes = c.scopes[:len(c.scopes)-1]
  1006. c.scopeIndex--
  1007. c.symbolTable = c.symbolTable.Parent(true)
  1008. if c.trace != nil {
  1009. c.printTrace("SCOPL", c.scopeIndex)
  1010. }
  1011. return
  1012. }
  1013. func (c *Compiler) fork(
  1014. file *parser.SourceFile,
  1015. modulePath string,
  1016. symbolTable *SymbolTable,
  1017. isFile bool,
  1018. ) *Compiler {
  1019. child := NewCompiler(file, symbolTable, nil, c.modules, c.trace)
  1020. child.modulePath = modulePath // module file path
  1021. child.parent = c // parent to set to current compiler
  1022. child.allowFileImport = c.allowFileImport
  1023. child.importDir = c.importDir
  1024. child.importFileExt = c.importFileExt
  1025. if isFile && c.importDir != "" {
  1026. child.importDir = filepath.Dir(modulePath)
  1027. }
  1028. return child
  1029. }
  1030. func (c *Compiler) error(node parser.Node, err error) error {
  1031. return &CompilerError{
  1032. FileSet: c.file.Set(),
  1033. Node: node,
  1034. Err: err,
  1035. }
  1036. }
  1037. func (c *Compiler) errorf(
  1038. node parser.Node,
  1039. format string,
  1040. args ...interface{},
  1041. ) error {
  1042. return &CompilerError{
  1043. FileSet: c.file.Set(),
  1044. Node: node,
  1045. Err: fmt.Errorf(format, args...),
  1046. }
  1047. }
  1048. func (c *Compiler) addConstant(o Object) int {
  1049. if c.parent != nil {
  1050. // module compilers will use their parent's constants array
  1051. return c.parent.addConstant(o)
  1052. }
  1053. c.constants = append(c.constants, o)
  1054. if c.trace != nil {
  1055. c.printTrace(fmt.Sprintf("CONST %04d %s", len(c.constants)-1, o))
  1056. }
  1057. return len(c.constants) - 1
  1058. }
  1059. func (c *Compiler) addInstruction(b []byte) int {
  1060. posNewIns := len(c.currentInstructions())
  1061. c.scopes[c.scopeIndex].Instructions = append(
  1062. c.currentInstructions(), b...)
  1063. return posNewIns
  1064. }
  1065. func (c *Compiler) replaceInstruction(pos int, inst []byte) {
  1066. copy(c.currentInstructions()[pos:], inst)
  1067. if c.trace != nil {
  1068. c.printTrace(fmt.Sprintf("REPLC %s",
  1069. FormatInstructions(
  1070. c.scopes[c.scopeIndex].Instructions[pos:], pos)[0]))
  1071. }
  1072. }
  1073. func (c *Compiler) changeOperand(opPos int, operand ...int) {
  1074. op := c.currentInstructions()[opPos]
  1075. inst := MakeInstruction(op, operand...)
  1076. c.replaceInstruction(opPos, inst)
  1077. }
  1078. // optimizeFunc performs some code-level optimization for the current function
  1079. // instructions. It also removes unreachable (dead code) instructions and adds
  1080. // "returns" instruction if needed.
  1081. func (c *Compiler) optimizeFunc(node parser.Node) {
  1082. // any instructions between RETURN and the function end
  1083. // or instructions between RETURN and jump target position
  1084. // are considered as unreachable.
  1085. // pass 1. identify all jump destinations
  1086. dsts := make(map[int]bool)
  1087. iterateInstructions(c.scopes[c.scopeIndex].Instructions,
  1088. func(pos int, opcode parser.Opcode, operands []int) bool {
  1089. switch opcode {
  1090. case parser.OpJump, parser.OpJumpFalsy,
  1091. parser.OpAndJump, parser.OpOrJump:
  1092. dsts[operands[0]] = true
  1093. }
  1094. return true
  1095. })
  1096. // pass 2. eliminate dead code
  1097. var newInsts []byte
  1098. posMap := make(map[int]int) // old position to new position
  1099. var dstIdx int
  1100. var deadCode bool
  1101. iterateInstructions(c.scopes[c.scopeIndex].Instructions,
  1102. func(pos int, opcode parser.Opcode, operands []int) bool {
  1103. switch {
  1104. case dsts[pos]:
  1105. dstIdx++
  1106. deadCode = false
  1107. case opcode == parser.OpReturn:
  1108. if deadCode {
  1109. return true
  1110. }
  1111. deadCode = true
  1112. case deadCode:
  1113. return true
  1114. }
  1115. posMap[pos] = len(newInsts)
  1116. newInsts = append(newInsts,
  1117. MakeInstruction(opcode, operands...)...)
  1118. return true
  1119. })
  1120. // pass 3. update jump positions
  1121. var lastOp parser.Opcode
  1122. var appendReturn bool
  1123. endPos := len(c.scopes[c.scopeIndex].Instructions)
  1124. newEndPost := len(newInsts)
  1125. iterateInstructions(newInsts,
  1126. func(pos int, opcode parser.Opcode, operands []int) bool {
  1127. switch opcode {
  1128. case parser.OpJump, parser.OpJumpFalsy, parser.OpAndJump,
  1129. parser.OpOrJump:
  1130. newDst, ok := posMap[operands[0]]
  1131. if ok {
  1132. copy(newInsts[pos:],
  1133. MakeInstruction(opcode, newDst))
  1134. } else if endPos == operands[0] {
  1135. // there's a jump instruction that jumps to the end of
  1136. // function compiler should append "return".
  1137. copy(newInsts[pos:],
  1138. MakeInstruction(opcode, newEndPost))
  1139. appendReturn = true
  1140. } else {
  1141. panic(fmt.Errorf("invalid jump position: %d", newDst))
  1142. }
  1143. }
  1144. lastOp = opcode
  1145. return true
  1146. })
  1147. if lastOp != parser.OpReturn {
  1148. appendReturn = true
  1149. }
  1150. // pass 4. update source map
  1151. newSourceMap := make(map[int]parser.Pos)
  1152. for pos, srcPos := range c.scopes[c.scopeIndex].SourceMap {
  1153. newPos, ok := posMap[pos]
  1154. if ok {
  1155. newSourceMap[newPos] = srcPos
  1156. }
  1157. }
  1158. c.scopes[c.scopeIndex].Instructions = newInsts
  1159. c.scopes[c.scopeIndex].SourceMap = newSourceMap
  1160. // append "return"
  1161. if appendReturn {
  1162. c.emit(node, parser.OpReturn, 0)
  1163. }
  1164. }
  1165. func (c *Compiler) emit(
  1166. node parser.Node,
  1167. opcode parser.Opcode,
  1168. operands ...int,
  1169. ) int {
  1170. filePos := parser.NoPos
  1171. if node != nil {
  1172. filePos = node.Pos()
  1173. }
  1174. inst := MakeInstruction(opcode, operands...)
  1175. pos := c.addInstruction(inst)
  1176. c.scopes[c.scopeIndex].SourceMap[pos] = filePos
  1177. if c.trace != nil {
  1178. c.printTrace(fmt.Sprintf("EMIT %s",
  1179. FormatInstructions(
  1180. c.scopes[c.scopeIndex].Instructions[pos:], pos)[0]))
  1181. }
  1182. return pos
  1183. }
  1184. func (c *Compiler) printTrace(a ...interface{}) {
  1185. const (
  1186. dots = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
  1187. n = len(dots)
  1188. )
  1189. i := 2 * c.indent
  1190. for i > n {
  1191. _, _ = fmt.Fprint(c.trace, dots)
  1192. i -= n
  1193. }
  1194. _, _ = fmt.Fprint(c.trace, dots[0:i])
  1195. _, _ = fmt.Fprintln(c.trace, a...)
  1196. }
  1197. func (c *Compiler) getPathModule(moduleName string) (pathFile string, err error) {
  1198. for _, ext := range c.importFileExt {
  1199. nameFile := moduleName
  1200. if !strings.HasSuffix(nameFile, ext) {
  1201. nameFile += ext
  1202. }
  1203. pathFile, err = filepath.Abs(filepath.Join(c.importDir, nameFile))
  1204. if err != nil {
  1205. continue
  1206. }
  1207. // Check if file exists
  1208. if _, err := os.Stat(pathFile); !errors.Is(err, os.ErrNotExist) {
  1209. return pathFile, nil
  1210. }
  1211. }
  1212. return "", fmt.Errorf("module '%s' not found at: %s", moduleName, pathFile)
  1213. }
  1214. func resolveAssignLHS(
  1215. expr parser.Expr,
  1216. ) (name string, selectors []parser.Expr) {
  1217. switch term := expr.(type) {
  1218. case *parser.SelectorExpr:
  1219. name, selectors = resolveAssignLHS(term.Expr)
  1220. selectors = append(selectors, term.Sel)
  1221. return
  1222. case *parser.IndexExpr:
  1223. name, selectors = resolveAssignLHS(term.Expr)
  1224. selectors = append(selectors, term.Index)
  1225. case *parser.Ident:
  1226. name = term.Name
  1227. }
  1228. return
  1229. }
  1230. func iterateInstructions(
  1231. b []byte,
  1232. fn func(pos int, opcode parser.Opcode, operands []int) bool,
  1233. ) {
  1234. for i := 0; i < len(b); i++ {
  1235. numOperands := parser.OpcodeOperands[b[i]]
  1236. operands, read := parser.ReadOperands(numOperands, b[i+1:])
  1237. if !fn(i, b[i], operands) {
  1238. break
  1239. }
  1240. i += read
  1241. }
  1242. }
  1243. func tracec(c *Compiler, msg string) *Compiler {
  1244. c.printTrace(msg, "{")
  1245. c.indent++
  1246. return c
  1247. }
  1248. func untracec(c *Compiler) {
  1249. c.indent--
  1250. c.printTrace("}")
  1251. }