compiler.go 33 KB

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