1 Star 0 Fork 0

systechn/gopher-lua

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
vm.go 44.84 KB
一键复制 编辑 原始数据 按行查看 历史
Mark Tully 提交于 2021-04-26 17:26 . fix exposed panic
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726
package lua
////////////////////////////////////////////////////////
// This file was generated by go-inline. DO NOT EDIT. //
////////////////////////////////////////////////////////
import (
"fmt"
"math"
"strings"
)
func mainLoop(L *LState, baseframe *callFrame) {
var inst uint32
var cf *callFrame
if L.stack.IsEmpty() {
return
}
L.currentFrame = L.stack.Last()
if L.currentFrame.Fn.IsG {
callGFunction(L, false)
return
}
for {
cf = L.currentFrame
inst = cf.Fn.Proto.Code[cf.Pc]
cf.Pc++
if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 {
return
}
}
}
func mainLoopWithContext(L *LState, baseframe *callFrame) {
var inst uint32
var cf *callFrame
if L.stack.IsEmpty() {
return
}
L.currentFrame = L.stack.Last()
if L.currentFrame.Fn.IsG {
callGFunction(L, false)
return
}
for {
cf = L.currentFrame
inst = cf.Fn.Proto.Code[cf.Pc]
cf.Pc++
select {
case <-L.ctx.Done():
L.RaiseError(L.ctx.Err().Error())
return
default:
if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 {
return
}
}
}
}
// regv is the first target register to copy the return values to.
// It can be reg.top, indicating that the copied values are going into new registers, or it can be below reg.top
// Indicating that the values should be within the existing registers.
// b is the available number of return values + 1.
// n is the desired number of return values.
// If n more than the available return values then the extra values are set to nil.
// When this function returns the top of the registry will be set to regv+n.
func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start
if b == 1 {
// this section is inlined by go-inline
// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
{
rg := L.reg
regm := regv
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
}
}
}
} else {
// this section is inlined by go-inline
// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
{
rg := L.reg
limit := -1
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
}
}
}
if b > 1 && n > (b-1) {
// this section is inlined by go-inline
// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
{
rg := L.reg
regm := regv + b - 1
n := n - (b - 1)
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 switchToParentThread(L *LState, nargs int, haserror bool, kill bool) {
parent := L.Parent
if parent == nil {
L.RaiseError("can not yield from outside of a coroutine")
}
L.G.CurrentThread = parent
L.Parent = nil
if !L.wrapped {
if haserror {
parent.Push(LFalse)
} else {
parent.Push(LTrue)
}
}
L.XMoveTo(parent, nargs)
L.stack.Pop()
offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase
L.currentFrame = L.stack.Last()
L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions)
if kill {
L.kill()
}
}
func callGFunction(L *LState, tailcall bool) bool {
frame := L.currentFrame
gfnret := frame.Fn.GFunction(L)
if tailcall {
L.currentFrame = L.RemoveCallerFrame()
}
if gfnret < 0 {
switchToParentThread(L, L.GetTop(), false, false)
return true
}
wantret := frame.NRet
if wantret == MultRet {
wantret = gfnret
}
if tailcall && L.Parent != nil && L.stack.Sp() == 1 {
switchToParentThread(L, wantret, false, true)
return true
}
// this section is inlined by go-inline
// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
{
rg := L.reg
regv := frame.ReturnBase
start := L.reg.Top() - gfnret
limit := -1
n := wantret
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
}
}
}
L.stack.Pop()
L.currentFrame = L.stack.Last()
return false
}
func threadRun(L *LState) {
if L.stack.IsEmpty() {
return
}
defer func() {
if rcv := recover(); rcv != nil {
var lv LValue
if v, ok := rcv.(*ApiError); ok {
lv = v.Object
} else {
lv = LString(fmt.Sprint(rcv))
}
if parent := L.Parent; parent != nil {
if L.wrapped {
L.Push(lv)
parent.Panic(L)
} else {
L.SetTop(0)
L.Push(lv)
switchToParentThread(L, 1, true, true)
}
} else {
panic(rcv)
}
}
}()
L.mainLoop(L, nil)
}
type instFunc func(*LState, uint32, *callFrame) int
var jumpTable [opCodeMax + 1]instFunc
func init() {
jumpTable = [opCodeMax + 1]instFunc{
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVE
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
reg.Set(RA, reg.Get(lbase+B))
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVEN
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
reg.Set(lbase+A, reg.Get(lbase+B))
code := cf.Fn.Proto.Code
pc := cf.Pc
for i := 0; i < C; i++ {
inst = code[pc]
pc++
A = int(inst>>18) & 0xff //GETA
B = int(inst & 0x1ff) //GETB
reg.Set(lbase+A, reg.Get(lbase+B))
}
cf.Pc = pc
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADK
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
Bx := int(inst & 0x3ffff) //GETBX
reg.Set(RA, cf.Fn.Proto.Constants[Bx])
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADBOOL
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
if B != 0 {
reg.Set(RA, LTrue)
} else {
reg.Set(RA, LFalse)
}
if C != 0 {
cf.Pc++
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADNIL
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
for i := RA; i <= lbase+B; i++ {
reg.Set(i, LNil)
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETUPVAL
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
reg.Set(RA, cf.Fn.Upvalues[B].Value())
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETGLOBAL
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
Bx := int(inst & 0x3ffff) //GETBX
//reg.Set(RA, L.getField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx]))
reg.Set(RA, L.getFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx]))
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLE
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
reg.Set(RA, L.getField(reg.Get(lbase+B), L.rkValue(C)))
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLEKS
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
reg.Set(RA, L.getFieldString(reg.Get(lbase+B), L.rkString(C)))
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETGLOBAL
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
Bx := int(inst & 0x3ffff) //GETBX
//L.setField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx], reg.Get(RA))
L.setFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx], reg.Get(RA))
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETUPVAL
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
cf.Fn.Upvalues[B].SetValue(reg.Get(RA))
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLE
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
L.setField(reg.Get(RA), L.rkValue(B), L.rkValue(C))
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLEKS
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
L.setFieldString(reg.Get(RA), L.rkString(B), L.rkValue(C))
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NEWTABLE
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
reg.Set(RA, newLTable(B, C))
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SELF
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
selfobj := reg.Get(lbase + B)
reg.Set(RA, L.getFieldString(selfobj, L.rkString(C)))
reg.Set(RA+1, selfobj)
return 0
},
opArith, // OP_ADD
opArith, // OP_SUB
opArith, // OP_MUL
opArith, // OP_DIV
opArith, // OP_MOD
opArith, // OP_POW
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_UNM
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
unaryv := L.rkValue(B)
if nm, ok := unaryv.(LNumber); ok {
reg.SetNumber(RA, -nm)
} else {
op := L.metaOp1(unaryv, "__unm")
if op.Type() == LTFunction {
reg.Push(op)
reg.Push(unaryv)
L.Call(1, 1)
reg.Set(RA, reg.Pop())
} else if str, ok1 := unaryv.(LString); ok1 {
if num, err := parseNumber(string(str)); err == nil {
reg.Set(RA, -num)
} else {
L.RaiseError("__unm undefined")
}
} else {
L.RaiseError("__unm undefined")
}
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOT
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
if LVIsFalse(reg.Get(lbase + B)) {
reg.Set(RA, LTrue)
} else {
reg.Set(RA, LFalse)
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LEN
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
switch lv := L.rkValue(B).(type) {
case LString:
reg.SetNumber(RA, LNumber(len(lv)))
default:
op := L.metaOp1(lv, "__len")
if op.Type() == LTFunction {
reg.Push(op)
reg.Push(lv)
L.Call(1, 1)
ret := reg.Pop()
if ret.Type() == LTNumber {
reg.SetNumber(RA, ret.(LNumber))
} else {
reg.SetNumber(RA, LNumber(0))
}
} else if lv.Type() == LTTable {
reg.SetNumber(RA, LNumber(lv.(*LTable).Len()))
} else {
L.RaiseError("__len undefined")
}
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CONCAT
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
RC := lbase + C
RB := lbase + B
reg.Set(RA, stringConcat(L, RC-RB+1, RC))
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_JMP
cf := L.currentFrame
Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
cf.Pc += Sbx
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_EQ
cf := L.currentFrame
A := int(inst>>18) & 0xff //GETA
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
ret := equals(L, L.rkValue(B), L.rkValue(C), false)
v := 1
if ret {
v = 0
}
if v == A {
cf.Pc++
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LT
cf := L.currentFrame
A := int(inst>>18) & 0xff //GETA
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
ret := lessThan(L, L.rkValue(B), L.rkValue(C))
v := 1
if ret {
v = 0
}
if v == A {
cf.Pc++
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LE
cf := L.currentFrame
A := int(inst>>18) & 0xff //GETA
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
lhs := L.rkValue(B)
rhs := L.rkValue(C)
ret := false
if v1, ok1 := lhs.assertFloat64(); ok1 {
if v2, ok2 := rhs.assertFloat64(); ok2 {
ret = v1 <= v2
} else {
L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
}
} else {
if lhs.Type() != rhs.Type() {
L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
}
switch lhs.Type() {
case LTString:
ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) <= 0
default:
switch objectRational(L, lhs, rhs, "__le") {
case 1:
ret = true
case 0:
ret = false
default:
ret = !objectRationalWithError(L, rhs, lhs, "__lt")
}
}
}
v := 1
if ret {
v = 0
}
if v == A {
cf.Pc++
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TEST
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
C := int(inst>>9) & 0x1ff //GETC
if LVAsBool(reg.Get(RA)) == (C == 0) {
cf.Pc++
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TESTSET
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
if value := reg.Get(lbase + B); LVAsBool(value) != (C == 0) {
reg.Set(RA, value)
} else {
cf.Pc++
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
nargs := B - 1
if B == 0 {
nargs = reg.Top() - (RA + 1)
}
lv := reg.Get(RA)
nret := C - 1
var callable *LFunction
var meta bool
if fn, ok := lv.assertFunction(); ok {
callable = fn
meta = false
} else {
callable, meta = L.metaCall(lv)
}
// this section is inlined by go-inline
// source function is 'func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) ' in '_state.go'
{
ls := L
cf := callFrame{Fn: callable, Pc: 0, Base: RA, LocalBase: RA + 1, ReturnBase: RA, NArgs: nargs, NRet: nret, Parent: cf, TailCall: 0}
fn := lv
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
}
if callable.IsG && callGFunction(L, false) {
return 1
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
nargs := B - 1
if B == 0 {
nargs = reg.Top() - (RA + 1)
}
lv := reg.Get(RA)
var callable *LFunction
var meta bool
if fn, ok := lv.assertFunction(); ok {
callable = fn
meta = false
} else {
callable, meta = L.metaCall(lv)
}
if callable == nil {
L.RaiseError("attempt to call a non-function object")
}
// this section is inlined by go-inline
// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go'
{
ls := L
idx := lbase
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
}
}
}
if callable.IsG {
luaframe := cf
L.pushCallFrame(callFrame{
Fn: callable,
Pc: 0,
Base: RA,
LocalBase: RA + 1,
ReturnBase: cf.ReturnBase,
NArgs: nargs,
NRet: cf.NRet,
Parent: cf,
TailCall: 0,
}, lv, meta)
if callGFunction(L, true) {
return 1
}
if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe {
return 1
}
} else {
base := cf.Base
cf.Fn = callable
cf.Pc = 0
cf.Base = RA
cf.LocalBase = RA + 1
cf.ReturnBase = cf.ReturnBase
cf.NArgs = nargs
cf.NRet = cf.NRet
cf.TailCall++
lbase := cf.LocalBase
if meta {
cf.NArgs++
L.reg.Insert(lv, cf.LocalBase)
}
// this section is inlined by go-inline
// source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go'
{
ls := L
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)
}
}
}
// this section is inlined by go-inline
// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
{
rg := L.reg
regv := base
start := RA
limit := -1
n := reg.Top() - RA - 1
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
}
}
}
cf.Base = base
cf.LocalBase = base + (cf.LocalBase - lbase + 1)
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
// this section is inlined by go-inline
// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go'
{
ls := L
idx := lbase
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
}
}
}
nret := B - 1
if B == 0 {
nret = reg.Top() - RA
}
n := cf.NRet
if cf.NRet == MultRet {
n = nret
}
if L.Parent != nil && L.stack.Sp() == 1 {
// this section is inlined by go-inline
// source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go'
{
regv := reg.Top()
start := RA
b := B
if b == 1 {
// this section is inlined by go-inline
// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
{
rg := L.reg
regm := regv
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
}
}
}
} else {
// this section is inlined by go-inline
// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
{
rg := L.reg
limit := -1
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
}
}
}
if b > 1 && n > (b-1) {
// this section is inlined by go-inline
// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
{
rg := L.reg
regm := regv + b - 1
n := n - (b - 1)
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
}
}
}
}
}
}
switchToParentThread(L, n, false, true)
return 1
}
islast := baseframe == L.stack.Pop() || L.stack.IsEmpty()
// this section is inlined by go-inline
// source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go'
{
regv := cf.ReturnBase
start := RA
b := B
if b == 1 {
// this section is inlined by go-inline
// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
{
rg := L.reg
regm := regv
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
}
}
}
} else {
// this section is inlined by go-inline
// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
{
rg := L.reg
limit := -1
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
}
}
}
if b > 1 && n > (b-1) {
// this section is inlined by go-inline
// source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go'
{
rg := L.reg
regm := regv + b - 1
n := n - (b - 1)
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
}
}
}
}
}
}
L.currentFrame = L.stack.Last()
if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG {
return 1
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 {
if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 {
init += step
reg.SetNumber(RA, LNumber(init))
if (step > 0 && init <= limit) || (step <= 0 && init >= limit) {
Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
cf.Pc += Sbx
reg.SetNumber(RA+3, LNumber(init))
} else {
reg.SetTop(RA + 1)
}
} else {
L.RaiseError("for statement step must be a number")
}
} else {
L.RaiseError("for statement limit must be a number")
}
} else {
L.RaiseError("for statement init must be a number")
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 {
reg.SetNumber(RA, LNumber(init-step))
} else {
L.RaiseError("for statement step must be a number")
}
} else {
L.RaiseError("for statement init must be a number")
}
cf.Pc += Sbx
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
C := int(inst>>9) & 0x1ff //GETC
nret := C
reg.SetTop(RA + 3 + 2)
reg.Set(RA+3+2, reg.Get(RA+2))
reg.Set(RA+3+1, reg.Get(RA+1))
reg.Set(RA+3, reg.Get(RA))
L.callR(2, nret, RA+3)
if value := reg.Get(RA + 3); value != LNil {
reg.Set(RA+2, value)
pc := cf.Fn.Proto.Code[cf.Pc]
cf.Pc += int(pc&0x3ffff) - opMaxArgSbx
}
cf.Pc++
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
if C == 0 {
C = int(cf.Fn.Proto.Code[cf.Pc])
cf.Pc++
}
offset := (C - 1) * FieldsPerFlush
table := reg.Get(RA).(*LTable)
nelem := B
if B == 0 {
nelem = reg.Top() - RA - 1
}
for i := 1; i <= nelem; i++ {
table.RawSetInt(offset+i, reg.Get(RA+i))
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
// this section is inlined by go-inline
// source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go'
{
ls := L
idx := RA
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
}
}
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
Bx := int(inst & 0x3ffff) //GETBX
proto := cf.Fn.Proto.FunctionPrototypes[Bx]
closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues))
reg.Set(RA, closure)
for i := 0; i < int(proto.NumUpvalues); i++ {
inst = cf.Fn.Proto.Code[cf.Pc]
cf.Pc++
B := opGetArgB(inst)
switch opGetOpCode(inst) {
case OP_MOVE:
closure.Upvalues[i] = L.findUpvalue(lbase + B)
case OP_GETUPVAL:
closure.Upvalues[i] = cf.Fn.Upvalues[B]
}
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
B := int(inst & 0x1ff) //GETB
nparams := int(cf.Fn.Proto.NumParameters)
nvarargs := cf.NArgs - nparams
if nvarargs < 0 {
nvarargs = 0
}
nwant := B - 1
if B == 0 {
nwant = nvarargs
}
// this section is inlined by go-inline
// source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go'
{
rg := reg
regv := RA
start := cf.Base + nparams + 1
limit := cf.LocalBase
n := nwant
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
}
}
}
return 0
},
func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP
return 0
},
}
}
func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW
reg := L.reg
cf := L.currentFrame
lbase := cf.LocalBase
A := int(inst>>18) & 0xff //GETA
RA := lbase + A
opcode := int(inst >> 26) //GETOPCODE
B := int(inst & 0x1ff) //GETB
C := int(inst>>9) & 0x1ff //GETC
lhs := L.rkValue(B)
rhs := L.rkValue(C)
v1, ok1 := lhs.assertFloat64()
v2, ok2 := rhs.assertFloat64()
if ok1 && ok2 {
reg.SetNumber(RA, numberArith(L, opcode, LNumber(v1), LNumber(v2)))
} else {
reg.Set(RA, objectArith(L, opcode, lhs, rhs))
}
return 0
}
func luaModulo(lhs, rhs LNumber) LNumber {
flhs := float64(lhs)
frhs := float64(rhs)
v := math.Mod(flhs, frhs)
if flhs < 0 || frhs < 0 && !(flhs < 0 && frhs < 0) {
v += frhs
}
return LNumber(v)
}
func numberArith(L *LState, opcode int, lhs, rhs LNumber) LNumber {
switch opcode {
case OP_ADD:
return lhs + rhs
case OP_SUB:
return lhs - rhs
case OP_MUL:
return lhs * rhs
case OP_DIV:
return lhs / rhs
case OP_MOD:
return luaModulo(lhs, rhs)
case OP_POW:
flhs := float64(lhs)
frhs := float64(rhs)
return LNumber(math.Pow(flhs, frhs))
}
panic("should not reach here")
return LNumber(0)
}
func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue {
event := ""
switch opcode {
case OP_ADD:
event = "__add"
case OP_SUB:
event = "__sub"
case OP_MUL:
event = "__mul"
case OP_DIV:
event = "__div"
case OP_MOD:
event = "__mod"
case OP_POW:
event = "__pow"
}
op := L.metaOp2(lhs, rhs, event)
if op.Type() == LTFunction {
L.reg.Push(op)
L.reg.Push(lhs)
L.reg.Push(rhs)
L.Call(2, 1)
return L.reg.Pop()
}
if str, ok := lhs.(LString); ok {
if lnum, err := parseNumber(string(str)); err == nil {
lhs = lnum
}
}
if str, ok := rhs.(LString); ok {
if rnum, err := parseNumber(string(str)); err == nil {
rhs = rnum
}
}
if v1, ok1 := lhs.assertFloat64(); ok1 {
if v2, ok2 := rhs.assertFloat64(); ok2 {
return numberArith(L, opcode, LNumber(v1), LNumber(v2))
}
}
L.RaiseError(fmt.Sprintf("cannot perform %v operation between %v and %v",
strings.TrimLeft(event, "_"), lhs.Type().String(), rhs.Type().String()))
return LNil
}
func stringConcat(L *LState, total, last int) LValue {
rhs := L.reg.Get(last)
total--
for i := last - 1; total > 0; {
lhs := L.reg.Get(i)
if !(LVCanConvToString(lhs) && LVCanConvToString(rhs)) {
op := L.metaOp2(lhs, rhs, "__concat")
if op.Type() == LTFunction {
L.reg.Push(op)
L.reg.Push(lhs)
L.reg.Push(rhs)
L.Call(2, 1)
rhs = L.reg.Pop()
total--
i--
} else {
L.RaiseError("cannot perform concat operation between %v and %v", lhs.Type().String(), rhs.Type().String())
return LNil
}
} else {
buf := make([]string, total+1)
buf[total] = LVAsString(rhs)
for total > 0 {
lhs = L.reg.Get(i)
if !LVCanConvToString(lhs) {
break
}
buf[total-1] = LVAsString(lhs)
i--
total--
}
rhs = LString(strings.Join(buf, ""))
}
}
return rhs
}
func lessThan(L *LState, lhs, rhs LValue) bool {
// optimization for numbers
if v1, ok1 := lhs.assertFloat64(); ok1 {
if v2, ok2 := rhs.assertFloat64(); ok2 {
return v1 < v2
}
L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
}
if lhs.Type() != rhs.Type() {
L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
return false
}
ret := false
switch lhs.Type() {
case LTString:
ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) < 0
default:
ret = objectRationalWithError(L, lhs, rhs, "__lt")
}
return ret
}
func equals(L *LState, lhs, rhs LValue, raw bool) bool {
if lhs.Type() != rhs.Type() {
return false
}
ret := false
switch lhs.Type() {
case LTNil:
ret = true
case LTNumber:
v1, _ := lhs.assertFloat64()
v2, _ := rhs.assertFloat64()
ret = v1 == v2
case LTBool:
ret = bool(lhs.(LBool)) == bool(rhs.(LBool))
case LTString:
ret = string(lhs.(LString)) == string(rhs.(LString))
case LTUserData, LTTable:
if lhs == rhs {
ret = true
} else if !raw {
switch objectRational(L, lhs, rhs, "__eq") {
case 1:
ret = true
default:
ret = false
}
}
default:
ret = lhs == rhs
}
return ret
}
func objectRationalWithError(L *LState, lhs, rhs LValue, event string) bool {
switch objectRational(L, lhs, rhs, event) {
case 1:
return true
case 0:
return false
}
L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
return false
}
func objectRational(L *LState, lhs, rhs LValue, event string) int {
m1 := L.metaOp1(lhs, event)
m2 := L.metaOp1(rhs, event)
if m1.Type() == LTFunction && m1 == m2 {
L.reg.Push(m1)
L.reg.Push(lhs)
L.reg.Push(rhs)
L.Call(2, 1)
if LVAsBool(L.reg.Pop()) {
return 1
}
return 0
}
return -1
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/systechn/gopher-lua.git
git@gitee.com:systechn/gopher-lua.git
systechn
gopher-lua
gopher-lua
master

搜索帮助