mt-lang 0.4.23 → 0.4.24
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 +4 -4
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/core/types/layout.rb +90 -19
- data/std/vec.mt +1 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 95423784419c8060f10277cb7abbb1fe1cd955fe648008781d1184976968e2d8
|
|
4
|
+
data.tar.gz: 6e1b33f4c2a17226dc34ba00618b89be6f329841c5badc7a53ccd022daa3c54d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aec1e36ac602ad755b89252058932df48abd25c0e645e212fa404afd25b23679e86d6cf45a970a36d566b08c9be774231496cf59766f64efa366da382e559963
|
|
7
|
+
data.tar.gz: 85af5d83647fd5cb635bec77a3ae8846be1b6f8f62638b5c82a2f99b9f76f2de6fb08455b6660e0cace75669e9281456a3d7336043ef3009988e50fc3efb4c0c
|
data/lib/milk_tea/base.rb
CHANGED
|
@@ -10,11 +10,11 @@ module MilkTea
|
|
|
10
10
|
POINTER_SIZE = Fiddle::SIZEOF_VOIDP
|
|
11
11
|
|
|
12
12
|
def self.size_of(type)
|
|
13
|
-
size_and_alignment(type,
|
|
13
|
+
size_and_alignment(type, nil)&.first
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def self.alignment_of(type)
|
|
17
|
-
size_and_alignment(type,
|
|
17
|
+
size_and_alignment(type, nil)&.last
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def self.offset_of(type, field_name)
|
|
@@ -38,6 +38,14 @@ module MilkTea
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
# Computes [size, alignment] for a type.
|
|
42
|
+
#
|
|
43
|
+
# `stack` carries the aggregates on the current root-to-leaf path,
|
|
44
|
+
# pass-down only (never popped). A field whose type reaches any aggregate
|
|
45
|
+
# on that path participates in a storage cycle, and the C backend embeds
|
|
46
|
+
# exactly those fields as pointers (see
|
|
47
|
+
# CBackend#build_cyclic_aggregate_pairs and the cyclic field emission in
|
|
48
|
+
# type_declaration.rb), so layout sizes back-edge fields as raw pointers.
|
|
41
49
|
def self.size_and_alignment(type, stack)
|
|
42
50
|
case type
|
|
43
51
|
when Types::Primitive
|
|
@@ -48,24 +56,24 @@ module MilkTea
|
|
|
48
56
|
if type.is_a?(Types::Function) || layout_pointer_like_nullable_base?(type.base)
|
|
49
57
|
[POINTER_SIZE, POINTER_SIZE]
|
|
50
58
|
else
|
|
51
|
-
with_stack(type, stack) do
|
|
52
|
-
layout = struct_layout(nullable_opt_layout_fields(type.base), packed: false, alignment: nil, stack:)
|
|
59
|
+
with_stack(type, stack) do |next_stack|
|
|
60
|
+
layout = struct_layout(nullable_opt_layout_fields(type.base), packed: false, alignment: nil, stack: next_stack)
|
|
53
61
|
[layout[:size], layout[:alignment]]
|
|
54
62
|
end
|
|
55
63
|
end
|
|
56
64
|
when Types::StringView, Types::Span, Types::Task, Types::Struct, Types::StructInstance
|
|
57
|
-
with_stack(type, stack) do
|
|
58
|
-
layout = struct_layout(ordered_fields(type), packed: packed_layout?(type), alignment: explicit_alignment(type), stack:)
|
|
65
|
+
with_stack(type, stack) do |next_stack|
|
|
66
|
+
layout = struct_layout(ordered_fields(type), packed: packed_layout?(type), alignment: explicit_alignment(type), stack: next_stack)
|
|
59
67
|
[layout[:size], layout[:alignment]]
|
|
60
68
|
end
|
|
61
69
|
when Types::Union
|
|
62
|
-
with_stack(type, stack) do
|
|
63
|
-
layout = union_layout(ordered_fields(type), packed: packed_layout?(type), alignment: explicit_alignment(type), stack:)
|
|
70
|
+
with_stack(type, stack) do |next_stack|
|
|
71
|
+
layout = union_layout(ordered_fields(type), packed: packed_layout?(type), alignment: explicit_alignment(type), stack: next_stack)
|
|
64
72
|
[layout[:size], layout[:alignment]]
|
|
65
73
|
end
|
|
66
74
|
when Types::Variant, Types::VariantInstance
|
|
67
|
-
with_stack(type, stack) do
|
|
68
|
-
layout = variant_layout(type, stack:)
|
|
75
|
+
with_stack(type, stack) do |next_stack|
|
|
76
|
+
layout = variant_layout(type, stack: next_stack)
|
|
69
77
|
[layout[:size], layout[:alignment]]
|
|
70
78
|
end
|
|
71
79
|
when Types::GenericInstance
|
|
@@ -128,8 +136,8 @@ module MilkTea
|
|
|
128
136
|
when "str_buffer"
|
|
129
137
|
return unless str_buffer_type?(type)
|
|
130
138
|
|
|
131
|
-
with_stack(type, stack) do
|
|
132
|
-
layout = struct_layout(str_buffer_fields(type), packed: false, alignment: nil, stack:)
|
|
139
|
+
with_stack(type, stack) do |next_stack|
|
|
140
|
+
layout = struct_layout(str_buffer_fields(type), packed: false, alignment: nil, stack: next_stack)
|
|
133
141
|
[layout[:size], layout[:alignment]]
|
|
134
142
|
end
|
|
135
143
|
end
|
|
@@ -151,7 +159,7 @@ module MilkTea
|
|
|
151
159
|
|
|
152
160
|
def self.struct_layout(fields, packed:, alignment:, stack:)
|
|
153
161
|
field_infos = fields.map do |field_name, field_type|
|
|
154
|
-
field_layout =
|
|
162
|
+
field_layout = field_size_and_alignment(field_type, stack)
|
|
155
163
|
return nil unless field_layout
|
|
156
164
|
|
|
157
165
|
[field_name, field_layout.first, field_layout.last]
|
|
@@ -162,7 +170,7 @@ module MilkTea
|
|
|
162
170
|
|
|
163
171
|
def self.union_layout(fields, packed:, alignment:, stack:)
|
|
164
172
|
field_infos = fields.map do |_field_name, field_type|
|
|
165
|
-
field_layout =
|
|
173
|
+
field_layout = field_size_and_alignment(field_type, stack)
|
|
166
174
|
return nil unless field_layout
|
|
167
175
|
|
|
168
176
|
field_layout
|
|
@@ -171,6 +179,30 @@ module MilkTea
|
|
|
171
179
|
union_layout_from_layouts(field_infos.map { |size, field_alignment| { size:, alignment: field_alignment } }, packed:, alignment:)
|
|
172
180
|
end
|
|
173
181
|
|
|
182
|
+
# A field whose type reaches any aggregate on the current path is a
|
|
183
|
+
# storage-cycle back edge. The C backend emits such fields as pointers
|
|
184
|
+
# (element pointer for arrays), so they occupy pointer-size storage here.
|
|
185
|
+
def self.field_size_and_alignment(field_type, stack)
|
|
186
|
+
return [POINTER_SIZE, POINTER_SIZE] if cyclic_back_edge?(field_type, stack)
|
|
187
|
+
|
|
188
|
+
size_and_alignment(field_type, stack)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def self.cyclic_back_edge?(field_type, stack)
|
|
192
|
+
return false if stack.nil? || stack.empty?
|
|
193
|
+
|
|
194
|
+
aggregate_reaches_in_progress?(field_type, stack, {})
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def self.aggregate_reaches_in_progress?(type, stack, visited)
|
|
198
|
+
return false if visited.key?(type.object_id)
|
|
199
|
+
|
|
200
|
+
visited[type.object_id] = true
|
|
201
|
+
return true if stack.key?(type)
|
|
202
|
+
|
|
203
|
+
reachability_children(type).any? { |child| aggregate_reaches_in_progress?(child, stack, visited) }
|
|
204
|
+
end
|
|
205
|
+
|
|
174
206
|
def self.struct_layout_from_infos(field_infos, packed:, alignment:)
|
|
175
207
|
offsets = {}
|
|
176
208
|
offset = 0
|
|
@@ -253,13 +285,52 @@ module MilkTea
|
|
|
253
285
|
remainder.zero? ? value : value + alignment - remainder
|
|
254
286
|
end
|
|
255
287
|
|
|
288
|
+
# `stack` is the set of aggregates on the current path, pass-down only.
|
|
289
|
+
# A nil or empty stack means the caller is not inside an aggregate yet.
|
|
290
|
+
# Yields the extended stack; returns nil when `type` is already in progress
|
|
291
|
+
# (callers treat that as unreachable while mirroring backend semantics).
|
|
256
292
|
def self.with_stack(type, stack)
|
|
257
|
-
|
|
293
|
+
next_stack = (stack || {}).dup
|
|
294
|
+
return nil if next_stack.key?(type)
|
|
295
|
+
|
|
296
|
+
next_stack[type] = true
|
|
297
|
+
yield(next_stack)
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# Structural expansion used for back-edge detection. Mirrors the
|
|
301
|
+
# CBackend's `aggregate_type_dependencies` so pointer-broken cyclic
|
|
302
|
+
# fields agree with the emitted C struct layout.
|
|
303
|
+
def self.reachability_children(type)
|
|
304
|
+
case type
|
|
305
|
+
when Types::Nullable
|
|
306
|
+
[type.base]
|
|
307
|
+
when Types::GenericInstance
|
|
308
|
+
if pointer_type?(type)
|
|
309
|
+
[]
|
|
310
|
+
elsif array_type?(type)
|
|
311
|
+
[array_element_type(type)]
|
|
312
|
+
else
|
|
313
|
+
[]
|
|
314
|
+
end
|
|
315
|
+
when Types::Span
|
|
316
|
+
[type.element_type]
|
|
317
|
+
when Types::Struct, Types::StructInstance, Types::Union
|
|
318
|
+
type.fields.values
|
|
319
|
+
when Types::Variant, Types::VariantInstance
|
|
320
|
+
type.arm_names.flat_map { |name| type.arm(name).values }
|
|
321
|
+
when Types::VariantArmPayload
|
|
322
|
+
type.fields.values
|
|
323
|
+
else
|
|
324
|
+
[]
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def self.pointer_type?(type)
|
|
329
|
+
type.is_a?(Types::GenericInstance) && %w[ptr const_ptr own ref].include?(type.name)
|
|
330
|
+
end
|
|
258
331
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
ensure
|
|
262
|
-
stack.delete(type)
|
|
332
|
+
def self.array_element_type(type)
|
|
333
|
+
type.arguments.first
|
|
263
334
|
end
|
|
264
335
|
end
|
|
265
336
|
end
|
data/std/vec.mt
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mt-lang
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.24
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Long (Teefan) Tran
|
|
@@ -630,7 +630,7 @@ metadata:
|
|
|
630
630
|
homepage_uri: https://teefan.github.io/mt-lang/
|
|
631
631
|
source_code_uri: https://github.com/teefan/mt-lang
|
|
632
632
|
post_install_message: |
|
|
633
|
-
Milk Tea 0.4.
|
|
633
|
+
Milk Tea 0.4.24 installed!
|
|
634
634
|
|
|
635
635
|
System requirements:
|
|
636
636
|
- A C compiler (gcc or clang) must be available on PATH
|