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,342 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MilkTea
|
|
4
|
+
module SexprDumper
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def dump_ir(program)
|
|
8
|
+
buf = +""
|
|
9
|
+
emit_value(program, buf)
|
|
10
|
+
buf
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def dump_ast(ast)
|
|
14
|
+
buf = +""
|
|
15
|
+
emit_value(ast, buf)
|
|
16
|
+
buf
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def dump_tokens(tokens)
|
|
20
|
+
buf = +""
|
|
21
|
+
buf << "("
|
|
22
|
+
tokens.each_with_index { |t, i| buf << " " if i > 0; emit_token(t, buf) }
|
|
23
|
+
buf << ")"
|
|
24
|
+
buf
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# ── value dispatcher ──────────────────────────────────────────────
|
|
28
|
+
|
|
29
|
+
def emit_value(value, buf)
|
|
30
|
+
case value
|
|
31
|
+
when ::Data then emit_data(value, buf)
|
|
32
|
+
when Array then emit_array(value, buf)
|
|
33
|
+
when *TYPES_CLASSES then emit_types_object(value, buf)
|
|
34
|
+
when nil then buf << "nil"
|
|
35
|
+
when true then buf << "true"
|
|
36
|
+
when false then buf << "false"
|
|
37
|
+
when Integer then buf << value.to_s
|
|
38
|
+
when Float then buf << format_float(value)
|
|
39
|
+
when String then emit_string(value, buf)
|
|
40
|
+
when Symbol then buf << ":" << value.to_s.tr("_", "-")
|
|
41
|
+
else buf << escape_string(value.to_s)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# ── Data serialisation ────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
def emit_data(node, buf)
|
|
48
|
+
type_name = node.class.name.split("::").last(2).join("::")
|
|
49
|
+
members = node.class.members
|
|
50
|
+
buf << "(" << type_name
|
|
51
|
+
members.each do |field|
|
|
52
|
+
val = node.public_send(field)
|
|
53
|
+
buf << " :" << field.to_s << " "
|
|
54
|
+
emit_value(val, buf)
|
|
55
|
+
end
|
|
56
|
+
buf << ")"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# ── Array serialisation ───────────────────────────────────────────
|
|
60
|
+
|
|
61
|
+
def emit_array(values, buf)
|
|
62
|
+
buf << "("
|
|
63
|
+
values.each_with_index do |v, i|
|
|
64
|
+
buf << " " if i > 0
|
|
65
|
+
emit_value(v, buf)
|
|
66
|
+
end
|
|
67
|
+
buf << ")"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# ── Token serialisation ───────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
def emit_token(token, buf)
|
|
73
|
+
buf << "(token :type " << emit_token_type(token.type)
|
|
74
|
+
buf << " :lexeme "
|
|
75
|
+
emit_string(token.lexeme, buf)
|
|
76
|
+
buf << " :literal "
|
|
77
|
+
emit_value(token.literal, buf)
|
|
78
|
+
buf << " :line " << token.line.to_s
|
|
79
|
+
buf << " :column " << token.column.to_s
|
|
80
|
+
buf << " :start_offset " << token.start_offset.to_s
|
|
81
|
+
buf << " :end_offset " << token.end_offset.to_s
|
|
82
|
+
buf << ")"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def emit_token_type(sym)
|
|
86
|
+
":" + sym.to_s.tr("_", "-")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# ── Types serialisation ───────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
TYPES_SHORT_NAMES = {
|
|
92
|
+
"MilkTea::Types::Primitive" => "Primitive",
|
|
93
|
+
"MilkTea::Types::Null" => "Null",
|
|
94
|
+
"MilkTea::Types::Nullable" => "Nullable",
|
|
95
|
+
"MilkTea::Types::GenericInstance" => "Generic",
|
|
96
|
+
"MilkTea::Types::Span" => "Span",
|
|
97
|
+
"MilkTea::Types::Task" => "Task",
|
|
98
|
+
"MilkTea::Types::Function" => "Function",
|
|
99
|
+
"MilkTea::Types::Proc" => "Proc",
|
|
100
|
+
"MilkTea::Types::Tuple" => "Tuple",
|
|
101
|
+
"MilkTea::Types::Vector" => "Vector",
|
|
102
|
+
"MilkTea::Types::Matrix" => "Matrix",
|
|
103
|
+
"MilkTea::Types::Quaternion" => "Quaternion",
|
|
104
|
+
"MilkTea::Types::SoA" => "SoA",
|
|
105
|
+
"MilkTea::Types::Simd" => "Simd",
|
|
106
|
+
"MilkTea::Types::Struct" => "Struct",
|
|
107
|
+
"MilkTea::Types::StructInstance" => "StructInstance",
|
|
108
|
+
"MilkTea::Types::Union" => "Union",
|
|
109
|
+
"MilkTea::Types::Variant" => "Variant",
|
|
110
|
+
"MilkTea::Types::VariantInstance" => "VariantInstance",
|
|
111
|
+
"MilkTea::Types::VariantArmPayload" => "VariantArmPayload",
|
|
112
|
+
"MilkTea::Types::Enum" => "Enum",
|
|
113
|
+
"MilkTea::Types::Flags" => "Flags",
|
|
114
|
+
"MilkTea::Types::Opaque" => "Opaque",
|
|
115
|
+
"MilkTea::Types::StringView" => "StringView",
|
|
116
|
+
"MilkTea::Types::Dyn" => "Dyn",
|
|
117
|
+
"MilkTea::Types::Parameter" => "Parameter",
|
|
118
|
+
"MilkTea::Types::LiteralTypeArg" => "LiteralTypeArg",
|
|
119
|
+
"MilkTea::Types::TypeVar" => "TypeVar",
|
|
120
|
+
"MilkTea::Types::LifetimeRef" => "LifetimeRef",
|
|
121
|
+
"MilkTea::Types::Event" => "Event",
|
|
122
|
+
"MilkTea::Types::Subscription" => "Subscription",
|
|
123
|
+
"MilkTea::Types::Handle" => "Handle",
|
|
124
|
+
"MilkTea::Types::TypeType" => "TypeType",
|
|
125
|
+
"MilkTea::Types::Error" => "Error",
|
|
126
|
+
"MilkTea::Types::DynVtable" => "DynVtable",
|
|
127
|
+
}.freeze
|
|
128
|
+
|
|
129
|
+
TYPES_CLASSES = TYPES_SHORT_NAMES.keys.map do |name|
|
|
130
|
+
name.split("::").reduce(Object) { |mod, part| mod.const_get(part) }
|
|
131
|
+
end.freeze
|
|
132
|
+
|
|
133
|
+
def emit_types_object(type, buf)
|
|
134
|
+
short = TYPES_SHORT_NAMES[type.class.name] || type.class.name.split("::").last
|
|
135
|
+
buf << "(Types::" << short
|
|
136
|
+
emit_types_fields(type, buf)
|
|
137
|
+
buf << ")"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def emit_types_fields(type, buf)
|
|
141
|
+
case type
|
|
142
|
+
when Types::Primitive
|
|
143
|
+
buf << " :name "
|
|
144
|
+
emit_string(type.name, buf)
|
|
145
|
+
when Types::Null
|
|
146
|
+
buf << " :target_type "
|
|
147
|
+
emit_value(type.target_type, buf)
|
|
148
|
+
when Types::Nullable
|
|
149
|
+
buf << " :base "
|
|
150
|
+
emit_value(type.base, buf)
|
|
151
|
+
when Types::GenericInstance
|
|
152
|
+
buf << " :name "
|
|
153
|
+
emit_string(type.name, buf)
|
|
154
|
+
buf << " :arguments "
|
|
155
|
+
emit_array(type.arguments, buf)
|
|
156
|
+
when Types::Span
|
|
157
|
+
buf << " :element_type "
|
|
158
|
+
emit_value(type.element_type, buf)
|
|
159
|
+
when Types::Task
|
|
160
|
+
buf << " :result_type "
|
|
161
|
+
emit_value(type.result_type, buf)
|
|
162
|
+
when Types::Function
|
|
163
|
+
buf << " :name "
|
|
164
|
+
emit_string(type.name, buf)
|
|
165
|
+
buf << " :params "
|
|
166
|
+
emit_array(type.params, buf)
|
|
167
|
+
buf << " :return_type "
|
|
168
|
+
emit_value(type.return_type, buf)
|
|
169
|
+
buf << " :receiver_type "
|
|
170
|
+
emit_value(type.receiver_type, buf)
|
|
171
|
+
buf << " :receiver_editable "
|
|
172
|
+
emit_value(type.receiver_editable, buf)
|
|
173
|
+
buf << " :variadic "
|
|
174
|
+
emit_value(type.variadic, buf)
|
|
175
|
+
buf << " :external "
|
|
176
|
+
emit_value(type.external, buf)
|
|
177
|
+
when Types::Proc
|
|
178
|
+
buf << " :params "
|
|
179
|
+
emit_array(type.params, buf)
|
|
180
|
+
buf << " :return_type "
|
|
181
|
+
emit_value(type.return_type, buf)
|
|
182
|
+
when Types::Tuple
|
|
183
|
+
buf << " :element_types "
|
|
184
|
+
emit_array(type.element_types, buf)
|
|
185
|
+
buf << " :field_names "
|
|
186
|
+
emit_value(type.field_names, buf)
|
|
187
|
+
when Types::Vector
|
|
188
|
+
buf << " :name "
|
|
189
|
+
emit_string(type.name, buf)
|
|
190
|
+
when Types::Matrix
|
|
191
|
+
buf << " :name "
|
|
192
|
+
emit_string(type.name, buf)
|
|
193
|
+
when Types::Quaternion
|
|
194
|
+
buf << " :name "
|
|
195
|
+
emit_string(type.name, buf)
|
|
196
|
+
when Types::SoA
|
|
197
|
+
buf << " :element_type "
|
|
198
|
+
emit_value(type.element_type, buf)
|
|
199
|
+
buf << " :count "
|
|
200
|
+
emit_value(type.count, buf)
|
|
201
|
+
when Types::Simd
|
|
202
|
+
buf << " :element_type "
|
|
203
|
+
emit_value(type.element_type, buf)
|
|
204
|
+
buf << " :lane_count "
|
|
205
|
+
emit_value(type.lane_count, buf)
|
|
206
|
+
when Types::Struct
|
|
207
|
+
buf << " :name "
|
|
208
|
+
emit_string(type.name, buf)
|
|
209
|
+
buf << " :module_name "
|
|
210
|
+
emit_value(type.module_name, buf)
|
|
211
|
+
when Types::StructInstance
|
|
212
|
+
buf << " :name "
|
|
213
|
+
emit_string(type.name, buf)
|
|
214
|
+
buf << " :module_name "
|
|
215
|
+
emit_value(type.module_name, buf)
|
|
216
|
+
buf << " :arguments "
|
|
217
|
+
emit_array(type.arguments, buf)
|
|
218
|
+
when Types::Union
|
|
219
|
+
buf << " :name "
|
|
220
|
+
emit_string(type.name, buf)
|
|
221
|
+
buf << " :module_name "
|
|
222
|
+
emit_value(type.module_name, buf)
|
|
223
|
+
when Types::Variant
|
|
224
|
+
buf << " :name "
|
|
225
|
+
emit_string(type.name, buf)
|
|
226
|
+
buf << " :module_name "
|
|
227
|
+
emit_value(type.module_name, buf)
|
|
228
|
+
when Types::VariantInstance
|
|
229
|
+
buf << " :name "
|
|
230
|
+
emit_string(type.name, buf)
|
|
231
|
+
buf << " :module_name "
|
|
232
|
+
emit_value(type.module_name, buf)
|
|
233
|
+
buf << " :arguments "
|
|
234
|
+
emit_array(type.arguments, buf)
|
|
235
|
+
when Types::VariantArmPayload
|
|
236
|
+
buf << " :variant_name "
|
|
237
|
+
emit_string(type.variant_type.name, buf)
|
|
238
|
+
buf << " :arm_name "
|
|
239
|
+
emit_string(type.arm_name, buf)
|
|
240
|
+
when Types::Enum
|
|
241
|
+
buf << " :name "
|
|
242
|
+
emit_string(type.name, buf)
|
|
243
|
+
buf << " :module_name "
|
|
244
|
+
emit_value(type.module_name, buf)
|
|
245
|
+
when Types::Flags
|
|
246
|
+
buf << " :name "
|
|
247
|
+
emit_string(type.name, buf)
|
|
248
|
+
buf << " :module_name "
|
|
249
|
+
emit_value(type.module_name, buf)
|
|
250
|
+
when Types::Opaque
|
|
251
|
+
buf << " :name "
|
|
252
|
+
emit_string(type.name, buf)
|
|
253
|
+
buf << " :module_name "
|
|
254
|
+
emit_value(type.module_name, buf)
|
|
255
|
+
when Types::StringView
|
|
256
|
+
# no fields
|
|
257
|
+
when Types::Dyn
|
|
258
|
+
buf << " :interface_name "
|
|
259
|
+
emit_string(type.interface_binding.name, buf)
|
|
260
|
+
buf << " :type_arguments "
|
|
261
|
+
emit_array(type.type_arguments, buf)
|
|
262
|
+
when Types::Parameter
|
|
263
|
+
buf << " :name "
|
|
264
|
+
emit_string(type.name, buf)
|
|
265
|
+
buf << " :type "
|
|
266
|
+
emit_value(type.type, buf)
|
|
267
|
+
buf << " :mutable "
|
|
268
|
+
emit_value(type.mutable, buf)
|
|
269
|
+
buf << " :passing_mode "
|
|
270
|
+
emit_value(type.passing_mode, buf)
|
|
271
|
+
buf << " :boundary_type "
|
|
272
|
+
emit_value(type.boundary_type, buf)
|
|
273
|
+
when Types::LiteralTypeArg
|
|
274
|
+
buf << " :value "
|
|
275
|
+
emit_value(type.value, buf)
|
|
276
|
+
when Types::TypeVar
|
|
277
|
+
buf << " :name "
|
|
278
|
+
emit_string(type.name, buf)
|
|
279
|
+
when Types::LifetimeRef
|
|
280
|
+
buf << " :name "
|
|
281
|
+
emit_string(type.name, buf)
|
|
282
|
+
when Types::Event
|
|
283
|
+
buf << " :name "
|
|
284
|
+
emit_string(type.name, buf)
|
|
285
|
+
buf << " :capacity "
|
|
286
|
+
emit_value(type.capacity, buf)
|
|
287
|
+
buf << " :payload_type "
|
|
288
|
+
emit_value(type.payload_type, buf)
|
|
289
|
+
when Types::Subscription
|
|
290
|
+
# no fields (singleton)
|
|
291
|
+
when Types::Handle
|
|
292
|
+
# no fields (singleton)
|
|
293
|
+
else
|
|
294
|
+
_emit_generic_type(type, buf)
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def _emit_generic_type(type, buf)
|
|
299
|
+
type.instance_variables.sort.each do |ivar|
|
|
300
|
+
next if skip_types_ivar?(ivar)
|
|
301
|
+
name = ivar.to_s.sub(/\A@/, "")
|
|
302
|
+
val = type.instance_variable_get(ivar)
|
|
303
|
+
next if val.is_a?(Hash) || val.is_a?(Set) || val.is_a?(Proc)
|
|
304
|
+
buf << " :" << name << " "
|
|
305
|
+
emit_value(val, buf)
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def skip_types_ivar?(ivar)
|
|
310
|
+
%i[@hash @integer @float @numeric @pointer_sized_integer
|
|
311
|
+
@signed_integer @unsigned_integer @fixed_width_integer
|
|
312
|
+
@boolean @void @integer_width @float_width @backing_type
|
|
313
|
+
@arms @arm_names @arm_field_hashes @instances].include?(ivar)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# ── atom helpers ──────────────────────────────────────────────────
|
|
317
|
+
|
|
318
|
+
def emit_string(value, buf)
|
|
319
|
+
escaped = value.to_s
|
|
320
|
+
.gsub("\\", "\\\\")
|
|
321
|
+
.gsub('"', '\"')
|
|
322
|
+
.gsub("\n", '\\n')
|
|
323
|
+
.gsub("\t", '\\t')
|
|
324
|
+
.gsub("\r", '\\r')
|
|
325
|
+
buf << '"' << escaped << '"'
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def escape_string(value)
|
|
329
|
+
value.to_s
|
|
330
|
+
.gsub("\\", "\\\\")
|
|
331
|
+
.gsub('"', '\"')
|
|
332
|
+
.gsub("\n", '\\n')
|
|
333
|
+
.gsub("\t", '\\t')
|
|
334
|
+
.gsub("\r", '\\r')
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def format_float(value)
|
|
338
|
+
s = sprintf("%.17g", value)
|
|
339
|
+
s.include?(".") || s.include?("e") ? s : s + ".0"
|
|
340
|
+
end
|
|
341
|
+
end
|
|
342
|
+
end
|