From 9a7bb95107ba25725efa26c98b99f8d3d7d8b5d7 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Tue, 22 Sep 2020 13:41:18 -0700 Subject: [PATCH] Support for out variable declarations in mixin arguments --- IDEHelper/Compiler/BfExprEvaluator.cpp | 50 +++++++++++++++++++++----- IDEHelper/Tests/src/Mixins.bf | 15 ++++++++ 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 8df36d1e..f82321b2 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -6498,8 +6498,8 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType else if ((resolvedArg.mArgFlags & (BfArgFlag_VariableDeclaration | BfArgFlag_UninitializedExpr)) != 0) { auto variableDeclaration = BfNodeDynCast(resolvedArg.mExpression); - - auto variableType = wantType; + + auto variableType = wantType; bool isLet = (variableDeclaration != NULL) && (variableDeclaration->mTypeRef->IsExact()); bool isVar = (variableDeclaration == NULL) || (variableDeclaration->mTypeRef->IsExact()); @@ -6511,12 +6511,29 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType if ((!isLet) && (!isVar)) { - mModule->Fail("Only 'ref' or 'var' variables can be declared in method arguments", variableDeclaration); + if (variableType->IsVar()) + { + auto resolvedType = mModule->ResolveTypeRef(variableDeclaration->mTypeRef); + if (resolvedType != NULL) + variableType = resolvedType; + } + else + { + mModule->Fail("Only 'ref' or 'var' variables can be declared in method arguments", variableDeclaration); - auto autoComplete = GetAutoComplete(); - if (autoComplete != NULL) - autoComplete->CheckTypeRef(variableDeclaration->mTypeRef, true, true); + auto autoComplete = GetAutoComplete(); + if (autoComplete != NULL) + autoComplete->CheckTypeRef(variableDeclaration->mTypeRef, true, true); + } } + else + { + if (variableType->IsVar()) + { + mModule->Fail("Variable type required for 'var' parameter types", variableDeclaration); + } + } + if (wantType->IsRef()) { @@ -13529,7 +13546,19 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo BfExprEvaluator* exprEvaluator = argExprEvaluators.back(); exprEvaluator->mResolveGenericParam = false; exprEvaluator->mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator->mBfEvalExprFlags | BfEvalExprFlags_NoCast | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_AllowOutExpr); - if (argExpr != NULL) + + bool deferExpr = false; + if (auto variableDecl = BfNodeDynCast(argExpr)) + { + deferExpr = true; + resolvedArg.mArgFlags = (BfArgFlags)(resolvedArg.mArgFlags | BfArgFlag_VariableDeclaration); + } + + if (deferExpr) + { + // + } + else if (argExpr != NULL) exprEvaluator->Evaluate(argExpr, false, false, true); auto argValue = exprEvaluator->mResult; mModule->FixIntUnknown(argValue); @@ -13779,7 +13808,12 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo BfType* wantType = methodInstance->mParams[paramIdx].mResolvedType; auto& arg = args[argIdx]; - + + if ((arg.mArgFlags & BfArgFlag_VariableDeclaration) != 0) + { + arg.mTypedValue = ResolveArgValue(arg, wantType); + } + if (wantType->IsGenericParam()) { // diff --git a/IDEHelper/Tests/src/Mixins.bf b/IDEHelper/Tests/src/Mixins.bf index 40674527..166c2287 100644 --- a/IDEHelper/Tests/src/Mixins.bf +++ b/IDEHelper/Tests/src/Mixins.bf @@ -37,6 +37,16 @@ namespace Tests } } + static mixin GetVal(var a) + { + a = 123; + } + + static mixin GetVal2(out int a) + { + a = 234; + } + [Test] public static void TestBasics() { @@ -47,6 +57,11 @@ namespace Tests Test.Assert(mc.mA == 120); Test.Assert(MixClass.MixC!(30) == 230); Test.Assert(cVal == 0x305); + + GetVal!(int val1); + Test.Assert(val1 == 123); + GetVal2!(var val2); + Test.Assert(val2 == 234); } [Test]