mt-lang 0.3.9 → 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 +8 -9
- 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 +0 -2
- 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 +112 -54
- 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
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
module MilkTea
|
|
4
4
|
class Linter
|
|
5
5
|
module LinterVisitors
|
|
6
|
-
private
|
|
7
|
-
|
|
8
6
|
def visit_source_file(source_file)
|
|
9
7
|
@declared_callable_names = declared_callable_names(source_file)
|
|
10
8
|
@declared_directional_functions = declared_directional_functions(source_file)
|
|
@@ -29,14 +27,14 @@ module MilkTea
|
|
|
29
27
|
end
|
|
30
28
|
def seed_module_bindings(source_file)
|
|
31
29
|
@module_bindings = {}
|
|
32
|
-
|
|
30
|
+
|
|
33
31
|
import_names = source_file.imports.filter_map do |import|
|
|
34
32
|
import.alias_name || import.path.parts.last
|
|
35
33
|
end
|
|
36
34
|
source_file.imports.each do |import|
|
|
37
35
|
local_name = import.alias_name || import.path.parts.last
|
|
38
36
|
next if ignored_binding_name?(local_name)
|
|
39
|
-
|
|
37
|
+
|
|
40
38
|
declare_reserved_import_alias_module_binding(
|
|
41
39
|
local_name,
|
|
42
40
|
kind_label: "import alias",
|
|
@@ -45,7 +43,7 @@ module MilkTea
|
|
|
45
43
|
unavailable_names: import_names,
|
|
46
44
|
)
|
|
47
45
|
end
|
|
48
|
-
|
|
46
|
+
|
|
49
47
|
source_file.declarations.each do |declaration|
|
|
50
48
|
kind_label = case declaration
|
|
51
49
|
when AST::FunctionDef, AST::ExternFunctionDecl, AST::ForeignFunctionDecl
|
|
@@ -61,7 +59,7 @@ module MilkTea
|
|
|
61
59
|
end
|
|
62
60
|
next unless kind_label
|
|
63
61
|
next if ignored_binding_name?(declaration.name)
|
|
64
|
-
|
|
62
|
+
|
|
65
63
|
declare_reserved_primitive_module_binding(
|
|
66
64
|
declaration.name,
|
|
67
65
|
kind_label:,
|
|
@@ -87,7 +85,7 @@ module MilkTea
|
|
|
87
85
|
source_file.declarations.each_with_object({}) do |declaration, functions|
|
|
88
86
|
next unless declaration.is_a?(AST::ExternFunctionDecl) || declaration.is_a?(AST::ForeignFunctionDecl)
|
|
89
87
|
next unless declaration.params.any? { |param| %i[in out inout].include?(param.mode) }
|
|
90
|
-
|
|
88
|
+
|
|
91
89
|
functions[declaration.name] = declaration
|
|
92
90
|
end
|
|
93
91
|
end
|
|
@@ -134,7 +132,7 @@ module MilkTea
|
|
|
134
132
|
terminated = false
|
|
135
133
|
stmts.each do |stmt|
|
|
136
134
|
next if terminated # skip visitation only; ControlFlow emits the warning
|
|
137
|
-
|
|
135
|
+
|
|
138
136
|
visit_statement(stmt)
|
|
139
137
|
terminated = true if terminator?(stmt)
|
|
140
138
|
end
|
|
@@ -299,7 +297,7 @@ module MilkTea
|
|
|
299
297
|
@unsafe_depth -= 1
|
|
300
298
|
when AST::ProcExpr
|
|
301
299
|
with_scope do
|
|
302
|
-
fallback_line = expression.
|
|
300
|
+
fallback_line = expression.line
|
|
303
301
|
expression.params.each do |param|
|
|
304
302
|
declare_param(
|
|
305
303
|
param.name,
|
|
@@ -325,7 +323,7 @@ module MilkTea
|
|
|
325
323
|
when AST::FormatString
|
|
326
324
|
expression.parts.each do |part|
|
|
327
325
|
next unless part.is_a?(AST::FormatExprPart)
|
|
328
|
-
|
|
326
|
+
|
|
329
327
|
visit_expression(part.expression)
|
|
330
328
|
end
|
|
331
329
|
when AST::IntegerLiteral, AST::FloatLiteral, AST::StringLiteral, AST::BooleanLiteral, AST::NullLiteral
|
|
@@ -337,6 +335,7 @@ module MilkTea
|
|
|
337
335
|
when AST::PrefixCast
|
|
338
336
|
visit_expression(expression.expression)
|
|
339
337
|
check_redundant_cast(expression)
|
|
338
|
+
check_redundant_cast_parens(expression)
|
|
340
339
|
else
|
|
341
340
|
nil
|
|
342
341
|
end
|
|
@@ -369,28 +368,28 @@ module MilkTea
|
|
|
369
368
|
end
|
|
370
369
|
def mark_assignment_target_reads(target, operator)
|
|
371
370
|
return if operator == "="
|
|
372
|
-
|
|
371
|
+
|
|
373
372
|
mark_used(target.name, identifier: target) if target.is_a?(AST::Identifier)
|
|
374
373
|
end
|
|
375
374
|
def mark_mutated(target)
|
|
376
375
|
return unless target.is_a?(AST::Identifier) || target.is_a?(AST::IndexAccess) || target.is_a?(AST::MemberAccess)
|
|
377
|
-
|
|
376
|
+
|
|
378
377
|
# For direct identifier assignment (e.g., x = value), mark x as mutated.
|
|
379
378
|
if target.is_a?(AST::Identifier)
|
|
380
379
|
@scopes.reverse_each do |scope|
|
|
381
380
|
binding = scope[target.name]
|
|
382
381
|
next unless binding
|
|
383
|
-
|
|
382
|
+
|
|
384
383
|
binding.mutated = true
|
|
385
384
|
return
|
|
386
385
|
end
|
|
387
386
|
end
|
|
388
|
-
|
|
387
|
+
|
|
389
388
|
# For index assignment (e.g., array[0] = value), mark the array as mutated.
|
|
390
389
|
if target.is_a?(AST::IndexAccess)
|
|
391
390
|
mark_mutated(target.receiver)
|
|
392
391
|
end
|
|
393
|
-
|
|
392
|
+
|
|
394
393
|
# For field assignment (e.g., rect.w = value), mark the struct variable as mutated.
|
|
395
394
|
if target.is_a?(AST::MemberAccess)
|
|
396
395
|
mark_mutated(target.receiver)
|
|
@@ -401,12 +400,12 @@ module MilkTea
|
|
|
401
400
|
mark_mutated(expression)
|
|
402
401
|
return
|
|
403
402
|
end
|
|
404
|
-
|
|
403
|
+
|
|
405
404
|
if expression.is_a?(AST::UnaryOp) && %w[out inout].include?(expression.operator)
|
|
406
405
|
mark_mutated(expression.operand)
|
|
407
406
|
return
|
|
408
407
|
end
|
|
409
|
-
|
|
408
|
+
|
|
410
409
|
# ref_of(x) and ptr_of(x) can expose writable aliases — treat as potential
|
|
411
410
|
# mutation since callees may write through them (common C-FFI out-param pattern).
|
|
412
411
|
if expression.is_a?(AST::Call) &&
|
|
@@ -418,10 +417,10 @@ module MilkTea
|
|
|
418
417
|
end
|
|
419
418
|
def mutating_argument_identifier?(expression)
|
|
420
419
|
return false unless expression.is_a?(AST::Identifier)
|
|
421
|
-
|
|
420
|
+
|
|
422
421
|
binding_resolution = @sema_facts&.binding_resolution
|
|
423
422
|
return false unless binding_resolution
|
|
424
|
-
|
|
423
|
+
|
|
425
424
|
binding_resolution.mutating_argument_identifier_ids&.key?(expression.object_id) ||
|
|
426
425
|
binding_resolution.mutable_lvalue_argument_identifier_ids&.key?(expression.object_id)
|
|
427
426
|
end
|
|
@@ -429,7 +428,7 @@ module MilkTea
|
|
|
429
428
|
return unless expression.is_a?(AST::Call)
|
|
430
429
|
return unless expression.callee.is_a?(AST::MemberAccess)
|
|
431
430
|
return unless editable_receiver_expression?(expression.callee.receiver)
|
|
432
|
-
|
|
431
|
+
|
|
433
432
|
mark_mutated(expression.callee.receiver)
|
|
434
433
|
end
|
|
435
434
|
def mark_alias_source_mutated(expression)
|
|
@@ -437,12 +436,12 @@ module MilkTea
|
|
|
437
436
|
return unless expression.callee.is_a?(AST::Identifier)
|
|
438
437
|
return unless %w[ref_of ptr_of].include?(expression.callee.name)
|
|
439
438
|
return unless expression.arguments.length == 1
|
|
440
|
-
|
|
439
|
+
|
|
441
440
|
mark_mutated(expression.arguments.first.value)
|
|
442
441
|
end
|
|
443
442
|
def editable_receiver_expression?(expression)
|
|
444
443
|
return true unless @sema_facts
|
|
445
|
-
|
|
444
|
+
|
|
446
445
|
@sema_facts&.binding_resolution&.editable_receiver_expression_ids&.key?(expression.object_id)
|
|
447
446
|
end
|
|
448
447
|
def with_scope
|
|
@@ -453,9 +452,9 @@ module MilkTea
|
|
|
453
452
|
end
|
|
454
453
|
def declare_local(name, line, column: nil, var: false)
|
|
455
454
|
return if ignored_binding_name?(name)
|
|
456
|
-
|
|
455
|
+
|
|
457
456
|
resolve_reserved_primitive_name_conflicts!(name)
|
|
458
|
-
|
|
457
|
+
|
|
459
458
|
replacement_name = nil
|
|
460
459
|
replacement_base_name = nil
|
|
461
460
|
if RESERVED_VALUE_TYPE_NAMES.include?(name)
|
|
@@ -465,7 +464,7 @@ module MilkTea
|
|
|
465
464
|
visible_binding_names(excluding_name: name),
|
|
466
465
|
)
|
|
467
466
|
end
|
|
468
|
-
|
|
467
|
+
|
|
469
468
|
# shadow: check whether any outer scope already has a binding for this name
|
|
470
469
|
if @scopes.length > 1
|
|
471
470
|
@scopes[0..-2].each do |outer_scope|
|
|
@@ -479,7 +478,7 @@ module MilkTea
|
|
|
479
478
|
end
|
|
480
479
|
end
|
|
481
480
|
end
|
|
482
|
-
|
|
481
|
+
|
|
483
482
|
@scopes.last[name] = Binding.new(
|
|
484
483
|
name:, line:, column:, used: false,
|
|
485
484
|
binding_kind: :local,
|
|
@@ -492,9 +491,9 @@ module MilkTea
|
|
|
492
491
|
end
|
|
493
492
|
def declare_param(name, line: nil, column: nil)
|
|
494
493
|
return if ignored_binding_name?(name)
|
|
495
|
-
|
|
494
|
+
|
|
496
495
|
resolve_reserved_primitive_name_conflicts!(name)
|
|
497
|
-
|
|
496
|
+
|
|
498
497
|
replacement_name = nil
|
|
499
498
|
replacement_base_name = nil
|
|
500
499
|
if RESERVED_VALUE_TYPE_NAMES.include?(name)
|
|
@@ -504,7 +503,7 @@ module MilkTea
|
|
|
504
503
|
visible_binding_names(excluding_name: name),
|
|
505
504
|
)
|
|
506
505
|
end
|
|
507
|
-
|
|
506
|
+
|
|
508
507
|
@scopes.last[name] = Binding.new(
|
|
509
508
|
name:, line:, column:, used: false,
|
|
510
509
|
binding_kind: :param,
|
|
@@ -801,8 +800,8 @@ module MilkTea
|
|
|
801
800
|
cond_src = source_line_from(b.line, b.column)
|
|
802
801
|
return false unless cond_src
|
|
803
802
|
|
|
804
|
-
stmt_col = stmts[i]
|
|
805
|
-
stmt_line = stmts[i]
|
|
803
|
+
stmt_col = stmts[i]&.column
|
|
804
|
+
stmt_line = stmts[i]&.line
|
|
806
805
|
body_src = source_line_from(stmt_line, stmt_col)
|
|
807
806
|
return false unless body_src
|
|
808
807
|
|
|
@@ -819,8 +818,8 @@ module MilkTea
|
|
|
819
818
|
text << " "
|
|
820
819
|
end
|
|
821
820
|
|
|
822
|
-
stmt_col = stmts.last
|
|
823
|
-
stmt_line = stmts.last
|
|
821
|
+
stmt_col = stmts.last&.column
|
|
822
|
+
stmt_line = stmts.last&.line
|
|
824
823
|
else_body = source_line_from(stmt_line, stmt_col)
|
|
825
824
|
return false unless else_body
|
|
826
825
|
text << else_body
|
|
@@ -840,9 +839,9 @@ module MilkTea
|
|
|
840
839
|
def visually_inline_if?(statement, stmts)
|
|
841
840
|
n = statement.branches.length
|
|
842
841
|
statement.branches.each_with_index.all? { |b, i|
|
|
843
|
-
stmts[i].
|
|
842
|
+
stmts[i].line == b.line
|
|
844
843
|
} && (
|
|
845
|
-
stmts[n].
|
|
844
|
+
stmts[n].line && statement.else_line && stmts[n].line == statement.else_line
|
|
846
845
|
)
|
|
847
846
|
end
|
|
848
847
|
|
|
@@ -897,8 +896,8 @@ module MilkTea
|
|
|
897
896
|
next unless node_fingerprint(body_of.call(first)) == node_fingerprint(body_of.call(second))
|
|
898
897
|
|
|
899
898
|
pattern = second.pattern
|
|
900
|
-
pattern_line = pattern.
|
|
901
|
-
pattern_column = pattern.
|
|
899
|
+
pattern_line = pattern.line || second.binding_line
|
|
900
|
+
pattern_column = pattern.column || second.binding_column
|
|
902
901
|
emit_conciseness_hint(
|
|
903
902
|
"prefer-or-pattern",
|
|
904
903
|
line: pattern_line,
|
|
@@ -935,8 +934,8 @@ module MilkTea
|
|
|
935
934
|
source_text = expr_source_name(copied.first.value.receiver)
|
|
936
935
|
emit_conciseness_hint(
|
|
937
936
|
"prefer-struct-with",
|
|
938
|
-
line: call.callee.
|
|
939
|
-
column: call.callee.
|
|
937
|
+
line: call.callee.line,
|
|
938
|
+
column: call.callee.column,
|
|
940
939
|
message: "copies #{copied.size} field(s) from `#{source_text}`; use `#{source_text}.with(#{changed_names.join(", ")} = …)`",
|
|
941
940
|
)
|
|
942
941
|
end
|
|
@@ -968,8 +967,8 @@ module MilkTea
|
|
|
968
967
|
|
|
969
968
|
emit_conciseness_hint(
|
|
970
969
|
"prefer-try",
|
|
971
|
-
line: scrutinee.
|
|
972
|
-
column: scrutinee.
|
|
970
|
+
line: scrutinee.line,
|
|
971
|
+
column: scrutinee.column,
|
|
973
972
|
message: "this #{base} match only propagates the failure branch; consider `expr?`",
|
|
974
973
|
)
|
|
975
974
|
end
|
|
@@ -1045,6 +1044,65 @@ module MilkTea
|
|
|
1045
1044
|
# check_boundary_widening_cast at the specific boundary sites.
|
|
1046
1045
|
end
|
|
1047
1046
|
|
|
1047
|
+
# ── redundant cast parentheses ────────────────────────────────────────────────────
|
|
1048
|
+
# `T<-(x)` when `T<-x` would be equivalent because the inner expression needs
|
|
1049
|
+
# no precedence protection. Parens are required when the inner expression
|
|
1050
|
+
# contains a binary operator, range, or inline conditional.
|
|
1051
|
+
|
|
1052
|
+
def check_redundant_cast_parens(cast)
|
|
1053
|
+
|
|
1054
|
+
line_idx = Integer(cast.line) - 1
|
|
1055
|
+
return if line_idx < 0 || line_idx >= @source_lines.length
|
|
1056
|
+
|
|
1057
|
+
line = @source_lines[line_idx].to_s
|
|
1058
|
+
col = Integer(cast.column) - 1
|
|
1059
|
+
arrow = line.index("<-", col)
|
|
1060
|
+
return unless arrow
|
|
1061
|
+
arrow_end = arrow + 2
|
|
1062
|
+
return if arrow_end >= line.length
|
|
1063
|
+
return unless line[arrow_end] == "("
|
|
1064
|
+
|
|
1065
|
+
close = match_paren(line, arrow_end)
|
|
1066
|
+
return unless close
|
|
1067
|
+
|
|
1068
|
+
inner = line[arrow_end + 1...close].strip
|
|
1069
|
+
return if inner.empty?
|
|
1070
|
+
return if inner_has_top_level_operators?(inner)
|
|
1071
|
+
|
|
1072
|
+
emit_redundant_cast(cast, type_ref_name(cast.target_type) || "",
|
|
1073
|
+
"parentheses around cast expression are redundant")
|
|
1074
|
+
end
|
|
1075
|
+
|
|
1076
|
+
def match_paren(line, open_pos)
|
|
1077
|
+
depth = 0
|
|
1078
|
+
(open_pos...line.length).each do |i|
|
|
1079
|
+
case line[i]
|
|
1080
|
+
when "(" then depth += 1
|
|
1081
|
+
when ")" then depth -= 1; return i if depth == 0
|
|
1082
|
+
end
|
|
1083
|
+
end
|
|
1084
|
+
nil
|
|
1085
|
+
end
|
|
1086
|
+
|
|
1087
|
+
BINARY_OP_CHARS = %w[+ - * / % & | ^ < > = ! ? :]
|
|
1088
|
+
|
|
1089
|
+
def inner_has_top_level_operators?(inner)
|
|
1090
|
+
depth = 0
|
|
1091
|
+
i = 0
|
|
1092
|
+
while i < inner.length
|
|
1093
|
+
case inner[i]
|
|
1094
|
+
when "(", "[", "{"
|
|
1095
|
+
depth += 1
|
|
1096
|
+
when ")", "]", "}"
|
|
1097
|
+
depth -= 1 if depth > 0
|
|
1098
|
+
when *BINARY_OP_CHARS
|
|
1099
|
+
return true if depth == 0
|
|
1100
|
+
end
|
|
1101
|
+
i += 1
|
|
1102
|
+
end
|
|
1103
|
+
false
|
|
1104
|
+
end
|
|
1105
|
+
|
|
1048
1106
|
# Reports a widening cast as redundant only when it sits *directly* at a
|
|
1049
1107
|
# coercion slot: the RHS of a typed `let`/`var`, a `return` value, or the
|
|
1050
1108
|
# RHS of a plain `=` assignment. At those positions the slot type is
|
|
@@ -1088,8 +1146,8 @@ module MilkTea
|
|
|
1088
1146
|
end
|
|
1089
1147
|
|
|
1090
1148
|
def emit_redundant_cast(cast_expr, target_name, reason)
|
|
1091
|
-
line = cast_expr.
|
|
1092
|
-
column = cast_expr.
|
|
1149
|
+
line = cast_expr.line || expression_line(cast_expr)
|
|
1150
|
+
column = cast_expr.column || expression_column(cast_expr)
|
|
1093
1151
|
|
|
1094
1152
|
@warnings << Warning.new(
|
|
1095
1153
|
path: @path,
|
|
@@ -1146,15 +1204,15 @@ module MilkTea
|
|
|
1146
1204
|
end
|
|
1147
1205
|
end
|
|
1148
1206
|
# ── borrow facts helpers ──────────────────────────────────────────────────
|
|
1149
|
-
|
|
1207
|
+
|
|
1150
1208
|
BORROW_CALL_NAMES = %w[ref_of ptr_of].freeze
|
|
1151
|
-
|
|
1209
|
+
|
|
1152
1210
|
def collect_borrowed_names(stmts)
|
|
1153
1211
|
names = Set.new
|
|
1154
1212
|
stmts.each { |s| collect_borrows_from_stmt(s, names) }
|
|
1155
1213
|
names
|
|
1156
1214
|
end
|
|
1157
|
-
|
|
1215
|
+
|
|
1158
1216
|
def collect_borrows_from_stmt(stmt, names)
|
|
1159
1217
|
case stmt
|
|
1160
1218
|
when AST::LocalDecl
|
|
@@ -1190,7 +1248,7 @@ module MilkTea
|
|
|
1190
1248
|
stmt.else_body&.each { |s| collect_borrows_from_stmt(s, names) }
|
|
1191
1249
|
end
|
|
1192
1250
|
end
|
|
1193
|
-
|
|
1251
|
+
|
|
1194
1252
|
def collect_borrows_from_expr(expr, names, inside_call_argument: false)
|
|
1195
1253
|
case expr
|
|
1196
1254
|
when nil then nil
|
|
@@ -1222,13 +1280,13 @@ module MilkTea
|
|
|
1222
1280
|
collect_borrows_from_expr(expr.index, names, inside_call_argument:)
|
|
1223
1281
|
end
|
|
1224
1282
|
end
|
|
1225
|
-
|
|
1283
|
+
|
|
1226
1284
|
def collect_written_names(stmts)
|
|
1227
1285
|
names = Set.new
|
|
1228
1286
|
stmts.each { |s| collect_writes_from_stmt(s, names) }
|
|
1229
1287
|
names
|
|
1230
1288
|
end
|
|
1231
|
-
|
|
1289
|
+
|
|
1232
1290
|
def collect_writes_from_stmt(stmt, names)
|
|
1233
1291
|
case stmt
|
|
1234
1292
|
when AST::Assignment
|
|
@@ -1252,15 +1310,15 @@ module MilkTea
|
|
|
1252
1310
|
stmt.body&.each { |s| collect_writes_from_stmt(s, names) }
|
|
1253
1311
|
end
|
|
1254
1312
|
end
|
|
1255
|
-
|
|
1313
|
+
|
|
1256
1314
|
def collect_writes_from_stmt_list(stmts, names)
|
|
1257
1315
|
stmts.each { |s| collect_writes_from_stmt(s, names) }
|
|
1258
1316
|
end
|
|
1259
|
-
|
|
1317
|
+
|
|
1260
1318
|
def stmt_sub_stmts(_stmt)
|
|
1261
1319
|
[]
|
|
1262
1320
|
end
|
|
1263
|
-
|
|
1321
|
+
|
|
1264
1322
|
def find_borrow_location(stmts, name)
|
|
1265
1323
|
stmts.each do |stmt|
|
|
1266
1324
|
location = find_borrow_location_in_stmt(stmt, name)
|
|
@@ -1268,7 +1326,7 @@ module MilkTea
|
|
|
1268
1326
|
end
|
|
1269
1327
|
nil
|
|
1270
1328
|
end
|
|
1271
|
-
|
|
1329
|
+
|
|
1272
1330
|
def find_borrow_location_in_stmt(stmt, name)
|
|
1273
1331
|
case stmt
|
|
1274
1332
|
when AST::LocalDecl
|
|
@@ -1320,7 +1378,7 @@ module MilkTea
|
|
|
1320
1378
|
nil
|
|
1321
1379
|
end
|
|
1322
1380
|
end
|
|
1323
|
-
|
|
1381
|
+
|
|
1324
1382
|
def find_borrow_location_in_expr(expr, name)
|
|
1325
1383
|
case expr
|
|
1326
1384
|
when nil then nil
|
data/lib/milk_tea/tooling/run.rb
CHANGED
data/std/cli.mt
CHANGED
|
@@ -485,11 +485,8 @@ function parse_long_option_impl(
|
|
|
485
485
|
|
|
486
486
|
match inline_value:
|
|
487
487
|
Option.some as inline_payload:
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
return Result[ptr_uint, Error].failure(error= set_error.error)
|
|
491
|
-
Result.success:
|
|
492
|
-
return Result[ptr_uint, Error].success(value= consumed)
|
|
488
|
+
let _ = set_option_value(result, spec, inline_payload.value)?
|
|
489
|
+
return Result[ptr_uint, Error].success(value= consumed)
|
|
493
490
|
Option.none:
|
|
494
491
|
pass
|
|
495
492
|
|
|
@@ -497,12 +494,9 @@ function parse_long_option_impl(
|
|
|
497
494
|
let missing = fmt.format(f"--#{spec.long_name}")
|
|
498
495
|
return Result[ptr_uint, Error].failure(error= require_value_arg(missing.as_str()))
|
|
499
496
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
Result.success:
|
|
504
|
-
consumed = 2z
|
|
505
|
-
return Result[ptr_uint, Error].success(value= consumed)
|
|
497
|
+
let _ = set_option_value(result, spec, value_arg)?
|
|
498
|
+
consumed = 2z
|
|
499
|
+
return Result[ptr_uint, Error].success(value= consumed)
|
|
506
500
|
|
|
507
501
|
match inline_value:
|
|
508
502
|
Option.some:
|
|
@@ -510,11 +504,8 @@ function parse_long_option_impl(
|
|
|
510
504
|
Option.none:
|
|
511
505
|
pass
|
|
512
506
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
return Result[ptr_uint, Error].failure(error= payload.error)
|
|
516
|
-
Result.success:
|
|
517
|
-
return Result[ptr_uint, Error].success(value= 1z)
|
|
507
|
+
let _ = set_option_flag(result, spec)?
|
|
508
|
+
return Result[ptr_uint, Error].success(value= 1z)
|
|
518
509
|
|
|
519
510
|
|
|
520
511
|
function parse_short_option_impl(
|
|
@@ -537,28 +528,18 @@ function parse_short_option_impl(
|
|
|
537
528
|
|
|
538
529
|
if short_index + 1 < arg.len:
|
|
539
530
|
let value = arg.slice(short_index + 1, arg.len - short_index - 1)
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
return Result[ptr_uint, Error].failure(error= payload.error)
|
|
543
|
-
Result.success:
|
|
544
|
-
return Result[ptr_uint, Error].success(value= consumed)
|
|
531
|
+
let _ = set_option_value(result, spec, value)?
|
|
532
|
+
return Result[ptr_uint, Error].success(value= consumed)
|
|
545
533
|
|
|
546
534
|
let value_arg = next_arg else:
|
|
547
535
|
let missing = fmt.format(f"-#{short_name}")
|
|
548
536
|
return Result[ptr_uint, Error].failure(error= require_value_arg(missing.as_str()))
|
|
549
537
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
Result.success:
|
|
554
|
-
consumed = 2z
|
|
555
|
-
return Result[ptr_uint, Error].success(value= consumed)
|
|
538
|
+
let _ = set_option_value(result, spec, value_arg)?
|
|
539
|
+
consumed = 2z
|
|
540
|
+
return Result[ptr_uint, Error].success(value= consumed)
|
|
556
541
|
|
|
557
|
-
|
|
558
|
-
Result.failure as payload:
|
|
559
|
-
return Result[ptr_uint, Error].failure(error= payload.error)
|
|
560
|
-
Result.success:
|
|
561
|
-
pass
|
|
542
|
+
let _ = set_option_flag(result, spec)?
|
|
562
543
|
|
|
563
544
|
short_index += 1
|
|
564
545
|
|
data/std/color.mt
CHANGED
|
@@ -50,8 +50,8 @@ function fabs(x: float) -> float:
|
|
|
50
50
|
function fmod(x: float, m: float) -> float:
|
|
51
51
|
# x - floor(x / m) * m
|
|
52
52
|
let div = x / m
|
|
53
|
-
let fl = float<-(int<-
|
|
54
|
-
if div < 0.0 and float<-(int<-
|
|
53
|
+
let fl = float<-(int<-div)
|
|
54
|
+
if div < 0.0 and float<-(int<-div) != div:
|
|
55
55
|
return x - (fl - 1.0) * m
|
|
56
56
|
return x - fl * m
|
|
57
57
|
|
|
@@ -143,9 +143,9 @@ extending Color:
|
|
|
143
143
|
|
|
144
144
|
|
|
145
145
|
public function to_hsl() -> (float, float, float):
|
|
146
|
-
let rf = float<-
|
|
147
|
-
let gf = float<-
|
|
148
|
-
let bf = float<-
|
|
146
|
+
let rf = float<-this.r / 255.0
|
|
147
|
+
let gf = float<-this.g / 255.0
|
|
148
|
+
let bf = float<-this.b / 255.0
|
|
149
149
|
|
|
150
150
|
let mx = fmax(fmax(rf, gf), bf)
|
|
151
151
|
let mn = fmin(fmin(rf, gf), bf)
|
|
@@ -171,9 +171,9 @@ extending Color:
|
|
|
171
171
|
|
|
172
172
|
|
|
173
173
|
public function to_hsv() -> (float, float, float):
|
|
174
|
-
let rf = float<-
|
|
175
|
-
let gf = float<-
|
|
176
|
-
let bf = float<-
|
|
174
|
+
let rf = float<-this.r / 255.0
|
|
175
|
+
let gf = float<-this.g / 255.0
|
|
176
|
+
let bf = float<-this.b / 255.0
|
|
177
177
|
|
|
178
178
|
let mx = fmax(fmax(rf, gf), bf)
|
|
179
179
|
let mn = fmin(fmin(rf, gf), bf)
|
|
@@ -198,11 +198,11 @@ extending Color:
|
|
|
198
198
|
|
|
199
199
|
|
|
200
200
|
public function lerp(target: Color, t: float) -> Color:
|
|
201
|
-
let r = float<-
|
|
202
|
-
let g = float<-
|
|
203
|
-
let b = float<-
|
|
204
|
-
let a = float<-
|
|
205
|
-
return Color(r = ubyte<-
|
|
201
|
+
let r = float<-this.r + (float<-target.r - float<-this.r) * t
|
|
202
|
+
let g = float<-this.g + (float<-target.g - float<-this.g) * t
|
|
203
|
+
let b = float<-this.b + (float<-target.b - float<-this.b) * t
|
|
204
|
+
let a = float<-this.a + (float<-target.a - float<-this.a) * t
|
|
205
|
+
return Color(r = ubyte<-r, g = ubyte<-g, b = ubyte<-b, a = ubyte<-a)
|
|
206
206
|
|
|
207
207
|
|
|
208
208
|
public function alpha_blend(background: Color) -> Color:
|
|
@@ -211,33 +211,33 @@ extending Color:
|
|
|
211
211
|
if this.a == 255:
|
|
212
212
|
return this
|
|
213
213
|
|
|
214
|
-
let sa = float<-
|
|
215
|
-
let da = float<-
|
|
214
|
+
let sa = float<-this.a / 255.0
|
|
215
|
+
let da = float<-background.a / 255.0
|
|
216
216
|
|
|
217
|
-
let r_out = float<-
|
|
218
|
-
let g_out = float<-
|
|
219
|
-
let b_out = float<-
|
|
217
|
+
let r_out = float<-this.r * sa + float<-background.r * da * (1.0 - sa)
|
|
218
|
+
let g_out = float<-this.g * sa + float<-background.g * da * (1.0 - sa)
|
|
219
|
+
let b_out = float<-this.b * sa + float<-background.b * da * (1.0 - sa)
|
|
220
220
|
let a_out = sa + da * (1.0 - sa)
|
|
221
221
|
|
|
222
222
|
return Color(
|
|
223
|
-
r = ubyte<-
|
|
224
|
-
g = ubyte<-
|
|
225
|
-
b = ubyte<-
|
|
223
|
+
r = ubyte<-r_out,
|
|
224
|
+
g = ubyte<-g_out,
|
|
225
|
+
b = ubyte<-b_out,
|
|
226
226
|
a = ubyte<-(a_out * 255.0)
|
|
227
227
|
)
|
|
228
228
|
|
|
229
229
|
|
|
230
230
|
public function scale(factor: float) -> Color:
|
|
231
|
-
let r = fmin(fmax(float<-
|
|
232
|
-
let g = fmin(fmax(float<-
|
|
233
|
-
let b = fmin(fmax(float<-
|
|
234
|
-
return Color(r = ubyte<-
|
|
231
|
+
let r = fmin(fmax(float<-this.r * factor, 0.0), 255.0)
|
|
232
|
+
let g = fmin(fmax(float<-this.g * factor, 0.0), 255.0)
|
|
233
|
+
let b = fmin(fmax(float<-this.b * factor, 0.0), 255.0)
|
|
234
|
+
return Color(r = ubyte<-r, g = ubyte<-g, b = ubyte<-b, a = this.a)
|
|
235
235
|
|
|
236
236
|
|
|
237
237
|
public function multiply(other: Color) -> Color:
|
|
238
|
-
let r = ubyte<-(
|
|
239
|
-
let g = ubyte<-(
|
|
240
|
-
let b = ubyte<-(
|
|
238
|
+
let r = ubyte<-((int<-this.r * int<-other.r) / 255)
|
|
239
|
+
let g = ubyte<-((int<-this.g * int<-other.g) / 255)
|
|
240
|
+
let b = ubyte<-((int<-this.b * int<-other.b) / 255)
|
|
241
241
|
return Color(r = r, g = g, b = b, a = this.a)
|
|
242
242
|
|
|
243
243
|
|
data/std/encoding.mt
CHANGED
|
@@ -47,15 +47,15 @@ public function decode_utf8_codepoint(text: str, byte_offset: ptr_uint) -> Optio
|
|
|
47
47
|
return Option[uint].none
|
|
48
48
|
|
|
49
49
|
if len == 1:
|
|
50
|
-
return Option[uint].some(value = uint<-
|
|
50
|
+
return Option[uint].some(value = uint<-b0)
|
|
51
51
|
|
|
52
52
|
var codepoint: uint = (b0)
|
|
53
53
|
if len == 2:
|
|
54
|
-
codepoint = codepoint & uint<-
|
|
54
|
+
codepoint = codepoint & uint<-0x1F
|
|
55
55
|
else if len == 3:
|
|
56
|
-
codepoint = codepoint & uint<-
|
|
56
|
+
codepoint = codepoint & uint<-0x0F
|
|
57
57
|
else if len == 4:
|
|
58
|
-
codepoint = codepoint & uint<-
|
|
58
|
+
codepoint = codepoint & uint<-0x07
|
|
59
59
|
var i: ptr_uint = 1
|
|
60
60
|
while i < len:
|
|
61
61
|
codepoint = (codepoint << 6) | uint<-(text.byte_at(byte_offset + i) & 0x3F)
|