github.com/xrash/gopher-lua@v0.0.0-20160304065408-e5faab4db06a/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  }