mt-lang 0.3.41 → 0.3.43

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -2
  3. data/docs/index.html +20 -4
  4. data/docs/language-design.md +5 -2
  5. data/docs/language-manual.md +28 -5
  6. data/lib/milk_tea/base.rb +1 -1
  7. data/lib/milk_tea/bindings/bindgen/declaration.rb +17 -0
  8. data/lib/milk_tea/bindings/bindgen/emitter.rb +44 -5
  9. data/lib/milk_tea/bindings/imported_bindings/defaults.rb +7 -0
  10. data/lib/milk_tea/bindings/raw_bindings/defaults.rb +22 -0
  11. data/lib/milk_tea/bindings/upstream_sources.rb +9 -0
  12. data/lib/milk_tea/bindings/vendored_box3d.rb +77 -0
  13. data/lib/milk_tea/bindings.rb +1 -0
  14. data/lib/milk_tea/core/c_backend/expressions.rb +21 -5
  15. data/lib/milk_tea/core/c_backend/feature_detection.rb +6 -1
  16. data/lib/milk_tea/core/c_backend/runtime_helpers.rb +38 -4
  17. data/lib/milk_tea/core/c_backend/statements.rb +1 -1
  18. data/lib/milk_tea/core/c_backend/type_collectors.rb +97 -4
  19. data/lib/milk_tea/core/c_backend.rb +9 -0
  20. data/lib/milk_tea/core/lowering/async/async_lowering.rb +2 -6
  21. data/lib/milk_tea/core/lowering/async/frame_builder.rb +12 -5
  22. data/lib/milk_tea/core/lowering/async/normalization.rb +28 -5
  23. data/lib/milk_tea/core/lowering/expressions.rb +31 -6
  24. data/lib/milk_tea/core/lowering/proc.rb +3 -0
  25. data/lib/milk_tea/core/lowering/resolve.rb +3 -0
  26. data/lib/milk_tea/core/lowering/utils.rb +26 -0
  27. data/lib/milk_tea/core/semantic_analyzer/expressions.rb +21 -2
  28. data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +49 -1
  29. data/lib/milk_tea/core/semantic_analyzer/statements.rb +1 -0
  30. data/lib/milk_tea/core/types/registry.rb +39 -16
  31. data/lib/milk_tea/lsp/server/hover.rb +0 -1
  32. data/lib/milk_tea/lsp/server/text_documents.rb +1 -1
  33. data/lib/milk_tea/tooling/docs_app.rb +1 -1
  34. data/std/box3d.mt +784 -0
  35. data/std/c/box3d.mt +1871 -0
  36. data/std/c/miniaudio.mt +19 -28
  37. data/std/c/steamworks.mt +2 -5
  38. data/std/miniaudio.mt +9 -12
  39. data/std/steamworks.mt +0 -1
  40. metadata +5 -2
@@ -21,40 +21,63 @@ module MilkTea
21
21
  end
22
22
 
23
23
  def self.nullable(base)
24
- _intern([:nullable, base]) { Nullable.new(base) }
24
+ _intern([:nullable, type_signature(base)]) { Nullable.new(base) }
25
25
  end
26
26
 
27
27
  def self.generic_instance(name, arguments)
28
28
  args = arguments.freeze
29
- _intern([:generic, name, args]) { GenericInstance.new(name, args) }
29
+ _intern([:generic, name, args.map { |a| type_signature(a) }.freeze]) { GenericInstance.new(name, args) }
30
30
  end
31
31
 
32
32
  def self.span(element_type)
33
- _intern([:span, element_type]) { Span.new(element_type) }
33
+ _intern([:span, type_signature(element_type)]) { Span.new(element_type) }
34
34
  end
35
35
 
36
36
  def self.task(result_type)
37
- _intern([:task, result_type]) { Task.new(result_type) }
37
+ _intern([:task, type_signature(result_type)]) { Task.new(result_type) }
38
38
  end
39
39
 
40
40
  def self.string_view
41
41
  _intern([:string_view]) { StringView.new }
42
42
  end
43
43
 
44
- # Param signature for intern keys. Parameter#eql? is name-insensitive
45
- # (assignability must not depend on parameter names), so arrays of
46
- # Parameter objects would conflate fn(value: int) with fn(arg0: int) in
47
- # the intern pool. Embedding names here keeps distinct signatures
48
- # distinct across independent programs sharing a long-lived pool (the LSP
49
- # never resets the registry between checks).
44
+ # Name-sensitive signature for intern keys. Parameter#eql? is
45
+ # name-insensitive (assignability must not depend on parameter names), so
46
+ # Function/Proc objects (and any wrapper containing them) that differ only
47
+ # in parameter names collide under Hash/==. Pool keys that embed such
48
+ # types raw therefore conflate fn(value: int) with fn(arg0: int) in a
49
+ # long-lived pool (the LSP never resets the registry between checks),
50
+ # leaking one program's parameter names into another's generated C.
51
+ # Embedding names here keeps distinct signatures distinct.
52
+ def self.type_signature(type)
53
+ case type
54
+ when Function
55
+ [:function, type.name, param_signature(type.params), type_signature(type.return_type), type_signature(type.receiver_type), type.receiver_editable, type.variadic, type.external]
56
+ when Proc
57
+ [:proc, param_signature(type.params), type_signature(type.return_type)]
58
+ when Nullable
59
+ [:nullable, type_signature(type.base)]
60
+ when GenericInstance
61
+ [:generic, type.name, type.arguments.map { |a| type_signature(a) }]
62
+ when Tuple
63
+ [:tuple, type.element_types.map { |t| type_signature(t) }, type.field_names]
64
+ when Span
65
+ [:span, type_signature(type.element_type)]
66
+ when Task
67
+ [:task, type_signature(type.result_type)]
68
+ else
69
+ type
70
+ end
71
+ end
72
+
50
73
  def self.param_signature(params)
51
- params.map { |p| [p.name, p.type, p.mutable, p.passing_mode, p.boundary_type] }
74
+ params.map { |p| [p.name, type_signature(p.type), p.mutable, p.passing_mode, p.boundary_type] }
52
75
  end
53
76
 
54
77
  def self.function(name, params:, return_type:, receiver_type: nil, receiver_editable: false, variadic: false, external: false)
55
78
  params_frozen = params.freeze
56
79
  param_key = param_signature(params_frozen)
57
- _intern([:function, name, param_key, return_type, receiver_type, receiver_editable, variadic, external]) {
80
+ _intern([:function, name, param_key, type_signature(return_type), type_signature(receiver_type), receiver_editable, variadic, external]) {
58
81
  Function.new(name, params: params_frozen, return_type: return_type, receiver_type: receiver_type, receiver_editable: receiver_editable, variadic: variadic, external: external)
59
82
  }
60
83
  end
@@ -62,7 +85,7 @@ module MilkTea
62
85
  def self.proc(params:, return_type:)
63
86
  params_frozen = params.freeze
64
87
  param_key = param_signature(params_frozen)
65
- _intern([:proc, param_key, return_type]) { Proc.new(params: params_frozen, return_type: return_type) }
88
+ _intern([:proc, param_key, type_signature(return_type)]) { Proc.new(params: params_frozen, return_type: return_type) }
66
89
  end
67
90
 
68
91
  def self.parameter(name, type, mutable: false, passing_mode: :plain, boundary_type: nil)
@@ -74,15 +97,15 @@ module MilkTea
74
97
  def self.tuple(element_types, field_names: nil)
75
98
  et_frozen = element_types.freeze
76
99
  fn_frozen = field_names&.freeze
77
- _intern([:tuple, et_frozen, fn_frozen]) { Tuple.new(et_frozen, field_names: fn_frozen) }
100
+ _intern([:tuple, et_frozen.map { |t| type_signature(t) }.freeze, fn_frozen]) { Tuple.new(et_frozen, field_names: fn_frozen) }
78
101
  end
79
102
 
80
103
  def self.soa(element_type, count:)
81
- _intern([:soa, element_type, count]) { SoA.new(element_type, count: count) }
104
+ _intern([:soa, type_signature(element_type), count]) { SoA.new(element_type, count: count) }
82
105
  end
83
106
 
84
107
  def self.simd(element_type, lane_count:)
85
- _intern([:simd, element_type, lane_count]) { Simd.new(element_type, lane_count: lane_count) }
108
+ _intern([:simd, type_signature(element_type), lane_count]) { Simd.new(element_type, lane_count: lane_count) }
86
109
  end
87
110
 
88
111
  def self.lifetime_ref(name)
@@ -1330,7 +1330,6 @@ module MilkTea
1330
1330
  end
1331
1331
  return nil unless idx && tokens[idx].type == :identifier
1332
1332
 
1333
- type_name = tokens[idx].lexeme
1334
1333
  type = resolve_arm_receiver_type(facts, tokens, idx)
1335
1334
 
1336
1335
  arm = if type.respond_to?(:arm)
@@ -86,7 +86,7 @@ module MilkTea
86
86
  rescue StandardError
87
87
  nil
88
88
  end
89
- clear_shared_module_cache if previous_content != disk_content
89
+ @workspace.clear_shared_module_cache if previous_content != disk_content
90
90
  unless defined?(@pull_diagnostics_active) && @pull_diagnostics_active
91
91
  @protocol.write_notification('textDocument/publishDiagnostics', {
92
92
  uri: uri,
@@ -18,7 +18,7 @@ module MilkTea
18
18
  "Files & I/O" => %w[fs path stdio],
19
19
  "System" => %w[ctype errno process time c],
20
20
  "Network & HTTP" => %w[net http uri cookie curl],
21
- "Game & Graphics" => %w[raylib box2d flecs enet cgltf cjson],
21
+ "Game & Graphics" => %w[raylib box2d box3d flecs enet cgltf cjson],
22
22
  "Algorithms & AI" => %w[fsm behavior_tree goap],
23
23
  "Database & Matching" => %w[sqlite3 pcre2],
24
24
  "Utilities" => %w[cli terminal span spatial asset_pack],