diff --git a/Yail.Shared/Objects/ArrayObj.cs b/Yail.Shared/Objects/ArrayObj.cs index afeab3a..fd8c334 100644 --- a/Yail.Shared/Objects/ArrayObj.cs +++ b/Yail.Shared/Objects/ArrayObj.cs @@ -6,7 +6,7 @@ public class ArrayObj : ValueObj, IAccessible { public List Items => Value as List; - public ArrayObj(List items) + public ArrayObj(IEnumerable items) { Value = items; DataType = EDataType.Array; @@ -55,10 +55,25 @@ public void Set(object index, ValueObj value) if (idx >= 0 && idx < Items.Count) Items[idx] = value; } + + public EDataType GetItemsDataType() + { + return Get().Select(x => x.DataType).FirstOrDefault(); + } public override void Print(bool newLine = false) { var x = Get().Select(x => x.Value.ToString()).ToArray(); + + if (GetItemsDataType() == EDataType.String) + { + x = x.Select(x => $@"""{x}""").ToArray(); + } + if (GetItemsDataType() == EDataType.Char) + { + x = x.Select(x => $@"'{x}'").ToArray(); + } + var output = $"[{string.Join(", ", x)}]"; if (newLine) @@ -71,4 +86,9 @@ public void RemoveAt(int idxValue) { Items.RemoveAt(idxValue); } + + public static ArrayObj operator+ (ArrayObj obj1, ArrayObj obj2) + { + return new ArrayObj(obj1.Get().Concat(obj2.Get())); + } } \ No newline at end of file diff --git a/Yail.Shared/ValueObj.cs b/Yail.Shared/ValueObj.cs index 8c5a1bf..3cd23f2 100644 --- a/Yail.Shared/ValueObj.cs +++ b/Yail.Shared/ValueObj.cs @@ -42,6 +42,11 @@ public ValueObj(EDataType dataType, bool isConst = false) public object? Value { get; set; } public EDataType DataType { get; set; } + public TValue? GetValue() + { + return Value is null ? default : (TValue)Value; + } + public override bool Equals(object? obj) { if (obj is ValueObj other) diff --git a/Yail.Tests/ScalarAdditionsTest.cs b/Yail.Tests/ScalarAdditionsTest.cs new file mode 100644 index 0000000..71710fb --- /dev/null +++ b/Yail.Tests/ScalarAdditionsTest.cs @@ -0,0 +1,126 @@ +using Yail.Tests.Shared; + +namespace Yail.Tests; + +public class ScalarAdditionsTest : BaseYailTest +{ + [Test] + public void PreAddition_Int_On_IntArr() + { + var code = @" + package main + + var a = [1, 2, 3] i32; + + var x = 1 + a; + + print(x); + "; + + var actual = RunCode(code); + + Assert.That(actual, Is.EqualTo("[2, 3, 4]")); + } + + [Test] + public void PostAddition_Int_On_IntArr() + { + var code = @" + package main + + var a = [1, 2, 3] i32; + + var x = a + 1; + + print(x); + "; + + var actual = RunCode(code); + + Assert.That(actual, Is.EqualTo("[2, 3, 4]")); + } + + [Test] + public void PreAddition_StringArr_On_String() + { + var code = @" + package main + + var a = [""foo"", ""bar""] string; + + var x = ""foo"" + a; + + print(x); + "; + + var actual = RunCode(code); + + Assert.That(actual, Is.EqualTo(@"[""foofoo"", ""foobar""]")); + } + + [Test] + public void PostAddition_StringArr_On_String() + { + var code = @" + package main + + var a = [""foo"", ""bar""] string; + + var x = a + ""foo""; + + print(x); + "; + + var actual = RunCode(code); + + Assert.That(actual, Is.EqualTo(@"[""foofoo"", ""barfoo""]")); + } + + [Test] + public void PreAddition_Int_On_StringArr_ShouldFail() + { + var code = @" + package main + + var a = [""foo"", ""bar""] string; + + var x = ""foo"" + 1; + + print(x); + "; + + try + { + RunCode(code); + Assert.Fail(); + } + catch + { + Assert.Pass(); + } + } + + [Test] + public void PostAddition_Int_On_StringArr_ShouldFail() + { + var code = @" + package main + + var a = [""foo"", ""bar""] string; + + var x = a + 1; + + print(x); + "; + + try + { + RunCode(code); + Assert.Fail(); + } + catch + { + Assert.Pass(); + } + } +} \ No newline at end of file diff --git a/Yail/Common/OperationsHelper.cs b/Yail/Common/OperationsHelper.cs index b23ec7f..346f278 100644 --- a/Yail/Common/OperationsHelper.cs +++ b/Yail/Common/OperationsHelper.cs @@ -1,4 +1,5 @@ using Yail.Shared; +using Yail.Shared.Objects; namespace Yail.Common; @@ -6,6 +7,16 @@ public static class OperationsHelper { public static ValueObj Add(ValueObj left, ValueObj right) { + if (left is ArrayObj leftArr && right is ArrayObj rightArr) + { + return leftArr + rightArr; + } + + if (left is ArrayObj || right is ArrayObj) + { + return ScalarAdd(left, right); + } + if (left.DataType == EDataType.String || right.DataType == EDataType.String || right.DataType == EDataType.Char) { // String concatenation @@ -300,4 +311,54 @@ public static object PerformOperation(ValueObj lhs, ValueObj rhs, string operato _ => throw new InvalidOperationException($"Unsupported operation for types {lhs.DataType} and {rhs.DataType}") }; } + + public static ArrayObj ScalarAdd(ValueObj left, ValueObj right) + { + var output = new ArrayObj(new List()); + + // pre add + if (left.DataType == EDataType.Int32 && right is ArrayObj rightArr) + { + var val1 = left.GetValue(); + var val2 = rightArr.GetValue>(); + + foreach (var x in val2) + { + output.Push(new ValueObj(val1 + x.GetValue(), EDataType.Int32)); + } + } + // post add + else if (left is ArrayObj leftArr && right.DataType == EDataType.Int32) + { + var val1 = right.GetValue(); + var val2 = leftArr.GetValue>(); + + foreach (var x in val2) + { + output.Push(new ValueObj(x.GetValue() + val1, EDataType.Int32)); + } + } + // pre add + else if (right is ArrayObj rightArr2 && rightArr2.Get().First().DataType == EDataType.String) + { + var val = rightArr2.GetValue>(); + + foreach (var x in val) + { + output.Push(new ValueObj(left.Value + x.GetValue(), EDataType.String)); + } + } + // post add + else if (left is ArrayObj leftArr2 && leftArr2.Get().First().DataType == EDataType.String) + { + var val = leftArr2.GetValue>(); + + foreach (var x in val) + { + output.Push(new ValueObj(x.GetValue() + right.Value, EDataType.String)); + } + } + + return output; + } } \ No newline at end of file