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,609 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MilkTea
|
|
4
|
+
module TypePredicates
|
|
5
|
+
def method_dispatch_receiver_type(receiver_type)
|
|
6
|
+
return receiver_type.definition if receiver_type.is_a?(Types::StructInstance) || receiver_type.is_a?(Types::VariantInstance)
|
|
7
|
+
if receiver_type.is_a?(Types::Nullable)
|
|
8
|
+
dispatch_base_type = method_dispatch_receiver_type(receiver_type.base)
|
|
9
|
+
return receiver_type if dispatch_base_type == receiver_type.base
|
|
10
|
+
|
|
11
|
+
return Types::Registry.nullable(dispatch_base_type)
|
|
12
|
+
end
|
|
13
|
+
return receiver_type unless receiver_type.is_a?(Types::GenericInstance)
|
|
14
|
+
|
|
15
|
+
dispatch_receiver_type = Types::Registry.generic_instance(
|
|
16
|
+
receiver_type.name,
|
|
17
|
+
receiver_type.arguments.each_with_index.map do |argument, index|
|
|
18
|
+
argument.is_a?(Types::LiteralTypeArg) ? argument : Types::TypeVar.new("__receiver_arg#{index}")
|
|
19
|
+
end,
|
|
20
|
+
)
|
|
21
|
+
dispatch_receiver_type == receiver_type ? receiver_type : dispatch_receiver_type
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def task_root_proc_type?(type)
|
|
25
|
+
proc_type?(type) && type.params.empty? && type.return_type.is_a?(Types::Task)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def function_type_matches_proc_type?(function_type, proc_type)
|
|
29
|
+
return false if function_type.receiver_type || function_type.variadic
|
|
30
|
+
return false unless function_type.params.length == proc_type.params.length
|
|
31
|
+
return false unless function_type.return_type == proc_type.return_type
|
|
32
|
+
|
|
33
|
+
function_type.params.zip(proc_type.params).all? do |function_param, proc_param|
|
|
34
|
+
next false unless function_param.mutable == proc_param.mutable
|
|
35
|
+
|
|
36
|
+
function_param.type == proc_param.type ||
|
|
37
|
+
same_external_opaque_handle_pointer_compatibility?(function_param.type, proc_param.type)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def null_assignable_to?(actual_type, expected_type)
|
|
42
|
+
return false unless actual_type.is_a?(Types::Null)
|
|
43
|
+
return false unless expected_type.is_a?(Types::Nullable)
|
|
44
|
+
return true unless actual_type.target_type
|
|
45
|
+
|
|
46
|
+
actual_type.target_type == expected_type.base
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def external_typed_null_pointer_compatibility?(actual_type, expected_type)
|
|
50
|
+
return false unless actual_type.is_a?(Types::Null)
|
|
51
|
+
return false unless actual_type.target_type
|
|
52
|
+
return false if expected_type.is_a?(Types::Nullable)
|
|
53
|
+
return true if expected_type == Types::Registry.primitive("cstr") && char_pointer_type?(actual_type.target_type)
|
|
54
|
+
return false unless pointer_type?(expected_type)
|
|
55
|
+
|
|
56
|
+
actual_type.target_type == expected_type
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def numeric_constant_fits_type?(value, expected_type)
|
|
60
|
+
if expected_type.integer?
|
|
61
|
+
integer_constant_fits_type?(value, expected_type)
|
|
62
|
+
else
|
|
63
|
+
float_constant_fits_type?(value, expected_type)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def integer_constant_fits_type?(value, expected_type)
|
|
68
|
+
integer_value = exact_integer_constant_value(value)
|
|
69
|
+
return false if integer_value.nil?
|
|
70
|
+
|
|
71
|
+
value_fits_integer_type?(integer_value, expected_type)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def float_constant_fits_type?(value, expected_type)
|
|
75
|
+
return false unless value.is_a?(Numeric)
|
|
76
|
+
return false unless value.finite?
|
|
77
|
+
|
|
78
|
+
if expected_type.name == "float"
|
|
79
|
+
return value.abs <= (1 << 24) if value.is_a?(Integer)
|
|
80
|
+
|
|
81
|
+
exactly_representable_float32?(value.to_f)
|
|
82
|
+
else
|
|
83
|
+
return true if expected_type.name == "double"
|
|
84
|
+
|
|
85
|
+
false
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def exact_integer_constant_value(value)
|
|
90
|
+
return value if value.is_a?(Integer)
|
|
91
|
+
return nil unless value.is_a?(Float) && value.finite?
|
|
92
|
+
|
|
93
|
+
integer_value = value.to_i
|
|
94
|
+
integer_value.to_f == value ? integer_value : nil
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def value_fits_integer_type?(value, expected_type)
|
|
98
|
+
return false unless expected_type.is_a?(Types::Primitive) && expected_type.integer?
|
|
99
|
+
|
|
100
|
+
width = expected_type.integer_width
|
|
101
|
+
return false if width.nil?
|
|
102
|
+
|
|
103
|
+
min_value, max_value = if expected_type.signed_integer?
|
|
104
|
+
[-(1 << (width - 1)), (1 << (width - 1)) - 1]
|
|
105
|
+
else
|
|
106
|
+
[0, (1 << width) - 1]
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
value >= min_value && value <= max_value
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def exactly_representable_float32?(value)
|
|
113
|
+
[value].pack("f").unpack1("f") == value
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def integer_to_char_compatibility?(actual_type, expected_type)
|
|
117
|
+
char_type?(expected_type) && integer_like_char_source_type?(actual_type)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def integer_like_char_source_type?(type)
|
|
121
|
+
return true if type.is_a?(Types::Primitive) && type.integer?
|
|
122
|
+
return true if type.is_a?(Types::EnumBase) && type.backing_type.is_a?(Types::Primitive) && type.backing_type.integer?
|
|
123
|
+
|
|
124
|
+
false
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def char_type?(type)
|
|
128
|
+
type.is_a?(Types::Primitive) && type.name == "char"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def external_numeric_compatibility?(actual_type, expected_type)
|
|
132
|
+
return false unless actual_type.is_a?(Types::Primitive) && expected_type.is_a?(Types::Primitive)
|
|
133
|
+
return false unless actual_type.numeric? && expected_type.numeric?
|
|
134
|
+
|
|
135
|
+
return lossless_external_integer_compatibility?(actual_type, expected_type) if actual_type.integer? && expected_type.integer?
|
|
136
|
+
return expected_type.float_width >= actual_type.float_width if actual_type.float? && expected_type.float?
|
|
137
|
+
|
|
138
|
+
false
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def lossless_external_integer_compatibility?(actual_type, expected_type)
|
|
142
|
+
return false unless actual_type.fixed_width_integer? && expected_type.fixed_width_integer?
|
|
143
|
+
|
|
144
|
+
if actual_type.signed_integer? == expected_type.signed_integer?
|
|
145
|
+
return expected_type.integer_width >= actual_type.integer_width
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
return false if actual_type.signed_integer?
|
|
149
|
+
|
|
150
|
+
expected_type.signed_integer? && expected_type.integer_width > actual_type.integer_width
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def lossless_integer_compatibility?(actual_type, expected_type)
|
|
154
|
+
return false unless actual_type.is_a?(Types::Primitive) && expected_type.is_a?(Types::Primitive)
|
|
155
|
+
return false unless actual_type.integer? && expected_type.integer?
|
|
156
|
+
|
|
157
|
+
lossless_external_integer_compatibility?(actual_type, expected_type)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def contextual_int_to_float_compatibility?(actual_type, expected_type)
|
|
161
|
+
actual_type.is_a?(Types::Primitive) && actual_type.integer? &&
|
|
162
|
+
expected_type.is_a?(Types::Primitive) && expected_type.float?
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def contextual_int_to_float_target?(type)
|
|
166
|
+
type.is_a?(Types::Primitive) && type.float?
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def mutable_to_const_pointer_compatibility?(actual_type, expected_type)
|
|
170
|
+
return mutable_to_const_pointer_compatibility?(actual_type.base, expected_type.base) if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
|
|
171
|
+
return mutable_to_const_pointer_compatibility?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
|
|
172
|
+
return false if actual_type.is_a?(Types::Nullable)
|
|
173
|
+
return false unless (mutable_pointer_type?(actual_type) || own_type?(actual_type)) && const_pointer_type?(expected_type)
|
|
174
|
+
|
|
175
|
+
pointee_type(actual_type) == pointee_type(expected_type)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def own_to_raw_pointer_compatibility?(actual_type, expected_type)
|
|
179
|
+
return own_to_raw_pointer_compatibility?(actual_type.base, expected_type.base) if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
|
|
180
|
+
return own_to_raw_pointer_compatibility?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
|
|
181
|
+
return false if actual_type.is_a?(Types::Nullable)
|
|
182
|
+
return false unless own_type?(actual_type)
|
|
183
|
+
return false unless mutable_pointer_type?(expected_type) || const_pointer_type?(expected_type)
|
|
184
|
+
|
|
185
|
+
pointee_type(actual_type) == pointee_type(expected_type)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def foreign_span_boundary_compatible?(public_type, boundary_type)
|
|
189
|
+
return false unless public_type.is_a?(Types::Span) && boundary_type.is_a?(Types::Span)
|
|
190
|
+
|
|
191
|
+
foreign_boundary_element_compatible?(public_type.element_type, boundary_type.element_type)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def foreign_char_pointer_buffer_boundary_compatible?(public_type, boundary_type)
|
|
195
|
+
return false unless char_pointer_type?(boundary_type)
|
|
196
|
+
|
|
197
|
+
return true if public_type.is_a?(Types::Span) && public_type.element_type == Types::Registry.primitive("char")
|
|
198
|
+
return true if char_array_text_type?(public_type)
|
|
199
|
+
return true if str_buffer_type?(public_type)
|
|
200
|
+
|
|
201
|
+
false
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def foreign_boundary_element_compatible?(public_type, boundary_type)
|
|
205
|
+
return true if public_type == boundary_type
|
|
206
|
+
return true if public_type == Types::Registry.string_view && boundary_type == Types::Registry.primitive("cstr")
|
|
207
|
+
return true if public_type == Types::Registry.string_view && char_pointer_type?(boundary_type)
|
|
208
|
+
|
|
209
|
+
foreign_identity_projection_compatible?(public_type, boundary_type)
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def foreign_identity_projection_compatible?(actual_type, expected_type)
|
|
213
|
+
foreign_identity_projection_cast_compatible?(actual_type, expected_type) ||
|
|
214
|
+
foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def foreign_identity_projection_cast_compatible?(actual_type, expected_type)
|
|
218
|
+
return true if actual_type == expected_type
|
|
219
|
+
return true if mutable_to_const_pointer_compatibility?(actual_type, expected_type)
|
|
220
|
+
return true if same_external_opaque_c_name?(actual_type, expected_type)
|
|
221
|
+
return true if foreign_function_type_projection_compatible?(actual_type, expected_type)
|
|
222
|
+
return true if native_foreign_layout_compatible?(actual_type, expected_type)
|
|
223
|
+
return true if native_foreign_layout_compatible?(expected_type, actual_type)
|
|
224
|
+
return true if quat_vec4_layout_compatible?(actual_type, expected_type)
|
|
225
|
+
|
|
226
|
+
if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
|
|
227
|
+
return foreign_identity_projection_cast_compatible?(actual_type.base, expected_type.base)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
return foreign_identity_projection_cast_compatible?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
|
|
231
|
+
return false if actual_type.is_a?(Types::Nullable)
|
|
232
|
+
|
|
233
|
+
return true if same_external_opaque_handle_pointer_compatibility?(actual_type, expected_type)
|
|
234
|
+
|
|
235
|
+
if pointer_type?(actual_type) && pointer_type?(expected_type)
|
|
236
|
+
return false if const_pointer_type?(actual_type) && mutable_pointer_type?(expected_type)
|
|
237
|
+
return true if void_pointer_type?(actual_type) || void_pointer_type?(expected_type)
|
|
238
|
+
|
|
239
|
+
return true if foreign_identity_projection_cast_compatible?(actual_type.arguments.first, expected_type.arguments.first)
|
|
240
|
+
|
|
241
|
+
return foreign_external_layout_compatible?(actual_type.arguments.first, expected_type.arguments.first)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
return true if void_pointer_type?(actual_type) && opaque_type?(expected_type)
|
|
245
|
+
return true if opaque_type?(actual_type) && void_pointer_type?(expected_type)
|
|
246
|
+
return true if char_pointer_type?(actual_type) && expected_type == Types::Registry.primitive("cstr")
|
|
247
|
+
return true if actual_type == Types::Registry.primitive("cstr") && char_pointer_type?(expected_type)
|
|
248
|
+
|
|
249
|
+
false
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def same_external_opaque_handle_pointer_compatibility?(actual_type, expected_type)
|
|
253
|
+
if actual_type.is_a?(Types::Opaque) && pointer_type?(expected_type)
|
|
254
|
+
return same_external_opaque_c_name?(actual_type, expected_type.arguments.first)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
if pointer_type?(actual_type) && expected_type.is_a?(Types::Opaque)
|
|
258
|
+
return same_external_opaque_c_name?(actual_type.arguments.first, expected_type)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
false
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def foreign_function_type_projection_compatible?(actual_type, expected_type)
|
|
265
|
+
return false unless actual_type.is_a?(Types::Function) && expected_type.is_a?(Types::Function)
|
|
266
|
+
return false unless actual_type.receiver_type == expected_type.receiver_type
|
|
267
|
+
return false unless actual_type.variadic == expected_type.variadic
|
|
268
|
+
return false unless actual_type.params.length == expected_type.params.length
|
|
269
|
+
return false unless foreign_identity_projection_compatible?(actual_type.return_type, expected_type.return_type)
|
|
270
|
+
|
|
271
|
+
actual_type.params.zip(expected_type.params).all? do |actual_param, expected_param|
|
|
272
|
+
actual_param.mutable == expected_param.mutable &&
|
|
273
|
+
actual_param.passing_mode == expected_param.passing_mode &&
|
|
274
|
+
actual_param.boundary_type == expected_param.boundary_type &&
|
|
275
|
+
foreign_identity_projection_compatible?(actual_param.type, expected_param.type)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def same_external_opaque_c_name?(actual_type, expected_type)
|
|
280
|
+
return false unless actual_type.is_a?(Types::Opaque) && expected_type.is_a?(Types::Opaque)
|
|
281
|
+
return false unless actual_type.external || actual_type.linkage_name
|
|
282
|
+
return false unless expected_type.external || expected_type.linkage_name
|
|
283
|
+
|
|
284
|
+
foreign_opaque_c_name(actual_type) == foreign_opaque_c_name(expected_type)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def foreign_opaque_c_name(type)
|
|
288
|
+
type.linkage_name || type.name
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type)
|
|
292
|
+
if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
|
|
293
|
+
return foreign_identity_projection_reinterpret_compatible?(actual_type.base, expected_type.base)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
return foreign_identity_projection_reinterpret_compatible?(actual_type, expected_type.base) if expected_type.is_a?(Types::Nullable)
|
|
297
|
+
return false if actual_type.is_a?(Types::Nullable)
|
|
298
|
+
|
|
299
|
+
foreign_external_layout_compatible?(actual_type, expected_type)
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def foreign_external_layout_compatible?(actual_type, expected_type, seen = {})
|
|
303
|
+
return false unless actual_type.is_a?(Types::Struct) && expected_type.is_a?(Types::Struct)
|
|
304
|
+
return false if actual_type.is_a?(Types::Union) != expected_type.is_a?(Types::Union)
|
|
305
|
+
return false unless actual_type.external && expected_type.external
|
|
306
|
+
return false unless actual_type.name == expected_type.name
|
|
307
|
+
return false unless actual_type.packed == expected_type.packed
|
|
308
|
+
return false unless actual_type.alignment == expected_type.alignment
|
|
309
|
+
|
|
310
|
+
key = [actual_type.object_id, expected_type.object_id]
|
|
311
|
+
return true if seen[key]
|
|
312
|
+
|
|
313
|
+
seen[key] = true
|
|
314
|
+
actual_fields = actual_type.fields
|
|
315
|
+
expected_fields = expected_type.fields
|
|
316
|
+
return false unless actual_fields.keys == expected_fields.keys
|
|
317
|
+
|
|
318
|
+
actual_fields.all? do |field_name, field_type|
|
|
319
|
+
foreign_external_layout_field_compatible?(field_type, expected_fields.fetch(field_name), seen)
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def foreign_external_layout_field_compatible?(actual_type, expected_type, seen)
|
|
324
|
+
return true if actual_type == expected_type
|
|
325
|
+
|
|
326
|
+
if actual_type.is_a?(Types::Nullable) && expected_type.is_a?(Types::Nullable)
|
|
327
|
+
return foreign_external_layout_field_compatible?(actual_type.base, expected_type.base, seen)
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
if pointer_type?(actual_type) && pointer_type?(expected_type)
|
|
331
|
+
return foreign_external_layout_field_compatible?(actual_type.arguments.first, expected_type.arguments.first, seen)
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
if array_type?(actual_type) && array_type?(expected_type)
|
|
335
|
+
return false unless array_length(actual_type) == array_length(expected_type)
|
|
336
|
+
|
|
337
|
+
return foreign_external_layout_field_compatible?(array_element_type(actual_type), array_element_type(expected_type), seen)
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
foreign_external_layout_compatible?(actual_type, expected_type, seen)
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def void_pointer_type?(type)
|
|
344
|
+
pointer_type?(type) && type.arguments.first == Types::Registry.primitive("void")
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def native_foreign_layout_compatible?(native_type, foreign_type)
|
|
348
|
+
return false unless (native_type.is_a?(Types::Vector) || native_type.is_a?(Types::Matrix) || native_type.is_a?(Types::Quaternion))
|
|
349
|
+
return false unless foreign_type.is_a?(Types::Struct) && foreign_type.external
|
|
350
|
+
|
|
351
|
+
native_flat = flatten_field_types(native_type)
|
|
352
|
+
foreign_flat = flatten_field_types(foreign_type)
|
|
353
|
+
return false unless native_flat.size == foreign_flat.size
|
|
354
|
+
|
|
355
|
+
native_flat.zip(foreign_flat).all? { |nf, ff| nf == ff }
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def quat_vec4_layout_compatible?(a, b)
|
|
359
|
+
(a.is_a?(Types::Quaternion) && b.is_a?(Types::Vector) && b.width == 4 && b.element_type.name == "float") ||
|
|
360
|
+
(b.is_a?(Types::Quaternion) && a.is_a?(Types::Vector) && a.width == 4 && a.element_type.name == "float")
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def flatten_field_types(type)
|
|
364
|
+
if type.is_a?(Types::Primitive)
|
|
365
|
+
[type]
|
|
366
|
+
elsif type.respond_to?(:fields) && type.fields
|
|
367
|
+
type.fields.values.flat_map { |ft| flatten_field_types(ft) }
|
|
368
|
+
else
|
|
369
|
+
[type]
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def char_pointer_type?(type)
|
|
374
|
+
pointer_type?(type) && type.arguments.first == Types::Registry.primitive("char")
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def opaque_type?(type)
|
|
378
|
+
type.is_a?(Types::Opaque)
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def pointer_type?(type)
|
|
382
|
+
mutable_pointer_type?(type) || const_pointer_type?(type) || own_type?(type)
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
def mutable_pointer_type?(type)
|
|
386
|
+
type.is_a?(Types::GenericInstance) && type.name == "ptr" && type.arguments.length == 1
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def const_pointer_type?(type)
|
|
390
|
+
type.is_a?(Types::GenericInstance) && type.name == "const_ptr" && type.arguments.length == 1
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
def own_type?(type)
|
|
394
|
+
type.is_a?(Types::GenericInstance) && type.name == "own" && type.arguments.length == 1
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def owned_referent_type(type)
|
|
398
|
+
type.arguments.first if own_type?(type)
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def ref_type?(type)
|
|
402
|
+
type.is_a?(Types::GenericInstance) && type.name == "ref" && [1, 2].include?(type.arguments.length)
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
def atomic_type?(type)
|
|
406
|
+
type.is_a?(Types::GenericInstance) && type.name == "atomic" && type.arguments.length == 1
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def atomic_element_type(type)
|
|
410
|
+
type.arguments.first
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
def ref_type_without_lifetime?(type)
|
|
414
|
+
type.is_a?(Types::GenericInstance) && type.name == "ref" && type.arguments.length == 1
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
def ref_lifetime(type)
|
|
418
|
+
return unless type.is_a?(Types::GenericInstance) && type.name == "ref" && type.arguments.length == 2
|
|
419
|
+
|
|
420
|
+
type.arguments.first
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def dyn_type?(type)
|
|
424
|
+
type.is_a?(Types::Dyn)
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
def task_type?(type)
|
|
428
|
+
type.is_a?(Types::Task)
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
def struct_with_target_type?(type)
|
|
432
|
+
type.is_a?(Types::Struct) || type.is_a?(Types::Vector) || type.is_a?(Types::Matrix) || type.is_a?(Types::Quaternion)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
def proc_type?(type)
|
|
436
|
+
type.is_a?(Types::Proc)
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
def pointee_type(type)
|
|
440
|
+
return unless pointer_type?(type)
|
|
441
|
+
|
|
442
|
+
type.arguments.first
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
def referenced_type(type)
|
|
446
|
+
return unless ref_type?(type)
|
|
447
|
+
|
|
448
|
+
type.arguments.length == 1 ? type.arguments.first : type.arguments[1]
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
def const_pointer_to(type)
|
|
452
|
+
Types::Registry.generic_instance("const_ptr", [type])
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
def call_arity_matches?(function_type, actual_count)
|
|
456
|
+
return actual_count >= function_type.params.length if function_type.is_a?(Types::Function) && function_type.variadic
|
|
457
|
+
|
|
458
|
+
actual_count == function_type.params.length
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
def arity_error_message(function_type, name, actual_count)
|
|
462
|
+
if function_type.is_a?(Types::Function) && function_type.variadic
|
|
463
|
+
"function #{name} expects at least #{function_type.params.length} arguments, got #{actual_count}"
|
|
464
|
+
else
|
|
465
|
+
"function #{name} expects #{function_type.params.length} arguments, got #{actual_count}"
|
|
466
|
+
end
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
def string_builder_type?(type)
|
|
470
|
+
type.respond_to?(:name) && type.respond_to?(:module_name) && type.name == "String" && type.module_name == "std.string"
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
def string_builder_ref_type?(type)
|
|
474
|
+
ref_type?(type) && string_builder_type?(referenced_type(type))
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
def callable_param_ref_supported?(type)
|
|
478
|
+
case type
|
|
479
|
+
when Types::Proc
|
|
480
|
+
type.params.all? { |param| ref_type?(param.type) || !contains_ref_type?(param.type) } &&
|
|
481
|
+
!contains_ref_type?(type.return_type)
|
|
482
|
+
when Types::Function
|
|
483
|
+
type.params.all? { |param| ref_type?(param.type) || !contains_ref_type?(param.type) } &&
|
|
484
|
+
!contains_ref_type?(type.return_type) &&
|
|
485
|
+
(type.receiver_type.nil? || !contains_ref_type?(type.receiver_type))
|
|
486
|
+
else
|
|
487
|
+
false
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
def contains_ref_type?(type, visited = {}, allow_lifetimes: [])
|
|
492
|
+
visitor = ContainsRefTypeVisitor.new(allow_lifetimes:)
|
|
493
|
+
visitor.visit(type)
|
|
494
|
+
visitor.found?
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
def contains_type_var?(type)
|
|
498
|
+
visitor = ContainsTypeVarVisitor.new
|
|
499
|
+
visitor.visit(type)
|
|
500
|
+
visitor.found?
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
def collection_loop_type(type)
|
|
504
|
+
return type.arguments.first if Types.array_type?(type)
|
|
505
|
+
return type.element_type if type.is_a?(Types::Span)
|
|
506
|
+
|
|
507
|
+
nil
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
def collection_loop_binding_type(iterable_type, element_type)
|
|
511
|
+
return nil unless Types.array_type?(iterable_type) || iterable_type.is_a?(Types::Span)
|
|
512
|
+
return nil unless collection_loop_ref_element_type?(element_type)
|
|
513
|
+
|
|
514
|
+
Types::Registry.generic_instance("ref", [element_type])
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
def collection_loop_ref_element_type?(type)
|
|
518
|
+
type.is_a?(Types::Struct)
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def integer_type_argument?(argument)
|
|
522
|
+
argument.is_a?(Types::LiteralTypeArg) && argument.value.is_a?(Integer)
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
def generic_integer_type_argument?(argument)
|
|
526
|
+
integer_type_argument?(argument) || argument.is_a?(Types::TypeVar)
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def validate_generic_type!(name, arguments, &error)
|
|
530
|
+
case name
|
|
531
|
+
when "ptr"
|
|
532
|
+
error.call("ptr requires exactly one type argument") unless arguments.length == 1
|
|
533
|
+
error.call("ptr type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
|
|
534
|
+
when "const_ptr"
|
|
535
|
+
error.call("const_ptr requires exactly one type argument") unless arguments.length == 1
|
|
536
|
+
error.call("const_ptr type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
|
|
537
|
+
error.call("const_ptr cannot target ref types") if contains_ref_type?(arguments.first)
|
|
538
|
+
when "own"
|
|
539
|
+
error.call("own requires exactly one type argument") unless arguments.length == 1
|
|
540
|
+
error.call("own type argument must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
|
|
541
|
+
when "ref"
|
|
542
|
+
unless [1, 2].include?(arguments.length)
|
|
543
|
+
error.call("ref requires exactly one type argument")
|
|
544
|
+
end
|
|
545
|
+
type_arg = arguments.length == 1 ? arguments.first : arguments[1]
|
|
546
|
+
error.call("ref type argument must be a type") if type_arg.is_a?(Types::LiteralTypeArg)
|
|
547
|
+
error.call("ref cannot target void") if type_arg.is_a?(Types::Primitive) && type_arg.void?
|
|
548
|
+
if contains_ref_type?(type_arg)
|
|
549
|
+
unless (type_arg.is_a?(Types::Struct) || type_arg.is_a?(Types::StructInstance)) && type_arg.lifetime_params&.any?
|
|
550
|
+
error.call("ref cannot target another ref type")
|
|
551
|
+
end
|
|
552
|
+
end
|
|
553
|
+
when "span"
|
|
554
|
+
error.call("span requires exactly one type argument") unless arguments.length == 1
|
|
555
|
+
error.call("span element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
|
|
556
|
+
when "array"
|
|
557
|
+
error.call("array requires exactly two type arguments") unless arguments.length == 2
|
|
558
|
+
error.call("array element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
|
|
559
|
+
error.call("array length must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments[1])
|
|
560
|
+
error.call("array length must be positive") if integer_type_argument?(arguments[1]) && !arguments[1].value.positive?
|
|
561
|
+
when "SoA"
|
|
562
|
+
error.call("SoA requires exactly two type arguments") unless arguments.length == 2
|
|
563
|
+
error.call("SoA element type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
|
|
564
|
+
error.call("SoA element type must be a struct with fields") unless arguments.first.respond_to?(:fields) && arguments.first.fields.any?
|
|
565
|
+
error.call("SoA length must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments[1])
|
|
566
|
+
error.call("SoA length must be positive") if integer_type_argument?(arguments[1]) && !arguments[1].value.positive?
|
|
567
|
+
when "str_buffer"
|
|
568
|
+
error.call("str_buffer requires exactly one type argument") unless arguments.length == 1
|
|
569
|
+
error.call("str_buffer capacity must be an integer literal, named const, or type parameter") unless generic_integer_type_argument?(arguments.first)
|
|
570
|
+
error.call("str_buffer capacity must be positive") if integer_type_argument?(arguments.first) && !arguments.first.value.positive?
|
|
571
|
+
when "Task"
|
|
572
|
+
error.call("Task requires exactly one type argument") unless arguments.length == 1
|
|
573
|
+
error.call("Task result type must be a type") if arguments.first.is_a?(Types::LiteralTypeArg)
|
|
574
|
+
when "atomic"
|
|
575
|
+
error.call("atomic requires exactly one type argument") unless arguments.length == 1
|
|
576
|
+
arg = arguments.first
|
|
577
|
+
error.call("atomic type argument must be a type") if arg.is_a?(Types::LiteralTypeArg)
|
|
578
|
+
error.call("atomic type argument must be a primitive integer or bool") unless arg.is_a?(Types::Primitive) && (arg.integer? || arg.boolean?)
|
|
579
|
+
else
|
|
580
|
+
error.call("unknown generic type #{name}")
|
|
581
|
+
end
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
private
|
|
585
|
+
|
|
586
|
+
def char_array_text_type?(type)
|
|
587
|
+
return false unless array_type?(type)
|
|
588
|
+
|
|
589
|
+
element = array_element_type(type)
|
|
590
|
+
element.is_a?(Types::Primitive) && element.name == "char"
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
def str_buffer_type?(type)
|
|
594
|
+
type.arguments.length == 1 && type.arguments.first.is_a?(Types::LiteralTypeArg) && type.arguments.first.value.is_a?(Integer)
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
def array_type?(type)
|
|
598
|
+
type.arguments.length == 2 && type.arguments[1].is_a?(Types::LiteralTypeArg) && type.arguments[1].value.is_a?(Integer)
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
def array_length(type)
|
|
602
|
+
type.arguments[1].value
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
def array_element_type(type)
|
|
606
|
+
type.arguments.first
|
|
607
|
+
end
|
|
608
|
+
end
|
|
609
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MilkTea
|
|
4
|
+
module Types
|
|
5
|
+
module Registry
|
|
6
|
+
@pool = {}
|
|
7
|
+
@mutex = Mutex.new
|
|
8
|
+
|
|
9
|
+
module_function
|
|
10
|
+
|
|
11
|
+
def reset!
|
|
12
|
+
@mutex.synchronize { @pool.clear }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def _intern(key, &construct)
|
|
16
|
+
@mutex.synchronize do
|
|
17
|
+
@pool[key] ||= construct.call
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def primitive(name)
|
|
22
|
+
_intern([:primitive, name]) { Primitive.new(name) }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def nullable(base)
|
|
26
|
+
_intern([:nullable, base]) { Nullable.new(base) }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def generic_instance(name, arguments)
|
|
30
|
+
args = arguments.freeze
|
|
31
|
+
_intern([:generic, name, args]) { GenericInstance.new(name, args) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def span(element_type)
|
|
35
|
+
_intern([:span, element_type]) { Span.new(element_type) }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def task(result_type)
|
|
39
|
+
_intern([:task, result_type]) { Task.new(result_type) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def string_view
|
|
43
|
+
_intern([:string_view]) { StringView.new }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def function(name, params:, return_type:, receiver_type: nil, receiver_editable: false, variadic: false, external: false)
|
|
47
|
+
params_frozen = params.freeze
|
|
48
|
+
_intern([:function, name, params_frozen, return_type, receiver_type, receiver_editable, variadic, external]) {
|
|
49
|
+
Function.new(name, params: params_frozen, return_type: return_type, receiver_type: receiver_type, receiver_editable: receiver_editable, variadic: variadic, external: external)
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def proc(params:, return_type:)
|
|
54
|
+
params_frozen = params.freeze
|
|
55
|
+
_intern([:proc, params_frozen, return_type]) { Proc.new(params: params_frozen, return_type: return_type) }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def parameter(name, type, mutable: false, passing_mode: :plain, boundary_type: nil)
|
|
59
|
+
_intern([:parameter, name, type, mutable, passing_mode, boundary_type]) {
|
|
60
|
+
Parameter.new(name, type, mutable: mutable, passing_mode: passing_mode, boundary_type: boundary_type)
|
|
61
|
+
}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def tuple(element_types, field_names: nil)
|
|
65
|
+
et_frozen = element_types.freeze
|
|
66
|
+
fn_frozen = field_names&.freeze
|
|
67
|
+
_intern([:tuple, et_frozen, fn_frozen]) { Tuple.new(et_frozen, field_names: fn_frozen) }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def soa(element_type, count:)
|
|
71
|
+
_intern([:soa, element_type, count]) { SoA.new(element_type, count: count) }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def lifetime_ref(name)
|
|
75
|
+
LifetimeRef.new(name)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def dyn(interface_binding, type_arguments = [])
|
|
79
|
+
Dyn.new(interface_binding, type_arguments)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|