From 2c53e1a7826ec43c592f1e809d448758c9c39edd Mon Sep 17 00:00:00 2001 From: Temo Nikolaishvili Date: Wed, 28 May 2025 10:35:17 +0400 Subject: [PATCH 1/2] ## Commit Summary ### Title Update version and improve dictionary support ### Details - Bumped version to `1.0.13` in `Directory.Build.props` - Enhanced dictionary index access in `SimpraParserVisitor` - Added `Countries` and `DictionaryOfObjects` properties to `TestModel` --- Directory.Build.props | 2 +- .../Visitor/SimpraParserVisitor.cs | 25 +++++++++ .../AltaSoft.Simpra.tests/Models/TestModel.cs | 3 ++ .../SimpraExpressionTests.cs | 54 +++++++++++++++++++ 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index d15ef0e..5f5b29b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,7 +9,7 @@ Simpra ALTA Software llc. Copyright © 2024 ALTA Software llc. - 1.0.12 + 1.0.13 diff --git a/src/AltaSoft.Simpra/Visitor/SimpraParserVisitor.cs b/src/AltaSoft.Simpra/Visitor/SimpraParserVisitor.cs index 989ccef..316616c 100644 --- a/src/AltaSoft.Simpra/Visitor/SimpraParserVisitor.cs +++ b/src/AltaSoft.Simpra/Visitor/SimpraParserVisitor.cs @@ -263,6 +263,14 @@ public Expression VisitIndexAccess(SimpraParser.IndexAccessContext context) objectType = left.Type; } + // Handle IDictionary (including Dictionary<,>) + var isDictionary = objectType.IsIReadOnlyDictionaryT(); + + if (isDictionary) + { + return HandleDictionaryIndexAccess(context, objectType, index, left); + } + // Handle indexable types (e.g., List) var defaultIndexer = objectType .GetProperties() @@ -552,4 +560,21 @@ public Expression VisitArray(SimpraParser.ArrayContext context) { return NewSimpraList(context.exp().Select(Visit), context); } + + private static Expression HandleDictionaryIndexAccess(SimpraParser.IndexAccessContext context, Type objectType, Expression index, Expression left) + { + var keyType = objectType.GetGenericArguments()[0]; + var valueType = objectType.GetGenericArguments()[1]; + var tryGetValueMethod = objectType.GetMethod("TryGetValue", [keyType, valueType.MakeByRefType()])!; + + var keyExpr = index.Type != keyType ? Expression.Convert(index, keyType) : index; + var valueVar = Expression.Variable(valueType, "dictValue"); + + var tryGetValueCall = Expression.Call(left, tryGetValueMethod, keyExpr, valueVar); + + var defaultValue = Expression.Default(valueType); + var block = Expression.Block([valueVar], Expression.Condition(tryGetValueCall, valueVar, defaultValue)); + + return ConvertToSimpraType(block, false, context); + } } diff --git a/tests/AltaSoft.Simpra.tests/Models/TestModel.cs b/tests/AltaSoft.Simpra.tests/Models/TestModel.cs index 3478df2..24f9f89 100644 --- a/tests/AltaSoft.Simpra.tests/Models/TestModel.cs +++ b/tests/AltaSoft.Simpra.tests/Models/TestModel.cs @@ -30,6 +30,9 @@ public class TestModel : BaseModel, ITransferModel public required Transfer? Transfer { get; set; } public required Customer Customer { get; set; } public required string Remittance { get; set; } + public Dictionary? Countries { get; set; } + + public Dictionary? DictionaryOfObjects { get; set; } public ColorX ColorX { get; set; } = ColorX.Green; public ColorM ColorM { get; set; } = ColorM.Green; diff --git a/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs b/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs index 695fc1b..212ffd8 100644 --- a/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs +++ b/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs @@ -4,6 +4,60 @@ namespace AltaSoft.Simpra.Tests; public class SimpraExpressionTests { + + [Fact] + public void CallGetValueFromDictionaryWhenKeyDoesNotExist_ShouldReturnDefault2() + { + const string expressionCode = + """ + return DictionaryOfObjects['test'].Id + """; + + var simpra = new Simpra(); + var model = GetTestModel(); + model.DictionaryOfObjects = new Dictionary { { "Georgia", new Customer + { + Id = 1, + Status = 10 + }} }; + + var result = simpra.Execute(model, new TestFunctions(), expressionCode); + Assert.Equal(0, result); + + } + + [Fact] + public void CallGetValueFromDictionaryWhenKeyDoesNotExist_ShouldReturnDefault() + { + const string expressionCode = + """ + return Countries['test'] is 'Test' + """; + + var simpra = new Simpra(); + var model = GetTestModel(); + model.Countries = new Dictionary { { "Georgia", "Test" } }; + var result = simpra.Execute(model, new TestFunctions(), expressionCode); + Assert.False(result); + + } + + [Fact] + public void CallGetValueFromDictionaryWhenKeyExist_ShouldReturnValue() + { + const string expressionCode = + """ + return Countries['Georgia'] is 'Test' + """; + + var simpra = new Simpra(); + var model = GetTestModel(); + model.Countries = new Dictionary { { "Georgia", "Test" } }; + var result = simpra.Execute(model, new TestFunctions(), expressionCode); + Assert.True(result); + + } + [Fact] public void CallInterfaceFunctionFromSimpra_ShouldReturnCorrectValue() { From 2cc6e69ce2a673466b1594139c8188743a041bba Mon Sep 17 00:00:00 2001 From: Temo Nikolaishvili Date: Wed, 28 May 2025 10:38:14 +0400 Subject: [PATCH 2/2] mc renamed a test case --- tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs b/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs index 212ffd8..7943ac6 100644 --- a/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs +++ b/tests/AltaSoft.Simpra.tests/SimpraExpressionTests.cs @@ -6,7 +6,7 @@ public class SimpraExpressionTests { [Fact] - public void CallGetValueFromDictionaryWhenKeyDoesNotExist_ShouldReturnDefault2() + public void DictionaryIndexer_MissingKey_ReturnsDefaultValueForProperty() { const string expressionCode = """