function.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. package lua
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. const (
  7. VarArgHasArg uint8 = 1
  8. VarArgIsVarArg uint8 = 2
  9. VarArgNeedsArg uint8 = 4
  10. )
  11. type DbgLocalInfo struct {
  12. Name string
  13. StartPc int
  14. EndPc int
  15. }
  16. type DbgCall struct {
  17. Name string
  18. Pc int
  19. }
  20. type FunctionProto struct {
  21. SourceName string
  22. LineDefined int
  23. LastLineDefined int
  24. NumUpvalues uint8
  25. NumParameters uint8
  26. IsVarArg uint8
  27. NumUsedRegisters uint8
  28. Code []uint32
  29. Constants []LValue
  30. FunctionPrototypes []*FunctionProto
  31. DbgSourcePositions []int
  32. DbgLocals []*DbgLocalInfo
  33. DbgCalls []DbgCall
  34. DbgUpvalues []string
  35. stringConstants []string
  36. }
  37. /* Upvalue {{{ */
  38. type Upvalue struct {
  39. next *Upvalue
  40. reg *registry
  41. index int
  42. value LValue
  43. closed bool
  44. }
  45. func (uv *Upvalue) Value() LValue {
  46. //if uv.IsClosed() {
  47. if uv.closed || uv.reg == nil {
  48. return uv.value
  49. }
  50. //return uv.reg.Get(uv.index)
  51. return uv.reg.array[uv.index]
  52. }
  53. func (uv *Upvalue) SetValue(value LValue) {
  54. if uv.IsClosed() {
  55. uv.value = value
  56. } else {
  57. uv.reg.Set(uv.index, value)
  58. }
  59. }
  60. func (uv *Upvalue) Close() {
  61. value := uv.Value()
  62. uv.closed = true
  63. uv.value = value
  64. }
  65. func (uv *Upvalue) IsClosed() bool {
  66. return uv.closed || uv.reg == nil
  67. }
  68. func UpvalueIndex(i int) int {
  69. return GlobalsIndex - i
  70. }
  71. /* }}} */
  72. /* FunctionProto {{{ */
  73. func newFunctionProto(name string) *FunctionProto {
  74. return &FunctionProto{
  75. SourceName: name,
  76. LineDefined: 0,
  77. LastLineDefined: 0,
  78. NumUpvalues: 0,
  79. NumParameters: 0,
  80. IsVarArg: 0,
  81. NumUsedRegisters: 2,
  82. Code: make([]uint32, 0, 128),
  83. Constants: make([]LValue, 0, 32),
  84. FunctionPrototypes: make([]*FunctionProto, 0, 16),
  85. DbgSourcePositions: make([]int, 0, 128),
  86. DbgLocals: make([]*DbgLocalInfo, 0, 16),
  87. DbgCalls: make([]DbgCall, 0, 128),
  88. DbgUpvalues: make([]string, 0, 16),
  89. stringConstants: make([]string, 0, 32),
  90. }
  91. }
  92. func (fp *FunctionProto) String() string {
  93. return fp.str(1, 0)
  94. }
  95. func (fp *FunctionProto) str(level int, count int) string {
  96. indent := strings.Repeat(" ", level-1)
  97. buf := []string{}
  98. buf = append(buf, fmt.Sprintf("%v; function [%v] definition (level %v)\n",
  99. indent, count, level))
  100. buf = append(buf, fmt.Sprintf("%v; %v upvalues, %v params, %v stacks\n",
  101. indent, fp.NumUpvalues, fp.NumParameters, fp.NumUsedRegisters))
  102. for reg, linfo := range fp.DbgLocals {
  103. buf = append(buf, fmt.Sprintf("%v.local %v ; %v\n", indent, linfo.Name, reg))
  104. }
  105. for reg, upvalue := range fp.DbgUpvalues {
  106. buf = append(buf, fmt.Sprintf("%v.upvalue %v ; %v\n", indent, upvalue, reg))
  107. }
  108. for reg, conzt := range fp.Constants {
  109. buf = append(buf, fmt.Sprintf("%v.const %v ; %v\n", indent, conzt.String(), reg))
  110. }
  111. buf = append(buf, "\n")
  112. protono := 0
  113. for no, code := range fp.Code {
  114. inst := opGetOpCode(code)
  115. if inst == OP_CLOSURE {
  116. buf = append(buf, "\n")
  117. buf = append(buf, fp.FunctionPrototypes[protono].str(level+1, protono))
  118. buf = append(buf, "\n")
  119. protono++
  120. }
  121. buf = append(buf, fmt.Sprintf("%v[%03d] %v (line:%v)\n",
  122. indent, no+1, opToString(code), fp.DbgSourcePositions[no]))
  123. }
  124. buf = append(buf, fmt.Sprintf("%v; end of function\n", indent))
  125. return strings.Join(buf, "")
  126. }
  127. /* }}} */
  128. /* LFunction {{{ */
  129. func newLFunctionL(proto *FunctionProto, env *LTable, nupvalue int) *LFunction {
  130. return &LFunction{
  131. IsG: false,
  132. Env: env,
  133. Proto: proto,
  134. GFunction: nil,
  135. Upvalues: make([]*Upvalue, nupvalue),
  136. }
  137. }
  138. func newLFunctionG(gfunc LGFunction, env *LTable, nupvalue int) *LFunction {
  139. return &LFunction{
  140. IsG: true,
  141. Env: env,
  142. Proto: nil,
  143. GFunction: gfunc,
  144. Upvalues: make([]*Upvalue, nupvalue),
  145. }
  146. }
  147. func (fn *LFunction) LocalName(regno, pc int) (string, bool) {
  148. if fn.IsG {
  149. return "", false
  150. }
  151. p := fn.Proto
  152. for i := 0; i < len(p.DbgLocals) && p.DbgLocals[i].StartPc < pc; i++ {
  153. if pc < p.DbgLocals[i].EndPc {
  154. regno--
  155. if regno == 0 {
  156. return p.DbgLocals[i].Name, true
  157. }
  158. }
  159. }
  160. return "", false
  161. }
  162. /* }}} */