compile.go 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869
  1. package lua
  2. import (
  3. "fmt"
  4. "math"
  5. "reflect"
  6. "github.com/yuin/gopher-lua/ast"
  7. )
  8. /* internal constants & structs {{{ */
  9. const maxRegisters = 200
  10. type expContextType int
  11. const (
  12. ecGlobal expContextType = iota
  13. ecUpvalue
  14. ecLocal
  15. ecTable
  16. ecVararg
  17. ecMethod
  18. ecNone
  19. )
  20. const regNotDefined = opMaxArgsA + 1
  21. const labelNoJump = 0
  22. type expcontext struct {
  23. ctype expContextType
  24. reg int
  25. // varargopt >= 0: wants varargopt+1 results, i.e a = func()
  26. // varargopt = -1: ignore results i.e func()
  27. // varargopt = -2: receive all results i.e a = {func()}
  28. varargopt int
  29. }
  30. type assigncontext struct {
  31. ec *expcontext
  32. keyrk int
  33. valuerk int
  34. keyks bool
  35. needmove bool
  36. }
  37. type lblabels struct {
  38. t int
  39. f int
  40. e int
  41. b bool
  42. }
  43. type constLValueExpr struct {
  44. ast.ExprBase
  45. Value LValue
  46. }
  47. // }}}
  48. /* utilities {{{ */
  49. var _ecnone0 = &expcontext{ecNone, regNotDefined, 0}
  50. var _ecnonem1 = &expcontext{ecNone, regNotDefined, -1}
  51. var _ecnonem2 = &expcontext{ecNone, regNotDefined, -2}
  52. var ecfuncdef = &expcontext{ecMethod, regNotDefined, 0}
  53. func ecupdate(ec *expcontext, ctype expContextType, reg, varargopt int) {
  54. if ec == _ecnone0 || ec == _ecnonem1 || ec == _ecnonem2 {
  55. panic("can not update ec cache")
  56. }
  57. ec.ctype = ctype
  58. ec.reg = reg
  59. ec.varargopt = varargopt
  60. }
  61. func ecnone(varargopt int) *expcontext {
  62. switch varargopt {
  63. case 0:
  64. return _ecnone0
  65. case -1:
  66. return _ecnonem1
  67. case -2:
  68. return _ecnonem2
  69. }
  70. return &expcontext{ecNone, regNotDefined, varargopt}
  71. }
  72. func shouldmove(ec *expcontext, reg int) bool {
  73. return ec.ctype == ecLocal && ec.reg != regNotDefined && ec.reg != reg
  74. }
  75. func sline(pos ast.PositionHolder) int {
  76. return pos.Line()
  77. }
  78. func eline(pos ast.PositionHolder) int {
  79. line := pos.LastLine()
  80. if line == 0 {
  81. return pos.Line()
  82. }
  83. return line
  84. }
  85. func savereg(ec *expcontext, reg int) int {
  86. if ec.ctype != ecLocal || ec.reg == regNotDefined {
  87. return reg
  88. }
  89. return ec.reg
  90. }
  91. func raiseCompileError(context *funcContext, line int, format string, args ...interface{}) {
  92. msg := fmt.Sprintf(format, args...)
  93. panic(&CompileError{context: context, Line: line, Message: msg})
  94. }
  95. func isVarArgReturnExpr(expr ast.Expr) bool {
  96. switch ex := expr.(type) {
  97. case *ast.FuncCallExpr:
  98. return !ex.AdjustRet
  99. case *ast.Comma3Expr:
  100. return !ex.AdjustRet
  101. }
  102. return false
  103. }
  104. func lnumberValue(expr ast.Expr) (LNumber, bool) {
  105. if ex, ok := expr.(*ast.NumberExpr); ok {
  106. lv, err := parseNumber(ex.Value)
  107. if err != nil {
  108. lv = LNumber(math.NaN())
  109. }
  110. return lv, true
  111. } else if ex, ok := expr.(*constLValueExpr); ok {
  112. return ex.Value.(LNumber), true
  113. }
  114. return 0, false
  115. }
  116. /* utilities }}} */
  117. type gotoLabelDesc struct { // {{{
  118. Id int
  119. Name string
  120. Pc int
  121. Line int
  122. NumActiveLocalVars int
  123. }
  124. func newLabelDesc(id int, name string, pc, line, n int) *gotoLabelDesc {
  125. return &gotoLabelDesc{
  126. Id: id,
  127. Name: name,
  128. Pc: pc,
  129. Line: line,
  130. NumActiveLocalVars: n,
  131. }
  132. }
  133. func (l *gotoLabelDesc) SetNumActiveLocalVars(n int) {
  134. l.NumActiveLocalVars = n
  135. } // }}}
  136. type CompileError struct { // {{{
  137. context *funcContext
  138. Line int
  139. Message string
  140. }
  141. func (e *CompileError) Error() string {
  142. return fmt.Sprintf("compile error near line(%v) %v: %v", e.Line, e.context.Proto.SourceName, e.Message)
  143. } // }}}
  144. type codeStore struct { // {{{
  145. codes []uint32
  146. lines []int
  147. pc int
  148. }
  149. func (cd *codeStore) Add(inst uint32, line int) {
  150. if l := len(cd.codes); l <= 0 || cd.pc == l {
  151. cd.codes = append(cd.codes, inst)
  152. cd.lines = append(cd.lines, line)
  153. } else {
  154. cd.codes[cd.pc] = inst
  155. cd.lines[cd.pc] = line
  156. }
  157. cd.pc++
  158. }
  159. func (cd *codeStore) AddABC(op int, a int, b int, c int, line int) {
  160. cd.Add(opCreateABC(op, a, b, c), line)
  161. }
  162. func (cd *codeStore) AddABx(op int, a int, bx int, line int) {
  163. cd.Add(opCreateABx(op, a, bx), line)
  164. }
  165. func (cd *codeStore) AddASbx(op int, a int, sbx int, line int) {
  166. cd.Add(opCreateASbx(op, a, sbx), line)
  167. }
  168. func (cd *codeStore) PropagateKMV(top int, save *int, reg *int, inc int) {
  169. lastinst := cd.Last()
  170. if opGetArgA(lastinst) >= top {
  171. switch opGetOpCode(lastinst) {
  172. case OP_LOADK:
  173. cindex := opGetArgBx(lastinst)
  174. if cindex <= opMaxIndexRk {
  175. cd.Pop()
  176. *save = opRkAsk(cindex)
  177. return
  178. }
  179. case OP_MOVE:
  180. cd.Pop()
  181. *save = opGetArgB(lastinst)
  182. return
  183. }
  184. }
  185. *save = *reg
  186. *reg = *reg + inc
  187. }
  188. func (cd *codeStore) PropagateMV(top int, save *int, reg *int, inc int) {
  189. lastinst := cd.Last()
  190. if opGetArgA(lastinst) >= top {
  191. switch opGetOpCode(lastinst) {
  192. case OP_MOVE:
  193. cd.Pop()
  194. *save = opGetArgB(lastinst)
  195. return
  196. }
  197. }
  198. *save = *reg
  199. *reg = *reg + inc
  200. }
  201. func (cd *codeStore) AddLoadNil(a, b, line int) {
  202. last := cd.Last()
  203. if opGetOpCode(last) == OP_LOADNIL && (opGetArgA(last)+opGetArgB(last)) == a {
  204. cd.SetB(cd.LastPC(), b)
  205. } else {
  206. cd.AddABC(OP_LOADNIL, a, b, 0, line)
  207. }
  208. }
  209. func (cd *codeStore) SetOpCode(pc int, v int) {
  210. opSetOpCode(&cd.codes[pc], v)
  211. }
  212. func (cd *codeStore) SetA(pc int, v int) {
  213. opSetArgA(&cd.codes[pc], v)
  214. }
  215. func (cd *codeStore) SetB(pc int, v int) {
  216. opSetArgB(&cd.codes[pc], v)
  217. }
  218. func (cd *codeStore) SetC(pc int, v int) {
  219. opSetArgC(&cd.codes[pc], v)
  220. }
  221. func (cd *codeStore) SetBx(pc int, v int) {
  222. opSetArgBx(&cd.codes[pc], v)
  223. }
  224. func (cd *codeStore) SetSbx(pc int, v int) {
  225. opSetArgSbx(&cd.codes[pc], v)
  226. }
  227. func (cd *codeStore) At(pc int) uint32 {
  228. return cd.codes[pc]
  229. }
  230. func (cd *codeStore) List() []uint32 {
  231. return cd.codes[:cd.pc]
  232. }
  233. func (cd *codeStore) PosList() []int {
  234. return cd.lines[:cd.pc]
  235. }
  236. func (cd *codeStore) LastPC() int {
  237. return cd.pc - 1
  238. }
  239. func (cd *codeStore) Last() uint32 {
  240. if cd.pc == 0 {
  241. return opInvalidInstruction
  242. }
  243. return cd.codes[cd.pc-1]
  244. }
  245. func (cd *codeStore) Pop() {
  246. cd.pc--
  247. } /* }}} Code */
  248. /* {{{ VarNamePool */
  249. type varNamePoolValue struct {
  250. Index int
  251. Name string
  252. }
  253. type varNamePool struct {
  254. names []string
  255. offset int
  256. }
  257. func newVarNamePool(offset int) *varNamePool {
  258. return &varNamePool{make([]string, 0, 16), offset}
  259. }
  260. func (vp *varNamePool) Names() []string {
  261. return vp.names
  262. }
  263. func (vp *varNamePool) List() []varNamePoolValue {
  264. result := make([]varNamePoolValue, len(vp.names), len(vp.names))
  265. for i, name := range vp.names {
  266. result[i].Index = i + vp.offset
  267. result[i].Name = name
  268. }
  269. return result
  270. }
  271. func (vp *varNamePool) LastIndex() int {
  272. return vp.offset + len(vp.names)
  273. }
  274. func (vp *varNamePool) Find(name string) int {
  275. for i := len(vp.names) - 1; i >= 0; i-- {
  276. if vp.names[i] == name {
  277. return i + vp.offset
  278. }
  279. }
  280. return -1
  281. }
  282. func (vp *varNamePool) RegisterUnique(name string) int {
  283. index := vp.Find(name)
  284. if index < 0 {
  285. return vp.Register(name)
  286. }
  287. return index
  288. }
  289. func (vp *varNamePool) Register(name string) int {
  290. vp.names = append(vp.names, name)
  291. return len(vp.names) - 1 + vp.offset
  292. }
  293. /* }}} VarNamePool */
  294. /* FuncContext {{{ */
  295. type codeBlock struct {
  296. LocalVars *varNamePool
  297. BreakLabel int
  298. Parent *codeBlock
  299. RefUpvalue bool
  300. LineStart int
  301. LastLine int
  302. labels map[string]*gotoLabelDesc
  303. firstGotoIndex int
  304. }
  305. func newCodeBlock(localvars *varNamePool, blabel int, parent *codeBlock, pos ast.PositionHolder, firstGotoIndex int) *codeBlock {
  306. bl := &codeBlock{localvars, blabel, parent, false, 0, 0, map[string]*gotoLabelDesc{}, firstGotoIndex}
  307. if pos != nil {
  308. bl.LineStart = pos.Line()
  309. bl.LastLine = pos.LastLine()
  310. }
  311. return bl
  312. }
  313. func (b *codeBlock) AddLabel(label *gotoLabelDesc) *gotoLabelDesc {
  314. if old, ok := b.labels[label.Name]; ok {
  315. return old
  316. }
  317. b.labels[label.Name] = label
  318. return nil
  319. }
  320. func (b *codeBlock) GetLabel(label string) *gotoLabelDesc {
  321. if v, ok := b.labels[label]; ok {
  322. return v
  323. }
  324. return nil
  325. }
  326. func (b *codeBlock) LocalVarsCount() int {
  327. count := 0
  328. for block := b; block != nil; block = block.Parent {
  329. count += len(block.LocalVars.Names())
  330. }
  331. return count
  332. }
  333. type funcContext struct {
  334. Proto *FunctionProto
  335. Code *codeStore
  336. Parent *funcContext
  337. Upvalues *varNamePool
  338. Block *codeBlock
  339. Blocks []*codeBlock
  340. regTop int
  341. labelId int
  342. labelPc map[int]int
  343. gotosCount int
  344. unresolvedGotos map[int]*gotoLabelDesc
  345. }
  346. func newFuncContext(sourcename string, parent *funcContext) *funcContext {
  347. fc := &funcContext{
  348. Proto: newFunctionProto(sourcename),
  349. Code: &codeStore{make([]uint32, 0, 1024), make([]int, 0, 1024), 0},
  350. Parent: parent,
  351. Upvalues: newVarNamePool(0),
  352. Block: newCodeBlock(newVarNamePool(0), labelNoJump, nil, nil, 0),
  353. regTop: 0,
  354. labelId: 1,
  355. labelPc: map[int]int{},
  356. gotosCount: 0,
  357. unresolvedGotos: map[int]*gotoLabelDesc{},
  358. }
  359. fc.Blocks = []*codeBlock{fc.Block}
  360. return fc
  361. }
  362. func (fc *funcContext) CheckUnresolvedGoto() {
  363. for i := fc.Block.firstGotoIndex; i < fc.gotosCount; i++ {
  364. gotoLabel, ok := fc.unresolvedGotos[i]
  365. if !ok {
  366. continue
  367. }
  368. raiseCompileError(fc, fc.Proto.LastLineDefined, "no visible label '%s' for <goto> at line %d", gotoLabel.Name, gotoLabel.Line)
  369. }
  370. }
  371. func (fc *funcContext) AddUnresolvedGoto(label *gotoLabelDesc) {
  372. fc.unresolvedGotos[fc.gotosCount] = label
  373. fc.gotosCount++
  374. }
  375. func (fc *funcContext) AddNamedLabel(label *gotoLabelDesc) {
  376. if old := fc.Block.AddLabel(label); old != nil {
  377. raiseCompileError(fc, label.Line+1, "label '%s' already defined on line %d", label.Name, old.Line)
  378. }
  379. fc.SetLabelPc(label.Id, label.Pc)
  380. }
  381. func (fc *funcContext) GetNamedLabel(name string) *gotoLabelDesc {
  382. return fc.Block.GetLabel(name)
  383. }
  384. func (fc *funcContext) ResolveGoto(from, to *gotoLabelDesc, index int) {
  385. if from.NumActiveLocalVars < to.NumActiveLocalVars {
  386. varName := fc.Block.LocalVars.Names()[len(fc.Block.LocalVars.Names())-1]
  387. raiseCompileError(fc, to.Line+1, "<goto %s> at line %d jumps into the scope of local '%s'", to.Name, from.Line, varName)
  388. }
  389. fc.Code.SetSbx(from.Pc, to.Id)
  390. delete(fc.unresolvedGotos, index)
  391. }
  392. func (fc *funcContext) FindLabel(block *codeBlock, gotoLabel *gotoLabelDesc, i int) bool {
  393. target := block.GetLabel(gotoLabel.Name)
  394. if target != nil {
  395. if gotoLabel.NumActiveLocalVars > target.NumActiveLocalVars && block.RefUpvalue {
  396. fc.Code.SetA(gotoLabel.Pc-1, target.NumActiveLocalVars)
  397. }
  398. fc.ResolveGoto(gotoLabel, target, i)
  399. return true
  400. }
  401. return false
  402. }
  403. func (fc *funcContext) ResolveCurrentBlockGotosWithParentBlock() {
  404. blockActiveLocalVars := fc.Block.Parent.LocalVarsCount()
  405. for i := fc.Block.firstGotoIndex; i < fc.gotosCount; i++ {
  406. gotoLabel, ok := fc.unresolvedGotos[i]
  407. if !ok {
  408. continue
  409. }
  410. if gotoLabel.NumActiveLocalVars > blockActiveLocalVars {
  411. if fc.Block.RefUpvalue {
  412. fc.Code.SetA(gotoLabel.Pc-1, blockActiveLocalVars)
  413. }
  414. gotoLabel.SetNumActiveLocalVars(blockActiveLocalVars)
  415. }
  416. fc.FindLabel(fc.Block.Parent, gotoLabel, i)
  417. }
  418. }
  419. func (fc *funcContext) ResolveForwardGoto(target *gotoLabelDesc) {
  420. for i := fc.Block.firstGotoIndex; i <= fc.gotosCount; i++ {
  421. gotoLabel, ok := fc.unresolvedGotos[i]
  422. if !ok {
  423. continue
  424. }
  425. if gotoLabel.Name == target.Name {
  426. fc.ResolveGoto(gotoLabel, target, i)
  427. }
  428. }
  429. }
  430. func (fc *funcContext) NewLabel() int {
  431. ret := fc.labelId
  432. fc.labelId++
  433. return ret
  434. }
  435. func (fc *funcContext) SetLabelPc(label int, pc int) {
  436. fc.labelPc[label] = pc
  437. }
  438. func (fc *funcContext) GetLabelPc(label int) int {
  439. return fc.labelPc[label]
  440. }
  441. func (fc *funcContext) ConstIndex(value LValue) int {
  442. ctype := value.Type()
  443. for i, lv := range fc.Proto.Constants {
  444. if lv.Type() == ctype && lv == value {
  445. return i
  446. }
  447. }
  448. fc.Proto.Constants = append(fc.Proto.Constants, value)
  449. v := len(fc.Proto.Constants) - 1
  450. if v > opMaxArgBx {
  451. raiseCompileError(fc, fc.Proto.LineDefined, "too many constants")
  452. }
  453. return v
  454. }
  455. func (fc *funcContext) BlockLocalVarsCount() int {
  456. count := 0
  457. for block := fc.Block; block != nil; block = block.Parent {
  458. count += len(block.LocalVars.Names())
  459. }
  460. return count
  461. }
  462. func (fc *funcContext) RegisterLocalVar(name string) int {
  463. ret := fc.Block.LocalVars.Register(name)
  464. fc.Proto.DbgLocals = append(fc.Proto.DbgLocals, &DbgLocalInfo{Name: name, StartPc: fc.Code.LastPC() + 1})
  465. fc.SetRegTop(fc.RegTop() + 1)
  466. return ret
  467. }
  468. func (fc *funcContext) FindLocalVarAndBlock(name string) (int, *codeBlock) {
  469. for block := fc.Block; block != nil; block = block.Parent {
  470. if index := block.LocalVars.Find(name); index > -1 {
  471. return index, block
  472. }
  473. }
  474. return -1, nil
  475. }
  476. func (fc *funcContext) FindLocalVar(name string) int {
  477. idx, _ := fc.FindLocalVarAndBlock(name)
  478. return idx
  479. }
  480. func (fc *funcContext) LocalVars() []varNamePoolValue {
  481. result := make([]varNamePoolValue, 0, 32)
  482. for _, block := range fc.Blocks {
  483. result = append(result, block.LocalVars.List()...)
  484. }
  485. return result
  486. }
  487. func (fc *funcContext) EnterBlock(blabel int, pos ast.PositionHolder) {
  488. fc.Block = newCodeBlock(newVarNamePool(fc.RegTop()), blabel, fc.Block, pos, fc.gotosCount)
  489. fc.Blocks = append(fc.Blocks, fc.Block)
  490. }
  491. func (fc *funcContext) CloseUpvalues() int {
  492. n := -1
  493. if fc.Block.RefUpvalue {
  494. n = fc.Block.Parent.LocalVars.LastIndex()
  495. fc.Code.AddABC(OP_CLOSE, n, 0, 0, fc.Block.LastLine)
  496. }
  497. return n
  498. }
  499. func (fc *funcContext) LeaveBlock() int {
  500. closed := fc.CloseUpvalues()
  501. fc.EndScope()
  502. if fc.Block.Parent != nil {
  503. fc.ResolveCurrentBlockGotosWithParentBlock()
  504. }
  505. fc.Block = fc.Block.Parent
  506. fc.SetRegTop(fc.Block.LocalVars.LastIndex())
  507. return closed
  508. }
  509. func (fc *funcContext) EndScope() {
  510. for _, vr := range fc.Block.LocalVars.List() {
  511. fc.Proto.DbgLocals[vr.Index].EndPc = fc.Code.LastPC()
  512. }
  513. }
  514. func (fc *funcContext) SetRegTop(top int) {
  515. if top > maxRegisters {
  516. raiseCompileError(fc, fc.Proto.LineDefined, "too many local variables")
  517. }
  518. fc.regTop = top
  519. }
  520. func (fc *funcContext) RegTop() int {
  521. return fc.regTop
  522. }
  523. /* FuncContext }}} */
  524. func compileChunk(context *funcContext, chunk []ast.Stmt, untilFollows bool) { // {{{
  525. for i, stmt := range chunk {
  526. lastStmt := true
  527. for j := i + 1; j < len(chunk); j++ {
  528. _, ok := chunk[j].(*ast.LabelStmt)
  529. if !ok {
  530. lastStmt = false
  531. break
  532. }
  533. }
  534. compileStmt(context, stmt, lastStmt && !untilFollows)
  535. }
  536. } // }}}
  537. func compileBlock(context *funcContext, chunk []ast.Stmt) { // {{{
  538. if len(chunk) == 0 {
  539. return
  540. }
  541. ph := &ast.Node{}
  542. ph.SetLine(sline(chunk[0]))
  543. ph.SetLastLine(eline(chunk[len(chunk)-1]))
  544. context.EnterBlock(labelNoJump, ph)
  545. for i, stmt := range chunk {
  546. lastStmt := true
  547. for j := i + 1; j < len(chunk); j++ {
  548. _, ok := chunk[j].(*ast.LabelStmt)
  549. if !ok {
  550. lastStmt = false
  551. break
  552. }
  553. }
  554. compileStmt(context, stmt, lastStmt)
  555. }
  556. context.LeaveBlock()
  557. } // }}}
  558. func compileStmt(context *funcContext, stmt ast.Stmt, isLastStmt bool) { // {{{
  559. switch st := stmt.(type) {
  560. case *ast.AssignStmt:
  561. compileAssignStmt(context, st)
  562. case *ast.LocalAssignStmt:
  563. compileLocalAssignStmt(context, st)
  564. case *ast.FuncCallStmt:
  565. compileFuncCallExpr(context, context.RegTop(), st.Expr.(*ast.FuncCallExpr), ecnone(-1))
  566. case *ast.DoBlockStmt:
  567. context.EnterBlock(labelNoJump, st)
  568. compileChunk(context, st.Stmts, false)
  569. context.LeaveBlock()
  570. case *ast.WhileStmt:
  571. compileWhileStmt(context, st)
  572. case *ast.RepeatStmt:
  573. compileRepeatStmt(context, st)
  574. case *ast.FuncDefStmt:
  575. compileFuncDefStmt(context, st)
  576. case *ast.ReturnStmt:
  577. compileReturnStmt(context, st)
  578. case *ast.IfStmt:
  579. compileIfStmt(context, st)
  580. case *ast.BreakStmt:
  581. compileBreakStmt(context, st)
  582. case *ast.NumberForStmt:
  583. compileNumberForStmt(context, st)
  584. case *ast.GenericForStmt:
  585. compileGenericForStmt(context, st)
  586. case *ast.LabelStmt:
  587. compileLabelStmt(context, st, isLastStmt)
  588. case *ast.GotoStmt:
  589. compileGotoStmt(context, st)
  590. }
  591. } // }}}
  592. func compileAssignStmtLeft(context *funcContext, stmt *ast.AssignStmt) (int, []*assigncontext) { // {{{
  593. reg := context.RegTop()
  594. acs := make([]*assigncontext, 0, len(stmt.Lhs))
  595. for _, lhs := range stmt.Lhs {
  596. switch st := lhs.(type) {
  597. case *ast.IdentExpr:
  598. identtype := getIdentRefType(context, context, st)
  599. ec := &expcontext{identtype, regNotDefined, 0}
  600. switch identtype {
  601. case ecGlobal:
  602. context.ConstIndex(LString(st.Value))
  603. case ecUpvalue:
  604. context.Upvalues.RegisterUnique(st.Value)
  605. case ecLocal:
  606. ec.reg = context.FindLocalVar(st.Value)
  607. }
  608. acs = append(acs, &assigncontext{ec, 0, 0, false, false})
  609. case *ast.AttrGetExpr:
  610. ac := &assigncontext{&expcontext{ecTable, regNotDefined, 0}, 0, 0, false, false}
  611. compileExprWithKMVPropagation(context, st.Object, &reg, &ac.ec.reg)
  612. ac.keyrk = reg
  613. reg += compileExpr(context, reg, st.Key, ecnone(0))
  614. if _, ok := st.Key.(*ast.StringExpr); ok {
  615. ac.keyks = true
  616. }
  617. acs = append(acs, ac)
  618. default:
  619. panic("invalid left expression.")
  620. }
  621. }
  622. return reg, acs
  623. } // }}}
  624. func compileAssignStmtRight(context *funcContext, stmt *ast.AssignStmt, reg int, acs []*assigncontext) (int, []*assigncontext) { // {{{
  625. lennames := len(stmt.Lhs)
  626. lenexprs := len(stmt.Rhs)
  627. namesassigned := 0
  628. for namesassigned < lennames {
  629. ac := acs[namesassigned]
  630. ec := ac.ec
  631. var expr ast.Expr = nil
  632. if namesassigned >= lenexprs {
  633. expr = &ast.NilExpr{}
  634. expr.SetLine(sline(stmt.Lhs[namesassigned]))
  635. expr.SetLastLine(eline(stmt.Lhs[namesassigned]))
  636. } else if isVarArgReturnExpr(stmt.Rhs[namesassigned]) && (lenexprs-namesassigned-1) <= 0 {
  637. varargopt := lennames - namesassigned - 1
  638. regstart := reg
  639. reginc := compileExpr(context, reg, stmt.Rhs[namesassigned], ecnone(varargopt))
  640. reg += reginc
  641. for i := namesassigned; i < namesassigned+int(reginc); i++ {
  642. acs[i].needmove = true
  643. if acs[i].ec.ctype == ecTable {
  644. acs[i].valuerk = regstart + (i - namesassigned)
  645. }
  646. }
  647. namesassigned = lennames
  648. continue
  649. }
  650. if expr == nil {
  651. expr = stmt.Rhs[namesassigned]
  652. }
  653. idx := reg
  654. reginc := compileExpr(context, reg, expr, ec)
  655. if ec.ctype == ecTable {
  656. if _, ok := expr.(*ast.LogicalOpExpr); !ok {
  657. context.Code.PropagateKMV(context.RegTop(), &ac.valuerk, &reg, reginc)
  658. } else {
  659. ac.valuerk = idx
  660. reg += reginc
  661. }
  662. } else {
  663. ac.needmove = reginc != 0
  664. reg += reginc
  665. }
  666. namesassigned += 1
  667. }
  668. rightreg := reg - 1
  669. // extra right exprs
  670. for i := namesassigned; i < lenexprs; i++ {
  671. varargopt := -1
  672. if i != lenexprs-1 {
  673. varargopt = 0
  674. }
  675. reg += compileExpr(context, reg, stmt.Rhs[i], ecnone(varargopt))
  676. }
  677. return rightreg, acs
  678. } // }}}
  679. func compileAssignStmt(context *funcContext, stmt *ast.AssignStmt) { // {{{
  680. code := context.Code
  681. lennames := len(stmt.Lhs)
  682. reg, acs := compileAssignStmtLeft(context, stmt)
  683. reg, acs = compileAssignStmtRight(context, stmt, reg, acs)
  684. for i := lennames - 1; i >= 0; i-- {
  685. ex := stmt.Lhs[i]
  686. switch acs[i].ec.ctype {
  687. case ecLocal:
  688. if acs[i].needmove {
  689. code.AddABC(OP_MOVE, context.FindLocalVar(ex.(*ast.IdentExpr).Value), reg, 0, sline(ex))
  690. reg -= 1
  691. }
  692. case ecGlobal:
  693. code.AddABx(OP_SETGLOBAL, reg, context.ConstIndex(LString(ex.(*ast.IdentExpr).Value)), sline(ex))
  694. reg -= 1
  695. case ecUpvalue:
  696. code.AddABC(OP_SETUPVAL, reg, context.Upvalues.RegisterUnique(ex.(*ast.IdentExpr).Value), 0, sline(ex))
  697. reg -= 1
  698. case ecTable:
  699. opcode := OP_SETTABLE
  700. if acs[i].keyks {
  701. opcode = OP_SETTABLEKS
  702. }
  703. code.AddABC(opcode, acs[i].ec.reg, acs[i].keyrk, acs[i].valuerk, sline(ex))
  704. if !opIsK(acs[i].valuerk) {
  705. reg -= 1
  706. }
  707. }
  708. }
  709. } // }}}
  710. func compileRegAssignment(context *funcContext, names []string, exprs []ast.Expr, reg int, nvars int, line int) { // {{{
  711. lennames := len(names)
  712. lenexprs := len(exprs)
  713. namesassigned := 0
  714. ec := &expcontext{}
  715. for namesassigned < lennames && namesassigned < lenexprs {
  716. if isVarArgReturnExpr(exprs[namesassigned]) && (lenexprs-namesassigned-1) <= 0 {
  717. varargopt := nvars - namesassigned
  718. ecupdate(ec, ecVararg, reg, varargopt-1)
  719. compileExpr(context, reg, exprs[namesassigned], ec)
  720. reg += varargopt
  721. namesassigned = lennames
  722. } else {
  723. ecupdate(ec, ecLocal, reg, 0)
  724. compileExpr(context, reg, exprs[namesassigned], ec)
  725. reg += 1
  726. namesassigned += 1
  727. }
  728. }
  729. // extra left names
  730. if lennames > namesassigned {
  731. restleft := lennames - namesassigned - 1
  732. context.Code.AddLoadNil(reg, reg+restleft, line)
  733. reg += restleft
  734. }
  735. // extra right exprs
  736. for i := namesassigned; i < lenexprs; i++ {
  737. varargopt := -1
  738. if i != lenexprs-1 {
  739. varargopt = 0
  740. }
  741. ecupdate(ec, ecNone, reg, varargopt)
  742. reg += compileExpr(context, reg, exprs[i], ec)
  743. }
  744. } // }}}
  745. func compileLocalAssignStmt(context *funcContext, stmt *ast.LocalAssignStmt) { // {{{
  746. reg := context.RegTop()
  747. if len(stmt.Names) == 1 && len(stmt.Exprs) == 1 {
  748. if _, ok := stmt.Exprs[0].(*ast.FunctionExpr); ok {
  749. context.RegisterLocalVar(stmt.Names[0])
  750. compileRegAssignment(context, stmt.Names, stmt.Exprs, reg, len(stmt.Names), sline(stmt))
  751. return
  752. }
  753. }
  754. compileRegAssignment(context, stmt.Names, stmt.Exprs, reg, len(stmt.Names), sline(stmt))
  755. for _, name := range stmt.Names {
  756. context.RegisterLocalVar(name)
  757. }
  758. } // }}}
  759. func compileReturnStmt(context *funcContext, stmt *ast.ReturnStmt) { // {{{
  760. lenexprs := len(stmt.Exprs)
  761. code := context.Code
  762. reg := context.RegTop()
  763. a := reg
  764. lastisvaarg := false
  765. if lenexprs == 1 {
  766. switch ex := stmt.Exprs[0].(type) {
  767. case *ast.IdentExpr:
  768. if idx := context.FindLocalVar(ex.Value); idx > -1 {
  769. code.AddABC(OP_RETURN, idx, 2, 0, sline(stmt))
  770. return
  771. }
  772. case *ast.FuncCallExpr:
  773. if ex.AdjustRet { // return (func())
  774. reg += compileExpr(context, reg, ex, ecnone(0))
  775. } else {
  776. reg += compileExpr(context, reg, ex, ecnone(-2))
  777. code.SetOpCode(code.LastPC(), OP_TAILCALL)
  778. }
  779. code.AddABC(OP_RETURN, a, 0, 0, sline(stmt))
  780. return
  781. }
  782. }
  783. for i, expr := range stmt.Exprs {
  784. if i == lenexprs-1 && isVarArgReturnExpr(expr) {
  785. compileExpr(context, reg, expr, ecnone(-2))
  786. lastisvaarg = true
  787. } else {
  788. reg += compileExpr(context, reg, expr, ecnone(0))
  789. }
  790. }
  791. count := reg - a + 1
  792. if lastisvaarg {
  793. count = 0
  794. }
  795. context.Code.AddABC(OP_RETURN, a, count, 0, sline(stmt))
  796. } // }}}
  797. func compileIfStmt(context *funcContext, stmt *ast.IfStmt) { // {{{
  798. thenlabel := context.NewLabel()
  799. elselabel := context.NewLabel()
  800. endlabel := context.NewLabel()
  801. compileBranchCondition(context, context.RegTop(), stmt.Condition, thenlabel, elselabel, false)
  802. context.SetLabelPc(thenlabel, context.Code.LastPC())
  803. compileBlock(context, stmt.Then)
  804. if len(stmt.Else) > 0 {
  805. context.Code.AddASbx(OP_JMP, 0, endlabel, sline(stmt))
  806. }
  807. context.SetLabelPc(elselabel, context.Code.LastPC())
  808. if len(stmt.Else) > 0 {
  809. compileBlock(context, stmt.Else)
  810. context.SetLabelPc(endlabel, context.Code.LastPC())
  811. }
  812. } // }}}
  813. func compileBranchCondition(context *funcContext, reg int, expr ast.Expr, thenlabel, elselabel int, hasnextcond bool) { // {{{
  814. // TODO folding constants?
  815. code := context.Code
  816. flip := 0
  817. jumplabel := elselabel
  818. if hasnextcond {
  819. flip = 1
  820. jumplabel = thenlabel
  821. }
  822. switch ex := expr.(type) {
  823. case *ast.FalseExpr, *ast.NilExpr:
  824. if !hasnextcond {
  825. code.AddASbx(OP_JMP, 0, elselabel, sline(expr))
  826. return
  827. }
  828. case *ast.TrueExpr, *ast.NumberExpr, *ast.StringExpr:
  829. if !hasnextcond {
  830. return
  831. }
  832. case *ast.UnaryNotOpExpr:
  833. compileBranchCondition(context, reg, ex.Expr, elselabel, thenlabel, !hasnextcond)
  834. return
  835. case *ast.LogicalOpExpr:
  836. switch ex.Operator {
  837. case "and":
  838. nextcondlabel := context.NewLabel()
  839. compileBranchCondition(context, reg, ex.Lhs, nextcondlabel, elselabel, false)
  840. context.SetLabelPc(nextcondlabel, context.Code.LastPC())
  841. compileBranchCondition(context, reg, ex.Rhs, thenlabel, elselabel, hasnextcond)
  842. case "or":
  843. nextcondlabel := context.NewLabel()
  844. compileBranchCondition(context, reg, ex.Lhs, thenlabel, nextcondlabel, true)
  845. context.SetLabelPc(nextcondlabel, context.Code.LastPC())
  846. compileBranchCondition(context, reg, ex.Rhs, thenlabel, elselabel, hasnextcond)
  847. }
  848. return
  849. case *ast.RelationalOpExpr:
  850. compileRelationalOpExprAux(context, reg, ex, flip, jumplabel)
  851. return
  852. }
  853. a := reg
  854. compileExprWithMVPropagation(context, expr, &reg, &a)
  855. code.AddABC(OP_TEST, a, 0, 0^flip, sline(expr))
  856. code.AddASbx(OP_JMP, 0, jumplabel, sline(expr))
  857. } // }}}
  858. func compileWhileStmt(context *funcContext, stmt *ast.WhileStmt) { // {{{
  859. thenlabel := context.NewLabel()
  860. elselabel := context.NewLabel()
  861. condlabel := context.NewLabel()
  862. context.SetLabelPc(condlabel, context.Code.LastPC())
  863. compileBranchCondition(context, context.RegTop(), stmt.Condition, thenlabel, elselabel, false)
  864. context.SetLabelPc(thenlabel, context.Code.LastPC())
  865. context.EnterBlock(elselabel, stmt)
  866. compileChunk(context, stmt.Stmts, false)
  867. context.CloseUpvalues()
  868. context.Code.AddASbx(OP_JMP, 0, condlabel, eline(stmt))
  869. context.LeaveBlock()
  870. context.SetLabelPc(elselabel, context.Code.LastPC())
  871. } // }}}
  872. func compileRepeatStmt(context *funcContext, stmt *ast.RepeatStmt) { // {{{
  873. initlabel := context.NewLabel()
  874. thenlabel := context.NewLabel()
  875. elselabel := context.NewLabel()
  876. context.SetLabelPc(initlabel, context.Code.LastPC())
  877. context.SetLabelPc(elselabel, context.Code.LastPC())
  878. context.EnterBlock(thenlabel, stmt)
  879. compileChunk(context, stmt.Stmts, true)
  880. compileBranchCondition(context, context.RegTop(), stmt.Condition, thenlabel, elselabel, false)
  881. context.SetLabelPc(thenlabel, context.Code.LastPC())
  882. n := context.LeaveBlock()
  883. if n > -1 {
  884. label := context.NewLabel()
  885. context.Code.AddASbx(OP_JMP, 0, label, eline(stmt))
  886. context.SetLabelPc(elselabel, context.Code.LastPC())
  887. context.Code.AddABC(OP_CLOSE, n, 0, 0, eline(stmt))
  888. context.Code.AddASbx(OP_JMP, 0, initlabel, eline(stmt))
  889. context.SetLabelPc(label, context.Code.LastPC())
  890. }
  891. } // }}}
  892. func compileBreakStmt(context *funcContext, stmt *ast.BreakStmt) { // {{{
  893. for block := context.Block; block != nil; block = block.Parent {
  894. if label := block.BreakLabel; label != labelNoJump {
  895. if block.RefUpvalue {
  896. context.Code.AddABC(OP_CLOSE, block.Parent.LocalVars.LastIndex(), 0, 0, sline(stmt))
  897. }
  898. context.Code.AddASbx(OP_JMP, 0, label, sline(stmt))
  899. return
  900. }
  901. }
  902. raiseCompileError(context, sline(stmt), "no loop to break")
  903. } // }}}
  904. func compileFuncDefStmt(context *funcContext, stmt *ast.FuncDefStmt) { // {{{
  905. if stmt.Name.Func == nil {
  906. reg := context.RegTop()
  907. var treg, kreg int
  908. compileExprWithKMVPropagation(context, stmt.Name.Receiver, &reg, &treg)
  909. kreg = loadRk(context, &reg, stmt.Func, LString(stmt.Name.Method))
  910. compileExpr(context, reg, stmt.Func, ecfuncdef)
  911. context.Code.AddABC(OP_SETTABLE, treg, kreg, reg, sline(stmt.Name.Receiver))
  912. } else {
  913. astmt := &ast.AssignStmt{Lhs: []ast.Expr{stmt.Name.Func}, Rhs: []ast.Expr{stmt.Func}}
  914. astmt.SetLine(sline(stmt.Func))
  915. astmt.SetLastLine(eline(stmt.Func))
  916. compileAssignStmt(context, astmt)
  917. }
  918. } // }}}
  919. func compileNumberForStmt(context *funcContext, stmt *ast.NumberForStmt) { // {{{
  920. code := context.Code
  921. endlabel := context.NewLabel()
  922. ec := &expcontext{}
  923. context.EnterBlock(endlabel, stmt)
  924. reg := context.RegTop()
  925. rindex := context.RegisterLocalVar("(for index)")
  926. ecupdate(ec, ecLocal, rindex, 0)
  927. compileExpr(context, reg, stmt.Init, ec)
  928. reg = context.RegTop()
  929. rlimit := context.RegisterLocalVar("(for limit)")
  930. ecupdate(ec, ecLocal, rlimit, 0)
  931. compileExpr(context, reg, stmt.Limit, ec)
  932. reg = context.RegTop()
  933. rstep := context.RegisterLocalVar("(for step)")
  934. if stmt.Step == nil {
  935. stmt.Step = &ast.NumberExpr{Value: "1"}
  936. stmt.Step.SetLine(sline(stmt.Init))
  937. }
  938. ecupdate(ec, ecLocal, rstep, 0)
  939. compileExpr(context, reg, stmt.Step, ec)
  940. code.AddASbx(OP_FORPREP, rindex, 0, sline(stmt))
  941. context.RegisterLocalVar(stmt.Name)
  942. bodypc := code.LastPC()
  943. compileChunk(context, stmt.Stmts, false)
  944. context.LeaveBlock()
  945. flpc := code.LastPC()
  946. code.AddASbx(OP_FORLOOP, rindex, bodypc-(flpc+1), sline(stmt))
  947. context.SetLabelPc(endlabel, code.LastPC())
  948. code.SetSbx(bodypc, flpc-bodypc)
  949. } // }}}
  950. func compileGenericForStmt(context *funcContext, stmt *ast.GenericForStmt) { // {{{
  951. code := context.Code
  952. endlabel := context.NewLabel()
  953. bodylabel := context.NewLabel()
  954. fllabel := context.NewLabel()
  955. nnames := len(stmt.Names)
  956. context.EnterBlock(endlabel, stmt)
  957. rgen := context.RegisterLocalVar("(for generator)")
  958. context.RegisterLocalVar("(for state)")
  959. context.RegisterLocalVar("(for control)")
  960. compileRegAssignment(context, stmt.Names, stmt.Exprs, context.RegTop()-3, 3, sline(stmt))
  961. code.AddASbx(OP_JMP, 0, fllabel, sline(stmt))
  962. for _, name := range stmt.Names {
  963. context.RegisterLocalVar(name)
  964. }
  965. context.SetLabelPc(bodylabel, code.LastPC())
  966. compileChunk(context, stmt.Stmts, false)
  967. context.LeaveBlock()
  968. context.SetLabelPc(fllabel, code.LastPC())
  969. code.AddABC(OP_TFORLOOP, rgen, 0, nnames, sline(stmt))
  970. code.AddASbx(OP_JMP, 0, bodylabel, sline(stmt))
  971. context.SetLabelPc(endlabel, code.LastPC())
  972. } // }}}
  973. func compileLabelStmt(context *funcContext, stmt *ast.LabelStmt, isLastStmt bool) { // {{{
  974. labelId := context.NewLabel()
  975. label := newLabelDesc(labelId, stmt.Name, context.Code.LastPC(), sline(stmt), context.BlockLocalVarsCount())
  976. context.AddNamedLabel(label)
  977. if isLastStmt {
  978. label.SetNumActiveLocalVars(context.Block.Parent.LocalVarsCount())
  979. }
  980. context.ResolveForwardGoto(label)
  981. } // }}}
  982. func compileGotoStmt(context *funcContext, stmt *ast.GotoStmt) { // {{{
  983. context.Code.AddABC(OP_CLOSE, 0, 0, 0, sline(stmt))
  984. context.Code.AddASbx(OP_JMP, 0, labelNoJump, sline(stmt))
  985. label := newLabelDesc(-1, stmt.Label, context.Code.LastPC(), sline(stmt), context.BlockLocalVarsCount())
  986. context.AddUnresolvedGoto(label)
  987. context.FindLabel(context.Block, label, context.gotosCount-1)
  988. } // }}}
  989. func compileExpr(context *funcContext, reg int, expr ast.Expr, ec *expcontext) int { // {{{
  990. code := context.Code
  991. sreg := savereg(ec, reg)
  992. sused := 1
  993. if sreg < reg {
  994. sused = 0
  995. }
  996. switch ex := expr.(type) {
  997. case *ast.StringExpr:
  998. code.AddABx(OP_LOADK, sreg, context.ConstIndex(LString(ex.Value)), sline(ex))
  999. return sused
  1000. case *ast.NumberExpr:
  1001. num, err := parseNumber(ex.Value)
  1002. if err != nil {
  1003. num = LNumber(math.NaN())
  1004. }
  1005. code.AddABx(OP_LOADK, sreg, context.ConstIndex(num), sline(ex))
  1006. return sused
  1007. case *constLValueExpr:
  1008. code.AddABx(OP_LOADK, sreg, context.ConstIndex(ex.Value), sline(ex))
  1009. return sused
  1010. case *ast.NilExpr:
  1011. code.AddLoadNil(sreg, sreg, sline(ex))
  1012. return sused
  1013. case *ast.FalseExpr:
  1014. code.AddABC(OP_LOADBOOL, sreg, 0, 0, sline(ex))
  1015. return sused
  1016. case *ast.TrueExpr:
  1017. code.AddABC(OP_LOADBOOL, sreg, 1, 0, sline(ex))
  1018. return sused
  1019. case *ast.IdentExpr:
  1020. switch getIdentRefType(context, context, ex) {
  1021. case ecGlobal:
  1022. code.AddABx(OP_GETGLOBAL, sreg, context.ConstIndex(LString(ex.Value)), sline(ex))
  1023. case ecUpvalue:
  1024. code.AddABC(OP_GETUPVAL, sreg, context.Upvalues.RegisterUnique(ex.Value), 0, sline(ex))
  1025. case ecLocal:
  1026. b := context.FindLocalVar(ex.Value)
  1027. code.AddABC(OP_MOVE, sreg, b, 0, sline(ex))
  1028. }
  1029. return sused
  1030. case *ast.Comma3Expr:
  1031. if context.Proto.IsVarArg == 0 {
  1032. raiseCompileError(context, sline(ex), "cannot use '...' outside a vararg function")
  1033. }
  1034. context.Proto.IsVarArg &= ^VarArgNeedsArg
  1035. code.AddABC(OP_VARARG, sreg, 2+ec.varargopt, 0, sline(ex))
  1036. if context.RegTop() > (sreg+2+ec.varargopt) || ec.varargopt < -1 {
  1037. return 0
  1038. }
  1039. return (sreg + 1 + ec.varargopt) - reg
  1040. case *ast.AttrGetExpr:
  1041. a := sreg
  1042. b := reg
  1043. compileExprWithMVPropagation(context, ex.Object, &reg, &b)
  1044. c := reg
  1045. compileExprWithKMVPropagation(context, ex.Key, &reg, &c)
  1046. opcode := OP_GETTABLE
  1047. if _, ok := ex.Key.(*ast.StringExpr); ok {
  1048. opcode = OP_GETTABLEKS
  1049. }
  1050. code.AddABC(opcode, a, b, c, sline(ex))
  1051. return sused
  1052. case *ast.TableExpr:
  1053. compileTableExpr(context, reg, ex, ec)
  1054. return 1
  1055. case *ast.ArithmeticOpExpr:
  1056. compileArithmeticOpExpr(context, reg, ex, ec)
  1057. return sused
  1058. case *ast.StringConcatOpExpr:
  1059. compileStringConcatOpExpr(context, reg, ex, ec)
  1060. return sused
  1061. case *ast.UnaryMinusOpExpr, *ast.UnaryNotOpExpr, *ast.UnaryLenOpExpr:
  1062. compileUnaryOpExpr(context, reg, ex, ec)
  1063. return sused
  1064. case *ast.RelationalOpExpr:
  1065. compileRelationalOpExpr(context, reg, ex, ec)
  1066. return sused
  1067. case *ast.LogicalOpExpr:
  1068. compileLogicalOpExpr(context, reg, ex, ec)
  1069. return sused
  1070. case *ast.FuncCallExpr:
  1071. return compileFuncCallExpr(context, reg, ex, ec)
  1072. case *ast.FunctionExpr:
  1073. childcontext := newFuncContext(context.Proto.SourceName, context)
  1074. compileFunctionExpr(childcontext, ex, ec)
  1075. protono := len(context.Proto.FunctionPrototypes)
  1076. context.Proto.FunctionPrototypes = append(context.Proto.FunctionPrototypes, childcontext.Proto)
  1077. code.AddABx(OP_CLOSURE, sreg, protono, sline(ex))
  1078. for _, upvalue := range childcontext.Upvalues.List() {
  1079. localidx, block := context.FindLocalVarAndBlock(upvalue.Name)
  1080. if localidx > -1 {
  1081. code.AddABC(OP_MOVE, 0, localidx, 0, sline(ex))
  1082. block.RefUpvalue = true
  1083. } else {
  1084. upvalueidx := context.Upvalues.Find(upvalue.Name)
  1085. if upvalueidx < 0 {
  1086. upvalueidx = context.Upvalues.RegisterUnique(upvalue.Name)
  1087. }
  1088. code.AddABC(OP_GETUPVAL, 0, upvalueidx, 0, sline(ex))
  1089. }
  1090. }
  1091. return sused
  1092. default:
  1093. panic(fmt.Sprintf("expr %v not implemented.", reflect.TypeOf(ex).Elem().Name()))
  1094. }
  1095. } // }}}
  1096. func compileExprWithPropagation(context *funcContext, expr ast.Expr, reg *int, save *int, propergator func(int, *int, *int, int)) { // {{{
  1097. reginc := compileExpr(context, *reg, expr, ecnone(0))
  1098. if _, ok := expr.(*ast.LogicalOpExpr); ok {
  1099. *save = *reg
  1100. *reg = *reg + reginc
  1101. } else {
  1102. propergator(context.RegTop(), save, reg, reginc)
  1103. }
  1104. } // }}}
  1105. func compileExprWithKMVPropagation(context *funcContext, expr ast.Expr, reg *int, save *int) { // {{{
  1106. compileExprWithPropagation(context, expr, reg, save, context.Code.PropagateKMV)
  1107. } // }}}
  1108. func compileExprWithMVPropagation(context *funcContext, expr ast.Expr, reg *int, save *int) { // {{{
  1109. compileExprWithPropagation(context, expr, reg, save, context.Code.PropagateMV)
  1110. } // }}}
  1111. func constFold(exp ast.Expr) ast.Expr { // {{{
  1112. switch expr := exp.(type) {
  1113. case *ast.ArithmeticOpExpr:
  1114. lvalue, lisconst := lnumberValue(constFold(expr.Lhs))
  1115. rvalue, risconst := lnumberValue(constFold(expr.Rhs))
  1116. if lisconst && risconst {
  1117. switch expr.Operator {
  1118. case "+":
  1119. return &constLValueExpr{Value: lvalue + rvalue}
  1120. case "-":
  1121. return &constLValueExpr{Value: lvalue - rvalue}
  1122. case "*":
  1123. return &constLValueExpr{Value: lvalue * rvalue}
  1124. case "/":
  1125. return &constLValueExpr{Value: lvalue / rvalue}
  1126. case "%":
  1127. return &constLValueExpr{Value: luaModulo(lvalue, rvalue)}
  1128. case "^":
  1129. return &constLValueExpr{Value: LNumber(math.Pow(float64(lvalue), float64(rvalue)))}
  1130. default:
  1131. panic(fmt.Sprintf("unknown binop: %v", expr.Operator))
  1132. }
  1133. } else {
  1134. return expr
  1135. }
  1136. case *ast.UnaryMinusOpExpr:
  1137. expr.Expr = constFold(expr.Expr)
  1138. if value, ok := lnumberValue(expr.Expr); ok {
  1139. return &constLValueExpr{Value: LNumber(-value)}
  1140. }
  1141. return expr
  1142. default:
  1143. return exp
  1144. }
  1145. } // }}}
  1146. func compileFunctionExpr(context *funcContext, funcexpr *ast.FunctionExpr, ec *expcontext) { // {{{
  1147. context.Proto.LineDefined = sline(funcexpr)
  1148. context.Proto.LastLineDefined = eline(funcexpr)
  1149. if len(funcexpr.ParList.Names) > maxRegisters {
  1150. raiseCompileError(context, context.Proto.LineDefined, "register overflow")
  1151. }
  1152. context.Proto.NumParameters = uint8(len(funcexpr.ParList.Names))
  1153. if ec.ctype == ecMethod {
  1154. context.Proto.NumParameters += 1
  1155. context.RegisterLocalVar("self")
  1156. }
  1157. for _, name := range funcexpr.ParList.Names {
  1158. context.RegisterLocalVar(name)
  1159. }
  1160. if funcexpr.ParList.HasVargs {
  1161. if CompatVarArg {
  1162. context.Proto.IsVarArg = VarArgHasArg | VarArgNeedsArg
  1163. if context.Parent != nil {
  1164. context.RegisterLocalVar("arg")
  1165. }
  1166. }
  1167. context.Proto.IsVarArg |= VarArgIsVarArg
  1168. }
  1169. compileChunk(context, funcexpr.Stmts, false)
  1170. context.Code.AddABC(OP_RETURN, 0, 1, 0, eline(funcexpr))
  1171. context.EndScope()
  1172. context.CheckUnresolvedGoto()
  1173. context.Proto.Code = context.Code.List()
  1174. context.Proto.DbgSourcePositions = context.Code.PosList()
  1175. context.Proto.DbgUpvalues = context.Upvalues.Names()
  1176. context.Proto.NumUpvalues = uint8(len(context.Proto.DbgUpvalues))
  1177. for _, clv := range context.Proto.Constants {
  1178. sv := ""
  1179. if slv, ok := clv.(LString); ok {
  1180. sv = string(slv)
  1181. }
  1182. context.Proto.stringConstants = append(context.Proto.stringConstants, sv)
  1183. }
  1184. patchCode(context)
  1185. } // }}}
  1186. func compileTableExpr(context *funcContext, reg int, ex *ast.TableExpr, ec *expcontext) { // {{{
  1187. code := context.Code
  1188. /*
  1189. tablereg := savereg(ec, reg)
  1190. if tablereg == reg {
  1191. reg += 1
  1192. }
  1193. */
  1194. tablereg := reg
  1195. reg++
  1196. code.AddABC(OP_NEWTABLE, tablereg, 0, 0, sline(ex))
  1197. tablepc := code.LastPC()
  1198. regbase := reg
  1199. arraycount := 0
  1200. lastvararg := false
  1201. for i, field := range ex.Fields {
  1202. islast := i == len(ex.Fields)-1
  1203. if field.Key == nil {
  1204. if islast && isVarArgReturnExpr(field.Value) {
  1205. reg += compileExpr(context, reg, field.Value, ecnone(-2))
  1206. lastvararg = true
  1207. } else {
  1208. reg += compileExpr(context, reg, field.Value, ecnone(0))
  1209. arraycount += 1
  1210. }
  1211. } else {
  1212. regorg := reg
  1213. b := reg
  1214. compileExprWithKMVPropagation(context, field.Key, &reg, &b)
  1215. c := reg
  1216. compileExprWithKMVPropagation(context, field.Value, &reg, &c)
  1217. opcode := OP_SETTABLE
  1218. if _, ok := field.Key.(*ast.StringExpr); ok {
  1219. opcode = OP_SETTABLEKS
  1220. }
  1221. code.AddABC(opcode, tablereg, b, c, sline(ex))
  1222. reg = regorg
  1223. }
  1224. flush := arraycount % FieldsPerFlush
  1225. if (arraycount != 0 && (flush == 0 || islast)) || lastvararg {
  1226. reg = regbase
  1227. num := flush
  1228. if num == 0 {
  1229. num = FieldsPerFlush
  1230. }
  1231. c := (arraycount-1)/FieldsPerFlush + 1
  1232. b := num
  1233. if islast && isVarArgReturnExpr(field.Value) {
  1234. b = 0
  1235. }
  1236. line := field.Value
  1237. if field.Key != nil {
  1238. line = field.Key
  1239. }
  1240. if c > 511 {
  1241. c = 0
  1242. }
  1243. code.AddABC(OP_SETLIST, tablereg, b, c, sline(line))
  1244. if c == 0 {
  1245. code.Add(uint32(c), sline(line))
  1246. }
  1247. }
  1248. }
  1249. code.SetB(tablepc, int2Fb(arraycount))
  1250. code.SetC(tablepc, int2Fb(len(ex.Fields)-arraycount))
  1251. if shouldmove(ec, tablereg) {
  1252. code.AddABC(OP_MOVE, ec.reg, tablereg, 0, sline(ex))
  1253. }
  1254. } // }}}
  1255. func compileArithmeticOpExpr(context *funcContext, reg int, expr *ast.ArithmeticOpExpr, ec *expcontext) { // {{{
  1256. exp := constFold(expr)
  1257. if ex, ok := exp.(*constLValueExpr); ok {
  1258. exp.SetLine(sline(expr))
  1259. compileExpr(context, reg, ex, ec)
  1260. return
  1261. }
  1262. expr, _ = exp.(*ast.ArithmeticOpExpr)
  1263. a := savereg(ec, reg)
  1264. b := reg
  1265. compileExprWithKMVPropagation(context, expr.Lhs, &reg, &b)
  1266. c := reg
  1267. compileExprWithKMVPropagation(context, expr.Rhs, &reg, &c)
  1268. op := 0
  1269. switch expr.Operator {
  1270. case "+":
  1271. op = OP_ADD
  1272. case "-":
  1273. op = OP_SUB
  1274. case "*":
  1275. op = OP_MUL
  1276. case "/":
  1277. op = OP_DIV
  1278. case "%":
  1279. op = OP_MOD
  1280. case "^":
  1281. op = OP_POW
  1282. }
  1283. context.Code.AddABC(op, a, b, c, sline(expr))
  1284. } // }}}
  1285. func compileStringConcatOpExpr(context *funcContext, reg int, expr *ast.StringConcatOpExpr, ec *expcontext) { // {{{
  1286. code := context.Code
  1287. crange := 1
  1288. for current := expr.Rhs; current != nil; {
  1289. if ex, ok := current.(*ast.StringConcatOpExpr); ok {
  1290. crange += 1
  1291. current = ex.Rhs
  1292. } else {
  1293. current = nil
  1294. }
  1295. }
  1296. a := savereg(ec, reg)
  1297. basereg := reg
  1298. reg += compileExpr(context, reg, expr.Lhs, ecnone(0))
  1299. reg += compileExpr(context, reg, expr.Rhs, ecnone(0))
  1300. for pc := code.LastPC(); pc != 0 && opGetOpCode(code.At(pc)) == OP_CONCAT; pc-- {
  1301. code.Pop()
  1302. }
  1303. code.AddABC(OP_CONCAT, a, basereg, basereg+crange, sline(expr))
  1304. } // }}}
  1305. func compileUnaryOpExpr(context *funcContext, reg int, expr ast.Expr, ec *expcontext) { // {{{
  1306. opcode := 0
  1307. code := context.Code
  1308. var operandexpr ast.Expr
  1309. switch ex := expr.(type) {
  1310. case *ast.UnaryMinusOpExpr:
  1311. exp := constFold(ex)
  1312. if lvexpr, ok := exp.(*constLValueExpr); ok {
  1313. exp.SetLine(sline(expr))
  1314. compileExpr(context, reg, lvexpr, ec)
  1315. return
  1316. }
  1317. ex, _ = exp.(*ast.UnaryMinusOpExpr)
  1318. operandexpr = ex.Expr
  1319. opcode = OP_UNM
  1320. case *ast.UnaryNotOpExpr:
  1321. switch ex.Expr.(type) {
  1322. case *ast.TrueExpr:
  1323. code.AddABC(OP_LOADBOOL, savereg(ec, reg), 0, 0, sline(expr))
  1324. return
  1325. case *ast.FalseExpr, *ast.NilExpr:
  1326. code.AddABC(OP_LOADBOOL, savereg(ec, reg), 1, 0, sline(expr))
  1327. return
  1328. default:
  1329. opcode = OP_NOT
  1330. operandexpr = ex.Expr
  1331. }
  1332. case *ast.UnaryLenOpExpr:
  1333. opcode = OP_LEN
  1334. operandexpr = ex.Expr
  1335. }
  1336. a := savereg(ec, reg)
  1337. b := reg
  1338. compileExprWithMVPropagation(context, operandexpr, &reg, &b)
  1339. code.AddABC(opcode, a, b, 0, sline(expr))
  1340. } // }}}
  1341. func compileRelationalOpExprAux(context *funcContext, reg int, expr *ast.RelationalOpExpr, flip int, label int) { // {{{
  1342. code := context.Code
  1343. b := reg
  1344. compileExprWithKMVPropagation(context, expr.Lhs, &reg, &b)
  1345. c := reg
  1346. compileExprWithKMVPropagation(context, expr.Rhs, &reg, &c)
  1347. switch expr.Operator {
  1348. case "<":
  1349. code.AddABC(OP_LT, 0^flip, b, c, sline(expr))
  1350. case ">":
  1351. code.AddABC(OP_LT, 0^flip, c, b, sline(expr))
  1352. case "<=":
  1353. code.AddABC(OP_LE, 0^flip, b, c, sline(expr))
  1354. case ">=":
  1355. code.AddABC(OP_LE, 0^flip, c, b, sline(expr))
  1356. case "==":
  1357. code.AddABC(OP_EQ, 0^flip, b, c, sline(expr))
  1358. case "~=":
  1359. code.AddABC(OP_EQ, 1^flip, b, c, sline(expr))
  1360. }
  1361. code.AddASbx(OP_JMP, 0, label, sline(expr))
  1362. } // }}}
  1363. func compileRelationalOpExpr(context *funcContext, reg int, expr *ast.RelationalOpExpr, ec *expcontext) { // {{{
  1364. a := savereg(ec, reg)
  1365. code := context.Code
  1366. jumplabel := context.NewLabel()
  1367. compileRelationalOpExprAux(context, reg, expr, 1, jumplabel)
  1368. code.AddABC(OP_LOADBOOL, a, 0, 1, sline(expr))
  1369. context.SetLabelPc(jumplabel, code.LastPC())
  1370. code.AddABC(OP_LOADBOOL, a, 1, 0, sline(expr))
  1371. } // }}}
  1372. func compileLogicalOpExpr(context *funcContext, reg int, expr *ast.LogicalOpExpr, ec *expcontext) { // {{{
  1373. a := savereg(ec, reg)
  1374. code := context.Code
  1375. endlabel := context.NewLabel()
  1376. lb := &lblabels{context.NewLabel(), context.NewLabel(), endlabel, false}
  1377. nextcondlabel := context.NewLabel()
  1378. if expr.Operator == "and" {
  1379. compileLogicalOpExprAux(context, reg, expr.Lhs, ec, nextcondlabel, endlabel, false, lb)
  1380. context.SetLabelPc(nextcondlabel, code.LastPC())
  1381. compileLogicalOpExprAux(context, reg, expr.Rhs, ec, endlabel, endlabel, false, lb)
  1382. } else {
  1383. compileLogicalOpExprAux(context, reg, expr.Lhs, ec, endlabel, nextcondlabel, true, lb)
  1384. context.SetLabelPc(nextcondlabel, code.LastPC())
  1385. compileLogicalOpExprAux(context, reg, expr.Rhs, ec, endlabel, endlabel, false, lb)
  1386. }
  1387. if lb.b {
  1388. context.SetLabelPc(lb.f, code.LastPC())
  1389. code.AddABC(OP_LOADBOOL, a, 0, 1, sline(expr))
  1390. context.SetLabelPc(lb.t, code.LastPC())
  1391. code.AddABC(OP_LOADBOOL, a, 1, 0, sline(expr))
  1392. }
  1393. lastinst := code.Last()
  1394. if opGetOpCode(lastinst) == OP_JMP && opGetArgSbx(lastinst) == endlabel {
  1395. code.Pop()
  1396. }
  1397. context.SetLabelPc(endlabel, code.LastPC())
  1398. } // }}}
  1399. func compileLogicalOpExprAux(context *funcContext, reg int, expr ast.Expr, ec *expcontext, thenlabel, elselabel int, hasnextcond bool, lb *lblabels) { // {{{
  1400. // TODO folding constants?
  1401. code := context.Code
  1402. flip := 0
  1403. jumplabel := elselabel
  1404. if hasnextcond {
  1405. flip = 1
  1406. jumplabel = thenlabel
  1407. }
  1408. switch ex := expr.(type) {
  1409. case *ast.FalseExpr:
  1410. if elselabel == lb.e {
  1411. code.AddASbx(OP_JMP, 0, lb.f, sline(expr))
  1412. lb.b = true
  1413. } else {
  1414. code.AddASbx(OP_JMP, 0, elselabel, sline(expr))
  1415. }
  1416. return
  1417. case *ast.NilExpr:
  1418. if elselabel == lb.e {
  1419. compileExpr(context, reg, expr, ec)
  1420. code.AddASbx(OP_JMP, 0, lb.e, sline(expr))
  1421. } else {
  1422. code.AddASbx(OP_JMP, 0, elselabel, sline(expr))
  1423. }
  1424. return
  1425. case *ast.TrueExpr:
  1426. if thenlabel == lb.e {
  1427. code.AddASbx(OP_JMP, 0, lb.t, sline(expr))
  1428. lb.b = true
  1429. } else {
  1430. code.AddASbx(OP_JMP, 0, thenlabel, sline(expr))
  1431. }
  1432. return
  1433. case *ast.NumberExpr, *ast.StringExpr:
  1434. if thenlabel == lb.e {
  1435. compileExpr(context, reg, expr, ec)
  1436. code.AddASbx(OP_JMP, 0, lb.e, sline(expr))
  1437. } else {
  1438. code.AddASbx(OP_JMP, 0, thenlabel, sline(expr))
  1439. }
  1440. return
  1441. case *ast.LogicalOpExpr:
  1442. switch ex.Operator {
  1443. case "and":
  1444. nextcondlabel := context.NewLabel()
  1445. compileLogicalOpExprAux(context, reg, ex.Lhs, ec, nextcondlabel, elselabel, false, lb)
  1446. context.SetLabelPc(nextcondlabel, context.Code.LastPC())
  1447. compileLogicalOpExprAux(context, reg, ex.Rhs, ec, thenlabel, elselabel, hasnextcond, lb)
  1448. case "or":
  1449. nextcondlabel := context.NewLabel()
  1450. compileLogicalOpExprAux(context, reg, ex.Lhs, ec, thenlabel, nextcondlabel, true, lb)
  1451. context.SetLabelPc(nextcondlabel, context.Code.LastPC())
  1452. compileLogicalOpExprAux(context, reg, ex.Rhs, ec, thenlabel, elselabel, hasnextcond, lb)
  1453. }
  1454. return
  1455. case *ast.RelationalOpExpr:
  1456. if thenlabel == elselabel {
  1457. flip ^= 1
  1458. jumplabel = lb.t
  1459. lb.b = true
  1460. } else if thenlabel == lb.e {
  1461. jumplabel = lb.t
  1462. lb.b = true
  1463. } else if elselabel == lb.e {
  1464. jumplabel = lb.f
  1465. lb.b = true
  1466. }
  1467. compileRelationalOpExprAux(context, reg, ex, flip, jumplabel)
  1468. return
  1469. }
  1470. a := reg
  1471. sreg := savereg(ec, a)
  1472. isLastAnd := elselabel == lb.e && thenlabel != elselabel
  1473. isLastOr := thenlabel == lb.e && hasnextcond
  1474. if ident, ok := expr.(*ast.IdentExpr); ok && (isLastAnd || isLastOr) && getIdentRefType(context, context, ident) == ecLocal {
  1475. b := context.FindLocalVar(ident.Value)
  1476. op := OP_TESTSET
  1477. if sreg == b {
  1478. op = OP_TEST
  1479. }
  1480. code.AddABC(op, sreg, b, 0^flip, sline(expr))
  1481. } else if !hasnextcond && thenlabel == elselabel {
  1482. reg += compileExpr(context, reg, expr, &expcontext{ec.ctype, intMax(a, sreg), ec.varargopt})
  1483. last := context.Code.Last()
  1484. if opGetOpCode(last) == OP_MOVE && opGetArgA(last) == a {
  1485. context.Code.SetA(context.Code.LastPC(), sreg)
  1486. } else {
  1487. context.Code.AddABC(OP_MOVE, sreg, a, 0, sline(expr))
  1488. }
  1489. } else {
  1490. reg += compileExpr(context, reg, expr, ecnone(0))
  1491. if !hasnextcond {
  1492. code.AddABC(OP_TEST, a, 0, 0^flip, sline(expr))
  1493. } else {
  1494. code.AddABC(OP_TESTSET, sreg, a, 0^flip, sline(expr))
  1495. }
  1496. }
  1497. code.AddASbx(OP_JMP, 0, jumplabel, sline(expr))
  1498. } // }}}
  1499. func compileFuncCallExpr(context *funcContext, reg int, expr *ast.FuncCallExpr, ec *expcontext) int { // {{{
  1500. funcreg := reg
  1501. if ec.ctype == ecLocal && ec.reg == (int(context.Proto.NumParameters)-1) {
  1502. funcreg = ec.reg
  1503. reg = ec.reg
  1504. }
  1505. argc := len(expr.Args)
  1506. islastvararg := false
  1507. name := "(anonymous)"
  1508. if expr.Func != nil { // hoge.func()
  1509. reg += compileExpr(context, reg, expr.Func, ecnone(0))
  1510. name = getExprName(context, expr.Func)
  1511. } else { // hoge:method()
  1512. b := reg
  1513. compileExprWithMVPropagation(context, expr.Receiver, &reg, &b)
  1514. c := loadRk(context, &reg, expr, LString(expr.Method))
  1515. context.Code.AddABC(OP_SELF, funcreg, b, c, sline(expr))
  1516. // increments a register for an implicit "self"
  1517. reg = b + 1
  1518. reg2 := funcreg + 2
  1519. if reg2 > reg {
  1520. reg = reg2
  1521. }
  1522. argc += 1
  1523. name = string(expr.Method)
  1524. }
  1525. for i, ar := range expr.Args {
  1526. islastvararg = (i == len(expr.Args)-1) && isVarArgReturnExpr(ar)
  1527. if islastvararg {
  1528. compileExpr(context, reg, ar, ecnone(-2))
  1529. } else {
  1530. reg += compileExpr(context, reg, ar, ecnone(0))
  1531. }
  1532. }
  1533. b := argc + 1
  1534. if islastvararg {
  1535. b = 0
  1536. }
  1537. context.Code.AddABC(OP_CALL, funcreg, b, ec.varargopt+2, sline(expr))
  1538. context.Proto.DbgCalls = append(context.Proto.DbgCalls, DbgCall{Pc: context.Code.LastPC(), Name: name})
  1539. if ec.varargopt == 0 && shouldmove(ec, funcreg) {
  1540. context.Code.AddABC(OP_MOVE, ec.reg, funcreg, 0, sline(expr))
  1541. return 1
  1542. }
  1543. if context.RegTop() > (funcreg+2+ec.varargopt) || ec.varargopt < -1 {
  1544. return 0
  1545. }
  1546. return ec.varargopt + 1
  1547. } // }}}
  1548. func loadRk(context *funcContext, reg *int, expr ast.Expr, cnst LValue) int { // {{{
  1549. cindex := context.ConstIndex(cnst)
  1550. if cindex <= opMaxIndexRk {
  1551. return opRkAsk(cindex)
  1552. } else {
  1553. ret := *reg
  1554. *reg++
  1555. context.Code.AddABx(OP_LOADK, ret, cindex, sline(expr))
  1556. return ret
  1557. }
  1558. } // }}}
  1559. func getIdentRefType(context *funcContext, current *funcContext, expr *ast.IdentExpr) expContextType { // {{{
  1560. if current == nil {
  1561. return ecGlobal
  1562. } else if current.FindLocalVar(expr.Value) > -1 {
  1563. if current == context {
  1564. return ecLocal
  1565. }
  1566. return ecUpvalue
  1567. }
  1568. return getIdentRefType(context, current.Parent, expr)
  1569. } // }}}
  1570. func getExprName(context *funcContext, expr ast.Expr) string { // {{{
  1571. switch ex := expr.(type) {
  1572. case *ast.IdentExpr:
  1573. return ex.Value
  1574. case *ast.AttrGetExpr:
  1575. switch kex := ex.Key.(type) {
  1576. case *ast.StringExpr:
  1577. return kex.Value
  1578. }
  1579. return "?"
  1580. }
  1581. return "?"
  1582. } // }}}
  1583. func patchCode(context *funcContext) { // {{{
  1584. maxreg := 1
  1585. if np := int(context.Proto.NumParameters); np > 1 {
  1586. maxreg = np
  1587. }
  1588. moven := 0
  1589. code := context.Code.List()
  1590. for pc := 0; pc < len(code); pc++ {
  1591. inst := code[pc]
  1592. curop := opGetOpCode(inst)
  1593. switch curop {
  1594. case OP_CLOSURE:
  1595. pc += int(context.Proto.FunctionPrototypes[opGetArgBx(inst)].NumUpvalues)
  1596. moven = 0
  1597. continue
  1598. case OP_SETGLOBAL, OP_SETUPVAL, OP_EQ, OP_LT, OP_LE, OP_TEST,
  1599. OP_TAILCALL, OP_RETURN, OP_FORPREP, OP_FORLOOP, OP_TFORLOOP,
  1600. OP_SETLIST, OP_CLOSE:
  1601. /* nothing to do */
  1602. case OP_CALL:
  1603. if reg := opGetArgA(inst) + opGetArgC(inst) - 2; reg > maxreg {
  1604. maxreg = reg
  1605. }
  1606. case OP_VARARG:
  1607. if reg := opGetArgA(inst) + opGetArgB(inst) - 1; reg > maxreg {
  1608. maxreg = reg
  1609. }
  1610. case OP_SELF:
  1611. if reg := opGetArgA(inst) + 1; reg > maxreg {
  1612. maxreg = reg
  1613. }
  1614. case OP_LOADNIL:
  1615. if reg := opGetArgB(inst); reg > maxreg {
  1616. maxreg = reg
  1617. }
  1618. case OP_JMP: // jump to jump optimization
  1619. distance := 0
  1620. count := 0 // avoiding infinite loops
  1621. for jmp := inst; opGetOpCode(jmp) == OP_JMP && count < 5; jmp = context.Code.At(pc + distance + 1) {
  1622. d := context.GetLabelPc(opGetArgSbx(jmp)) - pc
  1623. if d > opMaxArgSbx {
  1624. if distance == 0 {
  1625. raiseCompileError(context, context.Proto.LineDefined, "too long to jump.")
  1626. }
  1627. break
  1628. }
  1629. distance = d
  1630. count++
  1631. }
  1632. if distance == 0 {
  1633. context.Code.SetOpCode(pc, OP_NOP)
  1634. } else {
  1635. context.Code.SetSbx(pc, distance)
  1636. }
  1637. default:
  1638. if reg := opGetArgA(inst); reg > maxreg {
  1639. maxreg = reg
  1640. }
  1641. }
  1642. // bulk move optimization(reducing op dipatch costs)
  1643. if curop == OP_MOVE {
  1644. moven++
  1645. } else {
  1646. if moven > 1 {
  1647. context.Code.SetOpCode(pc-moven, OP_MOVEN)
  1648. context.Code.SetC(pc-moven, intMin(moven-1, opMaxArgsC))
  1649. }
  1650. moven = 0
  1651. }
  1652. }
  1653. maxreg++
  1654. if maxreg > maxRegisters {
  1655. raiseCompileError(context, context.Proto.LineDefined, "register overflow(too many local variables)")
  1656. }
  1657. context.Proto.NumUsedRegisters = uint8(maxreg)
  1658. } // }}}
  1659. func Compile(chunk []ast.Stmt, name string) (proto *FunctionProto, err error) { // {{{
  1660. defer func() {
  1661. if rcv := recover(); rcv != nil {
  1662. if _, ok := rcv.(*CompileError); ok {
  1663. err = rcv.(error)
  1664. } else {
  1665. panic(rcv)
  1666. }
  1667. }
  1668. }()
  1669. err = nil
  1670. parlist := &ast.ParList{HasVargs: true, Names: []string{}}
  1671. funcexpr := &ast.FunctionExpr{ParList: parlist, Stmts: chunk}
  1672. if len(chunk) > 0 {
  1673. funcexpr.SetLastLine(sline(chunk[0]))
  1674. funcexpr.SetLastLine(eline(chunk[len(chunk)-1]) + 1)
  1675. }
  1676. context := newFuncContext(name, nil)
  1677. compileFunctionExpr(context, funcexpr, ecnone(0))
  1678. proto = context.Proto
  1679. return
  1680. } // }}}