mt-lang 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/AUTHORS +3 -0
  4. data/Gemfile +19 -0
  5. data/Gemfile.lock +82 -0
  6. data/LICENSE +21 -0
  7. data/README.md +1208 -0
  8. data/Rakefile +332 -0
  9. data/bin/mtc +8 -0
  10. data/bin/profile-mtc-checks +133 -0
  11. data/bin/tracy-profiler +0 -0
  12. data/docs/build-guide.md +536 -0
  13. data/docs/index.html +2778 -0
  14. data/docs/language-design.md +1519 -0
  15. data/docs/language-manual.md +1534 -0
  16. data/lib/milk_tea/base.rb +49 -0
  17. data/lib/milk_tea/bindings/bindgen/ast_parser.rb +398 -0
  18. data/lib/milk_tea/bindings/bindgen/declaration.rb +319 -0
  19. data/lib/milk_tea/bindings/bindgen/emitter.rb +387 -0
  20. data/lib/milk_tea/bindings/bindgen/overrides.rb +134 -0
  21. data/lib/milk_tea/bindings/bindgen/type_mapper.rb +622 -0
  22. data/lib/milk_tea/bindings/bindgen.rb +207 -0
  23. data/lib/milk_tea/bindings/cli.rb +121 -0
  24. data/lib/milk_tea/bindings/imported_bindings/defaults.rb +210 -0
  25. data/lib/milk_tea/bindings/imported_bindings/generator.rb +1114 -0
  26. data/lib/milk_tea/bindings/imported_bindings/method_source.rb +190 -0
  27. data/lib/milk_tea/bindings/imported_bindings/naming.rb +286 -0
  28. data/lib/milk_tea/bindings/imported_bindings.rb +215 -0
  29. data/lib/milk_tea/bindings/opengl_registry.rb +547 -0
  30. data/lib/milk_tea/bindings/raw_bindings/defaults.rb +1338 -0
  31. data/lib/milk_tea/bindings/raw_bindings.rb +269 -0
  32. data/lib/milk_tea/bindings/steamworks.rb +629 -0
  33. data/lib/milk_tea/bindings/upstream_sources.rb +352 -0
  34. data/lib/milk_tea/bindings/vendored_box2d.rb +79 -0
  35. data/lib/milk_tea/bindings/vendored_c_library.rb +322 -0
  36. data/lib/milk_tea/bindings/vendored_cjson.rb +52 -0
  37. data/lib/milk_tea/bindings/vendored_flecs.rb +78 -0
  38. data/lib/milk_tea/bindings/vendored_glfw.rb +77 -0
  39. data/lib/milk_tea/bindings/vendored_libuv.rb +75 -0
  40. data/lib/milk_tea/bindings/vendored_pcre2.rb +84 -0
  41. data/lib/milk_tea/bindings/vendored_raylib.rb +131 -0
  42. data/lib/milk_tea/bindings/vendored_sdl3.rb +78 -0
  43. data/lib/milk_tea/bindings/vendored_steamworks.rb +71 -0
  44. data/lib/milk_tea/bindings/vendored_tool.rb +71 -0
  45. data/lib/milk_tea/bindings/vendored_tools.rb +23 -0
  46. data/lib/milk_tea/bindings/vendored_tracy.rb +37 -0
  47. data/lib/milk_tea/bindings.rb +23 -0
  48. data/lib/milk_tea/core/ast.rb +311 -0
  49. data/lib/milk_tea/core/async_runtime_installer.rb +28 -0
  50. data/lib/milk_tea/core/binding_types.rb +18 -0
  51. data/lib/milk_tea/core/bindings/attribute_binding.rb +58 -0
  52. data/lib/milk_tea/core/bindings/function_binding.rb +5 -0
  53. data/lib/milk_tea/core/bindings/module_binding.rb +58 -0
  54. data/lib/milk_tea/core/bindings/value_binding.rb +21 -0
  55. data/lib/milk_tea/core/c_backend/aggregate_utils.rb +103 -0
  56. data/lib/milk_tea/core/c_backend/control_flow_emission.rb +412 -0
  57. data/lib/milk_tea/core/c_backend/expressions.rb +468 -0
  58. data/lib/milk_tea/core/c_backend/feature_detection.rb +483 -0
  59. data/lib/milk_tea/core/c_backend/reachability.rb +398 -0
  60. data/lib/milk_tea/core/c_backend/reinterpret.rb +226 -0
  61. data/lib/milk_tea/core/c_backend/runtime_helpers.rb +1080 -0
  62. data/lib/milk_tea/core/c_backend/statements.rb +563 -0
  63. data/lib/milk_tea/core/c_backend/type_collectors.rb +1545 -0
  64. data/lib/milk_tea/core/c_backend/type_declaration.rb +223 -0
  65. data/lib/milk_tea/core/c_backend/type_system.rb +345 -0
  66. data/lib/milk_tea/core/c_backend.rb +287 -0
  67. data/lib/milk_tea/core/compatibility_helpers.rb +79 -0
  68. data/lib/milk_tea/core/compile_time/const_eval.rb +187 -0
  69. data/lib/milk_tea/core/compile_time.rb +329 -0
  70. data/lib/milk_tea/core/control_flow/builder.rb +582 -0
  71. data/lib/milk_tea/core/control_flow/constant_propagation.rb +143 -0
  72. data/lib/milk_tea/core/control_flow/dataflow.rb +74 -0
  73. data/lib/milk_tea/core/control_flow/definite_assignment.rb +79 -0
  74. data/lib/milk_tea/core/control_flow/graph.rb +90 -0
  75. data/lib/milk_tea/core/control_flow/liveness.rb +24 -0
  76. data/lib/milk_tea/core/control_flow/nullability_flow.rb +43 -0
  77. data/lib/milk_tea/core/control_flow/reachability.rb +22 -0
  78. data/lib/milk_tea/core/control_flow/termination.rb +31 -0
  79. data/lib/milk_tea/core/control_flow.rb +34 -0
  80. data/lib/milk_tea/core/cst.rb +48 -0
  81. data/lib/milk_tea/core/cst_builder.rb +19 -0
  82. data/lib/milk_tea/core/ir.rb +85 -0
  83. data/lib/milk_tea/core/keywords.rb +97 -0
  84. data/lib/milk_tea/core/lexer/character_classes.rb +60 -0
  85. data/lib/milk_tea/core/lexer/format_strings.rb +225 -0
  86. data/lib/milk_tea/core/lexer/heredocs.rb +199 -0
  87. data/lib/milk_tea/core/lexer/indentation.rb +62 -0
  88. data/lib/milk_tea/core/lexer/numbers.rb +96 -0
  89. data/lib/milk_tea/core/lexer/recovery.rb +32 -0
  90. data/lib/milk_tea/core/lexer/strings.rb +167 -0
  91. data/lib/milk_tea/core/lexer/symbols.rb +71 -0
  92. data/lib/milk_tea/core/lexer/trivia.rb +53 -0
  93. data/lib/milk_tea/core/lexer.rb +430 -0
  94. data/lib/milk_tea/core/lowering/artifacts.rb +26 -0
  95. data/lib/milk_tea/core/lowering/async/analysis.rb +245 -0
  96. data/lib/milk_tea/core/lowering/async/lowering.rb +1399 -0
  97. data/lib/milk_tea/core/lowering/async/normalization.rb +459 -0
  98. data/lib/milk_tea/core/lowering/async.rb +714 -0
  99. data/lib/milk_tea/core/lowering/block.rb +1052 -0
  100. data/lib/milk_tea/core/lowering/calls.rb +1565 -0
  101. data/lib/milk_tea/core/lowering/declarations.rb +214 -0
  102. data/lib/milk_tea/core/lowering/dyn.rb +206 -0
  103. data/lib/milk_tea/core/lowering/events.rb +1054 -0
  104. data/lib/milk_tea/core/lowering/expressions.rb +1645 -0
  105. data/lib/milk_tea/core/lowering/foreign_cstr.rb +206 -0
  106. data/lib/milk_tea/core/lowering/functions.rb +242 -0
  107. data/lib/milk_tea/core/lowering/loops.rb +1087 -0
  108. data/lib/milk_tea/core/lowering/lowering_context.rb +80 -0
  109. data/lib/milk_tea/core/lowering/proc.rb +419 -0
  110. data/lib/milk_tea/core/lowering/resolve.rb +2516 -0
  111. data/lib/milk_tea/core/lowering/scans.rb +220 -0
  112. data/lib/milk_tea/core/lowering/str_buffer.rb +125 -0
  113. data/lib/milk_tea/core/lowering/utils.rb +1453 -0
  114. data/lib/milk_tea/core/lowering.rb +378 -0
  115. data/lib/milk_tea/core/module_binder.rb +181 -0
  116. data/lib/milk_tea/core/module_loader/errors.rb +21 -0
  117. data/lib/milk_tea/core/module_loader.rb +479 -0
  118. data/lib/milk_tea/core/module_path_resolver.rb +153 -0
  119. data/lib/milk_tea/core/module_roots.rb +88 -0
  120. data/lib/milk_tea/core/parser/attributes.rb +71 -0
  121. data/lib/milk_tea/core/parser/blocks.rb +119 -0
  122. data/lib/milk_tea/core/parser/declarations.rb +749 -0
  123. data/lib/milk_tea/core/parser/expressions.rb +624 -0
  124. data/lib/milk_tea/core/parser/recovery.rb +131 -0
  125. data/lib/milk_tea/core/parser/statements.rb +756 -0
  126. data/lib/milk_tea/core/parser/types.rb +271 -0
  127. data/lib/milk_tea/core/parser.rb +400 -0
  128. data/lib/milk_tea/core/prelude_installer.rb +29 -0
  129. data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +917 -0
  130. data/lib/milk_tea/core/pretty_printer/base_formatter.rb +87 -0
  131. data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +300 -0
  132. data/lib/milk_tea/core/pretty_printer.rb +17 -0
  133. data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +314 -0
  134. data/lib/milk_tea/core/semantic_analyzer/attributes.rb +184 -0
  135. data/lib/milk_tea/core/semantic_analyzer/calls.rb +992 -0
  136. data/lib/milk_tea/core/semantic_analyzer/expressions.rb +1735 -0
  137. data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +355 -0
  138. data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +155 -0
  139. data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +354 -0
  140. data/lib/milk_tea/core/semantic_analyzer/generics.rb +383 -0
  141. data/lib/milk_tea/core/semantic_analyzer/interface_conformance.rb +78 -0
  142. data/lib/milk_tea/core/semantic_analyzer/module_context.rb +35 -0
  143. data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +1438 -0
  144. data/lib/milk_tea/core/semantic_analyzer/nullability.rb +421 -0
  145. data/lib/milk_tea/core/semantic_analyzer/statements.rb +1308 -0
  146. data/lib/milk_tea/core/semantic_analyzer/top_level.rb +588 -0
  147. data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +307 -0
  148. data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +851 -0
  149. data/lib/milk_tea/core/semantic_analyzer.rb +327 -0
  150. data/lib/milk_tea/core/token.rb +26 -0
  151. data/lib/milk_tea/core/token_stream.rb +30 -0
  152. data/lib/milk_tea/core/types/layout.rb +243 -0
  153. data/lib/milk_tea/core/types/predicates.rb +609 -0
  154. data/lib/milk_tea/core/types/registry.rb +83 -0
  155. data/lib/milk_tea/core/types/types.rb +1696 -0
  156. data/lib/milk_tea/core/types/visitor.rb +442 -0
  157. data/lib/milk_tea/core.rb +25 -0
  158. data/lib/milk_tea/dap/backends/lldb_dap.rb +158 -0
  159. data/lib/milk_tea/dap/protocol.rb +58 -0
  160. data/lib/milk_tea/dap/server/breakpoints.rb +66 -0
  161. data/lib/milk_tea/dap/server/debug_map.rb +291 -0
  162. data/lib/milk_tea/dap/server/handlers.rb +374 -0
  163. data/lib/milk_tea/dap/server/launch.rb +261 -0
  164. data/lib/milk_tea/dap/server/lldb_backend.rb +380 -0
  165. data/lib/milk_tea/dap/server/pause_diagnostics.rb +109 -0
  166. data/lib/milk_tea/dap/server/utilities.rb +160 -0
  167. data/lib/milk_tea/dap/server/wire.rb +55 -0
  168. data/lib/milk_tea/dap/server.rb +131 -0
  169. data/lib/milk_tea/dap/session.rb +152 -0
  170. data/lib/milk_tea/dap.rb +6 -0
  171. data/lib/milk_tea/lsp/dependency_resolution.rb +52 -0
  172. data/lib/milk_tea/lsp/diagnostics.rb +611 -0
  173. data/lib/milk_tea/lsp/protocol.rb +104 -0
  174. data/lib/milk_tea/lsp/server/call_hierarchy.rb +274 -0
  175. data/lib/milk_tea/lsp/server/code_actions.rb +446 -0
  176. data/lib/milk_tea/lsp/server/code_lens.rb +97 -0
  177. data/lib/milk_tea/lsp/server/completion.rb +1099 -0
  178. data/lib/milk_tea/lsp/server/configuration.rb +167 -0
  179. data/lib/milk_tea/lsp/server/debug_info.rb +45 -0
  180. data/lib/milk_tea/lsp/server/definition.rb +779 -0
  181. data/lib/milk_tea/lsp/server/diagnostics_scheduling.rb +239 -0
  182. data/lib/milk_tea/lsp/server/execute_command.rb +25 -0
  183. data/lib/milk_tea/lsp/server/folding_range.rb +153 -0
  184. data/lib/milk_tea/lsp/server/formatting.rb +575 -0
  185. data/lib/milk_tea/lsp/server/hover.rb +1465 -0
  186. data/lib/milk_tea/lsp/server/inlay_hints.rb +204 -0
  187. data/lib/milk_tea/lsp/server/lifecycle.rb +234 -0
  188. data/lib/milk_tea/lsp/server/linked_editing_range.rb +43 -0
  189. data/lib/milk_tea/lsp/server/on_type_formatting.rb +73 -0
  190. data/lib/milk_tea/lsp/server/progress.rb +47 -0
  191. data/lib/milk_tea/lsp/server/references.rb +433 -0
  192. data/lib/milk_tea/lsp/server/rename.rb +598 -0
  193. data/lib/milk_tea/lsp/server/selection_range.rb +130 -0
  194. data/lib/milk_tea/lsp/server/semantic_tokens.rb +1745 -0
  195. data/lib/milk_tea/lsp/server/signature_help.rb +200 -0
  196. data/lib/milk_tea/lsp/server/text_documents.rb +125 -0
  197. data/lib/milk_tea/lsp/server/type_hierarchy.rb +167 -0
  198. data/lib/milk_tea/lsp/server/utilities.rb +520 -0
  199. data/lib/milk_tea/lsp/server.rb +415 -0
  200. data/lib/milk_tea/lsp/workspace/analysis.rb +209 -0
  201. data/lib/milk_tea/lsp/workspace/caches.rb +260 -0
  202. data/lib/milk_tea/lsp/workspace/collection.rb +98 -0
  203. data/lib/milk_tea/lsp/workspace/definition_index.rb +184 -0
  204. data/lib/milk_tea/lsp/workspace/dependency_graph.rb +282 -0
  205. data/lib/milk_tea/lsp/workspace/store.rb +154 -0
  206. data/lib/milk_tea/lsp/workspace/utilities.rb +490 -0
  207. data/lib/milk_tea/lsp/workspace.rb +127 -0
  208. data/lib/milk_tea/lsp.rb +13 -0
  209. data/lib/milk_tea/packages/atomic_write.rb +63 -0
  210. data/lib/milk_tea/packages/dependency_solver.rb +194 -0
  211. data/lib/milk_tea/packages/graph.rb +139 -0
  212. data/lib/milk_tea/packages/lock.rb +421 -0
  213. data/lib/milk_tea/packages/manager_cli.rb +485 -0
  214. data/lib/milk_tea/packages/manifest.rb +356 -0
  215. data/lib/milk_tea/packages/manifest_editor.rb +134 -0
  216. data/lib/milk_tea/packages/registry_metadata_provider.rb +34 -0
  217. data/lib/milk_tea/packages/registry_store.rb +420 -0
  218. data/lib/milk_tea/packages/services.rb +41 -0
  219. data/lib/milk_tea/packages/source_cache.rb +71 -0
  220. data/lib/milk_tea/packages/source_fetcher.rb +124 -0
  221. data/lib/milk_tea/packages/source_resolver.rb +389 -0
  222. data/lib/milk_tea/packages/version.rb +164 -0
  223. data/lib/milk_tea/packages.rb +16 -0
  224. data/lib/milk_tea/tooling/asset_pack.rb +141 -0
  225. data/lib/milk_tea/tooling/build.rb +1124 -0
  226. data/lib/milk_tea/tooling/build_cache.rb +240 -0
  227. data/lib/milk_tea/tooling/cli.rb +2688 -0
  228. data/lib/milk_tea/tooling/cst_formatter.rb +13 -0
  229. data/lib/milk_tea/tooling/debug_info_formatter.rb +456 -0
  230. data/lib/milk_tea/tooling/debug_map.rb +248 -0
  231. data/lib/milk_tea/tooling/docs_app.rb +369 -0
  232. data/lib/milk_tea/tooling/error_formatter.rb +86 -0
  233. data/lib/milk_tea/tooling/formatter.rb +787 -0
  234. data/lib/milk_tea/tooling/linter/doc_tags.rb +212 -0
  235. data/lib/milk_tea/tooling/linter/fix_engine.rb +237 -0
  236. data/lib/milk_tea/tooling/linter/flow_rules.rb +380 -0
  237. data/lib/milk_tea/tooling/linter/imports_platform.rb +841 -0
  238. data/lib/milk_tea/tooling/linter/release_rules.rb +744 -0
  239. data/lib/milk_tea/tooling/linter/reserved_names.rb +199 -0
  240. data/lib/milk_tea/tooling/linter/rules.rb +593 -0
  241. data/lib/milk_tea/tooling/linter/source_helpers.rb +407 -0
  242. data/lib/milk_tea/tooling/linter/trailing_comma.rb +139 -0
  243. data/lib/milk_tea/tooling/linter/visitors.rb +1286 -0
  244. data/lib/milk_tea/tooling/linter.rb +798 -0
  245. data/lib/milk_tea/tooling/project_scaffold.rb +82 -0
  246. data/lib/milk_tea/tooling/public/css/docs.css +166 -0
  247. data/lib/milk_tea/tooling/public/js/docs.js +94 -0
  248. data/lib/milk_tea/tooling/run.rb +408 -0
  249. data/lib/milk_tea/tooling/templates/wasm_shell.html +48 -0
  250. data/lib/milk_tea/tooling/toolchain_cli.rb +157 -0
  251. data/lib/milk_tea/tooling/views/404.erb +7 -0
  252. data/lib/milk_tea/tooling/views/index.erb +87 -0
  253. data/lib/milk_tea/tooling/views/layout.erb +69 -0
  254. data/lib/milk_tea/tooling/views/module.erb +97 -0
  255. data/lib/milk_tea/tooling/views/stdlib.erb +21 -0
  256. data/lib/milk_tea/tooling.rb +20 -0
  257. data/lib/milk_tea.rb +8 -0
  258. metadata +426 -0
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ module DAP
5
+ class Server
6
+ module ServerBreakpoints
7
+ private
8
+
9
+ def sync_breakpoints_to_backend
10
+ return if @breakpoints_synced_to_backend
11
+
12
+ @session.each_breakpoint_source do |source_path, breakpoints|
13
+ response = backend_request("setBreakpoints", {
14
+ "source" => { "path" => source_path },
15
+ "breakpoints" => breakpoints.map { |bp| filter_breakpoint_for_backend(bp) }
16
+ })
17
+ next unless response["success"]
18
+
19
+ backend_bps = response.dig("body", "breakpoints") || []
20
+ breakpoints.each_with_index do |local_bp, i|
21
+ backend_bp = backend_bps[i]
22
+ next unless backend_bp
23
+
24
+ local_line = local_bp[:line] || local_bp["line"]
25
+ local_verified = local_bp[:verified]
26
+ backend_line = backend_bp["line"] || backend_bp[:line]
27
+ backend_verified = backend_bp["verified"] || backend_bp[:verified]
28
+ next if local_line == backend_line && local_verified == backend_verified
29
+
30
+ write_event("breakpoint", {
31
+ reason: "changed",
32
+ breakpoint: {
33
+ id: local_bp[:id] || local_bp["id"],
34
+ verified: backend_verified,
35
+ line: backend_line,
36
+ source: { path: source_path }
37
+ }
38
+ })
39
+ end
40
+ end
41
+ @breakpoints_synced_to_backend = true
42
+ end
43
+
44
+ def sync_function_breakpoints_to_backend
45
+ return if @function_breakpoints_synced_to_backend
46
+ return if @session.function_breakpoints.empty?
47
+
48
+ backend_request("setFunctionBreakpoints", {
49
+ "breakpoints" => @session.function_breakpoints.map { |bp| filter_breakpoint_for_backend(bp) }
50
+ })
51
+ @function_breakpoints_synced_to_backend = true
52
+ end
53
+
54
+ def sync_exception_breakpoints_to_backend
55
+ return if @exception_breakpoints_synced_to_backend
56
+
57
+ exception_breakpoints = @session.exception_breakpoints
58
+ return if exception_breakpoints.nil?
59
+
60
+ backend_request("setExceptionBreakpoints", exception_breakpoints)
61
+ @exception_breakpoints_synced_to_backend = true
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,291 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MilkTea
4
+ module DAP
5
+ class Server
6
+ module ServerDebugMap
7
+ private
8
+
9
+ def load_debug_map(runnable_path)
10
+ @debug_map = runnable_path ? DebugMap.load_for_binary(runnable_path) : nil
11
+ @frame_debug_functions = {}
12
+ @variables_reference_debug_functions = {}
13
+ end
14
+
15
+ def maybe_load_debug_map_from_backend_modules
16
+ return if @debug_map
17
+ return unless capability_enabled?("supportsModulesRequest")
18
+
19
+ response = backend_request("modules", {})
20
+ return unless response["success"]
21
+
22
+ modules = response.dig("body", "modules")
23
+ return unless modules.is_a?(Array)
24
+
25
+ modules.each do |mod|
26
+ candidate_path = dap_value(mod, "path") || dap_value(mod, "symbolFilePath")
27
+ next if candidate_path.to_s.empty?
28
+
29
+ candidate_path = File.expand_path(candidate_path)
30
+ debug_map = DebugMap.load_for_binary(candidate_path)
31
+ next unless debug_map
32
+
33
+ @debug_map = debug_map
34
+ @frame_debug_functions = {}
35
+ @variables_reference_debug_functions = {}
36
+ return
37
+ end
38
+ end
39
+
40
+ def clear_debug_context
41
+ @debug_map = nil
42
+ @frame_debug_functions = {}
43
+ @variables_reference_debug_functions = {}
44
+ @backend_stopped_thread_id = nil
45
+ end
46
+
47
+ def rewrite_stack_trace_response(backend_response)
48
+ return unless @debug_map
49
+ return unless backend_response["success"]
50
+
51
+ body = backend_response["body"]
52
+ stack_frames = dap_value(body, "stackFrames")
53
+ return unless stack_frames.is_a?(Array)
54
+
55
+ @frame_debug_functions.clear
56
+ stack_frames.each do |frame|
57
+ function = @debug_map.function_for_c_name(dap_value(frame, "name"))
58
+ next unless function
59
+
60
+ dap_set(frame, "name", function.name)
61
+ frame_id = normalize_reference_key(dap_value(frame, "id"))
62
+ @frame_debug_functions[frame_id] = function if frame_id
63
+ end
64
+ end
65
+
66
+ def rewrite_scopes_response(backend_response, frame_id)
67
+ return unless backend_response["success"]
68
+
69
+ normalized_frame_id = normalize_reference_key(frame_id)
70
+ function = @frame_debug_functions[normalized_frame_id]
71
+
72
+ body = backend_response["body"]
73
+ scopes = dap_value(body, "scopes")
74
+ return unless scopes.is_a?(Array)
75
+
76
+ scopes.each do |scope|
77
+ reference = normalize_reference_key(dap_value(scope, "variablesReference"))
78
+ next unless reference
79
+
80
+ scope_name = dap_value(scope, "name").to_s
81
+ @variables_reference_debug_functions[reference] = {
82
+ frame_id: normalized_frame_id,
83
+ function: scope_name == "Locals" ? function : nil,
84
+ }
85
+ end
86
+ end
87
+
88
+ def rewrite_variables_response(backend_response, variables_reference)
89
+ return unless @debug_map
90
+ return unless backend_response["success"]
91
+
92
+ function = debug_function_for_variables_reference(variables_reference)
93
+ return unless function
94
+
95
+ body = backend_response["body"]
96
+ variables = dap_value(body, "variables")
97
+ return unless variables.is_a?(Array)
98
+
99
+ rewritten = variables.each_with_object([]) do |variable, kept|
100
+ raw_name = dap_value(variable, "name").to_s
101
+ entry = @debug_map.variable_for(function.linkage_name, raw_name)
102
+
103
+ if entry
104
+ dap_set(variable, "name", entry.name)
105
+ kept << variable
106
+ next
107
+ end
108
+
109
+ next if raw_name.start_with?("__mt_")
110
+
111
+ kept << variable
112
+ end
113
+
114
+ dap_set(body, "variables", rewritten)
115
+ end
116
+
117
+ def rewrite_evaluate_arguments(arguments)
118
+ rewritten = arguments.dup
119
+ rewritten["expression"] = rewrite_expression_for_frame(arguments["expression"], arguments["frameId"])
120
+ rewritten
121
+ end
122
+
123
+ def rewrite_set_expression_arguments(arguments)
124
+ rewritten = arguments.dup
125
+ rewritten["expression"] = rewrite_expression_for_frame(arguments["expression"], arguments["frameId"])
126
+ rewritten["value"] = rewrite_expression_for_frame(arguments["value"], arguments["frameId"])
127
+ rewritten
128
+ end
129
+
130
+ def rewrite_set_variable_arguments(arguments)
131
+ rewritten = arguments.dup
132
+ function = debug_function_for_variables_reference(arguments["variablesReference"])
133
+ return rewritten unless function
134
+
135
+ if (entry = @debug_map.source_variable_for(function.linkage_name, arguments["name"]))
136
+ rewritten["name"] = entry.linkage_name
137
+ end
138
+ rewritten["value"] = rewrite_expression_for_function(arguments["value"], function)
139
+ rewritten
140
+ end
141
+
142
+ def rewrite_data_breakpoint_info_arguments(arguments)
143
+ rewritten = arguments.dup
144
+
145
+ if arguments.key?("variablesReference")
146
+ function = debug_function_for_variables_reference(arguments["variablesReference"])
147
+ return rewritten unless function
148
+
149
+ if (entry = @debug_map.source_variable_for(function.linkage_name, arguments["name"]))
150
+ rewritten["name"] = entry.linkage_name
151
+ end
152
+ return rewritten
153
+ end
154
+
155
+ rewritten["name"] = rewrite_expression_for_frame(arguments["name"], arguments["frameId"])
156
+ rewritten
157
+ end
158
+
159
+ def request_set_variable(arguments)
160
+ return backend_request("setVariable", arguments) if backend_supports_set_variable?
161
+
162
+ unless backend_supports_set_expression?
163
+ return {
164
+ "success" => false,
165
+ "message" => "setVariable is not supported by the lldb-dap backend"
166
+ }
167
+ end
168
+
169
+ context = variables_reference_context(arguments["variablesReference"])
170
+ frame_id = context && context[:frame_id]
171
+ unless frame_id
172
+ return {
173
+ "success" => false,
174
+ "message" => "setVariable requires a scope frame context"
175
+ }
176
+ end
177
+
178
+ set_expression_arguments = {
179
+ "expression" => arguments["name"],
180
+ "value" => arguments["value"],
181
+ "frameId" => frame_id,
182
+ }
183
+ set_expression_arguments["format"] = arguments["format"] if arguments.key?("format")
184
+
185
+ backend_request("setExpression", set_expression_arguments)
186
+ end
187
+
188
+ def rewrite_expression_for_frame(expression, frame_id)
189
+ rewrite_expression_for_function(expression, debug_function_for_frame(frame_id))
190
+ end
191
+
192
+ def rewrite_expression_for_function(expression, function)
193
+ return expression unless @debug_map
194
+ return expression unless function
195
+ return expression unless expression.is_a?(String)
196
+ return expression if expression.empty?
197
+
198
+ rewritten = +""
199
+ index = 0
200
+ while index < expression.length
201
+ char = expression[index]
202
+ if char == '"' || char == "'"
203
+ index = copy_quoted_segment(expression, index, rewritten)
204
+ next
205
+ end
206
+
207
+ if identifier_start_char?(char)
208
+ start = index
209
+ index += 1
210
+ index += 1 while index < expression.length && identifier_continue_char?(expression[index])
211
+ identifier = expression[start...index]
212
+ if accessor_identifier?(expression, start)
213
+ rewritten << identifier
214
+ next
215
+ end
216
+
217
+ entry = @debug_map.source_variable_for(function.linkage_name, identifier)
218
+ rewritten << (entry ? entry.linkage_name : identifier)
219
+ next
220
+ end
221
+
222
+ rewritten << char
223
+ index += 1
224
+ end
225
+
226
+ rewritten
227
+ end
228
+
229
+ def debug_function_for_frame(frame_id)
230
+ @frame_debug_functions[normalize_reference_key(frame_id)]
231
+ end
232
+
233
+ def debug_function_for_variables_reference(variables_reference)
234
+ context = variables_reference_context(variables_reference)
235
+ context && context[:function]
236
+ end
237
+
238
+ def variables_reference_context(variables_reference)
239
+ @variables_reference_debug_functions[normalize_reference_key(variables_reference)]
240
+ end
241
+
242
+ def copy_quoted_segment(expression, index, output)
243
+ quote = expression[index]
244
+ output << quote
245
+ index += 1
246
+
247
+ while index < expression.length
248
+ char = expression[index]
249
+ output << char
250
+ index += 1
251
+
252
+ if char == "\\" && index < expression.length
253
+ output << expression[index]
254
+ index += 1
255
+ next
256
+ end
257
+
258
+ break if char == quote
259
+ end
260
+
261
+ index
262
+ end
263
+
264
+ def accessor_identifier?(expression, index)
265
+ previous_index = index - 1
266
+ previous_index -= 1 while previous_index >= 0 && whitespace_char?(expression[previous_index])
267
+ return false if previous_index < 0
268
+ return true if expression[previous_index] == "."
269
+
270
+ return false unless expression[previous_index] == ">"
271
+
272
+ previous_index -= 1
273
+ previous_index -= 1 while previous_index >= 0 && whitespace_char?(expression[previous_index])
274
+ previous_index >= 0 && expression[previous_index] == "-"
275
+ end
276
+
277
+ def identifier_start_char?(char)
278
+ char.match?(/[A-Za-z_]/)
279
+ end
280
+
281
+ def identifier_continue_char?(char)
282
+ char.match?(/[A-Za-z0-9_]/)
283
+ end
284
+
285
+ def whitespace_char?(char)
286
+ char.match?(/\s/)
287
+ end
288
+ end
289
+ end
290
+ end
291
+ end