mt-lang 0.3.8 → 0.3.10
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 -2
- data/lib/milk_tea/bindings/bindgen/ast_parser.rb +0 -2
- data/lib/milk_tea/bindings/bindgen/declaration.rb +0 -2
- data/lib/milk_tea/bindings/bindgen/emitter.rb +0 -2
- data/lib/milk_tea/bindings/bindgen/overrides.rb +0 -2
- data/lib/milk_tea/bindings/bindgen/type_mapper.rb +51 -53
- data/lib/milk_tea/bindings/imported_bindings/generator.rb +7 -9
- data/lib/milk_tea/bindings/imported_bindings/method_source.rb +0 -2
- data/lib/milk_tea/bindings/imported_bindings/naming.rb +6 -8
- data/lib/milk_tea/bindings/imported_bindings.rb +0 -2
- data/lib/milk_tea/bindings/opengl_registry.rb +3 -7
- data/lib/milk_tea/bindings/steamworks.rb +12 -16
- data/lib/milk_tea/bindings/upstream_sources.rb +10 -14
- data/lib/milk_tea/bindings/vendored_box2d.rb +10 -12
- data/lib/milk_tea/bindings/vendored_cjson.rb +6 -8
- data/lib/milk_tea/bindings/vendored_flecs.rb +10 -12
- data/lib/milk_tea/bindings/vendored_glfw.rb +11 -13
- data/lib/milk_tea/bindings/vendored_libuv.rb +11 -13
- data/lib/milk_tea/bindings/vendored_pcre2.rb +11 -13
- data/lib/milk_tea/bindings/vendored_raylib.rb +6 -10
- data/lib/milk_tea/bindings/vendored_sdl3.rb +11 -13
- data/lib/milk_tea/bindings/vendored_steamworks.rb +1 -5
- data/lib/milk_tea/core/ast.rb +103 -45
- data/lib/milk_tea/core/async_runtime_installer.rb +0 -2
- data/lib/milk_tea/core/bindings/attribute_binding.rb +1 -3
- data/lib/milk_tea/core/c_backend/aggregate_utils.rb +147 -84
- data/lib/milk_tea/core/c_backend/control_flow_emission.rb +394 -396
- data/lib/milk_tea/core/c_backend/expressions.rb +489 -476
- data/lib/milk_tea/core/c_backend/feature_detection.rb +446 -437
- data/lib/milk_tea/core/c_backend/format_helpers.rb +0 -2
- data/lib/milk_tea/core/c_backend/reachability.rb +339 -341
- data/lib/milk_tea/core/c_backend/reinterpret.rb +231 -217
- data/lib/milk_tea/core/c_backend/runtime_helpers.rb +531 -526
- data/lib/milk_tea/core/c_backend/statements.rb +528 -530
- data/lib/milk_tea/core/c_backend/type_collectors.rb +1344 -1346
- data/lib/milk_tea/core/c_backend/type_declaration.rb +215 -213
- data/lib/milk_tea/core/c_backend/type_system.rb +347 -349
- data/lib/milk_tea/core/c_backend.rb +17 -9
- data/lib/milk_tea/core/compatibility_helpers.rb +0 -2
- data/lib/milk_tea/core/compile_time/const_eval.rb +7 -12
- data/lib/milk_tea/core/compile_time.rb +32 -38
- data/lib/milk_tea/core/control_flow/builder.rb +3 -5
- data/lib/milk_tea/core/control_flow/constant_propagation.rb +14 -17
- data/lib/milk_tea/core/control_flow/definite_assignment.rb +0 -1
- data/lib/milk_tea/core/ir.rb +10 -10
- data/lib/milk_tea/core/lexer/character_classes.rb +5 -7
- data/lib/milk_tea/core/lexer/format_strings.rb +7 -9
- data/lib/milk_tea/core/lexer/heredocs.rb +22 -22
- data/lib/milk_tea/core/lexer/indentation.rb +0 -2
- data/lib/milk_tea/core/lexer/numbers.rb +0 -2
- data/lib/milk_tea/core/lexer/recovery.rb +0 -2
- data/lib/milk_tea/core/lexer/strings.rb +0 -2
- data/lib/milk_tea/core/lexer/symbols.rb +0 -2
- data/lib/milk_tea/core/lexer/trivia.rb +0 -2
- data/lib/milk_tea/core/lexer.rb +0 -2
- data/lib/milk_tea/core/lowering/async/analysis.rb +0 -2
- data/lib/milk_tea/core/lowering/async/lowering.rb +1264 -1265
- data/lib/milk_tea/core/lowering/async/normalization.rb +0 -2
- data/lib/milk_tea/core/lowering/async.rb +627 -630
- data/lib/milk_tea/core/lowering/block.rb +413 -416
- data/lib/milk_tea/core/lowering/calls.rb +1381 -1384
- data/lib/milk_tea/core/lowering/declarations.rb +180 -183
- data/lib/milk_tea/core/lowering/dyn.rb +48 -50
- data/lib/milk_tea/core/lowering/events.rb +983 -985
- data/lib/milk_tea/core/lowering/expressions.rb +1513 -1518
- data/lib/milk_tea/core/lowering/foreign_cstr.rb +181 -184
- data/lib/milk_tea/core/lowering/functions.rb +185 -188
- data/lib/milk_tea/core/lowering/loops.rb +1028 -1031
- data/lib/milk_tea/core/lowering/proc.rb +363 -366
- data/lib/milk_tea/core/lowering/resolve.rb +2133 -2135
- data/lib/milk_tea/core/lowering/scans.rb +179 -181
- data/lib/milk_tea/core/lowering/str_buffer.rb +102 -105
- data/lib/milk_tea/core/lowering/utils.rb +1040 -1044
- data/lib/milk_tea/core/lowering.rb +5 -7
- data/lib/milk_tea/core/module_binder.rb +0 -2
- data/lib/milk_tea/core/module_loader/errors.rb +4 -2
- data/lib/milk_tea/core/module_loader.rb +113 -20
- data/lib/milk_tea/core/module_path_resolver.rb +0 -2
- data/lib/milk_tea/core/module_roots.rb +6 -8
- data/lib/milk_tea/core/parser/attributes.rb +0 -2
- data/lib/milk_tea/core/parser/blocks.rb +0 -2
- data/lib/milk_tea/core/parser/declarations.rb +0 -2
- data/lib/milk_tea/core/parser/expressions.rb +31 -14
- data/lib/milk_tea/core/parser/recovery.rb +0 -2
- data/lib/milk_tea/core/parser/statements.rb +0 -2
- data/lib/milk_tea/core/parser/types.rb +8 -10
- data/lib/milk_tea/core/parser.rb +1 -3
- data/lib/milk_tea/core/pretty_printer/ast_formatter.rb +31 -33
- data/lib/milk_tea/core/pretty_printer/base_formatter.rb +0 -2
- data/lib/milk_tea/core/pretty_printer/ir_formatter.rb +0 -2
- data/lib/milk_tea/core/semantic_analyzer/analysis_context.rb +0 -2
- data/lib/milk_tea/core/semantic_analyzer/attributes.rb +14 -16
- data/lib/milk_tea/core/semantic_analyzer/calls.rb +0 -2
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +1 -14
- data/lib/milk_tea/core/semantic_analyzer/flow_refinement.rb +18 -21
- data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +0 -3
- data/lib/milk_tea/core/semantic_analyzer/function_binding.rb +12 -15
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +57 -59
- data/lib/milk_tea/core/semantic_analyzer/interface_conformance.rb +0 -2
- data/lib/milk_tea/core/semantic_analyzer/name_resolution.rb +5 -9
- data/lib/milk_tea/core/semantic_analyzer/nullability.rb +0 -3
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +35 -40
- data/lib/milk_tea/core/semantic_analyzer/top_level.rb +10 -12
- data/lib/milk_tea/core/semantic_analyzer/type_compatibility.rb +0 -6
- data/lib/milk_tea/core/semantic_analyzer/type_declaration.rb +102 -105
- data/lib/milk_tea/core/semantic_analyzer.rb +17 -8
- data/lib/milk_tea/core/types/layout.rb +21 -22
- data/lib/milk_tea/core/types/predicates.rb +0 -2
- data/lib/milk_tea/core/types/registry.rb +16 -18
- data/lib/milk_tea/core/types/visitor.rb +0 -4
- data/lib/milk_tea/dap/backends/lldb_dap.rb +0 -2
- data/lib/milk_tea/dap/protocol.rb +1 -1
- data/lib/milk_tea/dap/server/breakpoints.rb +0 -2
- data/lib/milk_tea/dap/server/debug_map.rb +0 -2
- data/lib/milk_tea/dap/server/handlers.rb +0 -2
- data/lib/milk_tea/dap/server/launch.rb +0 -2
- data/lib/milk_tea/dap/server/lldb_backend.rb +8 -10
- data/lib/milk_tea/dap/server/pause_diagnostics.rb +14 -16
- data/lib/milk_tea/dap/server/utilities.rb +0 -2
- data/lib/milk_tea/dap/server/wire.rb +0 -2
- data/lib/milk_tea/dap/server.rb +0 -2
- data/lib/milk_tea/lsp/diagnostics.rb +16 -16
- data/lib/milk_tea/lsp/server/call_hierarchy.rb +11 -12
- data/lib/milk_tea/lsp/server/code_actions.rb +355 -357
- data/lib/milk_tea/lsp/server/code_lens.rb +23 -25
- data/lib/milk_tea/lsp/server/completion.rb +873 -875
- data/lib/milk_tea/lsp/server/configuration.rb +129 -131
- data/lib/milk_tea/lsp/server/debug_info.rb +0 -2
- data/lib/milk_tea/lsp/server/definition.rb +564 -565
- data/lib/milk_tea/lsp/server/diagnostics_scheduling.rb +191 -193
- data/lib/milk_tea/lsp/server/execute_command.rb +0 -2
- data/lib/milk_tea/lsp/server/folding_range.rb +0 -4
- data/lib/milk_tea/lsp/server/formatting.rb +478 -480
- data/lib/milk_tea/lsp/server/hover.rb +1282 -1284
- data/lib/milk_tea/lsp/server/inlay_hints.rb +179 -181
- data/lib/milk_tea/lsp/server/lifecycle.rb +192 -194
- data/lib/milk_tea/lsp/server/linked_editing_range.rb +0 -2
- data/lib/milk_tea/lsp/server/on_type_formatting.rb +0 -2
- data/lib/milk_tea/lsp/server/progress.rb +0 -2
- data/lib/milk_tea/lsp/server/references.rb +316 -318
- data/lib/milk_tea/lsp/server/rename.rb +445 -447
- data/lib/milk_tea/lsp/server/selection_range.rb +0 -4
- data/lib/milk_tea/lsp/server/semantic_tokens.rb +1318 -1320
- data/lib/milk_tea/lsp/server/signature_help.rb +146 -148
- data/lib/milk_tea/lsp/server/text_documents.rb +99 -101
- data/lib/milk_tea/lsp/server/type_hierarchy.rb +2 -4
- data/lib/milk_tea/lsp/server/utilities.rb +397 -399
- data/lib/milk_tea/lsp/server.rb +0 -3
- data/lib/milk_tea/lsp/workspace/analysis.rb +40 -42
- data/lib/milk_tea/lsp/workspace/dependency_graph.rb +4 -10
- data/lib/milk_tea/lsp/workspace/utilities.rb +19 -19
- data/lib/milk_tea/packages/atomic_write.rb +4 -5
- data/lib/milk_tea/packages/dependency_solver.rb +15 -15
- data/lib/milk_tea/packages/lock.rb +4 -4
- data/lib/milk_tea/packages/manager_cli.rb +1 -1
- data/lib/milk_tea/packages/manifest.rb +3 -3
- data/lib/milk_tea/packages/registry_store.rb +4 -6
- data/lib/milk_tea/packages/services.rb +16 -16
- data/lib/milk_tea/packages/source_cache.rb +4 -6
- data/lib/milk_tea/packages/source_resolver.rb +44 -44
- data/lib/milk_tea/packages/version.rb +8 -8
- data/lib/milk_tea/tooling/build.rb +3 -7
- data/lib/milk_tea/tooling/build_cache.rb +0 -2
- data/lib/milk_tea/tooling/debug_info_formatter.rb +31 -33
- data/lib/milk_tea/tooling/debug_map.rb +8 -10
- data/lib/milk_tea/tooling/docs_app.rb +0 -2
- data/lib/milk_tea/tooling/linter/doc_tags.rb +25 -27
- data/lib/milk_tea/tooling/linter/fix_engine.rb +87 -24
- data/lib/milk_tea/tooling/linter/flow_rules.rb +44 -46
- data/lib/milk_tea/tooling/linter/imports_platform.rb +14 -16
- data/lib/milk_tea/tooling/linter/release_rules.rb +3 -5
- data/lib/milk_tea/tooling/linter/reserved_names.rb +23 -25
- data/lib/milk_tea/tooling/linter/rules.rb +87 -89
- data/lib/milk_tea/tooling/linter/source_helpers.rb +40 -42
- data/lib/milk_tea/tooling/linter/trailing_comma.rb +17 -19
- data/lib/milk_tea/tooling/linter/visitors.rb +162 -50
- data/lib/milk_tea/tooling/linter.rb +0 -2
- data/lib/milk_tea/tooling/project_scaffold.rb +0 -2
- data/lib/milk_tea/tooling/run.rb +0 -2
- data/lib/milk_tea/tooling/toolchain_cli.rb +0 -2
- data/std/cli.mt +13 -32
- data/std/color.mt +28 -28
- data/std/encoding.mt +4 -4
- data/std/graph.mt +1 -2
- data/std/hash.mt +14 -14
- data/std/http/server.mt +3 -3
- data/std/input.mt +1 -1
- data/std/json.mt +1 -1
- data/std/linear_algebra.mt +6 -6
- data/std/net/mux.mt +1 -1
- data/std/noise.mt +23 -23
- data/std/parse.mt +2 -2
- data/std/process.mt +3 -4
- data/std/sparse_set.mt +1 -1
- data/std/steering.mt +5 -5
- data/std/str.mt +1 -1
- data/std/tween.mt +4 -4
- data/std/utility.mt +3 -3
- metadata +2 -2
|
@@ -139,7 +139,7 @@ module MilkTea
|
|
|
139
139
|
next if analysis.module_kind == :raw_module
|
|
140
140
|
next if modules.key?(analysis.module_name)
|
|
141
141
|
|
|
142
|
-
prepare_analysis(analysis,
|
|
142
|
+
prepare_analysis(analysis, path: path)
|
|
143
143
|
collect_structs
|
|
144
144
|
|
|
145
145
|
synth_before_s = @artifacts.synthetic_structs.length
|
|
@@ -159,7 +159,7 @@ module MilkTea
|
|
|
159
159
|
variants: lower_variants.dup,
|
|
160
160
|
static_asserts: lower_static_asserts.dup,
|
|
161
161
|
functions: [],
|
|
162
|
-
|
|
162
|
+
path: path,
|
|
163
163
|
)
|
|
164
164
|
per_module_funcs[analysis.module_name].concat(lower_functions)
|
|
165
165
|
|
|
@@ -178,7 +178,7 @@ module MilkTea
|
|
|
178
178
|
ordered_analysis_pairs.each do |path, analysis|
|
|
179
179
|
next if analysis.module_kind == :raw_module
|
|
180
180
|
|
|
181
|
-
prepare_analysis(analysis,
|
|
181
|
+
prepare_analysis(analysis, path: path)
|
|
182
182
|
ensure_events_for_analysis(analysis)
|
|
183
183
|
|
|
184
184
|
synth_before_s = @artifacts.synthetic_structs.length
|
|
@@ -279,7 +279,7 @@ module MilkTea
|
|
|
279
279
|
variants: all_variants,
|
|
280
280
|
static_asserts: all_static_asserts,
|
|
281
281
|
functions: all_functions,
|
|
282
|
-
|
|
282
|
+
path: @program.root_path,
|
|
283
283
|
)
|
|
284
284
|
end
|
|
285
285
|
|
|
@@ -287,7 +287,7 @@ module MilkTea
|
|
|
287
287
|
ordered_analysis_pairs.each do |path, analysis|
|
|
288
288
|
next if analysis.module_kind == :raw_module
|
|
289
289
|
|
|
290
|
-
prepare_analysis(analysis,
|
|
290
|
+
prepare_analysis(analysis, path: path)
|
|
291
291
|
analysis.ast.declarations.grep(AST::EventDecl).each do |decl|
|
|
292
292
|
event_type = analysis.values.fetch(decl.name).type
|
|
293
293
|
ensure_event_runtime(event_type) if event_type.is_a?(Types::Event)
|
|
@@ -359,8 +359,6 @@ module MilkTea
|
|
|
359
359
|
ordered
|
|
360
360
|
end
|
|
361
361
|
|
|
362
|
-
private
|
|
363
|
-
|
|
364
362
|
include LowererScans
|
|
365
363
|
include LowererDeclarations
|
|
366
364
|
include LowererEvents
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
module MilkTea
|
|
4
4
|
class ModuleLoadError < StandardError
|
|
5
|
-
attr_reader :path
|
|
5
|
+
attr_reader :path, :line, :column
|
|
6
6
|
|
|
7
|
-
def initialize(message, path:)
|
|
7
|
+
def initialize(message, path:, line: nil, column: nil)
|
|
8
8
|
@path = path
|
|
9
|
+
@line = line
|
|
10
|
+
@column = column
|
|
9
11
|
super("#{message}: #{path}")
|
|
10
12
|
end
|
|
11
13
|
|
|
@@ -98,6 +98,7 @@ module MilkTea
|
|
|
98
98
|
@collecting_analysis_cache = {}
|
|
99
99
|
@collecting_path_errors = {}
|
|
100
100
|
@checking_paths = []
|
|
101
|
+
@forward_bindings = {}
|
|
101
102
|
@platform = self.class.normalize_platform_name(platform)
|
|
102
103
|
@package_graph = package_graph
|
|
103
104
|
@package_manifest_cache = {}
|
|
@@ -176,7 +177,59 @@ module MilkTea
|
|
|
176
177
|
# Phase 3: Topological sort into independent levels
|
|
177
178
|
levels = topo_sort_levels(graph)
|
|
178
179
|
|
|
179
|
-
#
|
|
180
|
+
# Pre-register forward bindings for cycle members
|
|
181
|
+
all_checked = levels.flatten.to_set
|
|
182
|
+
cycle_members = graph.keys.reject { |p| all_checked.include?(p) }
|
|
183
|
+
cycle_members.each do |resolved_path|
|
|
184
|
+
ast = @parse_cache[resolved_path]
|
|
185
|
+
@forward_bindings[resolved_path] = create_forward_binding(ast)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Phase 4: Check cycle members with iterative refinement
|
|
189
|
+
# Pass 1: Check with forward bindings — registers type declarations.
|
|
190
|
+
# SemanticError is expected (forward types lack fields/constructors)
|
|
191
|
+
# but ModuleLoadError indicates a broken dependency graph.
|
|
192
|
+
cycle_members.each do |resolved_path|
|
|
193
|
+
check_path(resolved_path)
|
|
194
|
+
rescue SemanticError
|
|
195
|
+
# Forward types can't satisfy constructors. Pass 2 will retry.
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Update forward type objects in-place with field/arm info from the
|
|
199
|
+
# real analyses. This way, all references to forward types (function
|
|
200
|
+
# return types, struct field types, etc.) automatically see the full
|
|
201
|
+
# type information without needing to replace the objects themselves.
|
|
202
|
+
cycle_members.each do |resolved_path|
|
|
203
|
+
analysis = @analysis_cache[resolved_path]
|
|
204
|
+
next unless analysis
|
|
205
|
+
|
|
206
|
+
fw_binding = @forward_bindings[resolved_path]
|
|
207
|
+
next unless fw_binding
|
|
208
|
+
|
|
209
|
+
analysis.types.each do |name, real_type|
|
|
210
|
+
fw_type = fw_binding.types[name]
|
|
211
|
+
next unless fw_type
|
|
212
|
+
|
|
213
|
+
if real_type.respond_to?(:fields) && fw_type.respond_to?(:define_fields)
|
|
214
|
+
fw_type.define_fields(real_type.fields) unless real_type.fields.empty?
|
|
215
|
+
end
|
|
216
|
+
if real_type.respond_to?(:arms) && fw_type.respond_to?(:define_arms)
|
|
217
|
+
fw_type.define_arms(real_type.arms) unless real_type.arms.empty?
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Pass 2: Re-check with populated types — now cycle members see
|
|
223
|
+
# complete type information for each other.
|
|
224
|
+
cycle_members.each do |resolved_path|
|
|
225
|
+
previous = @analysis_cache.delete(resolved_path)
|
|
226
|
+
check_path(resolved_path)
|
|
227
|
+
rescue SemanticError
|
|
228
|
+
@analysis_cache[resolved_path] = previous if previous
|
|
229
|
+
end
|
|
230
|
+
@forward_bindings.clear
|
|
231
|
+
|
|
232
|
+
# Phase 5: Check acyclic modules (they see fully-checked analyses for all imports)
|
|
180
233
|
levels.each do |level_paths|
|
|
181
234
|
if level_paths.length == 1
|
|
182
235
|
check_path(level_paths.first)
|
|
@@ -189,10 +242,6 @@ module MilkTea
|
|
|
189
242
|
def parse_all(resolved_path)
|
|
190
243
|
return if @parse_cache.key?(resolved_path)
|
|
191
244
|
|
|
192
|
-
if @checking_paths.include?(resolved_path)
|
|
193
|
-
raise ModuleLoadError.new("cyclic import detected", path: resolved_path)
|
|
194
|
-
end
|
|
195
|
-
|
|
196
245
|
@checking_paths << resolved_path
|
|
197
246
|
ast = load_file(resolved_path)
|
|
198
247
|
@parse_cache[resolved_path] = ast
|
|
@@ -202,7 +251,7 @@ module MilkTea
|
|
|
202
251
|
parse_all(import_path)
|
|
203
252
|
end
|
|
204
253
|
ensure
|
|
205
|
-
@checking_paths.pop
|
|
254
|
+
@checking_paths.pop
|
|
206
255
|
end
|
|
207
256
|
|
|
208
257
|
def topo_sort_levels(graph)
|
|
@@ -252,8 +301,13 @@ module MilkTea
|
|
|
252
301
|
|
|
253
302
|
ast.imports.each do |import|
|
|
254
303
|
import_path = @path_resolver.resolve_module_path(import.path.to_s, importer_path:, importer_module_name: ast.module_name.to_s)
|
|
255
|
-
|
|
256
|
-
|
|
304
|
+
|
|
305
|
+
if @forward_bindings.key?(import_path)
|
|
306
|
+
modules[import.path.to_s] = @forward_bindings[import_path]
|
|
307
|
+
else
|
|
308
|
+
import_analysis = check_path(import_path)
|
|
309
|
+
modules[import.path.to_s] = @binder.module_binding(import_analysis)
|
|
310
|
+
end
|
|
257
311
|
end
|
|
258
312
|
|
|
259
313
|
@async_runtime_installer.install_async_runtime_dependency!(ast, modules, importer_path:, collecting_errors: false)
|
|
@@ -291,8 +345,13 @@ module MilkTea
|
|
|
291
345
|
ast.imports.each do |import|
|
|
292
346
|
begin
|
|
293
347
|
import_path = @path_resolver.resolve_module_path(import.path.to_s, importer_path:, importer_module_name: ast.module_name.to_s)
|
|
294
|
-
|
|
295
|
-
|
|
348
|
+
|
|
349
|
+
if @forward_bindings.key?(import_path)
|
|
350
|
+
modules[import.path.to_s] = @forward_bindings[import_path]
|
|
351
|
+
else
|
|
352
|
+
import_analysis = check_path_collecting_errors(import_path)
|
|
353
|
+
modules[import.path.to_s] = @binder.module_binding(import_analysis)
|
|
354
|
+
end
|
|
296
355
|
rescue ModuleLoadError, PackageLockError, SemanticError => e
|
|
297
356
|
errors << ImportResolutionError.new(import:, error: e)
|
|
298
357
|
end
|
|
@@ -321,8 +380,6 @@ module MilkTea
|
|
|
321
380
|
@collecting_path_errors
|
|
322
381
|
end
|
|
323
382
|
|
|
324
|
-
private
|
|
325
|
-
|
|
326
383
|
def self.raise_platform_conflict!(path, pinned_platform, active_platform, error_class: nil)
|
|
327
384
|
if error_class == ModuleLoadError
|
|
328
385
|
raise ModuleLoadError.new("source file targets platform #{pinned_platform}; active platform is #{active_platform}", path:)
|
|
@@ -331,12 +388,16 @@ module MilkTea
|
|
|
331
388
|
message = "source file #{path} targets platform #{pinned_platform}; active platform is #{active_platform}"
|
|
332
389
|
raise(error_class || ArgumentError, message)
|
|
333
390
|
end
|
|
334
|
-
private_class_method :raise_platform_conflict!
|
|
335
391
|
|
|
336
392
|
def check_path(path)
|
|
337
393
|
resolved_path, ast, cached = check_module_cache(path)
|
|
338
394
|
return cached if cached
|
|
339
395
|
|
|
396
|
+
if @checking_paths.include?(resolved_path) && !@forward_bindings.key?(resolved_path)
|
|
397
|
+
raise ModuleLoadError.new("circular import not resolvable: module #{@parse_cache[resolved_path]&.module_name || File.basename(path)}", path: resolved_path)
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
@checking_paths << resolved_path
|
|
340
401
|
imported_modules = imported_modules_for_ast(ast, importer_path: resolved_path)
|
|
341
402
|
global_index = build_global_import_index(ast)
|
|
342
403
|
analysis = SemanticAnalyzer.check(ast, imported_modules:, path: resolved_path, global_import_index: global_index)
|
|
@@ -344,13 +405,18 @@ module MilkTea
|
|
|
344
405
|
update_shared_cache(resolved_path, analysis)
|
|
345
406
|
analysis
|
|
346
407
|
ensure
|
|
347
|
-
@checking_paths.pop
|
|
408
|
+
@checking_paths.pop
|
|
348
409
|
end
|
|
349
410
|
|
|
350
411
|
def check_path_collecting_errors(path)
|
|
351
412
|
resolved_path, ast, cached = check_module_cache(path, extra_cache: @collecting_analysis_cache)
|
|
352
413
|
return cached if cached
|
|
353
414
|
|
|
415
|
+
if @checking_paths.include?(resolved_path) && !@forward_bindings.key?(resolved_path)
|
|
416
|
+
raise ModuleLoadError.new("circular import not resolvable: module #{@parse_cache[resolved_path]&.module_name || File.basename(path)}", path: resolved_path)
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
@checking_paths << resolved_path
|
|
354
420
|
imported_modules = imported_modules_for_ast_collecting_errors(ast, importer_path: resolved_path).modules
|
|
355
421
|
result = SemanticAnalyzer.check_collecting_errors(ast, imported_modules:, path: resolved_path)
|
|
356
422
|
analysis = result[:analysis]
|
|
@@ -360,7 +426,7 @@ module MilkTea
|
|
|
360
426
|
@collecting_analysis_cache[resolved_path] = analysis
|
|
361
427
|
analysis
|
|
362
428
|
ensure
|
|
363
|
-
@checking_paths.pop
|
|
429
|
+
@checking_paths.pop
|
|
364
430
|
end
|
|
365
431
|
|
|
366
432
|
def check_module_cache(path, extra_cache: nil)
|
|
@@ -380,9 +446,6 @@ module MilkTea
|
|
|
380
446
|
end
|
|
381
447
|
end
|
|
382
448
|
|
|
383
|
-
raise ModuleLoadError.new("cyclic import detected", path: resolved_path) if @checking_paths.include?(resolved_path)
|
|
384
|
-
|
|
385
|
-
@checking_paths << resolved_path
|
|
386
449
|
ast = load_file(resolved_path)
|
|
387
450
|
[resolved_path, ast, nil]
|
|
388
451
|
end
|
|
@@ -433,8 +496,8 @@ module MilkTea
|
|
|
433
496
|
end
|
|
434
497
|
|
|
435
498
|
matching_root = @module_roots
|
|
436
|
-
|
|
437
|
-
|
|
499
|
+
.select { |root| path_within_root?(path, root) }
|
|
500
|
+
.max_by(&:length)
|
|
438
501
|
return module_name_for_path(path, matching_root) if matching_root
|
|
439
502
|
|
|
440
503
|
File.basename(path).sub(/\.(linux|windows|wasm)\.mt\z/, ".mt").sub(/\.mt\z/, "")
|
|
@@ -453,6 +516,36 @@ module MilkTea
|
|
|
453
516
|
normalized_path == normalized_root || normalized_path.start_with?(normalized_root + File::SEPARATOR)
|
|
454
517
|
end
|
|
455
518
|
|
|
519
|
+
def create_forward_binding(ast)
|
|
520
|
+
module_name = ast.module_name.to_s
|
|
521
|
+
types = {}
|
|
522
|
+
|
|
523
|
+
ast.declarations.each do |decl|
|
|
524
|
+
case decl
|
|
525
|
+
when AST::StructDecl
|
|
526
|
+
types[decl.name] = Types::Struct.new(decl.name, module_name:)
|
|
527
|
+
when AST::VariantDecl
|
|
528
|
+
types[decl.name] = Types::Variant.new(decl.name, module_name:)
|
|
529
|
+
when AST::EnumDecl
|
|
530
|
+
types[decl.name] = Types::Enum.new(decl.name, module_name:)
|
|
531
|
+
when AST::FlagsDecl
|
|
532
|
+
types[decl.name] = Types::Flags.new(decl.name, module_name:)
|
|
533
|
+
when AST::OpaqueDecl
|
|
534
|
+
types[decl.name] = Types::Opaque.new(decl.name, module_name:, external: false)
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
ModuleBinding.new(
|
|
539
|
+
name: module_name, types:, type_declarations: {},
|
|
540
|
+
interfaces: {}, attributes: {}, attribute_applications: {},
|
|
541
|
+
values: {}, functions: {}, methods: {},
|
|
542
|
+
implemented_interfaces: {}, imports: {},
|
|
543
|
+
private_types: {}, private_interfaces: {}, private_attributes: {},
|
|
544
|
+
private_values: {}, private_functions: {}, private_methods: {},
|
|
545
|
+
private_implemented_interfaces: {},
|
|
546
|
+
)
|
|
547
|
+
end
|
|
548
|
+
|
|
456
549
|
def use_shared_cache?
|
|
457
550
|
@shared_cache && @source_overrides.empty?
|
|
458
551
|
end
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module MilkTea
|
|
4
4
|
module ModuleRoots
|
|
5
|
-
module_function
|
|
6
5
|
|
|
7
|
-
def roots_for_path(path, env: ENV, locked: false)
|
|
6
|
+
def self.roots_for_path(path, env: ENV, locked: false)
|
|
8
7
|
roots = []
|
|
9
8
|
|
|
10
9
|
add_env_roots!(roots, env)
|
|
@@ -24,7 +23,7 @@ module MilkTea
|
|
|
24
23
|
.select { |root| File.directory?(root) }
|
|
25
24
|
end
|
|
26
25
|
|
|
27
|
-
def package_roots_for_path(path, locked: false)
|
|
26
|
+
def self.package_roots_for_path(path, locked: false)
|
|
28
27
|
PackageGraph.load(path, locked:).source_roots
|
|
29
28
|
rescue PackageManifestError
|
|
30
29
|
package_root = package_root_for_path(path)
|
|
@@ -33,7 +32,7 @@ module MilkTea
|
|
|
33
32
|
[package_root]
|
|
34
33
|
end
|
|
35
34
|
|
|
36
|
-
def project_root_for_path(path)
|
|
35
|
+
def self.project_root_for_path(path)
|
|
37
36
|
return nil unless path
|
|
38
37
|
|
|
39
38
|
current = File.expand_path(File.directory?(path) ? path : File.dirname(path))
|
|
@@ -47,7 +46,7 @@ module MilkTea
|
|
|
47
46
|
end
|
|
48
47
|
end
|
|
49
48
|
|
|
50
|
-
def package_root_for_path(path)
|
|
49
|
+
def self.package_root_for_path(path)
|
|
51
50
|
return nil unless path
|
|
52
51
|
|
|
53
52
|
current = File.expand_path(File.directory?(path) ? path : File.dirname(path))
|
|
@@ -61,7 +60,7 @@ module MilkTea
|
|
|
61
60
|
end
|
|
62
61
|
end
|
|
63
62
|
|
|
64
|
-
def normalize_root(root)
|
|
63
|
+
def self.normalize_root(root)
|
|
65
64
|
return nil if root.nil? || root.to_s.strip.empty?
|
|
66
65
|
|
|
67
66
|
expanded = File.expand_path(root.to_s)
|
|
@@ -72,7 +71,7 @@ module MilkTea
|
|
|
72
71
|
end
|
|
73
72
|
end
|
|
74
73
|
|
|
75
|
-
def add_env_roots!(roots, env)
|
|
74
|
+
def self.add_env_roots!(roots, env)
|
|
76
75
|
env_keys = %w[MILK_TEA_MODULE_ROOT MILK_TEA_STD_ROOT]
|
|
77
76
|
env_keys.each do |key|
|
|
78
77
|
value = env[key]
|
|
@@ -83,6 +82,5 @@ module MilkTea
|
|
|
83
82
|
end
|
|
84
83
|
end
|
|
85
84
|
end
|
|
86
|
-
private_class_method :add_env_roots!
|
|
87
85
|
end
|
|
88
86
|
end
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
module MilkTea
|
|
4
4
|
module Parse
|
|
5
5
|
module Expressions
|
|
6
|
-
private
|
|
7
|
-
|
|
8
6
|
def parse_expression
|
|
9
7
|
return parse_if_expression if match(:if)
|
|
10
8
|
return parse_match_expression if match(:match)
|
|
@@ -18,18 +16,36 @@ module MilkTea
|
|
|
18
16
|
return expr unless match(:dot_dot)
|
|
19
17
|
|
|
20
18
|
line = previous.line
|
|
21
|
-
column = expr.
|
|
19
|
+
column = expr.column || 0
|
|
22
20
|
end_expr = parse_or
|
|
23
21
|
AST::RangeExpr.new(start_expr: expr, end_expr:, line:, column:)
|
|
24
22
|
end
|
|
25
23
|
|
|
26
24
|
def parse_if_expression
|
|
27
25
|
condition = parse_or
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
|
|
27
|
+
if inline_block_body?
|
|
28
|
+
consume(:colon, "expected ':' after condition in if expression")
|
|
29
|
+
then_expression = parse_expression
|
|
30
|
+
consume(:else, "expected 'else' in if expression")
|
|
31
|
+
consume(:colon, "expected ':' after 'else' in if expression")
|
|
32
|
+
else_expression = parse_expression
|
|
33
|
+
else
|
|
34
|
+
consume(:colon, "expected ':' after condition in if expression")
|
|
35
|
+
consume(:newline, "expected newline after 'if condition:' in if expression")
|
|
36
|
+
consume(:indent, "expected indented body in if expression")
|
|
37
|
+
then_expression = parse_expression
|
|
38
|
+
consume_end_of_statement unless block_expression?(then_expression)
|
|
39
|
+
consume(:dedent, "expected end of if expression body")
|
|
40
|
+
consume(:else, "expected 'else' in if expression")
|
|
41
|
+
consume(:colon, "expected ':' after 'else' in if expression")
|
|
42
|
+
consume(:newline, "expected newline after 'else:' in if expression")
|
|
43
|
+
consume(:indent, "expected indented else body in if expression")
|
|
44
|
+
else_expression = parse_expression
|
|
45
|
+
consume_end_of_statement unless block_expression?(else_expression)
|
|
46
|
+
consume(:dedent, "expected end of else expression body")
|
|
47
|
+
end
|
|
48
|
+
|
|
33
49
|
AST::IfExpr.new(condition:, then_expression:, else_expression:)
|
|
34
50
|
end
|
|
35
51
|
|
|
@@ -526,24 +542,25 @@ module MilkTea
|
|
|
526
542
|
)
|
|
527
543
|
end
|
|
528
544
|
|
|
529
|
-
parser = self.class.
|
|
545
|
+
parser = self.class.new(tokens, path: @path)
|
|
530
546
|
parser.instance_variable_set(:@known_type_names, @known_type_names.dup)
|
|
531
547
|
parser.instance_variable_set(:@known_import_aliases, @known_import_aliases.dup)
|
|
532
548
|
parser.instance_variable_set(:@known_generic_callable_names, @known_generic_callable_names.dup)
|
|
533
549
|
parser.instance_variable_set(:@current_type_param_names, @current_type_param_names.dup)
|
|
534
550
|
|
|
535
|
-
expression = parser.
|
|
536
|
-
parser.
|
|
537
|
-
raise parser.
|
|
551
|
+
expression = parser.parse_expression
|
|
552
|
+
parser.skip_newlines
|
|
553
|
+
raise parser.error(parser.peek, "expected end of interpolation") unless parser.eof?
|
|
538
554
|
|
|
539
555
|
expression
|
|
540
556
|
end
|
|
541
557
|
|
|
542
558
|
def parse_left_associative(operand_method, *operator_types)
|
|
543
|
-
|
|
559
|
+
operand = method(operand_method)
|
|
560
|
+
expression = operand.call
|
|
544
561
|
while match(*operator_types)
|
|
545
562
|
operator = previous.lexeme
|
|
546
|
-
right =
|
|
563
|
+
right = operand.call
|
|
547
564
|
expression = AST::BinaryOp.new(operator:, left: expression, right:)
|
|
548
565
|
end
|
|
549
566
|
expression
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
module MilkTea
|
|
4
4
|
module Parse
|
|
5
5
|
module Types
|
|
6
|
-
private
|
|
7
|
-
|
|
8
6
|
def parse_params(allow_variadic: false)
|
|
9
7
|
parse_parameter_list(allow_variadic:) { parse_param }
|
|
10
8
|
end
|
|
@@ -263,14 +261,14 @@ module MilkTea
|
|
|
263
261
|
parts << consume_path_component("expected identifier after '.'").lexeme
|
|
264
262
|
end
|
|
265
263
|
type_arguments = if match(:lbracket)
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
264
|
+
args = parse_comma_separated_until(:rbracket) do
|
|
265
|
+
parse_type_ref
|
|
266
|
+
end
|
|
267
|
+
consume(:rbracket, "expected ']' after type arguments")
|
|
268
|
+
args
|
|
269
|
+
else
|
|
270
|
+
[]
|
|
271
|
+
end
|
|
274
272
|
AST::QualifiedName.new(parts:, type_arguments:, line: first_token.line, column: first_token.column)
|
|
275
273
|
end
|
|
276
274
|
end
|
data/lib/milk_tea/core/parser.rb
CHANGED
|
@@ -92,8 +92,6 @@ module MilkTea
|
|
|
92
92
|
@recovery_errors = previous_recovery_errors
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
-
private
|
|
96
|
-
|
|
97
95
|
BUILTIN_ATTRIBUTE_NAME_LEXEMES = %w[packed align].freeze
|
|
98
96
|
|
|
99
97
|
def parse_source_file(errors: nil)
|
|
@@ -253,7 +251,7 @@ module MilkTea
|
|
|
253
251
|
end
|
|
254
252
|
|
|
255
253
|
def block_expression?(expression)
|
|
256
|
-
expression.is_a?(AST::ProcExpr) || expression.is_a?(AST::MatchExpr)
|
|
254
|
+
expression.is_a?(AST::ProcExpr) || expression.is_a?(AST::MatchExpr) || expression.is_a?(AST::IfExpr)
|
|
257
255
|
end
|
|
258
256
|
|
|
259
257
|
def parse_qualified_name
|