github.com/erikdubbelboer/gopher-lua@v0.0.0-20160512044044-e68f0dc85040/debuglib.go (about) 1 package lua 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 func OpenDebug(L *LState) int { 9 dbgmod := L.RegisterModule(DebugLibName, debugFuncs) 10 L.Push(dbgmod) 11 return 1 12 } 13 14 var debugFuncs = map[string]LGFunction{ 15 "getfenv": debugGetFEnv, 16 "getinfo": debugGetInfo, 17 "getlocal": debugGetLocal, 18 "getmetatable": debugGetMetatable, 19 "getupvalue": debugGetUpvalue, 20 "setfenv": debugSetFEnv, 21 "setlocal": debugSetLocal, 22 "setmetatable": debugSetMetatable, 23 "setupvalue": debugSetUpvalue, 24 "traceback": debugTraceback, 25 } 26 27 func debugGetFEnv(L *LState) int { 28 L.Push(L.GetFEnv(L.CheckAny(1))) 29 return 1 30 } 31 32 func debugGetInfo(L *LState) int { 33 L.CheckTypes(1, LTFunction, LTNumber) 34 arg1 := L.Get(1) 35 what := L.OptString(2, "Slunf") 36 var dbg *Debug 37 var fn LValue 38 var err error 39 var ok bool 40 switch lv := arg1.(type) { 41 case *LFunction: 42 dbg = &Debug{} 43 fn, err = L.GetInfo(">"+what, dbg, lv) 44 case LNumber: 45 dbg, ok = L.GetStack(int(lv)) 46 if !ok { 47 L.Push(LNil) 48 return 1 49 } 50 fn, err = L.GetInfo(what, dbg, LNil) 51 } 52 53 if err != nil { 54 L.Push(LNil) 55 return 1 56 } 57 tbl := L.NewTable() 58 if len(dbg.Name) > 0 { 59 tbl.RawSetString("name", LString(dbg.Name)) 60 } else { 61 tbl.RawSetString("name", LNil) 62 } 63 tbl.RawSetString("what", LString(dbg.What)) 64 tbl.RawSetString("source", LString(dbg.Source)) 65 tbl.RawSetString("currentline", LNumber(dbg.CurrentLine)) 66 tbl.RawSetString("nups", LNumber(dbg.NUpvalues)) 67 tbl.RawSetString("linedefined", LNumber(dbg.LineDefined)) 68 tbl.RawSetString("lastlinedefined", LNumber(dbg.LastLineDefined)) 69 tbl.RawSetString("func", fn) 70 L.Push(tbl) 71 return 1 72 } 73 74 func debugGetLocal(L *LState) int { 75 level := L.CheckInt(1) 76 idx := L.CheckInt(2) 77 dbg, ok := L.GetStack(level) 78 if !ok { 79 L.ArgError(1, "level out of range") 80 } 81 name, value := L.GetLocal(dbg, idx) 82 if len(name) > 0 { 83 L.Push(LString(name)) 84 L.Push(value) 85 return 2 86 } 87 L.Push(LNil) 88 return 1 89 } 90 91 func debugGetMetatable(L *LState) int { 92 L.Push(L.GetMetatable(L.CheckAny(1))) 93 return 1 94 } 95 96 func debugGetUpvalue(L *LState) int { 97 fn := L.CheckFunction(1) 98 idx := L.CheckInt(2) 99 name, value := L.GetUpvalue(fn, idx) 100 if len(name) > 0 { 101 L.Push(LString(name)) 102 L.Push(value) 103 return 2 104 } 105 L.Push(LNil) 106 return 1 107 } 108 109 func debugSetFEnv(L *LState) int { 110 L.SetFEnv(L.CheckAny(1), L.CheckAny(2)) 111 return 0 112 } 113 114 func debugSetLocal(L *LState) int { 115 level := L.CheckInt(1) 116 idx := L.CheckInt(2) 117 value := L.CheckAny(3) 118 dbg, ok := L.GetStack(level) 119 if !ok { 120 L.ArgError(1, "level out of range") 121 } 122 name := L.SetLocal(dbg, idx, value) 123 if len(name) > 0 { 124 L.Push(LString(name)) 125 } else { 126 L.Push(LNil) 127 } 128 return 1 129 } 130 131 func debugSetMetatable(L *LState) int { 132 L.CheckTypes(2, LTNil, LTTable) 133 obj := L.Get(1) 134 mt := L.Get(2) 135 L.SetMetatable(obj, mt) 136 L.SetTop(1) 137 return 1 138 } 139 140 func debugSetUpvalue(L *LState) int { 141 fn := L.CheckFunction(1) 142 idx := L.CheckInt(2) 143 value := L.CheckAny(3) 144 name := L.SetUpvalue(fn, idx, value) 145 if len(name) > 0 { 146 L.Push(LString(name)) 147 } else { 148 L.Push(LNil) 149 } 150 return 1 151 } 152 153 func debugTraceback(L *LState) int { 154 msg := L.OptString(1, "") 155 level := L.OptInt(2, 1) 156 traceback := strings.TrimSpace(L.stackTrace(level)) 157 if len(msg) > 0 { 158 traceback = fmt.Sprintf("%s\n%s", msg, traceback) 159 } 160 L.Push(LString(traceback)) 161 return 1 162 }