@@ -108,7 +108,7 @@ static GDScriptParser::DataType make_native_enum_type(const StringName &p_native
108
108
GDScriptParser::DataType type;
109
109
type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
110
110
type.kind = GDScriptParser::DataType::ENUM;
111
- type.builtin_type = Variant::OBJECT ;
111
+ type.builtin_type = Variant::INT ;
112
112
type.is_constant = true ;
113
113
type.is_meta_type = true ;
114
114
@@ -650,9 +650,9 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
650
650
datatype = specified_type;
651
651
652
652
if (member.variable ->initializer != nullptr ) {
653
- if (!is_type_compatible (datatype, member.variable ->initializer ->get_datatype (), true )) {
653
+ if (!is_type_compatible (datatype, member.variable ->initializer ->get_datatype (), true , member. variable -> initializer )) {
654
654
// Try reverse test since it can be a masked subtype.
655
- if (!is_type_compatible (member.variable ->initializer ->get_datatype (), datatype, true )) {
655
+ if (!is_type_compatible (member.variable ->initializer ->get_datatype (), datatype, true , member. variable -> initializer )) {
656
656
push_error (vformat (R"( Value of type "%s" cannot be assigned to a variable of type "%s".)" , member.variable ->initializer ->get_datatype ().to_string (), datatype.to_string ()), member.variable ->initializer );
657
657
} else {
658
658
// TODO: Add warning.
@@ -1400,9 +1400,9 @@ void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable
1400
1400
type.is_meta_type = false ;
1401
1401
1402
1402
if (p_variable->initializer != nullptr ) {
1403
- if (!is_type_compatible (type, p_variable->initializer ->get_datatype (), true )) {
1403
+ if (!is_type_compatible (type, p_variable->initializer ->get_datatype (), true , p_variable-> initializer )) {
1404
1404
// Try reverse test since it can be a masked subtype.
1405
- if (!is_type_compatible (p_variable->initializer ->get_datatype (), type, true )) {
1405
+ if (!is_type_compatible (p_variable->initializer ->get_datatype (), type, true , p_variable-> initializer )) {
1406
1406
push_error (vformat (R"( Value of type "%s" cannot be assigned to a variable of type "%s".)" , p_variable->initializer ->get_datatype ().to_string (), type.to_string ()), p_variable->initializer );
1407
1407
} else {
1408
1408
// TODO: Add warning.
@@ -1877,11 +1877,11 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
1877
1877
1878
1878
if (!assignee_type.is_variant () && assigned_value_type.is_hard_type ()) {
1879
1879
if (compatible) {
1880
- compatible = is_type_compatible (assignee_type, op_type, true );
1880
+ compatible = is_type_compatible (assignee_type, op_type, true , p_assignment-> assigned_value );
1881
1881
if (!compatible) {
1882
1882
if (assignee_type.is_hard_type ()) {
1883
1883
// Try reverse test since it can be a masked subtype.
1884
- if (!is_type_compatible (op_type, assignee_type, true )) {
1884
+ if (!is_type_compatible (op_type, assignee_type, true , p_assignment-> assigned_value )) {
1885
1885
push_error (vformat (R"( Cannot assign a value of type "%s" to a target of type "%s".)" , assigned_value_type.to_string (), assignee_type.to_string ()), p_assignment->assigned_value );
1886
1886
} else {
1887
1887
// TODO: Add warning.
@@ -2416,6 +2416,11 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
2416
2416
}
2417
2417
validate_call_arg (par_types, default_arg_count, is_vararg, p_call);
2418
2418
2419
+ if (base_type.kind == GDScriptParser::DataType::ENUM && base_type.is_meta_type ) {
2420
+ // Enum type is treated as a dictionary value for function calls.
2421
+ base_type.is_meta_type = false ;
2422
+ }
2423
+
2419
2424
if (is_self && parser->current_function != nullptr && parser->current_function ->is_static && !is_static) {
2420
2425
push_error (vformat (R"*( Cannot call non-static function "%s()" from static function "%s()".)*" , p_call->function_name , parser->current_function ->identifier ->name ), p_call->callee );
2421
2426
} else if (!is_self && base_type.is_meta_type && !is_static) {
@@ -2474,17 +2479,24 @@ void GDScriptAnalyzer::reduce_cast(GDScriptParser::CastNode *p_cast) {
2474
2479
GDScriptParser::DataType cast_type = resolve_datatype (p_cast->cast_type );
2475
2480
2476
2481
if (!cast_type.is_set ()) {
2482
+ mark_node_unsafe (p_cast);
2477
2483
return ;
2478
2484
}
2479
2485
2480
- cast_type. is_meta_type = false ; // The casted value won't be a type name.
2486
+ cast_type = type_from_metatype (cast_type) ; // The casted value won't be a type name.
2481
2487
p_cast->set_datatype (cast_type);
2482
2488
2483
2489
if (!cast_type.is_variant ()) {
2484
2490
GDScriptParser::DataType op_type = p_cast->operand ->get_datatype ();
2485
2491
if (!op_type.is_variant ()) {
2486
2492
bool valid = false ;
2487
- if (op_type.kind == GDScriptParser::DataType::BUILTIN && cast_type.kind == GDScriptParser::DataType::BUILTIN) {
2493
+ if (op_type.kind == GDScriptParser::DataType::ENUM && cast_type.kind == GDScriptParser::DataType::ENUM) {
2494
+ // Enum types are compatible between each other, so it's a safe cast.
2495
+ valid = true ;
2496
+ } else if (op_type.kind == GDScriptParser::DataType::BUILTIN && op_type.builtin_type == Variant::INT && cast_type.kind == GDScriptParser::DataType::ENUM) {
2497
+ // Convertint int to enum is always valid.
2498
+ valid = true ;
2499
+ } else if (op_type.kind == GDScriptParser::DataType::BUILTIN && cast_type.kind == GDScriptParser::DataType::BUILTIN) {
2488
2500
valid = Variant::can_convert (op_type.builtin_type , cast_type.builtin_type );
2489
2501
} else if (op_type.kind != GDScriptParser::DataType::BUILTIN && cast_type.kind != GDScriptParser::DataType::BUILTIN) {
2490
2502
valid = is_type_compatible (cast_type, op_type) || is_type_compatible (op_type, cast_type);
@@ -2586,6 +2598,34 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
2586
2598
2587
2599
const StringName &name = p_identifier->name ;
2588
2600
2601
+ if (base.kind == GDScriptParser::DataType::ENUM) {
2602
+ if (base.is_meta_type ) {
2603
+ if (base.enum_values .has (name)) {
2604
+ p_identifier->is_constant = true ;
2605
+ p_identifier->reduced_value = base.enum_values [name];
2606
+
2607
+ GDScriptParser::DataType result;
2608
+ result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
2609
+ result.kind = GDScriptParser::DataType::ENUM;
2610
+ result.is_constant = true ;
2611
+ result.builtin_type = Variant::INT;
2612
+ result.native_type = base.native_type ;
2613
+ result.enum_type = base.enum_type ;
2614
+ p_identifier->set_datatype (result);
2615
+ return ;
2616
+ } else {
2617
+ // Consider as a Dictionary, so it can be anything.
2618
+ // This will be evaluated in the next if block.
2619
+ base.kind = GDScriptParser::DataType::BUILTIN;
2620
+ base.builtin_type = Variant::DICTIONARY;
2621
+ base.is_meta_type = false ;
2622
+ }
2623
+ } else {
2624
+ push_error (R"( Cannot get property from enum value.)" , p_identifier);
2625
+ return ;
2626
+ }
2627
+ }
2628
+
2589
2629
if (base.kind == GDScriptParser::DataType::BUILTIN) {
2590
2630
if (base.is_meta_type ) {
2591
2631
bool valid = true ;
@@ -2632,32 +2672,6 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
2632
2672
return ;
2633
2673
}
2634
2674
2635
- if (base.kind == GDScriptParser::DataType::ENUM) {
2636
- if (base.is_meta_type ) {
2637
- if (base.enum_values .has (name)) {
2638
- p_identifier->is_constant = true ;
2639
- p_identifier->reduced_value = base.enum_values [name];
2640
-
2641
- GDScriptParser::DataType result;
2642
- result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
2643
- result.kind = GDScriptParser::DataType::ENUM_VALUE;
2644
- result.is_constant = true ;
2645
- result.builtin_type = Variant::INT;
2646
- result.native_type = base.native_type ;
2647
- result.enum_type = name;
2648
- p_identifier->set_datatype (result);
2649
- } else {
2650
- // Consider as a Dictionary
2651
- GDScriptParser::DataType dummy;
2652
- dummy.kind = GDScriptParser::DataType::VARIANT;
2653
- p_identifier->set_datatype (dummy);
2654
- }
2655
- } else {
2656
- push_error (R"( Cannot get property from enum value.)" , p_identifier);
2657
- }
2658
- return ;
2659
- }
2660
-
2661
2675
GDScriptParser::ClassNode *base_class = base.class_type ;
2662
2676
2663
2677
// TODO: Switch current class/function/suite here to avoid misrepresenting identifiers (in recursive reduce calls).
@@ -2793,7 +2807,7 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
2793
2807
if (element.identifier ->name == p_identifier->name ) {
2794
2808
GDScriptParser::DataType type;
2795
2809
type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
2796
- type.kind = element.parent_enum ->identifier ? GDScriptParser::DataType::ENUM_VALUE : GDScriptParser::DataType::BUILTIN;
2810
+ type.kind = element.parent_enum ->identifier ? GDScriptParser::DataType::ENUM : GDScriptParser::DataType::BUILTIN;
2797
2811
type.builtin_type = Variant::INT;
2798
2812
type.is_constant = true ;
2799
2813
if (element.parent_enum ->identifier ) {
@@ -3493,6 +3507,9 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_metatype(const GDScriptPars
3493
3507
GDScriptParser::DataType result = p_meta_type;
3494
3508
result.is_meta_type = false ;
3495
3509
result.is_constant = false ;
3510
+ if (p_meta_type.kind == GDScriptParser::DataType::ENUM) {
3511
+ result.builtin_type = Variant::INT;
3512
+ }
3496
3513
return result;
3497
3514
}
3498
3515
@@ -3549,6 +3566,18 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source
3549
3566
r_default_arg_count = 0 ;
3550
3567
StringName function_name = p_function;
3551
3568
3569
+ if (p_base_type.kind == GDScriptParser::DataType::ENUM) {
3570
+ if (p_base_type.is_meta_type ) {
3571
+ // Enum type can be treated as a dictionary value.
3572
+ p_base_type.kind = GDScriptParser::DataType::BUILTIN;
3573
+ p_base_type.builtin_type = Variant::DICTIONARY;
3574
+ p_base_type.is_meta_type = false ;
3575
+ } else {
3576
+ push_error (" Cannot call function on enum value." , p_source);
3577
+ return false ;
3578
+ }
3579
+ }
3580
+
3552
3581
if (p_base_type.kind == GDScriptParser::DataType::BUILTIN) {
3553
3582
// Construct a base type to get methods.
3554
3583
Callable::CallError err;
@@ -3799,6 +3828,22 @@ GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator
3799
3828
3800
3829
Variant::Type a_type = p_a.builtin_type ;
3801
3830
Variant::Type b_type = p_b.builtin_type ;
3831
+
3832
+ if (p_a.kind == GDScriptParser::DataType::ENUM) {
3833
+ if (p_a.is_meta_type ) {
3834
+ a_type = Variant::DICTIONARY;
3835
+ } else {
3836
+ a_type = Variant::INT;
3837
+ }
3838
+ }
3839
+ if (p_b.kind == GDScriptParser::DataType::ENUM) {
3840
+ if (p_b.is_meta_type ) {
3841
+ b_type = Variant::DICTIONARY;
3842
+ } else {
3843
+ b_type = Variant::INT;
3844
+ }
3845
+ }
3846
+
3802
3847
Variant::ValidatedOperatorEvaluator op_eval = Variant::get_validated_operator_evaluator (p_operation, a_type, b_type);
3803
3848
3804
3849
bool hard_operation = p_a.is_hard_type () && p_b.is_hard_type ();
@@ -3828,7 +3873,7 @@ GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator
3828
3873
}
3829
3874
3830
3875
// TODO: Add safe/unsafe return variable (for variant cases)
3831
- bool GDScriptAnalyzer::is_type_compatible (const GDScriptParser::DataType &p_target, const GDScriptParser::DataType &p_source, bool p_allow_implicit_conversion) const {
3876
+ bool GDScriptAnalyzer::is_type_compatible (const GDScriptParser::DataType &p_target, const GDScriptParser::DataType &p_source, bool p_allow_implicit_conversion, const GDScriptParser::Node *p_source_node) {
3832
3877
// These return "true" so it doesn't affect users negatively.
3833
3878
ERR_FAIL_COND_V_MSG (!p_target.is_set (), true , " Parser bug (please report): Trying to check compatibility of unset target type" );
3834
3879
ERR_FAIL_COND_V_MSG (!p_source.is_set (), true , " Parser bug (please report): Trying to check compatibility of unset value type" );
@@ -3848,7 +3893,7 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ
3848
3893
if (!valid && p_allow_implicit_conversion) {
3849
3894
valid = Variant::can_convert_strict (p_source.builtin_type , p_target.builtin_type );
3850
3895
}
3851
- if (!valid && p_target.builtin_type == Variant::INT && p_source.kind == GDScriptParser::DataType::ENUM_VALUE ) {
3896
+ if (!valid && p_target.builtin_type == Variant::INT && p_source.kind == GDScriptParser::DataType::ENUM && !p_source. is_meta_type ) {
3852
3897
// Enum value is also integer.
3853
3898
valid = true ;
3854
3899
}
@@ -3869,18 +3914,18 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ
3869
3914
3870
3915
if (p_target.kind == GDScriptParser::DataType::ENUM) {
3871
3916
if (p_source.kind == GDScriptParser::DataType::BUILTIN && p_source.builtin_type == Variant::INT) {
3917
+ #ifdef DEBUG_ENABLED
3918
+ if (p_source_node) {
3919
+ parser->push_warning (p_source_node, GDScriptWarning::INT_ASSIGNED_TO_ENUM);
3920
+ }
3921
+ #endif
3872
3922
return true ;
3873
3923
}
3874
3924
if (p_source.kind == GDScriptParser::DataType::ENUM) {
3875
3925
if (p_source.native_type == p_target.native_type ) {
3876
3926
return true ;
3877
3927
}
3878
3928
}
3879
- if (p_source.kind == GDScriptParser::DataType::ENUM_VALUE) {
3880
- if (p_source.native_type == p_target.native_type && p_target.enum_values .has (p_source.enum_type )) {
3881
- return true ;
3882
- }
3883
- }
3884
3929
return false ;
3885
3930
}
3886
3931
@@ -3935,7 +3980,6 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ
3935
3980
case GDScriptParser::DataType::VARIANT:
3936
3981
case GDScriptParser::DataType::BUILTIN:
3937
3982
case GDScriptParser::DataType::ENUM:
3938
- case GDScriptParser::DataType::ENUM_VALUE:
3939
3983
case GDScriptParser::DataType::UNRESOLVED:
3940
3984
break ; // Already solved before.
3941
3985
}
@@ -3972,7 +4016,6 @@ bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_targ
3972
4016
case GDScriptParser::DataType::VARIANT:
3973
4017
case GDScriptParser::DataType::BUILTIN:
3974
4018
case GDScriptParser::DataType::ENUM:
3975
- case GDScriptParser::DataType::ENUM_VALUE:
3976
4019
case GDScriptParser::DataType::UNRESOLVED:
3977
4020
break ; // Already solved before.
3978
4021
}
0 commit comments