mt-lang 0.3.12 → 0.3.14
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/README.md +3 -3
- data/docs/index.html +23 -15
- data/docs/language-design.md +9 -9
- data/docs/language-manual.md +2 -2
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/bindings/bindgen.rb +1 -1
- data/lib/milk_tea/bindings/imported_bindings.rb +1 -1
- data/lib/milk_tea/core/lowering/expressions.rb +47 -3
- data/lib/milk_tea/core/lowering/resolve.rb +26 -2
- data/lib/milk_tea/core/lowering/utils.rb +6 -1
- data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +29 -2
- data/lib/milk_tea/core/types/layout.rb +1 -1
- data/lib/milk_tea/core/{types/types.rb → types.rb} +2 -8
- data/lib/milk_tea/core.rb +1 -1
- data/lib/milk_tea/tooling/cli.rb +33 -6
- data/lib/milk_tea/tooling/sexpr_dumper.rb +342 -0
- data/lib/milk_tea/tooling/sexpr_parser.rb +420 -0
- data/lib/milk_tea/tooling.rb +2 -0
- data/std/{cell.mt → box.mt} +9 -9
- metadata +6 -4
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MilkTea
|
|
4
|
+
module SexprParser
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
# ── public API ────────────────────────────────────────────────────
|
|
8
|
+
|
|
9
|
+
def parse_ir(sexpr)
|
|
10
|
+
tokens = tokenize(sexpr)
|
|
11
|
+
_parse_value(tokens)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def parse_ast(sexpr)
|
|
15
|
+
tokens = tokenize(sexpr)
|
|
16
|
+
_parse_value(tokens)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def parse_tokens(sexpr)
|
|
20
|
+
tokens = tokenize(sexpr)
|
|
21
|
+
_parse_value(tokens)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# ── tokenizer ─────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
Token = Data.define(:kind, :text, :line, :column)
|
|
27
|
+
|
|
28
|
+
def tokenize(source)
|
|
29
|
+
tokens = []
|
|
30
|
+
i = 0
|
|
31
|
+
len = source.length
|
|
32
|
+
line = 1
|
|
33
|
+
col = 1
|
|
34
|
+
while i < len
|
|
35
|
+
ch = source[i]
|
|
36
|
+
case ch
|
|
37
|
+
when "(", ")"
|
|
38
|
+
tokens << Token.new(kind: ch, text: ch, line:, column: col)
|
|
39
|
+
i += 1
|
|
40
|
+
col += 1
|
|
41
|
+
when '"'
|
|
42
|
+
j = i + 1
|
|
43
|
+
chars = +""
|
|
44
|
+
while j < len
|
|
45
|
+
if source[j] == "\\" && j + 1 < len
|
|
46
|
+
case source[j + 1]
|
|
47
|
+
when "n" then chars << "\n"
|
|
48
|
+
when "t" then chars << "\t"
|
|
49
|
+
when "r" then chars << "\r"
|
|
50
|
+
when '"' then chars << '"'
|
|
51
|
+
when "\\" then chars << "\\"
|
|
52
|
+
else chars << source[j + 1]
|
|
53
|
+
end
|
|
54
|
+
j += 2
|
|
55
|
+
elsif source[j] == '"'
|
|
56
|
+
j += 1
|
|
57
|
+
break
|
|
58
|
+
else
|
|
59
|
+
chars << source[j]
|
|
60
|
+
j += 1
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
tokens << Token.new(kind: "string", text: chars, line:, column: col)
|
|
64
|
+
col += j - i
|
|
65
|
+
i = j
|
|
66
|
+
when ":", "-", "0".."9"
|
|
67
|
+
# keyword, negative number, or number
|
|
68
|
+
j = i
|
|
69
|
+
j += 1 while j < len && source[j] != " " && source[j] != "\n" && source[j] != "(" && source[j] != ")" && source[j] != '"'
|
|
70
|
+
text = source[i...j]
|
|
71
|
+
if text.start_with?(":")
|
|
72
|
+
tokens << Token.new(kind: "keyword", text: text[1..], line:, column: col)
|
|
73
|
+
elsif text.match?(/\A-?[0-9]+\.[0-9]+([eE][+-]?[0-9]+)?\z/) || text.match?(/\A-?[0-9]+\.[0-9]*([eE][+-]?[0-9]+)?\z/)
|
|
74
|
+
tokens << Token.new(kind: "float", text:, line:, column: col)
|
|
75
|
+
elsif text.match?(/\A-?[0-9]+\z/)
|
|
76
|
+
tokens << Token.new(kind: "integer", text:, line:, column: col)
|
|
77
|
+
else
|
|
78
|
+
tokens << Token.new(kind: "atom", text:, line:, column: col)
|
|
79
|
+
end
|
|
80
|
+
col += j - i
|
|
81
|
+
i = j
|
|
82
|
+
when /\s/
|
|
83
|
+
if ch == "\n"
|
|
84
|
+
line += 1
|
|
85
|
+
col = 0
|
|
86
|
+
end
|
|
87
|
+
i += 1
|
|
88
|
+
col += 1
|
|
89
|
+
else
|
|
90
|
+
# atom (identifier, true, false, nil)
|
|
91
|
+
j = i
|
|
92
|
+
j += 1 while j < len && source[j] != " " && source[j] != "\n" && source[j] != "(" && source[j] != ")" && source[j] != '"'
|
|
93
|
+
text = source[i...j]
|
|
94
|
+
tokens << Token.new(kind: "atom", text:, line:, column: col)
|
|
95
|
+
col += j - i
|
|
96
|
+
i = j
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
tokens
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# ── parser ────────────────────────────────────────────────────────
|
|
103
|
+
|
|
104
|
+
def _parse_value(tokens, index = [0])
|
|
105
|
+
token = tokens[index[0]]
|
|
106
|
+
return nil unless token
|
|
107
|
+
|
|
108
|
+
case token.kind
|
|
109
|
+
when "("
|
|
110
|
+
_parse_list(tokens, index)
|
|
111
|
+
when "string"
|
|
112
|
+
index[0] += 1
|
|
113
|
+
token.text
|
|
114
|
+
when "integer"
|
|
115
|
+
index[0] += 1
|
|
116
|
+
Integer(token.text)
|
|
117
|
+
when "float"
|
|
118
|
+
index[0] += 1
|
|
119
|
+
Float(token.text)
|
|
120
|
+
when "keyword"
|
|
121
|
+
index[0] += 1
|
|
122
|
+
token.text.gsub("-", "_").to_sym
|
|
123
|
+
when "atom"
|
|
124
|
+
index[0] += 1
|
|
125
|
+
case token.text
|
|
126
|
+
when "nil" then nil
|
|
127
|
+
when "true" then true
|
|
128
|
+
when "false" then false
|
|
129
|
+
else token.text
|
|
130
|
+
end
|
|
131
|
+
else
|
|
132
|
+
raise "unexpected token: #{token.inspect}"
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def _parse_list(tokens, index)
|
|
137
|
+
index[0] += 1 # skip "("
|
|
138
|
+
if tokens[index[0]]&.kind == ")"
|
|
139
|
+
index[0] += 1 # skip ")"
|
|
140
|
+
return []
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
first = _parse_value(tokens, index)
|
|
144
|
+
|
|
145
|
+
if first.is_a?(String) && first.match?(/\A[A-Z]/)
|
|
146
|
+
_parse_typed_node(tokens, index, first, first)
|
|
147
|
+
else
|
|
148
|
+
# plain array — first element was the first value
|
|
149
|
+
result = [first]
|
|
150
|
+
while tokens[index[0]]&.kind != ")"
|
|
151
|
+
result << _parse_value(tokens, index)
|
|
152
|
+
end
|
|
153
|
+
index[0] += 1 # skip ")"
|
|
154
|
+
result
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def _parse_typed_node(tokens, index, first_token, first_str)
|
|
159
|
+
type_name = _resolve_type_name(first_str)
|
|
160
|
+
|
|
161
|
+
# Collect keyword-value pairs
|
|
162
|
+
fields = {}
|
|
163
|
+
while tokens[index[0]]&.kind == "keyword"
|
|
164
|
+
kw = tokens[index[0]].text.gsub("-", "_").to_sym
|
|
165
|
+
index[0] += 1 # skip keyword
|
|
166
|
+
val = _parse_value(tokens, index)
|
|
167
|
+
fields[kw] = val
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
index[0] += 1 # skip ")"
|
|
171
|
+
|
|
172
|
+
if type_name.start_with?("Types::")
|
|
173
|
+
_construct_types_object(type_name, fields)
|
|
174
|
+
elsif type_name.start_with?("IR::")
|
|
175
|
+
_construct_ir_object(type_name, fields)
|
|
176
|
+
elsif type_name.start_with?("AST::")
|
|
177
|
+
_construct_ast_object(type_name, fields)
|
|
178
|
+
else
|
|
179
|
+
_construct_generic(type_name, fields)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# ── type name resolution ──────────────────────────────────────────
|
|
184
|
+
|
|
185
|
+
def _resolve_type_name(str)
|
|
186
|
+
# Already fully qualified ("Types::Primitive", "IR::Program")
|
|
187
|
+
return str if str.include?("::")
|
|
188
|
+
|
|
189
|
+
# Try common prefixes
|
|
190
|
+
[
|
|
191
|
+
"MilkTea::IR::#{str}",
|
|
192
|
+
"MilkTea::AST::#{str}",
|
|
193
|
+
"MilkTea::Types::#{str}",
|
|
194
|
+
].each do |candidate|
|
|
195
|
+
begin
|
|
196
|
+
return candidate if Object.const_get(candidate)
|
|
197
|
+
rescue NameError
|
|
198
|
+
nil
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
str
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# ── object constructors ───────────────────────────────────────────
|
|
205
|
+
|
|
206
|
+
def _construct_ir_object(type_name, fields)
|
|
207
|
+
name = type_name.split("::").last
|
|
208
|
+
klass = MilkTea::IR.const_get(name)
|
|
209
|
+
sym_fields = fields.transform_keys(&:to_sym)
|
|
210
|
+
klass.new(**sym_fields)
|
|
211
|
+
rescue NameError
|
|
212
|
+
_construct_generic(type_name, fields)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def _construct_ast_object(type_name, fields)
|
|
216
|
+
name = type_name.split("::").last
|
|
217
|
+
klass = MilkTea::AST.const_get(name)
|
|
218
|
+
sym_fields = fields.transform_keys(&:to_sym)
|
|
219
|
+
klass.new(**sym_fields)
|
|
220
|
+
rescue NameError
|
|
221
|
+
_construct_generic(type_name, fields)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def _construct_types_object(type_name, fields)
|
|
225
|
+
short = type_name.sub(/\ATypes::/, "")
|
|
226
|
+
case short
|
|
227
|
+
when "Primitive"
|
|
228
|
+
Types::Registry.primitive(fields[:name])
|
|
229
|
+
when "Null"
|
|
230
|
+
Types::Null.new(fields[:target_type])
|
|
231
|
+
when "Nullable"
|
|
232
|
+
Types::Registry.nullable(fields[:base])
|
|
233
|
+
when "Generic"
|
|
234
|
+
Types::Registry.generic_instance(fields[:name], fields[:arguments])
|
|
235
|
+
when "Span"
|
|
236
|
+
Types::Registry.span(fields[:element_type])
|
|
237
|
+
when "Task"
|
|
238
|
+
rt = fields[:result_type] || Types::Registry.primitive("void")
|
|
239
|
+
Types::Registry.task(rt)
|
|
240
|
+
when "Function"
|
|
241
|
+
Types::Registry.function(
|
|
242
|
+
fields[:name],
|
|
243
|
+
params: fields[:params] || [],
|
|
244
|
+
return_type: fields[:return_type],
|
|
245
|
+
receiver_type: fields[:receiver_type],
|
|
246
|
+
receiver_editable: fields[:receiver_editable] || false,
|
|
247
|
+
variadic: fields[:variadic] || false,
|
|
248
|
+
external: fields[:external] || false,
|
|
249
|
+
)
|
|
250
|
+
when "Proc"
|
|
251
|
+
Types::Registry.proc(params: fields[:params] || [], return_type: fields[:return_type])
|
|
252
|
+
when "Tuple"
|
|
253
|
+
Types::Registry.tuple(
|
|
254
|
+
fields.fetch(:element_types, []),
|
|
255
|
+
field_names: fields[:field_names],
|
|
256
|
+
)
|
|
257
|
+
when "Vector"
|
|
258
|
+
Types::Registry.generic_instance(fields[:name], [Types::LiteralTypeArg.new(fields[:name].delete_prefix("vec").to_i)])
|
|
259
|
+
when "Matrix"
|
|
260
|
+
Types::Registry.generic_instance(fields[:name], [Types::LiteralTypeArg.new(fields[:name].delete_prefix("mat").to_i)])
|
|
261
|
+
when "Quaternion"
|
|
262
|
+
Types::Registry.generic_instance("quat", [])
|
|
263
|
+
when "SoA"
|
|
264
|
+
Types::Registry.soa(fields[:element_type], count: fields[:count])
|
|
265
|
+
when "Simd"
|
|
266
|
+
Types::Registry.simd(fields[:element_type], lane_count: fields[:lane_count])
|
|
267
|
+
when "StringView"
|
|
268
|
+
Types::Registry.string_view
|
|
269
|
+
when "Parameter"
|
|
270
|
+
Types::Registry.parameter(
|
|
271
|
+
fields[:name],
|
|
272
|
+
fields[:type],
|
|
273
|
+
mutable: fields[:mutable] || false,
|
|
274
|
+
passing_mode: fields[:passing_mode]&.to_sym || :plain,
|
|
275
|
+
boundary_type: fields[:boundary_type],
|
|
276
|
+
)
|
|
277
|
+
when "LiteralTypeArg"
|
|
278
|
+
Types::LiteralTypeArg.new(fields[:value])
|
|
279
|
+
when "TypeVar"
|
|
280
|
+
Types::TypeVar.new(fields[:name])
|
|
281
|
+
when "LifetimeRef"
|
|
282
|
+
Types::LifetimeRef.new(fields[:name])
|
|
283
|
+
when "Dyn"
|
|
284
|
+
interface_binding = MilkTea::SemanticAnalyzer::InterfaceBinding.new(
|
|
285
|
+
name: fields[:interface_name],
|
|
286
|
+
methods: [],
|
|
287
|
+
ast: nil,
|
|
288
|
+
module_name: nil,
|
|
289
|
+
)
|
|
290
|
+
Types::Registry.dyn(interface_binding, fields.fetch(:type_arguments, []))
|
|
291
|
+
when "Struct", "StructInstance", "Union", "Variant", "VariantInstance",
|
|
292
|
+
"VariantArmPayload", "Enum", "Flags", "Opaque", "Event", "Subscription", "Handle",
|
|
293
|
+
"TypeType", "Error", "DynVtable", "ReflectionHandleType", "StructHandle",
|
|
294
|
+
"FieldHandle", "CallableHandle", "AttributeHandle", "MemberHandle",
|
|
295
|
+
"GenericStructDefinition", "GenericVariantDefinition"
|
|
296
|
+
_construct_standalone_type(short, fields)
|
|
297
|
+
else
|
|
298
|
+
_construct_standalone_type(short, fields)
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
def _construct_standalone_type(short, fields)
|
|
303
|
+
case short
|
|
304
|
+
when "TypeType"
|
|
305
|
+
Types::TypeType.new
|
|
306
|
+
when "Error"
|
|
307
|
+
Types::Error.new
|
|
308
|
+
when "Subscription"
|
|
309
|
+
Types::Subscription.new
|
|
310
|
+
when "Handle"
|
|
311
|
+
Types::Handle.new
|
|
312
|
+
when "Struct"
|
|
313
|
+
Types::Struct.new(
|
|
314
|
+
fields[:name],
|
|
315
|
+
module_name: fields[:module_name],
|
|
316
|
+
external: false,
|
|
317
|
+
packed: false,
|
|
318
|
+
alignment: nil,
|
|
319
|
+
linkage_name: nil,
|
|
320
|
+
lifetime_params: [],
|
|
321
|
+
)
|
|
322
|
+
when "Variant"
|
|
323
|
+
Types::Variant.new(fields[:name], module_name: fields[:module_name])
|
|
324
|
+
when "Union"
|
|
325
|
+
Types::Union.new(
|
|
326
|
+
fields[:name],
|
|
327
|
+
module_name: fields[:module_name],
|
|
328
|
+
external: false,
|
|
329
|
+
packed: false,
|
|
330
|
+
alignment: nil,
|
|
331
|
+
linkage_name: nil,
|
|
332
|
+
lifetime_params: [],
|
|
333
|
+
)
|
|
334
|
+
when "Opaque"
|
|
335
|
+
Types::Opaque.new(fields[:name], module_name: fields[:module_name], external: false, linkage_name: nil)
|
|
336
|
+
when "Enum"
|
|
337
|
+
Types::Enum.new(fields[:name], module_name: fields[:module_name], external: false)
|
|
338
|
+
when "Flags"
|
|
339
|
+
Types::Flags.new(fields[:name], module_name: fields[:module_name], external: false)
|
|
340
|
+
when "Event"
|
|
341
|
+
Types::Event.new(
|
|
342
|
+
fields[:name],
|
|
343
|
+
capacity: fields[:capacity],
|
|
344
|
+
payload_type: fields[:payload_type],
|
|
345
|
+
module_name: nil,
|
|
346
|
+
visibility: :private,
|
|
347
|
+
owner_type_name: nil,
|
|
348
|
+
)
|
|
349
|
+
when "StringView"
|
|
350
|
+
Types::Registry.string_view
|
|
351
|
+
else
|
|
352
|
+
_construct_types_fallback(short, fields)
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def _construct_types_fallback(short, fields)
|
|
357
|
+
klass = begin
|
|
358
|
+
Types.const_get(short)
|
|
359
|
+
rescue NameError
|
|
360
|
+
return fields
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
begin
|
|
364
|
+
sym_fields = fields.transform_keys(&:to_sym)
|
|
365
|
+
klass.new(**sym_fields)
|
|
366
|
+
rescue StandardError
|
|
367
|
+
begin
|
|
368
|
+
args = fields.values
|
|
369
|
+
klass.new(*args)
|
|
370
|
+
rescue StandardError
|
|
371
|
+
begin
|
|
372
|
+
obj = klass.allocate
|
|
373
|
+
fields.each do |k, v|
|
|
374
|
+
ivar = "@#{k}"
|
|
375
|
+
obj.instance_variable_set(ivar, v) if obj.instance_variable_defined?(ivar) || obj.respond_to?(:"#{k}=")
|
|
376
|
+
rescue StandardError
|
|
377
|
+
nil
|
|
378
|
+
end
|
|
379
|
+
begin
|
|
380
|
+
obj.instance_variable_set(:@hash, obj.object_id.hash)
|
|
381
|
+
rescue StandardError
|
|
382
|
+
nil
|
|
383
|
+
end
|
|
384
|
+
obj
|
|
385
|
+
rescue StandardError
|
|
386
|
+
fields
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
def _construct_generic(type_name, fields)
|
|
393
|
+
klass = begin
|
|
394
|
+
name_parts = type_name.split("::")
|
|
395
|
+
if name_parts.length > 1
|
|
396
|
+
top = Object.const_get(name_parts.first)
|
|
397
|
+
rest = name_parts[1..].join("::")
|
|
398
|
+
top.const_get(rest)
|
|
399
|
+
else
|
|
400
|
+
Object.const_get(type_name)
|
|
401
|
+
end
|
|
402
|
+
rescue NameError
|
|
403
|
+
nil
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
if klass && klass.respond_to?(:members)
|
|
407
|
+
sym_fields = fields.transform_keys(&:to_sym)
|
|
408
|
+
klass.new(**sym_fields)
|
|
409
|
+
else
|
|
410
|
+
fields
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
# ── helpers ───────────────────────────────────────────────────────
|
|
415
|
+
|
|
416
|
+
def _unescape(str)
|
|
417
|
+
str.gsub("\\n", "\n").gsub("\\t", "\t").gsub("\\r", "\r").gsub('\\"', '"').gsub("\\\\", "\\")
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
end
|
data/lib/milk_tea/tooling.rb
CHANGED
|
@@ -7,6 +7,8 @@ require_relative "packages"
|
|
|
7
7
|
require_relative "tooling/debug_map"
|
|
8
8
|
require_relative "tooling/debug_info_formatter"
|
|
9
9
|
require_relative "tooling/asset_pack"
|
|
10
|
+
require_relative "tooling/sexpr_dumper"
|
|
11
|
+
require_relative "tooling/sexpr_parser"
|
|
10
12
|
require_relative "tooling/build"
|
|
11
13
|
require_relative "tooling/run"
|
|
12
14
|
require_relative "tooling/cst_formatter"
|
data/std/{cell.mt → box.mt}
RENAMED
|
@@ -3,42 +3,42 @@ import std.mem.heap as heap
|
|
|
3
3
|
## Explicit single-value heap storage.
|
|
4
4
|
##
|
|
5
5
|
## This is the intended escape hatch for shared mutable proc state.
|
|
6
|
-
## Allocation stays visible at the call site via `
|
|
7
|
-
public struct
|
|
6
|
+
## Allocation stays visible at the call site via `box.alloc(...)`.
|
|
7
|
+
public struct Box[T]:
|
|
8
8
|
storage: own[T]?
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
public function alloc[T](value: T) ->
|
|
11
|
+
public function alloc[T](value: T) -> Box[T]:
|
|
12
12
|
let storage = heap.must_alloc[T](1)
|
|
13
13
|
read(storage) = value
|
|
14
|
-
return
|
|
14
|
+
return Box[T](storage = storage)
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
extending
|
|
17
|
+
extending Box[T]:
|
|
18
18
|
public function as_ptr() -> ptr[T]:
|
|
19
19
|
let storage = this.storage else:
|
|
20
|
-
fatal(c"
|
|
20
|
+
fatal(c"box.Box.as_ptr released box")
|
|
21
21
|
|
|
22
22
|
return storage
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
public function get() -> T:
|
|
26
26
|
let storage = this.storage else:
|
|
27
|
-
fatal(c"
|
|
27
|
+
fatal(c"box.Box.get released box")
|
|
28
28
|
|
|
29
29
|
return read(storage)
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
public function set(value: T) -> void:
|
|
33
33
|
let storage = this.storage else:
|
|
34
|
-
fatal(c"
|
|
34
|
+
fatal(c"box.Box.set released box")
|
|
35
35
|
|
|
36
36
|
read(storage) = value
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
public function replace(value: T) -> T:
|
|
40
40
|
let storage = this.storage else:
|
|
41
|
-
fatal(c"
|
|
41
|
+
fatal(c"box.Box.replace released box")
|
|
42
42
|
|
|
43
43
|
let previous = read(storage)
|
|
44
44
|
read(storage) = value
|
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.3.
|
|
4
|
+
version: 0.3.14
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Long (Teefan) Tran
|
|
@@ -288,10 +288,10 @@ files:
|
|
|
288
288
|
- lib/milk_tea/core/semantic_analyzer/type_declaration.rb
|
|
289
289
|
- lib/milk_tea/core/token.rb
|
|
290
290
|
- lib/milk_tea/core/token_stream.rb
|
|
291
|
+
- lib/milk_tea/core/types.rb
|
|
291
292
|
- lib/milk_tea/core/types/layout.rb
|
|
292
293
|
- lib/milk_tea/core/types/predicates.rb
|
|
293
294
|
- lib/milk_tea/core/types/registry.rb
|
|
294
|
-
- lib/milk_tea/core/types/types.rb
|
|
295
295
|
- lib/milk_tea/core/types/visitor.rb
|
|
296
296
|
- lib/milk_tea/dap.rb
|
|
297
297
|
- lib/milk_tea/dap/backends/lldb_dap.rb
|
|
@@ -385,6 +385,8 @@ files:
|
|
|
385
385
|
- lib/milk_tea/tooling/public/css/docs.css
|
|
386
386
|
- lib/milk_tea/tooling/public/js/docs.js
|
|
387
387
|
- lib/milk_tea/tooling/run.rb
|
|
388
|
+
- lib/milk_tea/tooling/sexpr_dumper.rb
|
|
389
|
+
- lib/milk_tea/tooling/sexpr_parser.rb
|
|
388
390
|
- lib/milk_tea/tooling/templates/wasm_shell.html
|
|
389
391
|
- lib/milk_tea/tooling/toolchain_cli.rb
|
|
390
392
|
- lib/milk_tea/tooling/views/404.erb
|
|
@@ -403,6 +405,7 @@ files:
|
|
|
403
405
|
- std/binary_heap.mt
|
|
404
406
|
- std/bitset.mt
|
|
405
407
|
- std/blackboard.mt
|
|
408
|
+
- std/box.mt
|
|
406
409
|
- std/box2d.mt
|
|
407
410
|
- std/bytes.mt
|
|
408
411
|
- std/c/box2d.mt
|
|
@@ -461,7 +464,6 @@ files:
|
|
|
461
464
|
- std/c/zlib.mt
|
|
462
465
|
- std/c/zlib_support.h
|
|
463
466
|
- std/c/zstd.mt
|
|
464
|
-
- std/cell.mt
|
|
465
467
|
- std/cgltf.mt
|
|
466
468
|
- std/cjson.mt
|
|
467
469
|
- std/cli.mt
|
|
@@ -603,7 +605,7 @@ metadata:
|
|
|
603
605
|
homepage_uri: https://teefan.github.io/mt-lang/
|
|
604
606
|
source_code_uri: https://github.com/teefan/mt-lang
|
|
605
607
|
post_install_message: |
|
|
606
|
-
Milk Tea 0.3.
|
|
608
|
+
Milk Tea 0.3.14 installed!
|
|
607
609
|
|
|
608
610
|
System requirements:
|
|
609
611
|
- A C compiler (gcc or clang) must be available on PATH
|