debuggers.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. package debugging
  2. import (
  3. "fmt"
  4. "time"
  5. "strconv"
  6. "kumachan/standalone/util"
  7. "kumachan/standalone/util/richtext"
  8. "kumachan/lang/typsys"
  9. "kumachan/interpreter/core"
  10. "kumachan/interpreter/compiler"
  11. "kumachan/support/tools"
  12. )
  13. func CreateNaiveDebugger(info *compiler.DebugInfo) core.Debugger {
  14. return naiveDebugger { info }
  15. }
  16. type naiveDebugger struct { info *compiler.DebugInfo }
  17. func (d naiveDebugger) CreateInstance(h core.RuntimeHandle) core.DebuggerInstance {
  18. var ictx = MakeInspectContext(d.info.Context)
  19. var repl = CreateRepl(d.info, h)
  20. var instance = &naiveDebuggerInstance {
  21. proc: tools.NaiveDebugger(h.ProgramPath()),
  22. exit: make(chan struct{}),
  23. next: 1,
  24. ictx: ictx,
  25. repl: repl,
  26. }
  27. instance.proc.SendMessage("repl", ReplHelp, instance.exit)
  28. go instance.receiveCommands()
  29. return instance
  30. }
  31. type naiveDebuggerInstance struct {
  32. proc *tools.NaiveDebuggerProcess
  33. exit chan struct{}
  34. next int
  35. ictx InspectContext
  36. repl *Repl
  37. }
  38. func (d *naiveDebuggerInstance) getCmdId() int {
  39. var id = d.next
  40. d.next += 1
  41. return id
  42. }
  43. func (d *naiveDebuggerInstance) receiveCommands() {
  44. loop: for {
  45. if line, ok := d.proc.ReceiveCommand(d.exit); ok {
  46. if line != "" {
  47. var id = d.getCmdId()
  48. d.repl.HandleCommand(line, id, d, d.ExitNotifier())
  49. }
  50. } else {
  51. break loop
  52. }
  53. }
  54. }
  55. func (d *naiveDebuggerInstance) sendEcho(cmd string, id int) {
  56. var b richtext.Block
  57. b.WriteSpan(fmt.Sprintf("[%d] ", id), richtext.TAG_INPUT)
  58. b.WriteSpan(cmd)
  59. d.proc.SendMessage("repl", b.RenderHtml(), d.exit)
  60. }
  61. func (d *naiveDebuggerInstance) sendReply(msg richtext.Block, id int, header string, tags ...string) {
  62. var b richtext.Block
  63. if header != "" { header = (" " + header) }
  64. b.WriteLine(fmt.Sprintf("(%d)%s", id, header), tags...)
  65. b.Append(msg)
  66. d.proc.SendMessage("repl", b.RenderHtml(), d.exit)
  67. }
  68. func (d *naiveDebuggerInstance) sendNotice(title string, msg richtext.Block) {
  69. var b richtext.Block
  70. b.WriteLine(fmt.Sprintf("[notice] %s", title), richtext.TAG_B)
  71. b.Append(msg)
  72. d.proc.SendMessage("repl", b.RenderHtml(), d.exit)
  73. }
  74. func (d *naiveDebuggerInstance) ExitNotifier() util.ExitNotifier {
  75. return util.MakeExitNotifier(d.exit)
  76. }
  77. func (d *naiveDebuggerInstance) NotifyProgramCrash(msg richtext.Block) bool {
  78. d.proc.SendMessage("*", msg.RenderHtml(), d.exit)
  79. d.proc.SendMessage("<control>", "PROGRAM_CRASH", d.exit)
  80. return true
  81. }
  82. func (d *naiveDebuggerInstance) ReplEcho(cmd string, id int) {
  83. d.sendEcho(cmd, id)
  84. }
  85. func (d *naiveDebuggerInstance) ReplRespondExprValue(v core.Object, t typsys.CertainType, id int) {
  86. d.sendReply(Inspect(v, t.Type, d.ictx), id, "", richtext.TAG_OUTPUT)
  87. }
  88. func (d *naiveDebuggerInstance) ReplRespondExprError(msg richtext.Block, id int) {
  89. d.sendReply(msg, id, "", richtext.TAG_FAILURE)
  90. }
  91. func (d *naiveDebuggerInstance) ReplNotifyObValue(v core.Object, t typsys.CertainType, id int) {
  92. d.sendReply(Inspect(v, t.Type, d.ictx), id, "<value>", richtext.TAG_OUTPUT)
  93. }
  94. func (d *naiveDebuggerInstance) ReplNotifyObError(err error, id int) {
  95. var msg richtext.Block
  96. msg.WriteLine(err.Error(), richtext.TAG_ERR)
  97. d.sendReply(msg, id, "<error>", richtext.TAG_FAILURE)
  98. }
  99. func (d *naiveDebuggerInstance) ReplNotifyObCompletion(id int) {
  100. var msg richtext.Block
  101. msg.WriteLine("|")
  102. d.sendReply(msg, id, "<complete>", richtext.TAG_SUCCESS)
  103. }
  104. func (d *naiveDebuggerInstance) ReplExposeValue(name string, v core.Object, t typsys.CertainType, info *core.FrameInfo) func() {
  105. var loc = info.CallSite
  106. var t_desc = typsys.Describe(t.Type)
  107. unset := d.repl.Expose(name, v, t, loc)
  108. var tip richtext.Block
  109. tip.WriteSpan(name, richtext.TAG_DBG_FIELD)
  110. tip.WriteSpan(t_desc, richtext.TAG_DBG_TYPE)
  111. var content = loc.FormatMessageLite(tip)
  112. d.sendNotice("exposed", content)
  113. return func() {
  114. unset()
  115. var tip richtext.Block
  116. tip.WriteSpan((name + " " + t_desc), richtext.TAG_DEL)
  117. var content = loc.FormatMessageLite(tip)
  118. d.sendNotice("unset (exposed value)", content)
  119. }
  120. }
  121. func (d *naiveDebuggerInstance) InspectValue(v core.Object, t typsys.CertainType, info *core.FrameInfo, hint string) {
  122. var f = info.DescribeCaller()
  123. var loc = info.CallSite
  124. var header = fmt.Sprintf("--- %s in %s", strconv.Quote(hint), f)
  125. var content = Inspect(v, t.Type, d.ictx)
  126. var msg richtext.Block
  127. msg.WriteLine(header, richtext.TAG_B)
  128. msg.Append(loc.FormatMessageLite(content))
  129. d.proc.SendMessage("inspection", msg.RenderHtml(), d.exit)
  130. }
  131. func (d *naiveDebuggerInstance) InspectError(err error, info *core.FrameInfo) {
  132. var f = info.DescribeCaller()
  133. var loc = info.CallSite
  134. var header = fmt.Sprintf("*** Error in %s", f)
  135. var content richtext.Block
  136. content.WriteLine(err.Error(), richtext.TAG_ERR)
  137. var msg richtext.Block
  138. msg.WriteLine(header, richtext.TAG_B)
  139. msg.Append(loc.FormatMessage(content))
  140. d.proc.SendMessage("inspection", msg.RenderHtml(), d.exit)
  141. }
  142. func (d *naiveDebuggerInstance) InspectObSub(sub string, info *core.FrameInfo, hint string) {
  143. var f = info.DescribeCaller()
  144. var loc = info.CallSite
  145. var header1 = fmt.Sprintf("--- %s subscribed in %s", strconv.Quote(hint), f)
  146. var header2 = fmt.Sprintf(" %s", sub)
  147. var content richtext.Block
  148. var msg richtext.Block
  149. msg.WriteLine(header1, richtext.TAG_B)
  150. msg.WriteLine(header2)
  151. msg.Append(loc.FormatMessageLite(content))
  152. d.proc.SendMessage("inspection", msg.RenderHtml(), d.exit)
  153. }
  154. func (d *naiveDebuggerInstance) InspectObValue(v core.Object, t typsys.CertainType, sub string, _ *core.FrameInfo, hint string) {
  155. var header1 = fmt.Sprintf(">>> %s <value>", strconv.Quote(hint))
  156. var header2 = fmt.Sprintf(" %s", sub)
  157. var content = Inspect(v, t.Type, d.ictx)
  158. var msg richtext.Block
  159. msg.WriteLine(header1, richtext.TAG_B, richtext.TAG_OUTPUT)
  160. msg.WriteLine(header2, richtext.TAG_OUTPUT)
  161. msg.Append(content)
  162. d.proc.SendMessage("inspection", msg.RenderHtml(), d.exit)
  163. }
  164. func (d *naiveDebuggerInstance) InspectObError(err error, sub string, _ *core.FrameInfo, hint string) {
  165. var header1 = fmt.Sprintf(">>> %s <error>", strconv.Quote(hint))
  166. var header2 = fmt.Sprintf(" %s", sub)
  167. var content richtext.Block
  168. content.WriteLine(err.Error(), richtext.TAG_ERR)
  169. var msg richtext.Block
  170. msg.WriteLine(header1, richtext.TAG_B, richtext.TAG_FAILURE)
  171. msg.WriteLine(header2, richtext.TAG_FAILURE)
  172. msg.Append(content)
  173. d.proc.SendMessage("inspection", msg.RenderHtml(), d.exit)
  174. }
  175. func (d *naiveDebuggerInstance) InspectObCompletion(sub string, _ *core.FrameInfo, hint string) {
  176. var header1 = fmt.Sprintf(">>> %s <complete>", strconv.Quote(hint))
  177. var header2 = fmt.Sprintf(" %s", sub)
  178. var content richtext.Block
  179. content.WriteLine("|")
  180. var msg richtext.Block
  181. msg.WriteLine(header1, richtext.TAG_B, richtext.TAG_SUCCESS)
  182. msg.WriteLine(header2, richtext.TAG_SUCCESS)
  183. msg.Append(content)
  184. d.proc.SendMessage("inspection", msg.RenderHtml(), d.exit)
  185. }
  186. func (d *naiveDebuggerInstance) InspectObContextDisposal(sub string, _ *core.FrameInfo, hint string) {
  187. var header1 = fmt.Sprintf(">>> %s <context-disposal>", strconv.Quote(hint))
  188. var header2 = fmt.Sprintf(" %s", sub)
  189. var content richtext.Block
  190. var msg richtext.Block
  191. msg.WriteLine(header1, richtext.TAG_B, richtext.TAG_I)
  192. msg.WriteLine(header2, richtext.TAG_I)
  193. msg.Append(content)
  194. d.proc.SendMessage("inspection", msg.RenderHtml(), d.exit)
  195. }
  196. func (d *naiveDebuggerInstance) LogRequest(method string, endpoint string, _ string, _ string, _ *core.FrameInfo) {
  197. var t = time.Now().Format("15:04:05")
  198. var msg richtext.Block
  199. msg.WriteLine(fmt.Sprintf("[%s] %s %s", t, method, endpoint))
  200. d.proc.SendMessage("io", msg.RenderHtml(), d.exit)
  201. }
  202. func (d *naiveDebuggerInstance) LogFileRead(file string, _ *core.FrameInfo) {
  203. var t = time.Now().Format("15:04:05")
  204. var msg richtext.Block
  205. msg.WriteLine(fmt.Sprintf("[%s] READ %s", t, file))
  206. d.proc.SendMessage("io", msg.RenderHtml(), d.exit)
  207. }
  208. func (d *naiveDebuggerInstance) LogFileWrite(file string, _ string, _ *core.FrameInfo) {
  209. var t = time.Now().Format("15:04:05")
  210. var msg richtext.Block
  211. msg.WriteLine(fmt.Sprintf("[%s] WRITE %s", t, file))
  212. d.proc.SendMessage("io", msg.RenderHtml(), d.exit)
  213. }