From 3af4101b21210385b898f5918b704a613cbf7e1e Mon Sep 17 00:00:00 2001 From: Boris Batkin Date: Thu, 26 Dec 2024 10:53:14 -0800 Subject: [PATCH] ?. is now same as ?as for the variant --- examples/test/unit_tests/variant.das | 3 +++ src/ast/ast_infer_type.cpp | 37 +++++++++++++--------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/test/unit_tests/variant.das b/examples/test/unit_tests/variant.das index 92f134808..f1d6a18a3 100644 --- a/examples/test/unit_tests/variant.das +++ b/examples/test/unit_tests/variant.das @@ -94,6 +94,8 @@ def test assert(t2[0] is i_value && t2[0] as i_value==1u) assert(t2[1] is f_value && t2[1] as f_value==2.0) + // with the latest changes ?. is now same as ?as + /* var f : Foo var fp : Foo? unsafe @@ -103,6 +105,7 @@ def test f.t = addr(t) assert ( fp?.t?.i_value ?? 15u == 0x3f800000 ) // unsafe ?.i_value assert ( fp?.t ?as i_value ?? 15u == 15u ) + */ var x : IorA unsafe diff --git a/src/ast/ast_infer_type.cpp b/src/ast/ast_infer_type.cpp index 680ea0bed..0ac0eb9ac 100644 --- a/src/ast/ast_infer_type.cpp +++ b/src/ast/ast_infer_type.cpp @@ -5481,7 +5481,7 @@ namespace das { } expr->fieldIndex = index; } else if ( valT->isGoodVariantType() ) { - if ( !safeExpression(expr) ) { + if ( !safeExpression(expr) ) { error("variant.field requires unsafe", "", "", expr->at, CompilationError::unsafe); return Visitor::visit(expr); @@ -5562,27 +5562,38 @@ namespace das { if ( auto opE = inferGenericOperatorWithName("?.",expr->at,expr->value,expr->name) ) return opE; } auto valT = expr->value->type; - if ( !valT->isPointer() || !valT->firstType ) { + if ( !(valT->isPointer() && valT->firstType) && !valT->isVariant() ) { if ( verbose && !expr->no_promotion ) { MatchingFunctions mf; collectMissingOperators("?.`"+expr->name,mf,false); collectMissingOperators("?.",mf,true); if ( !mf.empty() ) { - reportDualFunctionNotFound("?.`"+expr->name, "can only safe dereference a pointer to a tuple, a structure or a handle " + describeType(valT), + reportDualFunctionNotFound("?.`"+expr->name, "can only safe dereference a variant or a pointer to a tuple, a structure or a handle " + describeType(valT), expr->at, mf, {expr->value->type}, {expr->value->type, make_smart(Type::tString)}, true, false, true, CompilationError::cant_get_field, 0, ""); } else { - error("can only safe dereference a pointer to a tuple, a structure or a handle " + describeType(valT), "", "", + error("can only safe dereference a variant or a pointer to a tuple, a structure or a handle " + describeType(valT), "", "", expr->at, CompilationError::cant_get_field); } } else { - error("can only safe dereference a pointer to a tuple, a structure or a handle " + describeType(valT), "", "", + error("can only safe dereference a variant or a pointer to a tuple, a structure or a handle " + describeType(valT), "", "", expr->at, CompilationError::cant_get_field); } return Visitor::visit(expr); } expr->value = Expression::autoDereference(expr->value); - if ( valT->firstType->structType ) { + if ( valT->isGoodVariantType() || valT->firstType->isGoodVariantType() ) { + int index = valT->variantFieldIndex(expr->name); + auto argSize = valT->isGoodVariantType() ? valT->argTypes.size() : valT->firstType->argTypes.size(); + if ( index==-1 || index>=argSize ) { + error("can't get variant field '" + expr->name + "'", "", "", + expr->at, CompilationError::cant_get_field); + return Visitor::visit(expr); + } + reportAstChanged(); + auto safeAs = make_smart(expr->at, expr->value, expr->name); + return safeAs; + } else if ( valT->firstType->structType ) { expr->field = valT->firstType->structType->findField(expr->name); if ( !expr->field ) { error("can't safe get field '" + expr->name + "'", "", "", @@ -5607,20 +5618,6 @@ namespace das { } expr->fieldIndex = index; expr->type = make_smart(*valT->firstType->argTypes[expr->fieldIndex]); - } else if ( valT->firstType->isGoodVariantType() ) { - if ( !safeExpression(expr) ) { - error("variant?.field requires unsafe", "", "", - expr->at, CompilationError::unsafe); - return Visitor::visit(expr); - } - int index = valT->variantFieldIndex(expr->name); - if ( index==-1 || index>=int(valT->firstType->argTypes.size()) ) { - error("can't get variant field '" + expr->name + "'", "", "", - expr->at, CompilationError::cant_get_field); - return Visitor::visit(expr); - } - expr->fieldIndex = index; - expr->type = make_smart(*valT->firstType->argTypes[expr->fieldIndex]); } else { error("can only safe dereference a pointer to a tuple, a structure or a handle " + describeType(valT), "", "", expr->at, CompilationError::cant_get_field);