mt-lang 0.3.4 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/milk_tea/base.rb +1 -1
- data/lib/milk_tea/core/c_backend/feature_detection.rb +27 -55
- data/lib/milk_tea/core/c_backend/format_helpers.rb +551 -0
- data/lib/milk_tea/core/c_backend/runtime_helpers.rb +0 -542
- data/lib/milk_tea/core/c_backend/type_collectors.rb +51 -204
- data/lib/milk_tea/core/c_backend.rb +2 -0
- data/lib/milk_tea/core/compatibility_helpers.rb +1 -1
- data/lib/milk_tea/core/lowering/async/lowering.rb +147 -141
- data/lib/milk_tea/core/lowering/block.rb +759 -725
- data/lib/milk_tea/core/lowering/expressions.rb +94 -0
- data/lib/milk_tea/core/lowering/loops.rb +49 -0
- data/lib/milk_tea/core/lowering/resolve.rb +221 -214
- data/lib/milk_tea/core/lowering/utils.rb +0 -222
- data/lib/milk_tea/core/module_loader.rb +29 -48
- data/lib/milk_tea/core/parser/declarations.rb +2 -2
- data/lib/milk_tea/core/parser/recovery.rb +1 -1
- data/lib/milk_tea/core/parser.rb +1 -1
- data/lib/milk_tea/core/semantic_analyzer/expressions.rb +3 -120
- data/lib/milk_tea/core/semantic_analyzer/foreign_functions.rb +116 -113
- data/lib/milk_tea/core/semantic_analyzer/generics.rb +346 -343
- data/lib/milk_tea/core/semantic_analyzer/statements.rb +37 -12
- data/lib/milk_tea/core/types/predicates.rb +501 -499
- data/lib/milk_tea/core/types/visitor.rb +1 -1
- metadata +3 -2
|
@@ -4,6 +4,19 @@ module MilkTea
|
|
|
4
4
|
module LowererResolve
|
|
5
5
|
private
|
|
6
6
|
|
|
7
|
+
PASS_THROUGH_BUILTINS = {
|
|
8
|
+
"fatal" => :fatal,
|
|
9
|
+
"ref_of" => :ref_of,
|
|
10
|
+
"const_ptr_of" => :const_ptr_of,
|
|
11
|
+
"read" => :read,
|
|
12
|
+
"ptr_of" => :ptr_of,
|
|
13
|
+
"get" => :get,
|
|
14
|
+
}.freeze
|
|
15
|
+
|
|
16
|
+
COMPILE_TIME_BUILTINS = %w[
|
|
17
|
+
field_of callable_of has_attribute attribute_of
|
|
18
|
+
].freeze
|
|
19
|
+
|
|
7
20
|
|
|
8
21
|
def direct_function_to_proc_contextual_compatibility?(expression, actual_type, env:, expected_type:)
|
|
9
22
|
return false unless actual_type.is_a?(Types::Function) && proc_type?(expected_type)
|
|
@@ -397,256 +410,248 @@ module MilkTea
|
|
|
397
410
|
def resolve_callee(callee, env, arguments: nil)
|
|
398
411
|
case callee
|
|
399
412
|
when AST::Identifier
|
|
400
|
-
|
|
401
|
-
|
|
413
|
+
resolve_identifier_callee(callee, env, arguments)
|
|
414
|
+
when AST::MemberAccess
|
|
415
|
+
resolve_member_access_callee(callee, env, arguments)
|
|
416
|
+
when AST::Specialization
|
|
417
|
+
resolve_specialization_callee(callee, env)
|
|
418
|
+
else
|
|
419
|
+
resolve_expression_callee(callee, env)
|
|
420
|
+
end
|
|
421
|
+
end
|
|
402
422
|
|
|
403
|
-
|
|
404
|
-
|
|
423
|
+
def resolve_identifier_callee(callee, env, arguments)
|
|
424
|
+
if (binding = lookup_value(callee.name, env))
|
|
425
|
+
return [:callable_value, nil, nil, binding[:type], nil] if callable_type?(binding[:type])
|
|
405
426
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
callee_name = if binding.external
|
|
409
|
-
external_function_c_name(binding)
|
|
410
|
-
else
|
|
411
|
-
function_binding_c_name(binding, module_name: @ctx.module_name)
|
|
412
|
-
end
|
|
413
|
-
[ :function, callee_name, nil, binding.type, binding ]
|
|
414
|
-
elsif callee.name == "fatal"
|
|
415
|
-
[:fatal, nil, nil, nil]
|
|
416
|
-
elsif callee.name == "ref_of"
|
|
417
|
-
[:ref_of, nil, nil, nil]
|
|
418
|
-
elsif callee.name == "const_ptr_of"
|
|
419
|
-
[:const_ptr_of, nil, nil, nil]
|
|
420
|
-
elsif callee.name == "read"
|
|
421
|
-
[:read, nil, nil, nil]
|
|
422
|
-
elsif callee.name == "ptr_of"
|
|
423
|
-
[:ptr_of, nil, nil, nil]
|
|
424
|
-
elsif callee.name == "field_of"
|
|
425
|
-
[:compile_time_builtin, "field_of", nil, compile_time_builtin_function_type("field_of", arguments, env)]
|
|
426
|
-
elsif callee.name == "callable_of"
|
|
427
|
-
[:compile_time_builtin, "callable_of", nil, compile_time_builtin_function_type("callable_of", arguments, env)]
|
|
428
|
-
elsif callee.name == "has_attribute"
|
|
429
|
-
[:compile_time_builtin, "has_attribute", nil, compile_time_builtin_function_type("has_attribute", arguments, env)]
|
|
430
|
-
elsif callee.name == "attribute_of"
|
|
431
|
-
[:compile_time_builtin, "attribute_of", nil, compile_time_builtin_function_type("attribute_of", arguments, env)]
|
|
432
|
-
elsif callee.name == "get"
|
|
433
|
-
[:get, nil, nil, nil]
|
|
434
|
-
elsif (type = @ctx.types[callee.name]).is_a?(Types::Struct) || type.is_a?(Types::StringView) || task_type?(type) || type.is_a?(Types::Vector) || type.is_a?(Types::Matrix) || type.is_a?(Types::Quaternion)
|
|
435
|
-
[ :struct_literal, nil, nil, type ]
|
|
436
|
-
elsif (type = @ctx.types[callee.name]).is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
437
|
-
raise LoweringError, "generic type #{callee.name} requires type arguments"
|
|
438
|
-
else
|
|
439
|
-
emit_fn = @artifacts.emitted_declarations.find { |d| d.is_a?(IR::Function) && d.name == callee.name }
|
|
440
|
-
if emit_fn
|
|
441
|
-
return [:function, emit_fn.linkage_name, nil, emit_fn.return_type, nil]
|
|
442
|
-
end
|
|
427
|
+
raise LoweringError, "#{callee.name} is not callable"
|
|
428
|
+
end
|
|
443
429
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
430
|
+
if @ctx.functions.key?(callee.name)
|
|
431
|
+
binding = specialize_function_binding(@ctx.functions.fetch(callee.name), arguments, env)
|
|
432
|
+
callee_name = if binding.external
|
|
433
|
+
external_function_c_name(binding)
|
|
434
|
+
else
|
|
435
|
+
function_binding_c_name(binding, module_name: @ctx.module_name)
|
|
436
|
+
end
|
|
437
|
+
return [:function, callee_name, nil, binding.type, binding]
|
|
438
|
+
end
|
|
449
439
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
binding = binding.with(owner: imported_module.respond_to?(:analysis) ? imported_module.analysis : imported_module)
|
|
454
|
-
end
|
|
455
|
-
return [:function, function_binding_c_name(binding, module_name: imported_module.name), nil, binding.type, binding] unless binding.external
|
|
440
|
+
if (kind = PASS_THROUGH_BUILTINS[callee.name])
|
|
441
|
+
return [kind, nil, nil, nil]
|
|
442
|
+
end
|
|
456
443
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
if imported_type.is_a?(Types::GenericStructDefinition) || imported_type.is_a?(Types::GenericVariantDefinition)
|
|
461
|
-
raise LoweringError, "generic type #{callee.receiver.name}.#{callee.member} requires type arguments"
|
|
462
|
-
end
|
|
444
|
+
if COMPILE_TIME_BUILTINS.include?(callee.name)
|
|
445
|
+
return [:compile_time_builtin, callee.name, nil, compile_time_builtin_function_type(callee.name, arguments, env)]
|
|
446
|
+
end
|
|
463
447
|
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
448
|
+
type = @ctx.types[callee.name]
|
|
449
|
+
if type.is_a?(Types::Struct) || type.is_a?(Types::StringView) || task_type?(type) || type.is_a?(Types::Vector) || type.is_a?(Types::Matrix) || type.is_a?(Types::Quaternion)
|
|
450
|
+
return [:struct_literal, nil, nil, type]
|
|
451
|
+
end
|
|
467
452
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
end
|
|
472
|
-
end
|
|
453
|
+
if type.is_a?(Types::GenericStructDefinition) || type.is_a?(Types::GenericVariantDefinition)
|
|
454
|
+
raise LoweringError, "generic type #{callee.name} requires type arguments"
|
|
455
|
+
end
|
|
473
456
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
end
|
|
457
|
+
emit_fn = @artifacts.emitted_declarations.find { |d| d.is_a?(IR::Function) && d.name == callee.name }
|
|
458
|
+
if emit_fn
|
|
459
|
+
return [:function, emit_fn.linkage_name, nil, emit_fn.return_type, nil]
|
|
460
|
+
end
|
|
479
461
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
end
|
|
462
|
+
raise LoweringError, "unknown callee #{callee.name}"
|
|
463
|
+
end
|
|
483
464
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
end
|
|
493
|
-
if method_entry
|
|
494
|
-
method_analysis, method_ast = method_entry
|
|
495
|
-
method_binding = method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key(method_ast))
|
|
496
|
-
if method_binding.type.receiver_type.nil?
|
|
497
|
-
method_binding = specialize_function_binding(method_binding, arguments, env, receiver_type: type_expr) if method_binding.type_params.any?
|
|
498
|
-
return [:associated_method, function_binding_c_name(method_binding, module_name: method_analysis.module_name, receiver_type: method_entry_receiver_type), nil, method_binding.type, method_binding]
|
|
499
|
-
end
|
|
465
|
+
def resolve_member_access_callee(callee, env, arguments)
|
|
466
|
+
if callee.receiver.is_a?(AST::Identifier) && @ctx.imports.key?(callee.receiver.name)
|
|
467
|
+
imported_module = @ctx.imports.fetch(callee.receiver.name)
|
|
468
|
+
|
|
469
|
+
if imported_module.functions.key?(callee.member)
|
|
470
|
+
binding = specialize_function_binding(imported_module.functions.fetch(callee.member), arguments, env)
|
|
471
|
+
unless binding.owner
|
|
472
|
+
binding = binding.with(owner: imported_module.respond_to?(:analysis) ? imported_module.analysis : imported_module)
|
|
500
473
|
end
|
|
474
|
+
return [:function, function_binding_c_name(binding, module_name: imported_module.name), nil, binding.type, binding] unless binding.external
|
|
475
|
+
|
|
476
|
+
return [:function, external_function_c_name(binding), nil, binding.type, binding]
|
|
477
|
+
end
|
|
478
|
+
imported_type = imported_module.types[callee.member]
|
|
479
|
+
if imported_type.is_a?(Types::GenericStructDefinition) || imported_type.is_a?(Types::GenericVariantDefinition)
|
|
480
|
+
raise LoweringError, "generic type #{callee.receiver.name}.#{callee.member} requires type arguments"
|
|
481
|
+
end
|
|
501
482
|
|
|
502
|
-
|
|
483
|
+
if imported_type.is_a?(Types::Struct) || imported_type.is_a?(Types::StringView) || task_type?(imported_type) || imported_type.is_a?(Types::Vector) || imported_type.is_a?(Types::Matrix) || imported_type.is_a?(Types::Quaternion)
|
|
484
|
+
return [:struct_literal, nil, nil, imported_module.types.fetch(callee.member)]
|
|
503
485
|
end
|
|
504
486
|
|
|
505
|
-
|
|
487
|
+
if imported_type.is_a?(Types::Variant) && imported_type.arm_names.include?(callee.member)
|
|
488
|
+
arm_name = callee.member
|
|
489
|
+
return [:variant_arm_ctor, nil, nil, imported_type, [imported_type, arm_name]]
|
|
490
|
+
end
|
|
491
|
+
end
|
|
506
492
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
return [:dyn_method, nil, callee.receiver, method_binding, nil]
|
|
493
|
+
if (type_expr = resolve_type_expression(callee.receiver))
|
|
494
|
+
if type_expr.is_a?(Types::Variant) && type_expr.arm_names.include?(callee.member)
|
|
495
|
+
arm_name = callee.member
|
|
496
|
+
return [:variant_arm_ctor, nil, nil, type_expr, [type_expr, arm_name]]
|
|
512
497
|
end
|
|
513
498
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
499
|
+
if type_expr.respond_to?(:nested_types) && type_expr.nested_types.key?(callee.member)
|
|
500
|
+
return [:struct_literal, nil, nil, type_expr.nested_types[callee.member]]
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
dispatch_receiver_type = method_dispatch_receiver_type(type_expr)
|
|
504
|
+
method_entry_receiver_type = type_expr
|
|
505
|
+
method_entry = @method_definitions[[type_expr, callee.member]]
|
|
506
|
+
method_entry ||= @method_definitions[[type_expr, "static:#{callee.member}"]]
|
|
507
|
+
unless method_entry || dispatch_receiver_type == type_expr
|
|
518
508
|
method_entry_receiver_type = dispatch_receiver_type
|
|
519
509
|
method_entry = @method_definitions[[dispatch_receiver_type, callee.member]]
|
|
510
|
+
method_entry ||= @method_definitions[[dispatch_receiver_type, "static:#{callee.member}"]]
|
|
520
511
|
end
|
|
521
512
|
if method_entry
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
:method,
|
|
528
|
-
function_binding_c_name(method_binding, module_name: method_analysis.module_name, receiver_type: method_entry_receiver_type),
|
|
529
|
-
callee.receiver,
|
|
530
|
-
method_binding.type,
|
|
531
|
-
method_binding,
|
|
532
|
-
]
|
|
533
|
-
end
|
|
534
|
-
|
|
535
|
-
if callee.member == "with" && struct_with_target_type?(resolved_receiver_type)
|
|
536
|
-
return [:struct_with, nil, callee.receiver, resolved_receiver_type]
|
|
537
|
-
end
|
|
538
|
-
|
|
539
|
-
if (precomputed = @ctx.resolved_call_kinds[@ctx.ast.node_ids[callee.object_id]])
|
|
540
|
-
case precomputed
|
|
541
|
-
when :str_buffer_clear, :str_buffer_assign, :str_buffer_append, :str_buffer_assign_format, :str_buffer_append_format,
|
|
542
|
-
:str_buffer_len, :str_buffer_capacity, :str_buffer_as_str, :str_buffer_as_cstr
|
|
543
|
-
return [precomputed, nil, callee.receiver, str_buffer_method_type(precomputed, resolved_receiver_type)]
|
|
544
|
-
when :event_subscribe, :event_subscribe_once, :event_unsubscribe, :event_emit, :event_wait
|
|
545
|
-
event_type = infer_expression_type(callee.receiver, env:)
|
|
546
|
-
return [precomputed, nil, callee.receiver, event_method_type(precomputed, event_type)]
|
|
547
|
-
when :atomic_load, :atomic_store, :atomic_add, :atomic_sub, :atomic_exchange, :atomic_compare_exchange
|
|
548
|
-
elem = atomic_element_type(resolved_receiver_type)
|
|
549
|
-
ret = case precomputed
|
|
550
|
-
when :atomic_load, :atomic_add, :atomic_sub, :atomic_exchange then elem
|
|
551
|
-
when :atomic_store then @ctx.types.fetch("void")
|
|
552
|
-
when :atomic_compare_exchange then @ctx.types.fetch("bool")
|
|
553
|
-
end
|
|
554
|
-
return [precomputed, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
555
|
-
when :simd_lane_with
|
|
556
|
-
return [precomputed, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: resolved_receiver_type)]
|
|
513
|
+
method_analysis, method_ast = method_entry
|
|
514
|
+
method_binding = method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key(method_ast))
|
|
515
|
+
if method_binding.type.receiver_type.nil?
|
|
516
|
+
method_binding = specialize_function_binding(method_binding, arguments, env, receiver_type: type_expr) if method_binding.type_params.any?
|
|
517
|
+
return [:associated_method, function_binding_c_name(method_binding, module_name: method_analysis.module_name, receiver_type: method_entry_receiver_type), nil, method_binding.type, method_binding]
|
|
557
518
|
end
|
|
558
519
|
end
|
|
559
520
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
end
|
|
521
|
+
raise LoweringError, "unknown associated function #{type_expr}.#{callee.member}"
|
|
522
|
+
end
|
|
563
523
|
|
|
564
|
-
|
|
565
|
-
event_type = infer_expression_type(callee.receiver, env:)
|
|
566
|
-
return [event_method, nil, callee.receiver, event_method_type(event_method, event_type)]
|
|
567
|
-
end
|
|
524
|
+
resolved_receiver_type = infer_method_receiver_type(callee.receiver, env:, member_name: callee.member)
|
|
568
525
|
|
|
569
|
-
|
|
526
|
+
if dyn_type?(resolved_receiver_type)
|
|
527
|
+
interface = resolved_receiver_type.interface_binding
|
|
528
|
+
method_binding = interface.methods[callee.member]
|
|
529
|
+
raise LoweringError, "no method '#{callee.member}' on interface #{interface.name}" unless method_binding
|
|
530
|
+
return [:dyn_method, nil, callee.receiver, method_binding, nil]
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
dispatch_receiver_type = method_dispatch_receiver_type(resolved_receiver_type)
|
|
534
|
+
method_entry_receiver_type = resolved_receiver_type
|
|
535
|
+
method_entry = @method_definitions[[resolved_receiver_type, callee.member]]
|
|
536
|
+
unless method_entry || dispatch_receiver_type == resolved_receiver_type
|
|
537
|
+
method_entry_receiver_type = dispatch_receiver_type
|
|
538
|
+
method_entry = @method_definitions[[dispatch_receiver_type, callee.member]]
|
|
539
|
+
end
|
|
540
|
+
if method_entry
|
|
541
|
+
method_analysis, method_ast = method_entry
|
|
542
|
+
method_analysis_key = method_ast.kind == :static ? "static:#{method_ast.name}" : method_ast.name
|
|
543
|
+
method_binding = method_analysis.methods.fetch(method_entry_receiver_type).fetch(method_analysis_key)
|
|
544
|
+
method_binding = specialize_function_binding(method_binding, arguments, env, receiver_type: resolved_receiver_type)
|
|
545
|
+
return [
|
|
546
|
+
:method,
|
|
547
|
+
function_binding_c_name(method_binding, module_name: method_analysis.module_name, receiver_type: method_entry_receiver_type),
|
|
548
|
+
callee.receiver,
|
|
549
|
+
method_binding.type,
|
|
550
|
+
method_binding,
|
|
551
|
+
]
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
if callee.member == "with" && struct_with_target_type?(resolved_receiver_type)
|
|
555
|
+
return [:struct_with, nil, callee.receiver, resolved_receiver_type]
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
if (precomputed = @ctx.resolved_call_kinds[@ctx.ast.node_ids[callee.object_id]])
|
|
559
|
+
case precomputed
|
|
560
|
+
when :str_buffer_clear, :str_buffer_assign, :str_buffer_append, :str_buffer_assign_format, :str_buffer_append_format,
|
|
561
|
+
:str_buffer_len, :str_buffer_capacity, :str_buffer_as_str, :str_buffer_as_cstr
|
|
562
|
+
return [precomputed, nil, callee.receiver, str_buffer_method_type(precomputed, resolved_receiver_type)]
|
|
563
|
+
when :event_subscribe, :event_subscribe_once, :event_unsubscribe, :event_emit, :event_wait
|
|
564
|
+
event_type = infer_expression_type(callee.receiver, env:)
|
|
565
|
+
return [precomputed, nil, callee.receiver, event_method_type(precomputed, event_type)]
|
|
566
|
+
when :atomic_load, :atomic_store, :atomic_add, :atomic_sub, :atomic_exchange, :atomic_compare_exchange
|
|
570
567
|
elem = atomic_element_type(resolved_receiver_type)
|
|
571
|
-
ret = case
|
|
568
|
+
ret = case precomputed
|
|
572
569
|
when :atomic_load, :atomic_add, :atomic_sub, :atomic_exchange then elem
|
|
573
570
|
when :atomic_store then @ctx.types.fetch("void")
|
|
574
571
|
when :atomic_compare_exchange then @ctx.types.fetch("bool")
|
|
575
572
|
end
|
|
576
|
-
return [
|
|
573
|
+
return [precomputed, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
574
|
+
when :simd_lane_with
|
|
575
|
+
return [precomputed, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: resolved_receiver_type)]
|
|
577
576
|
end
|
|
577
|
+
end
|
|
578
578
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
end
|
|
583
|
-
return [simd_method, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
584
|
-
end
|
|
579
|
+
if (str_buffer_method = str_buffer_method_kind(resolved_receiver_type, callee.member))
|
|
580
|
+
return [str_buffer_method, nil, callee.receiver, str_buffer_method_type(str_buffer_method, resolved_receiver_type)]
|
|
581
|
+
end
|
|
585
582
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
583
|
+
if (event_method = event_method_kind(resolved_receiver_type, callee.member))
|
|
584
|
+
event_type = infer_expression_type(callee.receiver, env:)
|
|
585
|
+
return [event_method, nil, callee.receiver, event_method_type(event_method, event_type)]
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
if (atomic_method = atomic_method_kind(resolved_receiver_type, callee.member))
|
|
589
|
+
elem = atomic_element_type(resolved_receiver_type)
|
|
590
|
+
ret = case atomic_method
|
|
591
|
+
when :atomic_load, :atomic_add, :atomic_sub, :atomic_exchange then elem
|
|
592
|
+
when :atomic_store then @ctx.types.fetch("void")
|
|
593
|
+
when :atomic_compare_exchange then @ctx.types.fetch("bool")
|
|
594
|
+
end
|
|
595
|
+
return [atomic_method, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
596
|
+
end
|
|
590
597
|
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
598
|
+
if (simd_method = simd_method_kind(resolved_receiver_type, callee.member))
|
|
599
|
+
ret = case simd_method
|
|
600
|
+
when :simd_lane_with then resolved_receiver_type
|
|
601
|
+
end
|
|
602
|
+
return [simd_method, nil, callee.receiver, Types::Registry.function(nil, params: [], return_type: ret)]
|
|
603
|
+
end
|
|
594
604
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
605
|
+
field_receiver_type = infer_field_receiver_type(callee.receiver, env:)
|
|
606
|
+
if array_type?(field_receiver_type) && callee.member == "as_span"
|
|
607
|
+
return [:array_as_span, nil, callee.receiver, Types::Registry.span(array_element_type(field_receiver_type))]
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
member_type = field_receiver_type.respond_to?(:field) ? field_receiver_type.field(callee.member) : nil
|
|
611
|
+
member_type = field_receiver_type.respond_to?(:field) ? field_receiver_type.field(callee.member) : nil
|
|
612
|
+
return [:callable_value, nil, nil, member_type, nil] if callable_type?(member_type)
|
|
613
|
+
|
|
614
|
+
raise LoweringError, "unknown callee #{callee.receiver}.#{callee.member}"
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
def resolve_specialization_callee(callee, env)
|
|
618
|
+
if callee.callee.is_a?(AST::Identifier)
|
|
619
|
+
case callee.callee.name
|
|
620
|
+
when "reinterpret"
|
|
598
621
|
target_type = resolve_type_ref(callee.arguments.fetch(0).value)
|
|
599
622
|
return [:reinterpret, nil, nil, Types::Registry.function("reinterpret", params: [Types::Registry.parameter("value", target_type)], return_type: target_type)]
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "array"
|
|
623
|
+
when "array"
|
|
603
624
|
array_type = resolve_type_ref(AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["array"]), arguments: callee.arguments, nullable: false))
|
|
604
625
|
return [:array, nil, nil, array_type]
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "simd"
|
|
626
|
+
when "simd"
|
|
608
627
|
simd_type = resolve_type_ref(AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["simd"]), arguments: callee.arguments, nullable: false))
|
|
609
628
|
return [:simd, nil, nil, simd_type]
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "span"
|
|
629
|
+
when "span"
|
|
613
630
|
span_type = resolve_type_ref(AST::TypeRef.new(name: AST::QualifiedName.new(parts: ["span"]), arguments: callee.arguments, nullable: false))
|
|
614
631
|
return [:struct_literal, nil, nil, span_type]
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "zero"
|
|
632
|
+
when "zero"
|
|
618
633
|
target_type = resolve_type_ref(callee.arguments.fetch(0).value)
|
|
619
634
|
return [:zero, nil, nil, Types::Registry.function("zero", params: [], return_type: target_type)]
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "hash"
|
|
635
|
+
when "hash"
|
|
623
636
|
resolution = resolve_hash_specialization(callee, env:)
|
|
624
637
|
return [:hash, resolution.callee_name, nil, Types::Registry.function("hash", params: [Types::Registry.parameter("value", resolution.target_type)], return_type: @ctx.types.fetch("uint")), resolution.binding]
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "equal"
|
|
638
|
+
when "equal"
|
|
628
639
|
resolution = resolve_equal_specialization(callee, env:)
|
|
629
640
|
params = [
|
|
630
641
|
Types::Registry.parameter("left", resolution.target_type),
|
|
631
642
|
Types::Registry.parameter("right", resolution.target_type),
|
|
632
643
|
]
|
|
633
644
|
return [:equal, resolution.callee_name, nil, Types::Registry.function("equal", params:, return_type: @ctx.types.fetch("bool")), resolution.binding]
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "order"
|
|
645
|
+
when "order"
|
|
637
646
|
resolution = resolve_order_specialization(callee, env:)
|
|
638
647
|
params = [
|
|
639
648
|
Types::Registry.parameter("left", resolution.target_type),
|
|
640
649
|
Types::Registry.parameter("right", resolution.target_type),
|
|
641
650
|
]
|
|
642
651
|
return [:order, resolution.callee_name, nil, Types::Registry.function("order", params:, return_type: @ctx.types.fetch("int")), resolution.binding]
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "attribute_arg"
|
|
652
|
+
when "attribute_arg"
|
|
646
653
|
return [:compile_time_builtin, "attribute_arg", nil, compile_time_builtin_specialization_function_type(callee)]
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
if callee.callee.is_a?(AST::Identifier) && callee.callee.name == "adapt"
|
|
654
|
+
when "adapt"
|
|
650
655
|
raise LoweringError, "adapt requires exactly one type argument" unless callee.arguments.length == 1
|
|
651
656
|
|
|
652
657
|
type_arg = callee.arguments.first.value
|
|
@@ -658,38 +663,40 @@ module MilkTea
|
|
|
658
663
|
dyn_type = Types::Dyn.new(interface, interface.respond_to?(:type_arguments) ? (interface.type_arguments || []) : [])
|
|
659
664
|
return [:adapt, nil, nil, dyn_type, interface]
|
|
660
665
|
end
|
|
666
|
+
end
|
|
661
667
|
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
end
|
|
673
|
-
|
|
674
|
-
if function_binding.external
|
|
675
|
-
return [:function, external_function_c_name(function_binding), nil, function_binding.type, function_binding]
|
|
676
|
-
end
|
|
677
|
-
|
|
678
|
-
return [:function, function_binding_c_name(function_binding, module_name: function_binding.owner.module_name), nil, function_binding.type, function_binding]
|
|
668
|
+
if (callable_resolution = resolve_specialized_callable_binding(callee, env:))
|
|
669
|
+
callable_kind, function_binding, receiver = callable_resolution
|
|
670
|
+
if callable_kind == :method
|
|
671
|
+
return [
|
|
672
|
+
:method,
|
|
673
|
+
function_binding_c_name(function_binding, module_name: function_binding.owner.module_name, receiver_type: function_binding.type.receiver_type),
|
|
674
|
+
receiver,
|
|
675
|
+
function_binding.type,
|
|
676
|
+
function_binding,
|
|
677
|
+
]
|
|
679
678
|
end
|
|
680
679
|
|
|
681
|
-
if
|
|
682
|
-
|
|
683
|
-
return [:struct_literal, nil, nil, specialized_type] if specialized_type.is_a?(Types::Struct) || task_type?(specialized_type) || specialized_type.is_a?(Types::Vector) || specialized_type.is_a?(Types::Matrix) || specialized_type.is_a?(Types::Quaternion) || specialized_type.is_a?(Types::Simd)
|
|
680
|
+
if function_binding.external
|
|
681
|
+
return [:function, external_function_c_name(function_binding), nil, function_binding.type, function_binding]
|
|
684
682
|
end
|
|
685
683
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
callee_type = infer_expression_type(callee, env:)
|
|
689
|
-
return [:callable_value, nil, nil, callee_type, nil] if callable_type?(callee_type)
|
|
684
|
+
return [:function, function_binding_c_name(function_binding, module_name: function_binding.owner.module_name), nil, function_binding.type, function_binding]
|
|
685
|
+
end
|
|
690
686
|
|
|
691
|
-
|
|
687
|
+
if (type_ref = type_ref_from_specialization(callee))
|
|
688
|
+
specialized_type = resolve_type_ref(type_ref)
|
|
689
|
+
return [:struct_literal, nil, nil, specialized_type] if specialized_type.is_a?(Types::Struct) || task_type?(specialized_type) || specialized_type.is_a?(Types::Vector) || specialized_type.is_a?(Types::Matrix) || specialized_type.is_a?(Types::Quaternion) || specialized_type.is_a?(Types::Simd)
|
|
692
690
|
end
|
|
691
|
+
|
|
692
|
+
raise LoweringError, "unsupported specialization callee"
|
|
693
|
+
end
|
|
694
|
+
|
|
695
|
+
def resolve_expression_callee(callee, env)
|
|
696
|
+
callee_type = infer_expression_type(callee, env:)
|
|
697
|
+
return [:callable_value, nil, nil, callee_type, nil] if callable_type?(callee_type)
|
|
698
|
+
|
|
699
|
+
raise LoweringError, "unsupported callee #{callee.class.name}"
|
|
693
700
|
end
|
|
694
701
|
|
|
695
702
|
def infer_expression_type(expression, env:, expected_type: nil)
|