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.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/AUTHORS +3 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +82 -0
- data/LICENSE +21 -0
- data/README.md +1208 -0
- data/Rakefile +332 -0
- data/bin/mtc +8 -0
- data/bin/profile-mtc-checks +133 -0
- data/bin/tracy-profiler +0 -0
- data/docs/build-guide.md +536 -0
- data/docs/index.html +2778 -0
- data/docs/language-design.md +1519 -0
- data/docs/language-manual.md +1534 -0
- data/lib/milk_tea/base.rb +49 -0
- data/lib/milk_tea/bindings/bindgen/ast_parser.rb +398 -0
- data/lib/milk_tea/bindings/bindgen/declaration.rb +319 -0
- data/lib/milk_tea/bindings/bindgen/emitter.rb +387 -0
- data/lib/milk_tea/bindings/bindgen/overrides.rb +134 -0
- data/lib/milk_tea/bindings/bindgen/type_mapper.rb +622 -0
- data/lib/milk_tea/bindings/bindgen.rb +207 -0
- data/lib/milk_tea/bindings/cli.rb +121 -0
- data/lib/milk_tea/bindings/imported_bindings/defaults.rb +210 -0
- data/lib/milk_tea/bindings/imported_bindings/generator.rb +1114 -0
- data/lib/milk_tea/bindings/imported_bindings/method_source.rb +190 -0
- data/lib/milk_tea/bindings/imported_bindings/naming.rb +286 -0
- data/lib/milk_tea/bindings/imported_bindings.rb +215 -0
- data/lib/milk_tea/bindings/opengl_registry.rb +547 -0
- data/lib/milk_tea/bindings/raw_bindings/defaults.rb +1338 -0
- data/lib/milk_tea/bindings/raw_bindings.rb +269 -0
- data/lib/milk_tea/bindings/steamworks.rb +629 -0
- data/lib/milk_tea/bindings/upstream_sources.rb +352 -0
- data/lib/milk_tea/bindings/vendored_box2d.rb +79 -0
- data/lib/milk_tea/bindings/vendored_c_library.rb +322 -0
- data/lib/milk_tea/bindings/vendored_cjson.rb +52 -0
- data/lib/milk_tea/bindings/vendored_flecs.rb +78 -0
- data/lib/milk_tea/bindings/vendored_glfw.rb +77 -0
- data/lib/milk_tea/bindings/vendored_libuv.rb +75 -0
- data/lib/milk_tea/bindings/vendored_pcre2.rb +84 -0
- data/lib/milk_tea/bindings/vendored_raylib.rb +131 -0
- data/lib/milk_tea/bindings/vendored_sdl3.rb +78 -0
- data/lib/milk_tea/bindings/vendored_steamworks.rb +71 -0
- data/lib/milk_tea/bindings/vendored_tool.rb +71 -0
- data/lib/milk_tea/bindings/vendored_tools.rb +23 -0
- data/lib/milk_tea/bindings/vendored_tracy.rb +37 -0
- data/lib/milk_tea/bindings.rb +23 -0
- data/lib/milk_tea/core/ast.rb +311 -0
- data/lib/milk_tea/core/async_runtime_installer.rb +28 -0
- data/lib/milk_tea/core/binding_types.rb +18 -0
- data/lib/milk_tea/core/bindings/attribute_binding.rb +58 -0
- data/lib/milk_tea/core/bindings/function_binding.rb +5 -0
- data/lib/milk_tea/core/bindings/module_binding.rb +58 -0
- data/lib/milk_tea/core/bindings/value_binding.rb +21 -0
- data/lib/milk_tea/core/c_backend/aggregate_utils.rb +103 -0
- data/lib/milk_tea/core/c_backend/control_flow_emission.rb +412 -0
- data/lib/milk_tea/core/c_backend/expressions.rb +468 -0
- data/lib/milk_tea/core/c_backend/feature_detection.rb +483 -0
- data/lib/milk_tea/core/c_backend/reachability.rb +398 -0
- data/lib/milk_tea/core/c_backend/reinterpret.rb +226 -0
- data/lib/milk_tea/core/c_backend/runtime_helpers.rb +1080 -0
- data/lib/milk_tea/core/c_backend/statements.rb +563 -0
- data/lib/milk_tea/core/c_backend/type_collectors.rb +1545 -0
- data/lib/milk_tea/core/c_backend/type_declaration.rb +223 -0
- data/lib/milk_tea/core/c_backend/type_system.rb +345 -0
- data/lib/milk_tea/core/c_backend.rb +287 -0
- data/lib/milk_tea/core/compatibility_helpers.rb +79 -0
- data/lib/milk_tea/core/compile_time/const_eval.rb +187 -0
- data/lib/milk_tea/core/compile_time.rb +329 -0
- data/lib/milk_tea/core/control_flow/builder.rb +582 -0
- data/lib/milk_tea/core/control_flow/constant_propagation.rb +143 -0
- data/lib/milk_tea/core/control_flow/dataflow.rb +74 -0
- data/lib/milk_tea/core/control_flow/definite_assignment.rb +79 -0
- data/lib/milk_tea/core/control_flow/graph.rb +90 -0
- data/lib/milk_tea/core/control_flow/liveness.rb +24 -0
- data/lib/milk_tea/core/control_flow/nullability_flow.rb +43 -0
- data/lib/milk_tea/core/control_flow/reachability.rb +22 -0
- data/lib/milk_tea/core/control_flow/termination.rb +31 -0
- data/lib/milk_tea/core/control_flow.rb +34 -0
- data/lib/milk_tea/core/cst.rb +48 -0
- data/lib/milk_tea/core/cst_builder.rb +19 -0
- data/lib/milk_tea/core/ir.rb +85 -0
- data/lib/milk_tea/core/keywords.rb +97 -0
- data/lib/milk_tea/core/lexer/character_classes.rb +60 -0
- data/lib/milk_tea/core/lexer/format_strings.rb +225 -0
- data/lib/milk_tea/core/lexer/heredocs.rb +199 -0
- data/lib/milk_tea/core/lexer/indentation.rb +62 -0
- data/lib/milk_tea/core/lexer/numbers.rb +96 -0
- data/lib/milk_tea/core/lexer/recovery.rb +32 -0
- data/lib/milk_tea/core/lexer/strings.rb +167 -0
- data/lib/milk_tea/core/lexer/symbols.rb +71 -0
- data/lib/milk_tea/core/lexer/trivia.rb +53 -0
- data/lib/milk_tea/core/lexer.rb +430 -0
- data/lib/milk_tea/core/lowering/artifacts.rb +26 -0
- data/lib/milk_tea/core/lowering/async/analysis.rb +245 -0
- data/lib/milk_tea/core/lowering/async/lowering.rb +1399 -0
- data/lib/milk_tea/core/lowering/async/normalization.rb +459 -0
- data/lib/milk_tea/core/lowering/async.rb +714 -0
- data/lib/milk_tea/core/lowering/block.rb +1052 -0
- data/lib/milk_tea/core/lowering/calls.rb +1565 -0
- data/lib/milk_tea/core/lowering/declarations.rb +214 -0
- data/lib/milk_tea/core/lowering/dyn.rb +206 -0
- data/lib/milk_tea/core/lowering/events.rb +1054 -0
- data/lib/milk_tea/core/lowering/expressions.rb +1645 -0
- data/lib/milk_tea/core/lowering/foreign_cstr.rb +206 -0
- data/lib/milk_tea/core/lowering/functions.rb +242 -0
- data/lib/milk_tea/core/lowering/loops.rb +1087 -0
- data/lib/milk_tea/core/lowering/lowering_context.rb +80 -0
- data/lib/milk_tea/core/lowering/proc.rb +419 -0
- data/lib/milk_tea/core/lowering/resolve.rb +2516 -0
- data/lib/milk_tea/core/lowering/scans.rb +220 -0
- data/lib/milk_tea/core/lowering/str_buffer.rb +125 -0
- data/lib/milk_tea/core/lowering/utils.rb +1453 -0
- data/lib/milk_tea/core/lowering.rb +378 -0
- data/lib/milk_tea/core/module_binder.rb +181 -0
- data/lib/milk_tea/core/module_loader/errors.rb +21 -0
- data/lib/milk_tea/core/module_loader.rb +479 -0
- data/lib/milk_tea/core/module_path_resolver.rb +153 -0
- data/lib/milk_tea/core/module_roots.rb +88 -0
- data/lib/milk_tea/core/parser/attributes.rb +71 -0
- data/lib/milk_tea/core/parser/blocks.rb +119 -0
- data/lib/milk_tea/core/parser/declarations.rb +749 -0
- data/lib/milk_tea/core/parser/expressions.rb +624 -0
- data/lib/milk_tea/core/parser/recovery.rb +131 -0
- data/lib/milk_tea/core/parser/statements.rb +756 -0
- data/lib/milk_tea/core/parser/types.rb +271 -0
- data/lib/milk_tea/core/parser.rb +400 -0
- data/lib/milk_tea/core/prelude_installer.rb +29 -0
- data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +917 -0
- data/lib/milk_tea/core/pretty_printer/base_formatter.rb +87 -0
- data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +300 -0
- data/lib/milk_tea/core/pretty_printer.rb +17 -0
- data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +314 -0
- data/lib/milk_tea/core/semantic_analyzer/attributes.rb +184 -0
- data/lib/milk_tea/core/semantic_analyzer/calls.rb +992 -0
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +1735 -0
- data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +355 -0
- data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +155 -0
- data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +354 -0
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +383 -0
- data/lib/milk_tea/core/semantic_analyzer/interface_conformance.rb +78 -0
- data/lib/milk_tea/core/semantic_analyzer/module_context.rb +35 -0
- data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +1438 -0
- data/lib/milk_tea/core/semantic_analyzer/nullability.rb +421 -0
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +1308 -0
- data/lib/milk_tea/core/semantic_analyzer/top_level.rb +588 -0
- data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +307 -0
- data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +851 -0
- data/lib/milk_tea/core/semantic_analyzer.rb +327 -0
- data/lib/milk_tea/core/token.rb +26 -0
- data/lib/milk_tea/core/token_stream.rb +30 -0
- data/lib/milk_tea/core/types/layout.rb +243 -0
- data/lib/milk_tea/core/types/predicates.rb +609 -0
- data/lib/milk_tea/core/types/registry.rb +83 -0
- data/lib/milk_tea/core/types/types.rb +1696 -0
- data/lib/milk_tea/core/types/visitor.rb +442 -0
- data/lib/milk_tea/core.rb +25 -0
- data/lib/milk_tea/dap/backends/lldb_dap.rb +158 -0
- data/lib/milk_tea/dap/protocol.rb +58 -0
- data/lib/milk_tea/dap/server/breakpoints.rb +66 -0
- data/lib/milk_tea/dap/server/debug_map.rb +291 -0
- data/lib/milk_tea/dap/server/handlers.rb +374 -0
- data/lib/milk_tea/dap/server/launch.rb +261 -0
- data/lib/milk_tea/dap/server/lldb_backend.rb +380 -0
- data/lib/milk_tea/dap/server/pause_diagnostics.rb +109 -0
- data/lib/milk_tea/dap/server/utilities.rb +160 -0
- data/lib/milk_tea/dap/server/wire.rb +55 -0
- data/lib/milk_tea/dap/server.rb +131 -0
- data/lib/milk_tea/dap/session.rb +152 -0
- data/lib/milk_tea/dap.rb +6 -0
- data/lib/milk_tea/lsp/dependency_resolution.rb +52 -0
- data/lib/milk_tea/lsp/diagnostics.rb +611 -0
- data/lib/milk_tea/lsp/protocol.rb +104 -0
- data/lib/milk_tea/lsp/server/call_hierarchy.rb +274 -0
- data/lib/milk_tea/lsp/server/code_actions.rb +446 -0
- data/lib/milk_tea/lsp/server/code_lens.rb +97 -0
- data/lib/milk_tea/lsp/server/completion.rb +1099 -0
- data/lib/milk_tea/lsp/server/configuration.rb +167 -0
- data/lib/milk_tea/lsp/server/debug_info.rb +45 -0
- data/lib/milk_tea/lsp/server/definition.rb +779 -0
- data/lib/milk_tea/lsp/server/diagnostics_scheduling.rb +239 -0
- data/lib/milk_tea/lsp/server/execute_command.rb +25 -0
- data/lib/milk_tea/lsp/server/folding_range.rb +153 -0
- data/lib/milk_tea/lsp/server/formatting.rb +575 -0
- data/lib/milk_tea/lsp/server/hover.rb +1465 -0
- data/lib/milk_tea/lsp/server/inlay_hints.rb +204 -0
- data/lib/milk_tea/lsp/server/lifecycle.rb +234 -0
- data/lib/milk_tea/lsp/server/linked_editing_range.rb +43 -0
- data/lib/milk_tea/lsp/server/on_type_formatting.rb +73 -0
- data/lib/milk_tea/lsp/server/progress.rb +47 -0
- data/lib/milk_tea/lsp/server/references.rb +433 -0
- data/lib/milk_tea/lsp/server/rename.rb +598 -0
- data/lib/milk_tea/lsp/server/selection_range.rb +130 -0
- data/lib/milk_tea/lsp/server/semantic_tokens.rb +1745 -0
- data/lib/milk_tea/lsp/server/signature_help.rb +200 -0
- data/lib/milk_tea/lsp/server/text_documents.rb +125 -0
- data/lib/milk_tea/lsp/server/type_hierarchy.rb +167 -0
- data/lib/milk_tea/lsp/server/utilities.rb +520 -0
- data/lib/milk_tea/lsp/server.rb +415 -0
- data/lib/milk_tea/lsp/workspace/analysis.rb +209 -0
- data/lib/milk_tea/lsp/workspace/caches.rb +260 -0
- data/lib/milk_tea/lsp/workspace/collection.rb +98 -0
- data/lib/milk_tea/lsp/workspace/definition_index.rb +184 -0
- data/lib/milk_tea/lsp/workspace/dependency_graph.rb +282 -0
- data/lib/milk_tea/lsp/workspace/store.rb +154 -0
- data/lib/milk_tea/lsp/workspace/utilities.rb +490 -0
- data/lib/milk_tea/lsp/workspace.rb +127 -0
- data/lib/milk_tea/lsp.rb +13 -0
- data/lib/milk_tea/packages/atomic_write.rb +63 -0
- data/lib/milk_tea/packages/dependency_solver.rb +194 -0
- data/lib/milk_tea/packages/graph.rb +139 -0
- data/lib/milk_tea/packages/lock.rb +421 -0
- data/lib/milk_tea/packages/manager_cli.rb +485 -0
- data/lib/milk_tea/packages/manifest.rb +356 -0
- data/lib/milk_tea/packages/manifest_editor.rb +134 -0
- data/lib/milk_tea/packages/registry_metadata_provider.rb +34 -0
- data/lib/milk_tea/packages/registry_store.rb +420 -0
- data/lib/milk_tea/packages/services.rb +41 -0
- data/lib/milk_tea/packages/source_cache.rb +71 -0
- data/lib/milk_tea/packages/source_fetcher.rb +124 -0
- data/lib/milk_tea/packages/source_resolver.rb +389 -0
- data/lib/milk_tea/packages/version.rb +164 -0
- data/lib/milk_tea/packages.rb +16 -0
- data/lib/milk_tea/tooling/asset_pack.rb +141 -0
- data/lib/milk_tea/tooling/build.rb +1124 -0
- data/lib/milk_tea/tooling/build_cache.rb +240 -0
- data/lib/milk_tea/tooling/cli.rb +2688 -0
- data/lib/milk_tea/tooling/cst_formatter.rb +13 -0
- data/lib/milk_tea/tooling/debug_info_formatter.rb +456 -0
- data/lib/milk_tea/tooling/debug_map.rb +248 -0
- data/lib/milk_tea/tooling/docs_app.rb +369 -0
- data/lib/milk_tea/tooling/error_formatter.rb +86 -0
- data/lib/milk_tea/tooling/formatter.rb +787 -0
- data/lib/milk_tea/tooling/linter/doc_tags.rb +212 -0
- data/lib/milk_tea/tooling/linter/fix_engine.rb +237 -0
- data/lib/milk_tea/tooling/linter/flow_rules.rb +380 -0
- data/lib/milk_tea/tooling/linter/imports_platform.rb +841 -0
- data/lib/milk_tea/tooling/linter/release_rules.rb +744 -0
- data/lib/milk_tea/tooling/linter/reserved_names.rb +199 -0
- data/lib/milk_tea/tooling/linter/rules.rb +593 -0
- data/lib/milk_tea/tooling/linter/source_helpers.rb +407 -0
- data/lib/milk_tea/tooling/linter/trailing_comma.rb +139 -0
- data/lib/milk_tea/tooling/linter/visitors.rb +1286 -0
- data/lib/milk_tea/tooling/linter.rb +798 -0
- data/lib/milk_tea/tooling/project_scaffold.rb +82 -0
- data/lib/milk_tea/tooling/public/css/docs.css +166 -0
- data/lib/milk_tea/tooling/public/js/docs.js +94 -0
- data/lib/milk_tea/tooling/run.rb +408 -0
- data/lib/milk_tea/tooling/templates/wasm_shell.html +48 -0
- data/lib/milk_tea/tooling/toolchain_cli.rb +157 -0
- data/lib/milk_tea/tooling/views/404.erb +7 -0
- data/lib/milk_tea/tooling/views/index.erb +87 -0
- data/lib/milk_tea/tooling/views/layout.erb +69 -0
- data/lib/milk_tea/tooling/views/module.erb +97 -0
- data/lib/milk_tea/tooling/views/stdlib.erb +21 -0
- data/lib/milk_tea/tooling.rb +20 -0
- data/lib/milk_tea.rb +8 -0
- metadata +426 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MilkTea
|
|
4
|
+
module DAP
|
|
5
|
+
class Server
|
|
6
|
+
module ServerHandlers
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def handle_initialize(message)
|
|
10
|
+
if @session.initialized?
|
|
11
|
+
write_error_response(message, "initialize can only be called once")
|
|
12
|
+
return
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
@session.initialize!
|
|
16
|
+
|
|
17
|
+
if default_backend_kind == "lldb-dap"
|
|
18
|
+
start_lldb_backend({})
|
|
19
|
+
backend_response = ensure_backend_initialized(message["arguments"] || {})
|
|
20
|
+
return write_backend_response(message, backend_response) unless backend_response["success"]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
write_response(message, effective_adapter_capabilities)
|
|
24
|
+
|
|
25
|
+
write_event("initialized")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def handle_set_breakpoints(message)
|
|
29
|
+
args = message["arguments"] || {}
|
|
30
|
+
source = args["source"] || {}
|
|
31
|
+
source_path = source["path"].to_s
|
|
32
|
+
requested = args["breakpoints"] || Array(args["lines"]).map { |line| { "line" => line } }
|
|
33
|
+
breakpoints = @session.set_breakpoints(source_path, requested)
|
|
34
|
+
|
|
35
|
+
if using_lldb_backend?
|
|
36
|
+
if backend_configuration_pending?
|
|
37
|
+
@breakpoints_synced_to_backend = false
|
|
38
|
+
write_response(message, { breakpoints: breakpoints })
|
|
39
|
+
return
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
backend_response = backend_request("setBreakpoints", {
|
|
43
|
+
"source" => source,
|
|
44
|
+
"breakpoints" => requested
|
|
45
|
+
})
|
|
46
|
+
@breakpoints_synced_to_backend = false if backend_response["success"]
|
|
47
|
+
return write_backend_response(message, backend_response)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Process backend: mark breakpoints unverified
|
|
51
|
+
if default_backend_kind == "process"
|
|
52
|
+
breakpoints.each do |bp|
|
|
53
|
+
bp["verified"] = false
|
|
54
|
+
bp["message"] = "Process backend runs without a debugger; set breakpoints via lldb-dap backend instead."
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
write_response(message, { breakpoints: breakpoints })
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def handle_set_function_breakpoints(message)
|
|
62
|
+
args = message["arguments"] || {}
|
|
63
|
+
requested = args["breakpoints"] || []
|
|
64
|
+
breakpoints = @session.set_function_breakpoints(requested)
|
|
65
|
+
|
|
66
|
+
if using_lldb_backend?
|
|
67
|
+
if backend_configuration_pending?
|
|
68
|
+
@function_breakpoints_synced_to_backend = false
|
|
69
|
+
write_response(message, { breakpoints: breakpoints })
|
|
70
|
+
return
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
backend_response = backend_request("setFunctionBreakpoints", {
|
|
74
|
+
"breakpoints" => requested
|
|
75
|
+
})
|
|
76
|
+
@function_breakpoints_synced_to_backend = false if backend_response["success"]
|
|
77
|
+
return write_backend_response(message, backend_response)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
write_response(message, { breakpoints: breakpoints })
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def handle_configuration_done(message)
|
|
84
|
+
@session.configuration_done!
|
|
85
|
+
|
|
86
|
+
if using_lldb_backend?
|
|
87
|
+
backend_response = ensure_backend_initialized({})
|
|
88
|
+
return write_backend_response(message, backend_response) unless backend_response["success"]
|
|
89
|
+
|
|
90
|
+
unless wait_for_backend_configuration_ready
|
|
91
|
+
write_error_response(message, "lldb-dap did not become ready for configuration")
|
|
92
|
+
return
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
sync_breakpoints_to_backend
|
|
96
|
+
sync_function_breakpoints_to_backend
|
|
97
|
+
sync_exception_breakpoints_to_backend
|
|
98
|
+
backend_response = backend_request("configurationDone", {})
|
|
99
|
+
return write_backend_response(message, backend_response) unless backend_response["success"]
|
|
100
|
+
|
|
101
|
+
if @backend_auto_continue_after_configuration
|
|
102
|
+
continue_response = backend_request("continue", backend_continue_arguments)
|
|
103
|
+
@backend_auto_continue_after_configuration = false
|
|
104
|
+
return write_error_response(message, backend_error_message(continue_response)) unless continue_response["success"]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
write_response(message, backend_response["body"] || {})
|
|
108
|
+
return
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
write_response(message, {})
|
|
112
|
+
maybe_start_or_stop_on_entry
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def handle_launch(message)
|
|
116
|
+
request_start(message)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def handle_attach(message)
|
|
120
|
+
args = message["arguments"] || {}
|
|
121
|
+
unless args["backend"].to_s == "lldb-dap"
|
|
122
|
+
write_error_response(message, "attach requires the lldb-dap backend")
|
|
123
|
+
return
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
request_start(message)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def handle_threads(message)
|
|
130
|
+
return write_backend_response(message, backend_request("threads", {})) if using_lldb_backend?
|
|
131
|
+
|
|
132
|
+
write_response(message, {
|
|
133
|
+
threads: [
|
|
134
|
+
{ id: @session.thread_id, name: "main" }
|
|
135
|
+
]
|
|
136
|
+
})
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def handle_stack_trace(message)
|
|
140
|
+
if using_lldb_backend?
|
|
141
|
+
maybe_load_debug_map_from_backend_modules
|
|
142
|
+
backend_response = backend_request("stackTrace", message["arguments"] || {})
|
|
143
|
+
rewrite_stack_trace_response(backend_response)
|
|
144
|
+
return write_backend_response(message, backend_response)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
source_path = @session.program_path || "(unknown)"
|
|
148
|
+
write_response(message, {
|
|
149
|
+
stackFrames: [
|
|
150
|
+
{
|
|
151
|
+
id: 1,
|
|
152
|
+
name: "main",
|
|
153
|
+
line: 1,
|
|
154
|
+
column: 1,
|
|
155
|
+
source: {
|
|
156
|
+
name: File.basename(source_path),
|
|
157
|
+
path: source_path
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
],
|
|
161
|
+
totalFrames: 1
|
|
162
|
+
})
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def handle_scopes(message)
|
|
166
|
+
if using_lldb_backend?
|
|
167
|
+
arguments = message["arguments"] || {}
|
|
168
|
+
backend_response = backend_request("scopes", arguments)
|
|
169
|
+
rewrite_scopes_response(backend_response, arguments["frameId"])
|
|
170
|
+
return write_backend_response(message, backend_response)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
write_response(message, {
|
|
174
|
+
scopes: [
|
|
175
|
+
{
|
|
176
|
+
name: "Locals",
|
|
177
|
+
variablesReference: 1,
|
|
178
|
+
expensive: false
|
|
179
|
+
}
|
|
180
|
+
]
|
|
181
|
+
})
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def handle_variables(message)
|
|
185
|
+
if using_lldb_backend?
|
|
186
|
+
arguments = message["arguments"] || {}
|
|
187
|
+
backend_response = backend_request("variables", arguments)
|
|
188
|
+
rewrite_variables_response(backend_response, arguments["variablesReference"])
|
|
189
|
+
return write_backend_response(message, backend_response)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
_args = message["arguments"] || {}
|
|
193
|
+
write_response(message, { variables: [] })
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def handle_continue(message)
|
|
197
|
+
return write_backend_response(message, backend_request("continue", message["arguments"] || {})) if using_lldb_backend?
|
|
198
|
+
|
|
199
|
+
start_runtime_if_needed
|
|
200
|
+
continue_runtime_if_paused
|
|
201
|
+
write_response(message, { allThreadsContinued: true })
|
|
202
|
+
write_event("continued", {
|
|
203
|
+
threadId: @session.thread_id,
|
|
204
|
+
allThreadsContinued: true
|
|
205
|
+
})
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def handle_next(message)
|
|
209
|
+
return write_backend_response(message, backend_request("next", message["arguments"] || {})) if using_lldb_backend?
|
|
210
|
+
|
|
211
|
+
write_error_response(message, "next is not supported by the process backend")
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def handle_step_in(message)
|
|
215
|
+
return write_backend_response(message, backend_request("stepIn", message["arguments"] || {})) if using_lldb_backend?
|
|
216
|
+
|
|
217
|
+
write_error_response(message, "stepIn is not supported by the process backend")
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def handle_step_out(message)
|
|
221
|
+
return write_backend_response(message, backend_request("stepOut", message["arguments"] || {})) if using_lldb_backend?
|
|
222
|
+
|
|
223
|
+
write_error_response(message, "stepOut is not supported by the process backend")
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def handle_pause(message)
|
|
227
|
+
if using_lldb_backend?
|
|
228
|
+
@backend_pause_requested = true
|
|
229
|
+
backend_response = backend_request("pause", message["arguments"] || {})
|
|
230
|
+
@backend_pause_requested = false unless backend_response["success"]
|
|
231
|
+
return write_backend_response(message, backend_response)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
unless pause_runtime_if_running
|
|
235
|
+
return write_error_response(message, "pause failed: process is not running")
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
write_response(message, {})
|
|
239
|
+
write_event("stopped", {
|
|
240
|
+
reason: "pause",
|
|
241
|
+
threadId: @session.thread_id,
|
|
242
|
+
allThreadsStopped: true
|
|
243
|
+
})
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def handle_terminate(message)
|
|
247
|
+
if using_lldb_backend?
|
|
248
|
+
backend_response = request_backend_terminate(message["arguments"] || {})
|
|
249
|
+
write_backend_response(message, backend_response)
|
|
250
|
+
return
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
terminate_runtime_if_running
|
|
254
|
+
write_response(message, {})
|
|
255
|
+
return if @session.runtime_started?
|
|
256
|
+
|
|
257
|
+
@session.terminate!
|
|
258
|
+
write_event("terminated")
|
|
259
|
+
write_event("exited", { exitCode: 0 })
|
|
260
|
+
cleanup_tmp_dirs
|
|
261
|
+
@session.request_exit!
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def handle_disconnect(message)
|
|
265
|
+
if using_lldb_backend?
|
|
266
|
+
join_background_threads
|
|
267
|
+
backend_response = backend_request("disconnect", message["arguments"] || {})
|
|
268
|
+
write_backend_response(message, backend_response)
|
|
269
|
+
stop_lldb_backend
|
|
270
|
+
cleanup_tmp_dirs
|
|
271
|
+
@session.request_exit!
|
|
272
|
+
return
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
write_response(message, {})
|
|
276
|
+
terminate_runtime_if_running
|
|
277
|
+
unless @session.runtime_started?
|
|
278
|
+
@session.terminate!
|
|
279
|
+
write_event("terminated")
|
|
280
|
+
write_event("exited", { exitCode: 0 })
|
|
281
|
+
end
|
|
282
|
+
cleanup_tmp_dirs
|
|
283
|
+
@session.request_exit!
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
def handle_set_exception_breakpoints(message)
|
|
287
|
+
arguments = message["arguments"] || {}
|
|
288
|
+
@session.set_exception_breakpoints(arguments)
|
|
289
|
+
|
|
290
|
+
if using_lldb_backend?
|
|
291
|
+
if backend_configuration_pending?
|
|
292
|
+
@exception_breakpoints_synced_to_backend = false
|
|
293
|
+
write_response(message, {})
|
|
294
|
+
return
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
backend_response = backend_request("setExceptionBreakpoints", arguments)
|
|
298
|
+
@exception_breakpoints_synced_to_backend = false if backend_response["success"]
|
|
299
|
+
return write_backend_response(message, backend_response)
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
write_response(message, {})
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
def handle_evaluate(message)
|
|
306
|
+
if using_lldb_backend?
|
|
307
|
+
arguments = rewrite_evaluate_arguments(message["arguments"] || {})
|
|
308
|
+
return write_backend_response(message, backend_request("evaluate", arguments))
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
write_error_response(message, "evaluate is not supported by the process backend")
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def handle_set_expression(message)
|
|
315
|
+
if using_lldb_backend?
|
|
316
|
+
arguments = rewrite_set_expression_arguments(message["arguments"] || {})
|
|
317
|
+
return write_backend_response(message, backend_request("setExpression", arguments))
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
write_error_response(message, "setExpression is not supported by the process backend")
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def handle_set_variable(message)
|
|
324
|
+
if using_lldb_backend?
|
|
325
|
+
arguments = rewrite_set_variable_arguments(message["arguments"] || {})
|
|
326
|
+
return write_backend_response(message, request_set_variable(arguments))
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
write_error_response(message, "setVariable is not supported by the process backend")
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
def handle_data_breakpoint_info(message)
|
|
333
|
+
if using_lldb_backend?
|
|
334
|
+
arguments = rewrite_data_breakpoint_info_arguments(message["arguments"] || {})
|
|
335
|
+
return write_backend_response(message, backend_request("dataBreakpointInfo", arguments))
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
write_error_response(message, "dataBreakpointInfo is not supported by the process backend")
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def handle_source(message)
|
|
342
|
+
return write_backend_response(message, backend_request("source", message["arguments"] || {})) if using_lldb_backend?
|
|
343
|
+
|
|
344
|
+
write_error_response(message, "source retrieval is not supported")
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def handle_loaded_sources(message)
|
|
348
|
+
return write_backend_response(message, backend_request("loadedSources", message["arguments"] || {})) if using_lldb_backend?
|
|
349
|
+
|
|
350
|
+
write_response(message, { sources: [] })
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def handle_restart(message)
|
|
354
|
+
return write_backend_response(message, backend_request("restart", message["arguments"] || {})) if using_lldb_backend?
|
|
355
|
+
|
|
356
|
+
write_error_response(message, "restart is not supported by the process backend")
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
def handle_cancel(message)
|
|
360
|
+
args = message["arguments"] || {}
|
|
361
|
+
request_id = args["requestId"] || args["progressId"]
|
|
362
|
+
|
|
363
|
+
if using_lldb_backend?
|
|
364
|
+
backend_response = backend_request("cancel", { "requestId" => request_id }.compact)
|
|
365
|
+
write_backend_response(message, backend_response)
|
|
366
|
+
else
|
|
367
|
+
join_background_threads(timeout: 0.1)
|
|
368
|
+
write_response(message, {})
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
end
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MilkTea
|
|
4
|
+
module DAP
|
|
5
|
+
class Server
|
|
6
|
+
module ServerLaunch
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def request_start(message)
|
|
10
|
+
if @session.launched?
|
|
11
|
+
write_error_response(message, "Program already launched")
|
|
12
|
+
return
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
args = message["arguments"] || {}
|
|
16
|
+
if message["command"] == "launch" && args["program"].to_s.empty?
|
|
17
|
+
write_error_response(message, "launch requires a non-empty 'program' argument")
|
|
18
|
+
return
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
resolved = resolve_debug_program(message["command"], args["program"])
|
|
22
|
+
unless resolved[:ok]
|
|
23
|
+
write_error_response(message, resolved[:error])
|
|
24
|
+
return
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
program_args = args["args"] || []
|
|
28
|
+
unless program_args.is_a?(Array)
|
|
29
|
+
write_error_response(message, "launch 'args' must be an array when provided")
|
|
30
|
+
return
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
no_debug = message["command"] == "launch" && args["noDebug"] == true
|
|
34
|
+
stop_on_entry = no_debug ? false : (args.key?("stopOnEntry") ? !!args["stopOnEntry"] : true)
|
|
35
|
+
backend_kind = if no_debug
|
|
36
|
+
"process"
|
|
37
|
+
else
|
|
38
|
+
resolved_backend_kind(args["backend"])
|
|
39
|
+
end
|
|
40
|
+
unless backend_kind
|
|
41
|
+
write_error_response(message, "unsupported backend: #{args['backend']}")
|
|
42
|
+
return
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
@session.request_start!(
|
|
46
|
+
program_path: args["program"].to_s.empty? ? nil : args["program"],
|
|
47
|
+
runnable_path: resolved[:runnable_path],
|
|
48
|
+
program_args:,
|
|
49
|
+
stop_on_entry:,
|
|
50
|
+
backend_kind:
|
|
51
|
+
)
|
|
52
|
+
@session.launch!
|
|
53
|
+
@backend_auto_continue_after_configuration = using_lldb_backend? && message["command"] == "launch" && !stop_on_entry
|
|
54
|
+
@backend_stopped_thread_id = nil if using_lldb_backend?
|
|
55
|
+
@last_forwarded_continued_signature = nil
|
|
56
|
+
load_debug_map(resolved[:runnable_path])
|
|
57
|
+
|
|
58
|
+
if using_lldb_backend?
|
|
59
|
+
start_lldb_backend(args)
|
|
60
|
+
reset_backend_configuration_ready
|
|
61
|
+
init_response = ensure_backend_initialized({})
|
|
62
|
+
return write_backend_response(message, init_response) unless init_response["success"]
|
|
63
|
+
|
|
64
|
+
# Merge backend capabilities with adapter capabilities and notify the client.
|
|
65
|
+
merged_caps = effective_adapter_capabilities
|
|
66
|
+
write_event("capabilities", merged_caps)
|
|
67
|
+
|
|
68
|
+
launch_arguments = backend_start_arguments(message["command"], args, resolved)
|
|
69
|
+
@breakpoints_synced_to_backend = false
|
|
70
|
+
@function_breakpoints_synced_to_backend = false
|
|
71
|
+
@exception_breakpoints_synced_to_backend = false
|
|
72
|
+
start_backend_start_request(message, launch_arguments)
|
|
73
|
+
return
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
write_response(message, {})
|
|
77
|
+
write_event("process", {
|
|
78
|
+
name: File.basename(@session.program_path.to_s),
|
|
79
|
+
startMethod: "launch",
|
|
80
|
+
isLocalProcess: true
|
|
81
|
+
})
|
|
82
|
+
maybe_start_or_stop_on_entry
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def maybe_start_or_stop_on_entry
|
|
86
|
+
return if using_lldb_backend?
|
|
87
|
+
|
|
88
|
+
return unless @session.launched?
|
|
89
|
+
return unless @session.configuration_done?
|
|
90
|
+
return if @session.runtime_started?
|
|
91
|
+
|
|
92
|
+
if @session.stop_on_entry?
|
|
93
|
+
return if @session.entry_stop_emitted?
|
|
94
|
+
|
|
95
|
+
write_stopped("entry")
|
|
96
|
+
@session.mark_entry_stop_emitted!
|
|
97
|
+
else
|
|
98
|
+
start_runtime_if_needed
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def write_stopped(reason)
|
|
103
|
+
write_event("stopped", {
|
|
104
|
+
reason: reason,
|
|
105
|
+
threadId: @session.thread_id,
|
|
106
|
+
allThreadsStopped: true
|
|
107
|
+
})
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def default_backend_kind
|
|
111
|
+
@preferred_backend_kind
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def resolved_backend_kind(requested_backend)
|
|
115
|
+
backend = requested_backend.to_s.strip
|
|
116
|
+
backend = default_backend_kind if backend.empty?
|
|
117
|
+
return backend if backend == "process" || backend == "lldb-dap"
|
|
118
|
+
|
|
119
|
+
nil
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def resolve_launch_program(program)
|
|
123
|
+
path = program.to_s
|
|
124
|
+
return { ok: false, error: "launch requires a non-empty 'program' argument" } if path.empty?
|
|
125
|
+
|
|
126
|
+
expanded = File.expand_path(path)
|
|
127
|
+
if expanded.end_with?(".mt")
|
|
128
|
+
return { ok: false, error: "Milk Tea program not found: #{expanded}" } unless File.file?(expanded)
|
|
129
|
+
|
|
130
|
+
tmp_dir = Dir.mktmpdir("milk-tea-dap")
|
|
131
|
+
@tmp_dirs << tmp_dir
|
|
132
|
+
output_path = File.join(tmp_dir, File.basename(expanded, ".mt"))
|
|
133
|
+
|
|
134
|
+
begin
|
|
135
|
+
Build.build(expanded, output_path:, debug: true, debug_guards: false)
|
|
136
|
+
rescue BuildError => e
|
|
137
|
+
return { ok: false, error: e.message }
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
return { ok: true, runnable_path: output_path }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
return { ok: false, error: "Program not found: #{expanded}" } unless File.file?(expanded)
|
|
144
|
+
|
|
145
|
+
{ ok: true, runnable_path: expanded }
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def resolve_debug_program(command, program)
|
|
149
|
+
return resolve_launch_program(program) if command == "launch"
|
|
150
|
+
|
|
151
|
+
path = program.to_s
|
|
152
|
+
return { ok: true, runnable_path: nil } if path.empty?
|
|
153
|
+
|
|
154
|
+
resolve_launch_program(path)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def backend_start_arguments(command, arguments, resolved)
|
|
158
|
+
rewritten = arguments.dup
|
|
159
|
+
|
|
160
|
+
rewritten.delete("backend")
|
|
161
|
+
rewritten.delete("adapterPath")
|
|
162
|
+
|
|
163
|
+
if resolved[:runnable_path]
|
|
164
|
+
rewritten["program"] = resolved[:runnable_path]
|
|
165
|
+
elsif rewritten["program"].to_s.empty?
|
|
166
|
+
rewritten.delete("program")
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
rewritten["stopOnEntry"] = true if command == "launch"
|
|
170
|
+
|
|
171
|
+
rewritten["cwd"] = File.expand_path(rewritten["cwd"]) if rewritten["cwd"].is_a?(String) && !rewritten["cwd"].empty?
|
|
172
|
+
rewritten["coreFile"] = File.expand_path(rewritten["coreFile"]) if rewritten["coreFile"].is_a?(String) && !rewritten["coreFile"].empty?
|
|
173
|
+
rewritten
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def start_runtime_if_needed
|
|
177
|
+
return if @session.runtime_started?
|
|
178
|
+
return unless @session.runnable_path
|
|
179
|
+
|
|
180
|
+
@session.mark_runtime_started!
|
|
181
|
+
runnable_path = @session.runnable_path
|
|
182
|
+
command = [runnable_path, *@session.program_args]
|
|
183
|
+
chdir = File.dirname(File.expand_path(@session.program_path || runnable_path))
|
|
184
|
+
|
|
185
|
+
Thread.new do
|
|
186
|
+
Open3.popen3(*command, chdir:) do |stdin, stdout, stderr, wait_thr|
|
|
187
|
+
stdin.close
|
|
188
|
+
@runtime_mutex.synchronize { @runtime_pid = wait_thr.pid }
|
|
189
|
+
|
|
190
|
+
out_thread = Thread.new do
|
|
191
|
+
stdout.each_line do |line|
|
|
192
|
+
write_event("output", { category: "stdout", output: line })
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
err_thread = Thread.new do
|
|
197
|
+
stderr.each_line do |line|
|
|
198
|
+
write_event("output", { category: "stderr", output: line })
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
out_thread.join
|
|
203
|
+
err_thread.join
|
|
204
|
+
|
|
205
|
+
status = wait_thr.value
|
|
206
|
+
exit_code = status.exited? ? status.exitstatus : 1
|
|
207
|
+
@session.terminate!
|
|
208
|
+
|
|
209
|
+
write_event("terminated")
|
|
210
|
+
write_event("exited", { exitCode: exit_code })
|
|
211
|
+
@session.request_exit!
|
|
212
|
+
end
|
|
213
|
+
rescue StandardError => e
|
|
214
|
+
@session.terminate!
|
|
215
|
+
write_event("output", { category: "stderr", output: "DAP runtime error: #{e.message}\n" })
|
|
216
|
+
write_event("terminated")
|
|
217
|
+
write_event("exited", { exitCode: 1 })
|
|
218
|
+
@session.request_exit!
|
|
219
|
+
ensure
|
|
220
|
+
@runtime_mutex.synchronize do
|
|
221
|
+
@runtime_pid = nil
|
|
222
|
+
@runtime_paused = false
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def pause_runtime_if_running
|
|
228
|
+
pid = @runtime_mutex.synchronize { @runtime_pid }
|
|
229
|
+
return false if pid.nil?
|
|
230
|
+
|
|
231
|
+
Process.kill("STOP", pid)
|
|
232
|
+
@runtime_mutex.synchronize { @runtime_paused = true }
|
|
233
|
+
true
|
|
234
|
+
rescue StandardError
|
|
235
|
+
false
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def continue_runtime_if_paused
|
|
239
|
+
pid, paused = @runtime_mutex.synchronize { [@runtime_pid, @runtime_paused] }
|
|
240
|
+
return unless paused
|
|
241
|
+
return if pid.nil?
|
|
242
|
+
|
|
243
|
+
Process.kill("CONT", pid)
|
|
244
|
+
@runtime_mutex.synchronize { @runtime_paused = false }
|
|
245
|
+
rescue StandardError
|
|
246
|
+
nil
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
def terminate_runtime_if_running
|
|
250
|
+
pid = @runtime_mutex.synchronize { @runtime_pid }
|
|
251
|
+
return if pid.nil?
|
|
252
|
+
|
|
253
|
+
Process.kill("TERM", pid)
|
|
254
|
+
@runtime_mutex.synchronize { @runtime_paused = false }
|
|
255
|
+
rescue StandardError
|
|
256
|
+
nil
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|