inspect.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. package debugging
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. "kumachan/standalone/util/richtext"
  7. "kumachan/lang/source"
  8. "kumachan/lang/typsys"
  9. "kumachan/interpreter/core"
  10. "kumachan/interpreter/compiler"
  11. )
  12. type InspectContext struct {
  13. context *compiler.NsHeaderMap
  14. }
  15. func MakeInspectContext(ctx *compiler.NsHeaderMap) InspectContext {
  16. return InspectContext { ctx }
  17. }
  18. func (ctx InspectContext) FindType(ref source.Ref) (*typsys.TypeDef, bool) {
  19. return ctx.context.FindType(ref)
  20. }
  21. func Inspect(v core.Object, t typsys.Type, ctx InspectContext) richtext.Block {
  22. var opaque = func(t_desc string) richtext.Block {
  23. var b richtext.Block
  24. b.WriteRawSpan(t_desc, richtext.TAG_DBG_TYPE)
  25. return b
  26. }
  27. var primitive = func(v_desc string, v_tag string) richtext.Block {
  28. var b richtext.Block
  29. b.WriteSpan(v_desc, v_tag)
  30. return b
  31. }
  32. var write_type_line = func(b *richtext.Block) {
  33. var t_desc = typsys.Describe(t)
  34. b.WriteLine(t_desc, richtext.TAG_DBG_TYPE)
  35. }
  36. var collection = func(inner_t typsys.Type, size int, forEach func(func(core.Object))) richtext.Block {
  37. var b richtext.Block
  38. write_type_line(&b)
  39. var size_desc = fmt.Sprintf("<%d>", size)
  40. b.WriteLine(size_desc, richtext.TAG_DBG_NUMBER)
  41. forEach(func(item core.Object) {
  42. b.Append(Inspect(item, inner_t, ctx))
  43. })
  44. return b
  45. }
  46. if t == nil {
  47. return opaque("(?)")
  48. }
  49. switch T := t.(type) {
  50. case typsys.InferringType:
  51. return opaque(T.Id)
  52. case typsys.ParameterType:
  53. return opaque(T.Name)
  54. case typsys.RefType:
  55. var t_ref = T.Def
  56. if t_ref.Namespace == "" {
  57. switch t_ref.ItemName {
  58. case core.T_Null:
  59. var b richtext.Block
  60. b.WriteLine("Null", richtext.TAG_DBG_CONSTANT)
  61. return b
  62. case core.T_Bool:
  63. if core.GetBool(v) {
  64. return primitive("Yes", richtext.TAG_DBG_CONSTANT)
  65. } else {
  66. return primitive("No", richtext.TAG_DBG_CONSTANT)
  67. }
  68. case core.T_Char:
  69. var char = core.GetChar(v)
  70. var char_str = string([] rune { rune(char) })
  71. var char_str_desc = strconv.Quote(char_str)
  72. var char_desc = fmt.Sprintf("\\u%X %s", char, char_str_desc)
  73. return primitive(char_desc, richtext.TAG_DBG_NUMBER)
  74. case core.T_String:
  75. var str_desc = strconv.Quote(core.GetString(v))
  76. return primitive(str_desc, richtext.TAG_DBG_STRING)
  77. case core.T_Bytes:
  78. var bin = core.GetBytes(v)
  79. var buf strings.Builder
  80. for _, n := range bin {
  81. var hi = ((n & 0xF0) >> 4)
  82. var lo = (n & 0x0F)
  83. fmt.Fprintf(&buf, `\x%X%X`, hi, lo)
  84. }
  85. var bin_desc = buf.String()
  86. return primitive(bin_desc, richtext.TAG_DBG_NUMBER)
  87. case core.T_Int:
  88. var n = core.GetIntAsRawBigInt(v)
  89. var n_desc = n.String()
  90. return primitive(n_desc, richtext.TAG_DBG_NUMBER)
  91. case core.T_Float:
  92. var x = core.GetFloat(v)
  93. var x_desc = fmt.Sprint(x)
  94. if !(strings.Contains(x_desc, ".") ||
  95. strings.Contains(x_desc, "e") ||
  96. strings.Contains(x_desc, "E") ||
  97. strings.Contains(x_desc, "NaN") ||
  98. strings.Contains(x_desc, "Inf")) {
  99. x_desc = (x_desc + ".0")
  100. }
  101. return primitive(x_desc, richtext.TAG_DBG_NUMBER)
  102. case core.T_Time:
  103. var tau = core.GetTime(v)
  104. var tau_desc = tau.String()
  105. return primitive(tau_desc, richtext.TAG_DBG_NUMBER)
  106. case core.T_File:
  107. var f = core.GetFile(v)
  108. var f_desc = f.Path
  109. return primitive(f_desc, richtext.TAG_DBG_STRING)
  110. case core.T_Error:
  111. var b richtext.Block
  112. b.WriteLine(typsys.Describe(t), richtext.TAG_DBG_TYPE)
  113. var child richtext.Block
  114. var err = core.GetError(v)
  115. var err_desc = strconv.Quote(err.Error())
  116. child.WriteLine(err_desc, richtext.TAG_DBG_STRING)
  117. b.Append(child)
  118. return b
  119. case core.T_Lambda:
  120. return opaque(typsys.Describe(t))
  121. case core.T_List:
  122. var l = core.GetList(v)
  123. return collection(T.Args[0], l.Length(), l.ForEach)
  124. case core.T_Seq:
  125. var s = core.GetSeq(v)
  126. return collection(T.Args[0], s.Length(), s.ToList().ForEach)
  127. case core.T_Queue:
  128. var q = core.GetQueue(v)
  129. return collection(T.Args[0], q.Size(), q.ForEach)
  130. case core.T_Heap:
  131. var h = core.GetHeap(v)
  132. return collection(T.Args[0], h.Size(), h.ForEach)
  133. case core.T_Set:
  134. var s = core.GetSet(v)
  135. return collection(T.Args[0], s.Size(), s.ForEach)
  136. case core.T_Map:
  137. var b richtext.Block
  138. b.WriteLine(typsys.Describe(t), richtext.TAG_DBG_TYPE)
  139. var m = core.GetMap(v)
  140. var size_desc = fmt.Sprintf("<%d>", m.Size())
  141. b.WriteLine(size_desc, richtext.TAG_DBG_NUMBER)
  142. m.ForEach(func(key core.Object, val core.Object) {
  143. var item richtext.Block
  144. item.WriteLine("*")
  145. item.Append(Inspect(key, T.Args[0], ctx))
  146. item.Append(Inspect(val, T.Args[1], ctx))
  147. b.Append(item)
  148. })
  149. return b
  150. }
  151. }
  152. var def, ok = ctx.FindType(t_ref)
  153. if ok {
  154. switch content := def.Content.(type) {
  155. case typsys.Record:
  156. var V = (*v).(core.Record)
  157. var b richtext.Block
  158. write_type_line(&b)
  159. for i, field := range content.FieldList {
  160. var field_t = typsys.Inflate(
  161. field.Type, def.Parameters, T.Args,
  162. )
  163. var child richtext.Block
  164. child.WriteSpan(field.Name, richtext.TAG_DBG_FIELD)
  165. child.Append(Inspect(V.Objects[i], field_t, ctx))
  166. b.Append(child)
  167. }
  168. return b
  169. case typsys.Union:
  170. var u = (*v).(core.Union)
  171. var b richtext.Block
  172. write_type_line(&b)
  173. var index_desc = fmt.Sprintf("(%d)", u.Index)
  174. b.WriteLine(index_desc, richtext.TAG_DBG_NUMBER)
  175. var item = content.FieldList[u.Index]
  176. var case_t = typsys.Inflate(item.Type, def.Parameters, T.Args)
  177. var inner = Inspect(u.Object, case_t, ctx)
  178. b.Append(inner)
  179. return b
  180. case typsys.Enum:
  181. var index = int((*v).(core.Enum))
  182. var item = content.FieldList[index]
  183. var b richtext.Block
  184. write_type_line(&b)
  185. var item_desc = fmt.Sprintf("%s(%d)", item.Name, index)
  186. b.WriteLine(item_desc, richtext.TAG_DBG_NUMBER)
  187. return b
  188. }
  189. }
  190. var b richtext.Block
  191. write_type_line(&b)
  192. return b
  193. default:
  194. panic("impossible branch")
  195. }
  196. }