12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306 |
- package lua
- ////////////////////////////////////////////////////////
- // This file was generated by go-inline. DO NOT EDIT. //
- ////////////////////////////////////////////////////////
- import (
- "context"
- "fmt"
- "io"
- "math"
- "os"
- "runtime"
- "strings"
- "sync"
- "sync/atomic"
- "time"
- "github.com/yuin/gopher-lua/parse"
- )
- const MultRet = -1
- const RegistryIndex = -10000
- const EnvironIndex = -10001
- const GlobalsIndex = -10002
- /* ApiError {{{ */
- type ApiError struct {
- Type ApiErrorType
- Object LValue
- StackTrace string
- // Underlying error. This attribute is set only if the Type is ApiErrorFile or ApiErrorSyntax
- Cause error
- }
- func newApiError(code ApiErrorType, object LValue) *ApiError {
- return &ApiError{code, object, "", nil}
- }
- func newApiErrorS(code ApiErrorType, message string) *ApiError {
- return newApiError(code, LString(message))
- }
- func newApiErrorE(code ApiErrorType, err error) *ApiError {
- return &ApiError{code, LString(err.Error()), "", err}
- }
- func (e *ApiError) Error() string {
- if len(e.StackTrace) > 0 {
- return fmt.Sprintf("%s\n%s", e.Object.String(), e.StackTrace)
- }
- return e.Object.String()
- }
- type ApiErrorType int
- const (
- ApiErrorSyntax ApiErrorType = iota
- ApiErrorFile
- ApiErrorRun
- ApiErrorError
- ApiErrorPanic
- )
- /* }}} */
- /* ResumeState {{{ */
- type ResumeState int
- const (
- ResumeOK ResumeState = iota
- ResumeYield
- ResumeError
- )
- /* }}} */
- /* P {{{ */
- type P struct {
- Fn LValue
- NRet int
- Protect bool
- Handler *LFunction
- }
- /* }}} */
- /* Options {{{ */
- // Options is a configuration that is used to create a new LState.
- type Options struct {
- // Call stack size. This defaults to `lua.CallStackSize`.
- CallStackSize int
- // Data stack size. This defaults to `lua.RegistrySize`.
- RegistrySize int
- // Allow the registry to grow from the registry size specified up to a value of RegistryMaxSize. A value of 0
- // indicates no growth is permitted. The registry will not shrink again after any growth.
- RegistryMaxSize int
- // If growth is enabled, step up by an additional `RegistryGrowStep` each time to avoid having to resize too often.
- // This defaults to `lua.RegistryGrowStep`
- RegistryGrowStep int
- // Controls whether or not libraries are opened by default
- SkipOpenLibs bool
- // Tells whether a Go stacktrace should be included in a Lua stacktrace when panics occur.
- IncludeGoStackTrace bool
- // If `MinimizeStackMemory` is set, the call stack will be automatically grown or shrank up to a limit of
- // `CallStackSize` in order to minimize memory usage. This does incur a slight performance penalty.
- MinimizeStackMemory bool
- }
- /* }}} */
- /* Debug {{{ */
- type Debug struct {
- frame *callFrame
- Name string
- What string
- Source string
- CurrentLine int
- NUpvalues int
- LineDefined int
- LastLineDefined int
- }
- /* }}} */
- /* callFrame {{{ */
- type callFrame struct {
- Idx int
- Fn *LFunction
- Parent *callFrame
- Pc int
- Base int
- LocalBase int
- ReturnBase int
- NArgs int
- NRet int
- TailCall int
- }
- type callFrameStack interface {
- Push(v callFrame)
- Pop() *callFrame
- Last() *callFrame
- SetSp(sp int)
- Sp() int
- At(sp int) *callFrame
- IsFull() bool
- IsEmpty() bool
- FreeAll()
- }
- type fixedCallFrameStack struct {
- array []callFrame
- sp int
- }
- func newFixedCallFrameStack(size int) callFrameStack {
- return &fixedCallFrameStack{
- array: make([]callFrame, size),
- sp: 0,
- }
- }
- func (cs *fixedCallFrameStack) IsEmpty() bool { return cs.sp == 0 }
- func (cs *fixedCallFrameStack) IsFull() bool { return cs.sp == len(cs.array) }
- func (cs *fixedCallFrameStack) Clear() {
- cs.sp = 0
- }
- func (cs *fixedCallFrameStack) Push(v callFrame) {
- cs.array[cs.sp] = v
- cs.array[cs.sp].Idx = cs.sp
- cs.sp++
- }
- func (cs *fixedCallFrameStack) Sp() int {
- return cs.sp
- }
- func (cs *fixedCallFrameStack) SetSp(sp int) {
- cs.sp = sp
- }
- func (cs *fixedCallFrameStack) Last() *callFrame {
- if cs.sp == 0 {
- return nil
- }
- return &cs.array[cs.sp-1]
- }
- func (cs *fixedCallFrameStack) At(sp int) *callFrame {
- return &cs.array[sp]
- }
- func (cs *fixedCallFrameStack) Pop() *callFrame {
- cs.sp--
- return &cs.array[cs.sp]
- }
- func (cs *fixedCallFrameStack) FreeAll() {
- // nothing to do for fixed callframestack
- }
- // FramesPerSegment should be a power of 2 constant for performance reasons. It will allow the go compiler to change
- // the divs and mods into bitshifts. Max is 256 due to current use of uint8 to count how many frames in a segment are
- // used.
- const FramesPerSegment = 8
- type callFrameStackSegment struct {
- array [FramesPerSegment]callFrame
- }
- type segIdx uint16
- type autoGrowingCallFrameStack struct {
- segments []*callFrameStackSegment
- segIdx segIdx
- // segSp is the number of frames in the current segment which are used. Full 'sp' value is segIdx * FramesPerSegment + segSp.
- // It points to the next stack slot to use, so 0 means to use the 0th element in the segment, and a value of
- // FramesPerSegment indicates that the segment is full and cannot accommodate another frame.
- segSp uint8
- }
- var segmentPool sync.Pool
- func newCallFrameStackSegment() *callFrameStackSegment {
- seg := segmentPool.Get()
- if seg == nil {
- return &callFrameStackSegment{}
- }
- return seg.(*callFrameStackSegment)
- }
- func freeCallFrameStackSegment(seg *callFrameStackSegment) {
- segmentPool.Put(seg)
- }
- // newCallFrameStack allocates a new stack for a lua state, which will auto grow up to a max size of at least maxSize.
- // it will actually grow up to the next segment size multiple after maxSize, where the segment size is dictated by
- // FramesPerSegment.
- func newAutoGrowingCallFrameStack(maxSize int) callFrameStack {
- cs := &autoGrowingCallFrameStack{
- segments: make([]*callFrameStackSegment, (maxSize+(FramesPerSegment-1))/FramesPerSegment),
- segIdx: 0,
- }
- cs.segments[0] = newCallFrameStackSegment()
- return cs
- }
- func (cs *autoGrowingCallFrameStack) IsEmpty() bool {
- return cs.segIdx == 0 && cs.segSp == 0
- }
- // IsFull returns true if the stack cannot receive any more stack pushes without overflowing
- func (cs *autoGrowingCallFrameStack) IsFull() bool {
- return int(cs.segIdx) == len(cs.segments) && cs.segSp >= FramesPerSegment
- }
- func (cs *autoGrowingCallFrameStack) Clear() {
- for i := segIdx(1); i <= cs.segIdx; i++ {
- freeCallFrameStackSegment(cs.segments[i])
- cs.segments[i] = nil
- }
- cs.segIdx = 0
- cs.segSp = 0
- }
- func (cs *autoGrowingCallFrameStack) FreeAll() {
- for i := segIdx(0); i <= cs.segIdx; i++ {
- freeCallFrameStackSegment(cs.segments[i])
- cs.segments[i] = nil
- }
- }
- // Push pushes the passed callFrame onto the stack. it panics if the stack is full, caller should call IsFull() before
- // invoking this to avoid this.
- func (cs *autoGrowingCallFrameStack) Push(v callFrame) {
- curSeg := cs.segments[cs.segIdx]
- if cs.segSp >= FramesPerSegment {
- // segment full, push new segment if allowed
- if cs.segIdx < segIdx(len(cs.segments)-1) {
- curSeg = newCallFrameStackSegment()
- cs.segIdx++
- cs.segments[cs.segIdx] = curSeg
- cs.segSp = 0
- } else {
- panic("lua callstack overflow")
- }
- }
- curSeg.array[cs.segSp] = v
- curSeg.array[cs.segSp].Idx = int(cs.segSp) + FramesPerSegment*int(cs.segIdx)
- cs.segSp++
- }
- // Sp retrieves the current stack depth, which is the number of frames currently pushed on the stack.
- func (cs *autoGrowingCallFrameStack) Sp() int {
- return int(cs.segSp) + int(cs.segIdx)*FramesPerSegment
- }
- // SetSp can be used to rapidly unwind the stack, freeing all stack frames on the way. It should not be used to
- // allocate new stack space, use Push() for that.
- func (cs *autoGrowingCallFrameStack) SetSp(sp int) {
- desiredSegIdx := segIdx(sp / FramesPerSegment)
- desiredFramesInLastSeg := uint8(sp % FramesPerSegment)
- for {
- if cs.segIdx <= desiredSegIdx {
- break
- }
- freeCallFrameStackSegment(cs.segments[cs.segIdx])
- cs.segments[cs.segIdx] = nil
- cs.segIdx--
- }
- cs.segSp = desiredFramesInLastSeg
- }
- func (cs *autoGrowingCallFrameStack) Last() *callFrame {
- curSeg := cs.segments[cs.segIdx]
- segSp := cs.segSp
- if segSp == 0 {
- if cs.segIdx == 0 {
- return nil
- }
- curSeg = cs.segments[cs.segIdx-1]
- segSp = FramesPerSegment
- }
- return &curSeg.array[segSp-1]
- }
- func (cs *autoGrowingCallFrameStack) At(sp int) *callFrame {
- segIdx := segIdx(sp / FramesPerSegment)
- frameIdx := uint8(sp % FramesPerSegment)
- return &cs.segments[segIdx].array[frameIdx]
- }
- // Pop pops off the most recent stack frame and returns it
- func (cs *autoGrowingCallFrameStack) Pop() *callFrame {
- curSeg := cs.segments[cs.segIdx]
- if cs.segSp == 0 {
- if cs.segIdx == 0 {
- // stack empty
- return nil
- }
- freeCallFrameStackSegment(curSeg)
- cs.segments[cs.segIdx] = nil
- cs.segIdx--
- cs.segSp = FramesPerSegment
- curSeg = cs.segments[cs.segIdx]
- }
- cs.segSp--
- return &curSeg.array[cs.segSp]
- }
- /* }}} */
- /* registry {{{ */
- type registryHandler interface {
- registryOverflow()
- }
- type registry struct {
- array []LValue
- top int
- growBy int
- maxSize int
- alloc *allocator
- handler registryHandler
- }
- func newRegistry(handler registryHandler, initialSize int, growBy int, maxSize int, alloc *allocator) *registry {
- return ®istry{make([]LValue, initialSize), 0, growBy, maxSize, alloc, handler}
- }
- func (rg *registry) checkSize(requiredSize int) { // +inline-start
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- } // +inline-end
- func (rg *registry) resize(requiredSize int) { // +inline-start
- newSize := requiredSize + rg.growBy // give some padding
- if newSize > rg.maxSize {
- newSize = rg.maxSize
- }
- if newSize < requiredSize {
- rg.handler.registryOverflow()
- return
- }
- rg.forceResize(newSize)
- } // +inline-end
- func (rg *registry) forceResize(newSize int) {
- newSlice := make([]LValue, newSize)
- copy(newSlice, rg.array[:rg.top]) // should we copy the area beyond top? there shouldn't be any valid values there so it shouldn't be necessary.
- rg.array = newSlice
- }
- func (rg *registry) SetTop(topi int) { // +inline-start
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- requiredSize := topi
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- oldtopi := rg.top
- rg.top = topi
- for i := oldtopi; i < rg.top; i++ {
- rg.array[i] = LNil
- }
- // values beyond top don't need to be valid LValues, so setting them to nil is fine
- // setting them to nil rather than LNil lets us invoke the golang memclr opto
- if rg.top < oldtopi {
- nilRange := rg.array[rg.top:oldtopi]
- for i := range nilRange {
- nilRange[i] = nil
- }
- }
- //for i := rg.top; i < oldtop; i++ {
- // rg.array[i] = LNil
- //}
- } // +inline-end
- func (rg *registry) Top() int {
- return rg.top
- }
- func (rg *registry) Push(v LValue) {
- newSize := rg.top + 1
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- rg.array[rg.top] = v
- rg.top++
- }
- func (rg *registry) Pop() LValue {
- v := rg.array[rg.top-1]
- rg.array[rg.top-1] = LNil
- rg.top--
- return v
- }
- func (rg *registry) Get(reg int) LValue {
- return rg.array[reg]
- }
- // CopyRange will move a section of values from index `start` to index `regv`
- // It will move `n` values.
- // `limit` specifies the maximum end range that can be copied from. If it's set to -1, then it defaults to stopping at
- // the top of the registry (values beyond the top are not initialized, so if specifying an alternative `limit` you should
- // pass a value <= rg.top.
- // If start+n is beyond the limit, then nil values will be copied to the destination slots.
- // After the copy, the registry is truncated to be at the end of the copied range, ie the original of the copied values
- // are nilled out. (So top will be regv+n)
- // CopyRange should ideally be renamed to MoveRange.
- func (rg *registry) CopyRange(regv, start, limit, n int) { // +inline-start
- newSize := regv + n
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- if limit == -1 || limit > rg.top {
- limit = rg.top
- }
- for i := 0; i < n; i++ {
- srcIdx := start + i
- if srcIdx >= limit || srcIdx < 0 {
- rg.array[regv+i] = LNil
- } else {
- rg.array[regv+i] = rg.array[srcIdx]
- }
- }
- // values beyond top don't need to be valid LValues, so setting them to nil is fine
- // setting them to nil rather than LNil lets us invoke the golang memclr opto
- oldtop := rg.top
- rg.top = regv + n
- if rg.top < oldtop {
- nilRange := rg.array[rg.top:oldtop]
- for i := range nilRange {
- nilRange[i] = nil
- }
- }
- } // +inline-end
- // FillNil fills the registry with nil values from regm to regm+n and then sets the registry top to regm+n
- func (rg *registry) FillNil(regm, n int) { // +inline-start
- newSize := regm + n
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- for i := 0; i < n; i++ {
- rg.array[regm+i] = LNil
- }
- // values beyond top don't need to be valid LValues, so setting them to nil is fine
- // setting them to nil rather than LNil lets us invoke the golang memclr opto
- oldtop := rg.top
- rg.top = regm + n
- if rg.top < oldtop {
- nilRange := rg.array[rg.top:oldtop]
- for i := range nilRange {
- nilRange[i] = nil
- }
- }
- } // +inline-end
- func (rg *registry) Insert(value LValue, reg int) {
- top := rg.Top()
- if reg >= top {
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go'
- {
- regi := reg
- vali := value
- newSize := regi + 1
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- rg.array[regi] = vali
- if regi >= rg.top {
- rg.top = regi + 1
- }
- }
- return
- }
- top--
- for ; top >= reg; top-- {
- // FIXME consider using copy() here if Insert() is called enough
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go'
- {
- regi := top + 1
- vali := rg.Get(top)
- newSize := regi + 1
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- rg.array[regi] = vali
- if regi >= rg.top {
- rg.top = regi + 1
- }
- }
- }
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) Set(regi int, vali LValue) ' in '_state.go'
- {
- regi := reg
- vali := value
- newSize := regi + 1
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- rg.array[regi] = vali
- if regi >= rg.top {
- rg.top = regi + 1
- }
- }
- }
- func (rg *registry) Set(regi int, vali LValue) { // +inline-start
- newSize := regi + 1
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- rg.array[regi] = vali
- if regi >= rg.top {
- rg.top = regi + 1
- }
- } // +inline-end
- func (rg *registry) SetNumber(regi int, vali LNumber) { // +inline-start
- newSize := regi + 1
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- rg.array[regi] = rg.alloc.LNumber2I(vali)
- if regi >= rg.top {
- rg.top = regi + 1
- }
- } // +inline-end
- func (rg *registry) IsFull() bool {
- return rg.top >= cap(rg.array)
- }
- /* }}} */
- /* Global {{{ */
- func newGlobal() *Global {
- return &Global{
- MainThread: nil,
- Registry: newLTable(0, 32),
- Global: newLTable(0, 64),
- builtinMts: make(map[int]LValue),
- tempFiles: make([]*os.File, 0, 10),
- }
- }
- /* }}} */
- /* package local methods {{{ */
- func panicWithTraceback(L *LState) {
- err := newApiError(ApiErrorRun, L.Get(-1))
- err.StackTrace = L.stackTrace(0)
- panic(err)
- }
- func panicWithoutTraceback(L *LState) {
- err := newApiError(ApiErrorRun, L.Get(-1))
- panic(err)
- }
- func newLState(options Options) *LState {
- al := newAllocator(32)
- ls := &LState{
- G: newGlobal(),
- Parent: nil,
- Panic: panicWithTraceback,
- Dead: false,
- Options: options,
- stop: 0,
- alloc: al,
- currentFrame: nil,
- wrapped: false,
- uvcache: nil,
- hasErrorFunc: false,
- mainLoop: mainLoop,
- ctx: nil,
- }
- if options.MinimizeStackMemory {
- ls.stack = newAutoGrowingCallFrameStack(options.CallStackSize)
- } else {
- ls.stack = newFixedCallFrameStack(options.CallStackSize)
- }
- ls.reg = newRegistry(ls, options.RegistrySize, options.RegistryGrowStep, options.RegistryMaxSize, al)
- ls.Env = ls.G.Global
- return ls
- }
- func (ls *LState) printReg() {
- println("-------------------------")
- println("thread:", ls)
- println("top:", ls.reg.Top())
- if ls.currentFrame != nil {
- println("function base:", ls.currentFrame.Base)
- println("return base:", ls.currentFrame.ReturnBase)
- } else {
- println("(vm not started)")
- }
- println("local base:", ls.currentLocalBase())
- for i := 0; i < ls.reg.Top(); i++ {
- println(i, ls.reg.Get(i).String())
- }
- println("-------------------------")
- }
- func (ls *LState) printCallStack() {
- println("-------------------------")
- for i := 0; i < ls.stack.Sp(); i++ {
- print(i)
- print(" ")
- frame := ls.stack.At(i)
- if frame == nil {
- break
- }
- if frame.Fn.IsG {
- println("IsG:", true, "Frame:", frame, "Fn:", frame.Fn)
- } else {
- println("IsG:", false, "Frame:", frame, "Fn:", frame.Fn, "pc:", frame.Pc)
- }
- }
- println("-------------------------")
- }
- func (ls *LState) closeAllUpvalues() { // +inline-start
- for cf := ls.currentFrame; cf != nil; cf = cf.Parent {
- if !cf.Fn.IsG {
- ls.closeUpvalues(cf.LocalBase)
- }
- }
- } // +inline-end
- func (ls *LState) raiseError(level int, format string, args ...interface{}) {
- if !ls.hasErrorFunc {
- ls.closeAllUpvalues()
- }
- message := format
- if len(args) > 0 {
- message = fmt.Sprintf(format, args...)
- }
- if level > 0 {
- message = fmt.Sprintf("%v %v", ls.where(level-1, true), message)
- }
- if ls.reg.IsFull() {
- // if the registry is full then it won't be possible to push a value, in this case, force a larger size
- ls.reg.forceResize(ls.reg.Top() + 1)
- }
- ls.reg.Push(LString(message))
- ls.Panic(ls)
- }
- func (ls *LState) findLocal(frame *callFrame, no int) string {
- fn := frame.Fn
- if !fn.IsG {
- if name, ok := fn.LocalName(no, frame.Pc-1); ok {
- return name
- }
- }
- var top int
- if ls.currentFrame == frame {
- top = ls.reg.Top()
- } else if frame.Idx+1 < ls.stack.Sp() {
- top = ls.stack.At(frame.Idx + 1).Base
- } else {
- return ""
- }
- if top-frame.LocalBase >= no {
- return "(*temporary)"
- }
- return ""
- }
- func (ls *LState) where(level int, skipg bool) string {
- dbg, ok := ls.GetStack(level)
- if !ok {
- return ""
- }
- cf := dbg.frame
- proto := cf.Fn.Proto
- sourcename := "[G]"
- if proto != nil {
- sourcename = proto.SourceName
- } else if skipg {
- return ls.where(level+1, skipg)
- }
- line := ""
- if proto != nil {
- line = fmt.Sprintf("%v:", proto.DbgSourcePositions[cf.Pc-1])
- }
- return fmt.Sprintf("%v:%v", sourcename, line)
- }
- func (ls *LState) stackTrace(level int) string {
- buf := []string{}
- header := "stack traceback:"
- if ls.currentFrame != nil {
- i := 0
- for dbg, ok := ls.GetStack(i); ok; dbg, ok = ls.GetStack(i) {
- cf := dbg.frame
- buf = append(buf, fmt.Sprintf("\t%v in %v", ls.Where(i), ls.formattedFrameFuncName(cf)))
- if !cf.Fn.IsG && cf.TailCall > 0 {
- for tc := cf.TailCall; tc > 0; tc-- {
- buf = append(buf, "\t(tailcall): ?")
- i++
- }
- }
- i++
- }
- }
- buf = append(buf, fmt.Sprintf("\t%v: %v", "[G]", "?"))
- buf = buf[intMax(0, intMin(level, len(buf))):len(buf)]
- if len(buf) > 20 {
- newbuf := make([]string, 0, 20)
- newbuf = append(newbuf, buf[0:7]...)
- newbuf = append(newbuf, "\t...")
- newbuf = append(newbuf, buf[len(buf)-7:len(buf)]...)
- buf = newbuf
- }
- return fmt.Sprintf("%s\n%s", header, strings.Join(buf, "\n"))
- }
- func (ls *LState) formattedFrameFuncName(fr *callFrame) string {
- name, ischunk := ls.frameFuncName(fr)
- if ischunk {
- return name
- }
- if name[0] != '(' && name[0] != '<' {
- return fmt.Sprintf("function '%s'", name)
- }
- return fmt.Sprintf("function %s", name)
- }
- func (ls *LState) rawFrameFuncName(fr *callFrame) string {
- name, _ := ls.frameFuncName(fr)
- return name
- }
- func (ls *LState) frameFuncName(fr *callFrame) (string, bool) {
- frame := fr.Parent
- if frame == nil {
- if ls.Parent == nil {
- return "main chunk", true
- } else {
- return "corountine", true
- }
- }
- if !frame.Fn.IsG {
- pc := frame.Pc - 1
- for _, call := range frame.Fn.Proto.DbgCalls {
- if call.Pc == pc {
- name := call.Name
- if (name == "?" || fr.TailCall > 0) && !fr.Fn.IsG {
- name = fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined)
- }
- return name, false
- }
- }
- }
- if !fr.Fn.IsG {
- return fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined), false
- }
- return "(anonymous)", false
- }
- func (ls *LState) isStarted() bool {
- return ls.currentFrame != nil
- }
- func (ls *LState) kill() {
- ls.Dead = true
- if ls.ctxCancelFn != nil {
- ls.ctxCancelFn()
- }
- }
- func (ls *LState) indexToReg(idx int) int {
- base := ls.currentLocalBase()
- if idx > 0 {
- return base + idx - 1
- } else if idx == 0 {
- return -1
- } else {
- tidx := ls.reg.Top() + idx
- if tidx < base {
- return -1
- }
- return tidx
- }
- }
- func (ls *LState) currentLocalBase() int {
- base := 0
- if ls.currentFrame != nil {
- base = ls.currentFrame.LocalBase
- }
- return base
- }
- func (ls *LState) currentEnv() *LTable {
- return ls.Env
- /*
- if ls.currentFrame == nil {
- return ls.Env
- }
- return ls.currentFrame.Fn.Env
- */
- }
- func (ls *LState) rkValue(idx int) LValue {
- /*
- if OpIsK(idx) {
- return ls.currentFrame.Fn.Proto.Constants[opIndexK(idx)]
- }
- return ls.reg.Get(ls.currentFrame.LocalBase + idx)
- */
- if (idx & opBitRk) != 0 {
- return ls.currentFrame.Fn.Proto.Constants[idx & ^opBitRk]
- }
- return ls.reg.array[ls.currentFrame.LocalBase+idx]
- }
- func (ls *LState) rkString(idx int) string {
- if (idx & opBitRk) != 0 {
- return ls.currentFrame.Fn.Proto.stringConstants[idx & ^opBitRk]
- }
- return string(ls.reg.array[ls.currentFrame.LocalBase+idx].(LString))
- }
- func (ls *LState) closeUpvalues(idx int) { // +inline-start
- if ls.uvcache != nil {
- var prev *Upvalue
- for uv := ls.uvcache; uv != nil; uv = uv.next {
- if uv.index >= idx {
- if prev != nil {
- prev.next = nil
- } else {
- ls.uvcache = nil
- }
- uv.Close()
- }
- prev = uv
- }
- }
- } // +inline-end
- func (ls *LState) findUpvalue(idx int) *Upvalue {
- var prev *Upvalue
- var next *Upvalue
- if ls.uvcache != nil {
- for uv := ls.uvcache; uv != nil; uv = uv.next {
- if uv.index == idx {
- return uv
- }
- if uv.index > idx {
- next = uv
- break
- }
- prev = uv
- }
- }
- uv := &Upvalue{reg: ls.reg, index: idx, closed: false}
- if prev != nil {
- prev.next = uv
- } else {
- ls.uvcache = uv
- }
- if next != nil {
- uv.next = next
- }
- return uv
- }
- func (ls *LState) metatable(lvalue LValue, rawget bool) LValue {
- var metatable LValue = LNil
- switch obj := lvalue.(type) {
- case *LTable:
- metatable = obj.Metatable
- case *LUserData:
- metatable = obj.Metatable
- default:
- if table, ok := ls.G.builtinMts[int(obj.Type())]; ok {
- metatable = table
- }
- }
- if !rawget && metatable != LNil {
- oldmt := metatable
- if tb, ok := metatable.(*LTable); ok {
- metatable = tb.RawGetString("__metatable")
- if metatable == LNil {
- metatable = oldmt
- }
- }
- }
- return metatable
- }
- func (ls *LState) metaOp1(lvalue LValue, event string) LValue {
- if mt := ls.metatable(lvalue, true); mt != LNil {
- if tb, ok := mt.(*LTable); ok {
- return tb.RawGetString(event)
- }
- }
- return LNil
- }
- func (ls *LState) metaOp2(value1, value2 LValue, event string) LValue {
- if mt := ls.metatable(value1, true); mt != LNil {
- if tb, ok := mt.(*LTable); ok {
- if ret := tb.RawGetString(event); ret != LNil {
- return ret
- }
- }
- }
- if mt := ls.metatable(value2, true); mt != LNil {
- if tb, ok := mt.(*LTable); ok {
- return tb.RawGetString(event)
- }
- }
- return LNil
- }
- func (ls *LState) metaCall(lvalue LValue) (*LFunction, bool) {
- if fn, ok := lvalue.(*LFunction); ok {
- return fn, false
- }
- if fn, ok := ls.metaOp1(lvalue, "__call").(*LFunction); ok {
- return fn, true
- }
- return nil, false
- }
- func (ls *LState) initCallFrame(cf *callFrame) { // +inline-start
- if cf.Fn.IsG {
- ls.reg.SetTop(cf.LocalBase + cf.NArgs)
- } else {
- proto := cf.Fn.Proto
- nargs := cf.NArgs
- np := int(proto.NumParameters)
- if nargs < np {
- // default any missing arguments to nil
- newSize := cf.LocalBase + np
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- rg := ls.reg
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- for i := nargs; i < np; i++ {
- ls.reg.array[cf.LocalBase+i] = LNil
- }
- nargs = np
- ls.reg.top = newSize
- }
- if (proto.IsVarArg & VarArgIsVarArg) == 0 {
- if nargs < int(proto.NumUsedRegisters) {
- nargs = int(proto.NumUsedRegisters)
- }
- newSize := cf.LocalBase + nargs
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- rg := ls.reg
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- for i := np; i < nargs; i++ {
- ls.reg.array[cf.LocalBase+i] = LNil
- }
- ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters)
- } else {
- /* swap vararg positions:
- closure
- namedparam1 <- lbase
- namedparam2
- vararg1
- vararg2
- TO
- closure
- nil
- nil
- vararg1
- vararg2
- namedparam1 <- lbase
- namedparam2
- */
- nvarargs := nargs - np
- if nvarargs < 0 {
- nvarargs = 0
- }
- ls.reg.SetTop(cf.LocalBase + nargs + np)
- for i := 0; i < np; i++ {
- //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i))
- ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i]
- //ls.reg.Set(cf.LocalBase+i, LNil)
- ls.reg.array[cf.LocalBase+i] = LNil
- }
- if CompatVarArg {
- ls.reg.SetTop(cf.LocalBase + nargs + np + 1)
- if (proto.IsVarArg & VarArgNeedsArg) != 0 {
- argtb := newLTable(nvarargs, 0)
- for i := 0; i < nvarargs; i++ {
- argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i))
- }
- argtb.RawSetString("n", LNumber(nvarargs))
- //ls.reg.Set(cf.LocalBase+nargs+np, argtb)
- ls.reg.array[cf.LocalBase+nargs+np] = argtb
- } else {
- ls.reg.array[cf.LocalBase+nargs+np] = LNil
- }
- }
- cf.LocalBase += nargs
- maxreg := cf.LocalBase + int(proto.NumUsedRegisters)
- ls.reg.SetTop(maxreg)
- }
- }
- } // +inline-end
- func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) { // +inline-start
- if meta {
- cf.NArgs++
- ls.reg.Insert(fn, cf.LocalBase)
- }
- if cf.Fn == nil {
- ls.RaiseError("attempt to call a non-function object")
- }
- if ls.stack.IsFull() {
- ls.RaiseError("stack overflow")
- }
- ls.stack.Push(cf)
- newcf := ls.stack.Last()
- // this section is inlined by go-inline
- // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go'
- {
- cf := newcf
- if cf.Fn.IsG {
- ls.reg.SetTop(cf.LocalBase + cf.NArgs)
- } else {
- proto := cf.Fn.Proto
- nargs := cf.NArgs
- np := int(proto.NumParameters)
- if nargs < np {
- // default any missing arguments to nil
- newSize := cf.LocalBase + np
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- rg := ls.reg
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- for i := nargs; i < np; i++ {
- ls.reg.array[cf.LocalBase+i] = LNil
- }
- nargs = np
- ls.reg.top = newSize
- }
- if (proto.IsVarArg & VarArgIsVarArg) == 0 {
- if nargs < int(proto.NumUsedRegisters) {
- nargs = int(proto.NumUsedRegisters)
- }
- newSize := cf.LocalBase + nargs
- // this section is inlined by go-inline
- // source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
- {
- rg := ls.reg
- requiredSize := newSize
- if requiredSize > cap(rg.array) {
- rg.resize(requiredSize)
- }
- }
- for i := np; i < nargs; i++ {
- ls.reg.array[cf.LocalBase+i] = LNil
- }
- ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters)
- } else {
- /* swap vararg positions:
- closure
- namedparam1 <- lbase
- namedparam2
- vararg1
- vararg2
- TO
- closure
- nil
- nil
- vararg1
- vararg2
- namedparam1 <- lbase
- namedparam2
- */
- nvarargs := nargs - np
- if nvarargs < 0 {
- nvarargs = 0
- }
- ls.reg.SetTop(cf.LocalBase + nargs + np)
- for i := 0; i < np; i++ {
- //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i))
- ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i]
- //ls.reg.Set(cf.LocalBase+i, LNil)
- ls.reg.array[cf.LocalBase+i] = LNil
- }
- if CompatVarArg {
- ls.reg.SetTop(cf.LocalBase + nargs + np + 1)
- if (proto.IsVarArg & VarArgNeedsArg) != 0 {
- argtb := newLTable(nvarargs, 0)
- for i := 0; i < nvarargs; i++ {
- argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i))
- }
- argtb.RawSetString("n", LNumber(nvarargs))
- //ls.reg.Set(cf.LocalBase+nargs+np, argtb)
- ls.reg.array[cf.LocalBase+nargs+np] = argtb
- } else {
- ls.reg.array[cf.LocalBase+nargs+np] = LNil
- }
- }
- cf.LocalBase += nargs
- maxreg := cf.LocalBase + int(proto.NumUsedRegisters)
- ls.reg.SetTop(maxreg)
- }
- }
- }
- ls.currentFrame = newcf
- } // +inline-end
- func (ls *LState) callR(nargs, nret, rbase int) {
- base := ls.reg.Top() - nargs - 1
- if rbase < 0 {
- rbase = base
- }
- lv := ls.reg.Get(base)
- fn, meta := ls.metaCall(lv)
- ls.pushCallFrame(callFrame{
- Fn: fn,
- Pc: 0,
- Base: base,
- LocalBase: base + 1,
- ReturnBase: rbase,
- NArgs: nargs,
- NRet: nret,
- Parent: ls.currentFrame,
- TailCall: 0,
- }, lv, meta)
- if ls.G.MainThread == nil {
- ls.G.MainThread = ls
- ls.G.CurrentThread = ls
- ls.mainLoop(ls, nil)
- } else {
- ls.mainLoop(ls, ls.currentFrame)
- }
- if nret != MultRet {
- ls.reg.SetTop(rbase + nret)
- }
- }
- func (ls *LState) getField(obj LValue, key LValue) LValue {
- curobj := obj
- for i := 0; i < MaxTableGetLoop; i++ {
- tb, istable := curobj.(*LTable)
- if istable {
- ret := tb.RawGet(key)
- if ret != LNil {
- return ret
- }
- }
- metaindex := ls.metaOp1(curobj, "__index")
- if metaindex == LNil {
- if !istable {
- ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key.String())
- }
- return LNil
- }
- if metaindex.Type() == LTFunction {
- ls.reg.Push(metaindex)
- ls.reg.Push(curobj)
- ls.reg.Push(key)
- ls.Call(2, 1)
- return ls.reg.Pop()
- } else {
- curobj = metaindex
- }
- }
- ls.RaiseError("too many recursions in gettable")
- return nil
- }
- func (ls *LState) getFieldString(obj LValue, key string) LValue {
- curobj := obj
- for i := 0; i < MaxTableGetLoop; i++ {
- tb, istable := curobj.(*LTable)
- if istable {
- ret := tb.RawGetString(key)
- if ret != LNil {
- return ret
- }
- }
- metaindex := ls.metaOp1(curobj, "__index")
- if metaindex == LNil {
- if !istable {
- ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key)
- }
- return LNil
- }
- if metaindex.Type() == LTFunction {
- ls.reg.Push(metaindex)
- ls.reg.Push(curobj)
- ls.reg.Push(LString(key))
- ls.Call(2, 1)
- return ls.reg.Pop()
- } else {
- curobj = metaindex
- }
- }
- ls.RaiseError("too many recursions in gettable")
- return nil
- }
- func (ls *LState) setField(obj LValue, key LValue, value LValue) {
- curobj := obj
- for i := 0; i < MaxTableGetLoop; i++ {
- tb, istable := curobj.(*LTable)
- if istable {
- if tb.RawGet(key) != LNil {
- ls.RawSet(tb, key, value)
- return
- }
- }
- metaindex := ls.metaOp1(curobj, "__newindex")
- if metaindex == LNil {
- if !istable {
- ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key.String())
- }
- ls.RawSet(tb, key, value)
- return
- }
- if metaindex.Type() == LTFunction {
- ls.reg.Push(metaindex)
- ls.reg.Push(curobj)
- ls.reg.Push(key)
- ls.reg.Push(value)
- ls.Call(3, 0)
- return
- } else {
- curobj = metaindex
- }
- }
- ls.RaiseError("too many recursions in settable")
- }
- func (ls *LState) setFieldString(obj LValue, key string, value LValue) {
- curobj := obj
- for i := 0; i < MaxTableGetLoop; i++ {
- tb, istable := curobj.(*LTable)
- if istable {
- if tb.RawGetString(key) != LNil {
- tb.RawSetString(key, value)
- return
- }
- }
- metaindex := ls.metaOp1(curobj, "__newindex")
- if metaindex == LNil {
- if !istable {
- ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key)
- }
- tb.RawSetString(key, value)
- return
- }
- if metaindex.Type() == LTFunction {
- ls.reg.Push(metaindex)
- ls.reg.Push(curobj)
- ls.reg.Push(LString(key))
- ls.reg.Push(value)
- ls.Call(3, 0)
- return
- } else {
- curobj = metaindex
- }
- }
- ls.RaiseError("too many recursions in settable")
- }
- /* }}} */
- /* api methods {{{ */
- func NewState(opts ...Options) *LState {
- var ls *LState
- if len(opts) == 0 {
- ls = newLState(Options{
- CallStackSize: CallStackSize,
- RegistrySize: RegistrySize,
- })
- ls.OpenLibs()
- } else {
- if opts[0].CallStackSize < 1 {
- opts[0].CallStackSize = CallStackSize
- }
- if opts[0].RegistrySize < 128 {
- opts[0].RegistrySize = RegistrySize
- }
- if opts[0].RegistryMaxSize < opts[0].RegistrySize {
- opts[0].RegistryMaxSize = 0 // disable growth if max size is smaller than initial size
- } else {
- // if growth enabled, grow step is set
- if opts[0].RegistryGrowStep < 1 {
- opts[0].RegistryGrowStep = RegistryGrowStep
- }
- }
- ls = newLState(opts[0])
- if !opts[0].SkipOpenLibs {
- ls.OpenLibs()
- }
- }
- return ls
- }
- func (ls *LState) IsClosed() bool {
- return ls.stack == nil
- }
- func (ls *LState) Close() {
- atomic.AddInt32(&ls.stop, 1)
- for _, file := range ls.G.tempFiles {
- // ignore errors in these operations
- file.Close()
- os.Remove(file.Name())
- }
- ls.stack.FreeAll()
- ls.stack = nil
- }
- /* registry operations {{{ */
- func (ls *LState) GetTop() int {
- return ls.reg.Top() - ls.currentLocalBase()
- }
- func (ls *LState) SetTop(idx int) {
- base := ls.currentLocalBase()
- newtop := ls.indexToReg(idx) + 1
- if newtop < base {
- ls.reg.SetTop(base)
- } else {
- ls.reg.SetTop(newtop)
- }
- }
- func (ls *LState) Replace(idx int, value LValue) {
- base := ls.currentLocalBase()
- if idx > 0 {
- reg := base + idx - 1
- if reg < ls.reg.Top() {
- ls.reg.Set(reg, value)
- }
- } else if idx == 0 {
- } else if idx > RegistryIndex {
- if tidx := ls.reg.Top() + idx; tidx >= base {
- ls.reg.Set(tidx, value)
- }
- } else {
- switch idx {
- case RegistryIndex:
- if tb, ok := value.(*LTable); ok {
- ls.G.Registry = tb
- } else {
- ls.RaiseError("registry must be a table(%v)", value.Type().String())
- }
- case EnvironIndex:
- if ls.currentFrame == nil {
- ls.RaiseError("no calling environment")
- }
- if tb, ok := value.(*LTable); ok {
- ls.currentFrame.Fn.Env = tb
- } else {
- ls.RaiseError("environment must be a table(%v)", value.Type().String())
- }
- case GlobalsIndex:
- if tb, ok := value.(*LTable); ok {
- ls.G.Global = tb
- } else {
- ls.RaiseError("_G must be a table(%v)", value.Type().String())
- }
- default:
- fn := ls.currentFrame.Fn
- index := GlobalsIndex - idx - 1
- if index < len(fn.Upvalues) {
- fn.Upvalues[index].SetValue(value)
- }
- }
- }
- }
- func (ls *LState) Get(idx int) LValue {
- base := ls.currentLocalBase()
- if idx > 0 {
- reg := base + idx - 1
- if reg < ls.reg.Top() {
- return ls.reg.Get(reg)
- }
- return LNil
- } else if idx == 0 {
- return LNil
- } else if idx > RegistryIndex {
- tidx := ls.reg.Top() + idx
- if tidx < base {
- return LNil
- }
- return ls.reg.Get(tidx)
- } else {
- switch idx {
- case RegistryIndex:
- return ls.G.Registry
- case EnvironIndex:
- if ls.currentFrame == nil {
- return ls.Env
- }
- return ls.currentFrame.Fn.Env
- case GlobalsIndex:
- return ls.G.Global
- default:
- fn := ls.currentFrame.Fn
- index := GlobalsIndex - idx - 1
- if index < len(fn.Upvalues) {
- return fn.Upvalues[index].Value()
- }
- return LNil
- }
- }
- return LNil
- }
- func (ls *LState) Push(value LValue) {
- ls.reg.Push(value)
- }
- func (ls *LState) Pop(n int) {
- for i := 0; i < n; i++ {
- if ls.GetTop() == 0 {
- ls.RaiseError("register underflow")
- }
- ls.reg.Pop()
- }
- }
- func (ls *LState) Insert(value LValue, index int) {
- reg := ls.indexToReg(index)
- top := ls.reg.Top()
- if reg >= top {
- ls.reg.Set(reg, value)
- return
- }
- if reg <= ls.currentLocalBase() {
- reg = ls.currentLocalBase()
- }
- top--
- for ; top >= reg; top-- {
- ls.reg.Set(top+1, ls.reg.Get(top))
- }
- ls.reg.Set(reg, value)
- }
- func (ls *LState) Remove(index int) {
- reg := ls.indexToReg(index)
- top := ls.reg.Top()
- switch {
- case reg >= top:
- return
- case reg < ls.currentLocalBase():
- return
- case reg == top-1:
- ls.Pop(1)
- return
- }
- for i := reg; i < top-1; i++ {
- ls.reg.Set(i, ls.reg.Get(i+1))
- }
- ls.reg.SetTop(top - 1)
- }
- /* }}} */
- /* object allocation {{{ */
- func (ls *LState) NewTable() *LTable {
- return newLTable(defaultArrayCap, defaultHashCap)
- }
- func (ls *LState) CreateTable(acap, hcap int) *LTable {
- return newLTable(acap, hcap)
- }
- // NewThread returns a new LState that shares with the original state all global objects.
- // If the original state has context.Context, the new state has a new child context of the original state and this function returns its cancel function.
- func (ls *LState) NewThread() (*LState, context.CancelFunc) {
- thread := newLState(ls.Options)
- thread.G = ls.G
- thread.Env = ls.Env
- var f context.CancelFunc = nil
- if ls.ctx != nil {
- thread.mainLoop = mainLoopWithContext
- thread.ctx, f = context.WithCancel(ls.ctx)
- thread.ctxCancelFn = f
- }
- return thread, f
- }
- func (ls *LState) NewFunctionFromProto(proto *FunctionProto) *LFunction {
- return newLFunctionL(proto, ls.Env, int(proto.NumUpvalues))
- }
- func (ls *LState) NewUserData() *LUserData {
- return &LUserData{
- Env: ls.currentEnv(),
- Metatable: LNil,
- }
- }
- func (ls *LState) NewFunction(fn LGFunction) *LFunction {
- return newLFunctionG(fn, ls.currentEnv(), 0)
- }
- func (ls *LState) NewClosure(fn LGFunction, upvalues ...LValue) *LFunction {
- cl := newLFunctionG(fn, ls.currentEnv(), len(upvalues))
- for i, lv := range upvalues {
- cl.Upvalues[i] = &Upvalue{}
- cl.Upvalues[i].Close()
- cl.Upvalues[i].SetValue(lv)
- }
- return cl
- }
- /* }}} */
- /* toType {{{ */
- func (ls *LState) ToBool(n int) bool {
- return LVAsBool(ls.Get(n))
- }
- func (ls *LState) ToInt(n int) int {
- if lv, ok := ls.Get(n).(LNumber); ok {
- return int(lv)
- }
- if lv, ok := ls.Get(n).(LString); ok {
- if num, err := parseNumber(string(lv)); err == nil {
- return int(num)
- }
- }
- return 0
- }
- func (ls *LState) ToInt64(n int) int64 {
- if lv, ok := ls.Get(n).(LNumber); ok {
- return int64(lv)
- }
- if lv, ok := ls.Get(n).(LString); ok {
- if num, err := parseNumber(string(lv)); err == nil {
- return int64(num)
- }
- }
- return 0
- }
- func (ls *LState) ToNumber(n int) LNumber {
- return LVAsNumber(ls.Get(n))
- }
- func (ls *LState) ToString(n int) string {
- return LVAsString(ls.Get(n))
- }
- func (ls *LState) ToTable(n int) *LTable {
- if lv, ok := ls.Get(n).(*LTable); ok {
- return lv
- }
- return nil
- }
- func (ls *LState) ToFunction(n int) *LFunction {
- if lv, ok := ls.Get(n).(*LFunction); ok {
- return lv
- }
- return nil
- }
- func (ls *LState) ToUserData(n int) *LUserData {
- if lv, ok := ls.Get(n).(*LUserData); ok {
- return lv
- }
- return nil
- }
- func (ls *LState) ToThread(n int) *LState {
- if lv, ok := ls.Get(n).(*LState); ok {
- return lv
- }
- return nil
- }
- /* }}} */
- /* error & debug operations {{{ */
- func (ls *LState) registryOverflow() {
- ls.RaiseError("registry overflow")
- }
- // This function is equivalent to luaL_error( http://www.lua.org/manual/5.1/manual.html#luaL_error ).
- func (ls *LState) RaiseError(format string, args ...interface{}) {
- ls.raiseError(1, format, args...)
- }
- // This function is equivalent to lua_error( http://www.lua.org/manual/5.1/manual.html#lua_error ).
- func (ls *LState) Error(lv LValue, level int) {
- if str, ok := lv.(LString); ok {
- ls.raiseError(level, string(str))
- } else {
- if !ls.hasErrorFunc {
- ls.closeAllUpvalues()
- }
- ls.Push(lv)
- ls.Panic(ls)
- }
- }
- func (ls *LState) GetInfo(what string, dbg *Debug, fn LValue) (LValue, error) {
- if !strings.HasPrefix(what, ">") {
- fn = dbg.frame.Fn
- } else {
- what = what[1:]
- }
- f, ok := fn.(*LFunction)
- if !ok {
- return LNil, newApiErrorS(ApiErrorRun, "can not get debug info(an object in not a function)")
- }
- retfn := false
- for _, c := range what {
- switch c {
- case 'f':
- retfn = true
- case 'S':
- if dbg.frame != nil && dbg.frame.Parent == nil {
- dbg.What = "main"
- } else if f.IsG {
- dbg.What = "G"
- } else if dbg.frame != nil && dbg.frame.TailCall > 0 {
- dbg.What = "tail"
- } else {
- dbg.What = "Lua"
- }
- if !f.IsG {
- dbg.Source = f.Proto.SourceName
- dbg.LineDefined = f.Proto.LineDefined
- dbg.LastLineDefined = f.Proto.LastLineDefined
- }
- case 'l':
- if !f.IsG && dbg.frame != nil {
- if dbg.frame.Pc > 0 {
- dbg.CurrentLine = f.Proto.DbgSourcePositions[dbg.frame.Pc-1]
- }
- } else {
- dbg.CurrentLine = -1
- }
- case 'u':
- dbg.NUpvalues = len(f.Upvalues)
- case 'n':
- if dbg.frame != nil {
- dbg.Name = ls.rawFrameFuncName(dbg.frame)
- }
- default:
- return LNil, newApiErrorS(ApiErrorRun, "invalid what: "+string(c))
- }
- }
- if retfn {
- return f, nil
- }
- return LNil, nil
- }
- func (ls *LState) GetStack(level int) (*Debug, bool) {
- frame := ls.currentFrame
- for ; level > 0 && frame != nil; frame = frame.Parent {
- level--
- if !frame.Fn.IsG {
- level -= frame.TailCall
- }
- }
- if level == 0 && frame != nil {
- return &Debug{frame: frame}, true
- } else if level < 0 && ls.stack.Sp() > 0 {
- return &Debug{frame: ls.stack.At(0)}, true
- }
- return &Debug{}, false
- }
- func (ls *LState) GetLocal(dbg *Debug, no int) (string, LValue) {
- frame := dbg.frame
- if name := ls.findLocal(frame, no); len(name) > 0 {
- return name, ls.reg.Get(frame.LocalBase + no - 1)
- }
- return "", LNil
- }
- func (ls *LState) SetLocal(dbg *Debug, no int, lv LValue) string {
- frame := dbg.frame
- if name := ls.findLocal(frame, no); len(name) > 0 {
- ls.reg.Set(frame.LocalBase+no-1, lv)
- return name
- }
- return ""
- }
- func (ls *LState) GetUpvalue(fn *LFunction, no int) (string, LValue) {
- if fn.IsG {
- return "", LNil
- }
- no--
- if no >= 0 && no < len(fn.Upvalues) {
- return fn.Proto.DbgUpvalues[no], fn.Upvalues[no].Value()
- }
- return "", LNil
- }
- func (ls *LState) SetUpvalue(fn *LFunction, no int, lv LValue) string {
- if fn.IsG {
- return ""
- }
- no--
- if no >= 0 && no < len(fn.Upvalues) {
- fn.Upvalues[no].SetValue(lv)
- return fn.Proto.DbgUpvalues[no]
- }
- return ""
- }
- /* }}} */
- /* env operations {{{ */
- func (ls *LState) GetFEnv(obj LValue) LValue {
- switch lv := obj.(type) {
- case *LFunction:
- return lv.Env
- case *LUserData:
- return lv.Env
- case *LState:
- return lv.Env
- }
- return LNil
- }
- func (ls *LState) SetFEnv(obj LValue, env LValue) {
- tb, ok := env.(*LTable)
- if !ok {
- ls.RaiseError("cannot use %v as an environment", env.Type().String())
- }
- switch lv := obj.(type) {
- case *LFunction:
- lv.Env = tb
- case *LUserData:
- lv.Env = tb
- case *LState:
- lv.Env = tb
- }
- /* do nothing */
- }
- /* }}} */
- /* table operations {{{ */
- func (ls *LState) RawGet(tb *LTable, key LValue) LValue {
- return tb.RawGet(key)
- }
- func (ls *LState) RawGetInt(tb *LTable, key int) LValue {
- return tb.RawGetInt(key)
- }
- func (ls *LState) GetField(obj LValue, skey string) LValue {
- return ls.getFieldString(obj, skey)
- }
- func (ls *LState) GetTable(obj LValue, key LValue) LValue {
- return ls.getField(obj, key)
- }
- func (ls *LState) RawSet(tb *LTable, key LValue, value LValue) {
- if n, ok := key.(LNumber); ok && math.IsNaN(float64(n)) {
- ls.RaiseError("table index is NaN")
- } else if key == LNil {
- ls.RaiseError("table index is nil")
- }
- tb.RawSet(key, value)
- }
- func (ls *LState) RawSetInt(tb *LTable, key int, value LValue) {
- tb.RawSetInt(key, value)
- }
- func (ls *LState) SetField(obj LValue, key string, value LValue) {
- ls.setFieldString(obj, key, value)
- }
- func (ls *LState) SetTable(obj LValue, key LValue, value LValue) {
- ls.setField(obj, key, value)
- }
- func (ls *LState) ForEach(tb *LTable, cb func(LValue, LValue)) {
- tb.ForEach(cb)
- }
- func (ls *LState) GetGlobal(name string) LValue {
- return ls.GetField(ls.Get(GlobalsIndex), name)
- }
- func (ls *LState) SetGlobal(name string, value LValue) {
- ls.SetField(ls.Get(GlobalsIndex), name, value)
- }
- func (ls *LState) Next(tb *LTable, key LValue) (LValue, LValue) {
- return tb.Next(key)
- }
- /* }}} */
- /* unary operations {{{ */
- func (ls *LState) ObjLen(v1 LValue) int {
- if v1.Type() == LTString {
- return len(string(v1.(LString)))
- }
- op := ls.metaOp1(v1, "__len")
- if op.Type() == LTFunction {
- ls.Push(op)
- ls.Push(v1)
- ls.Call(1, 1)
- ret := ls.reg.Pop()
- if ret.Type() == LTNumber {
- return int(ret.(LNumber))
- }
- } else if v1.Type() == LTTable {
- return v1.(*LTable).Len()
- }
- return 0
- }
- /* }}} */
- /* binary operations {{{ */
- func (ls *LState) Concat(values ...LValue) string {
- top := ls.reg.Top()
- for _, value := range values {
- ls.reg.Push(value)
- }
- ret := stringConcat(ls, len(values), ls.reg.Top()-1)
- ls.reg.SetTop(top)
- return LVAsString(ret)
- }
- func (ls *LState) LessThan(lhs, rhs LValue) bool {
- return lessThan(ls, lhs, rhs)
- }
- func (ls *LState) Equal(lhs, rhs LValue) bool {
- return equals(ls, lhs, rhs, false)
- }
- func (ls *LState) RawEqual(lhs, rhs LValue) bool {
- return equals(ls, lhs, rhs, true)
- }
- /* }}} */
- /* register operations {{{ */
- func (ls *LState) Register(name string, fn LGFunction) {
- ls.SetGlobal(name, ls.NewFunction(fn))
- }
- /* }}} */
- /* load and function call operations {{{ */
- func (ls *LState) Load(reader io.Reader, name string) (*LFunction, error) {
- chunk, err := parse.Parse(reader, name)
- if err != nil {
- return nil, newApiErrorE(ApiErrorSyntax, err)
- }
- proto, err := Compile(chunk, name)
- if err != nil {
- return nil, newApiErrorE(ApiErrorSyntax, err)
- }
- return newLFunctionL(proto, ls.currentEnv(), 0), nil
- }
- func (ls *LState) Call(nargs, nret int) {
- ls.callR(nargs, nret, -1)
- }
- func (ls *LState) PCall(nargs, nret int, errfunc *LFunction) (err error) {
- err = nil
- sp := ls.stack.Sp()
- base := ls.reg.Top() - nargs - 1
- oldpanic := ls.Panic
- ls.Panic = panicWithoutTraceback
- if errfunc != nil {
- ls.hasErrorFunc = true
- }
- defer func() {
- ls.Panic = oldpanic
- ls.hasErrorFunc = false
- rcv := recover()
- if rcv != nil {
- if _, ok := rcv.(*ApiError); !ok {
- err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv))
- if ls.Options.IncludeGoStackTrace {
- buf := make([]byte, 4096)
- runtime.Stack(buf, false)
- err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + "\n" + ls.stackTrace(0)
- }
- } else {
- err = rcv.(*ApiError)
- }
- if errfunc != nil {
- ls.Push(errfunc)
- ls.Push(err.(*ApiError).Object)
- ls.Panic = panicWithoutTraceback
- defer func() {
- ls.Panic = oldpanic
- rcv := recover()
- if rcv != nil {
- if _, ok := rcv.(*ApiError); !ok {
- err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv))
- if ls.Options.IncludeGoStackTrace {
- buf := make([]byte, 4096)
- runtime.Stack(buf, false)
- err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + ls.stackTrace(0)
- }
- } else {
- err = rcv.(*ApiError)
- err.(*ApiError).StackTrace = ls.stackTrace(0)
- }
- ls.stack.SetSp(sp)
- ls.currentFrame = ls.stack.Last()
- ls.reg.SetTop(base)
- }
- }()
- ls.Call(1, 1)
- err = newApiError(ApiErrorError, ls.Get(-1))
- } else if len(err.(*ApiError).StackTrace) == 0 {
- err.(*ApiError).StackTrace = ls.stackTrace(0)
- }
- ls.stack.SetSp(sp)
- ls.currentFrame = ls.stack.Last()
- ls.reg.SetTop(base)
- }
- ls.stack.SetSp(sp)
- if sp == 0 {
- ls.currentFrame = nil
- }
- }()
- ls.Call(nargs, nret)
- return
- }
- func (ls *LState) GPCall(fn LGFunction, data LValue) error {
- ls.Push(newLFunctionG(fn, ls.currentEnv(), 0))
- ls.Push(data)
- return ls.PCall(1, MultRet, nil)
- }
- func (ls *LState) CallByParam(cp P, args ...LValue) error {
- ls.Push(cp.Fn)
- for _, arg := range args {
- ls.Push(arg)
- }
- if cp.Protect {
- return ls.PCall(len(args), cp.NRet, cp.Handler)
- }
- ls.Call(len(args), cp.NRet)
- return nil
- }
- /* }}} */
- /* metatable operations {{{ */
- func (ls *LState) GetMetatable(obj LValue) LValue {
- return ls.metatable(obj, false)
- }
- func (ls *LState) SetMetatable(obj LValue, mt LValue) {
- switch mt.(type) {
- case *LNilType, *LTable:
- default:
- ls.RaiseError("metatable must be a table or nil, but got %v", mt.Type().String())
- }
- switch v := obj.(type) {
- case *LTable:
- v.Metatable = mt
- case *LUserData:
- v.Metatable = mt
- default:
- ls.G.builtinMts[int(obj.Type())] = mt
- }
- }
- /* }}} */
- /* coroutine operations {{{ */
- func (ls *LState) Status(th *LState) string {
- status := "suspended"
- if th.Dead {
- status = "dead"
- } else if ls.G.CurrentThread == th {
- status = "running"
- } else if ls.Parent == th {
- status = "normal"
- }
- return status
- }
- func (ls *LState) Resume(th *LState, fn *LFunction, args ...LValue) (ResumeState, error, []LValue) {
- isstarted := th.isStarted()
- if !isstarted {
- base := 0
- th.stack.Push(callFrame{
- Fn: fn,
- Pc: 0,
- Base: base,
- LocalBase: base + 1,
- ReturnBase: base,
- NArgs: 0,
- NRet: MultRet,
- Parent: nil,
- TailCall: 0,
- })
- }
- if ls.G.CurrentThread == th {
- return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a running thread"), nil
- }
- if th.Dead {
- return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a dead thread"), nil
- }
- th.Parent = ls
- ls.G.CurrentThread = th
- if !isstarted {
- cf := th.stack.Last()
- th.currentFrame = cf
- th.SetTop(0)
- for _, arg := range args {
- th.Push(arg)
- }
- cf.NArgs = len(args)
- th.initCallFrame(cf)
- th.Panic = panicWithoutTraceback
- } else {
- for _, arg := range args {
- th.Push(arg)
- }
- }
- top := ls.GetTop()
- threadRun(th)
- haserror := LVIsFalse(ls.Get(top + 1))
- ret := make([]LValue, 0, ls.GetTop())
- for idx := top + 2; idx <= ls.GetTop(); idx++ {
- ret = append(ret, ls.Get(idx))
- }
- if len(ret) == 0 {
- ret = append(ret, LNil)
- }
- ls.SetTop(top)
- if haserror {
- return ResumeError, newApiError(ApiErrorRun, ret[0]), nil
- } else if th.stack.IsEmpty() {
- return ResumeOK, nil, ret
- }
- return ResumeYield, nil, ret
- }
- func (ls *LState) Yield(values ...LValue) int {
- ls.SetTop(0)
- for _, lv := range values {
- ls.Push(lv)
- }
- return -1
- }
- func (ls *LState) XMoveTo(other *LState, n int) {
- if ls == other {
- return
- }
- top := ls.GetTop()
- n = intMin(n, top)
- for i := n; i > 0; i-- {
- other.Push(ls.Get(top - i + 1))
- }
- ls.SetTop(top - n)
- }
- /* }}} */
- /* GopherLua original APIs {{{ */
- // Set maximum memory size. This function can only be called from the main thread.
- func (ls *LState) SetMx(mx int) {
- if ls.Parent != nil {
- ls.RaiseError("sub threads are not allowed to set a memory limit")
- }
- go func() {
- limit := uint64(mx * 1024 * 1024) //MB
- var s runtime.MemStats
- for atomic.LoadInt32(&ls.stop) == 0 {
- runtime.ReadMemStats(&s)
- if s.Alloc >= limit {
- fmt.Println("out of memory")
- os.Exit(3)
- }
- time.Sleep(100 * time.Millisecond)
- }
- }()
- }
- // SetContext set a context ctx to this LState. The provided ctx must be non-nil.
- func (ls *LState) SetContext(ctx context.Context) {
- ls.mainLoop = mainLoopWithContext
- ls.ctx = ctx
- }
- // Context returns the LState's context. To change the context, use WithContext.
- func (ls *LState) Context() context.Context {
- return ls.ctx
- }
- // RemoveContext removes the context associated with this LState and returns this context.
- func (ls *LState) RemoveContext() context.Context {
- oldctx := ls.ctx
- ls.mainLoop = mainLoop
- ls.ctx = nil
- return oldctx
- }
- // Converts the Lua value at the given acceptable index to the chan LValue.
- func (ls *LState) ToChannel(n int) chan LValue {
- if lv, ok := ls.Get(n).(LChannel); ok {
- return (chan LValue)(lv)
- }
- return nil
- }
- // RemoveCallerFrame removes the stack frame above the current stack frame. This is useful in tail calls. It returns
- // the new current frame.
- func (ls *LState) RemoveCallerFrame() *callFrame {
- cs := ls.stack
- sp := cs.Sp()
- parentFrame := cs.At(sp - 2)
- currentFrame := cs.At(sp - 1)
- parentsParentFrame := parentFrame.Parent
- *parentFrame = *currentFrame
- parentFrame.Parent = parentsParentFrame
- parentFrame.Idx = sp - 2
- cs.Pop()
- return parentFrame
- }
- /* }}} */
- /* }}} */
- //
|