diff --git a/src/UiPath.Workflow.Runtime/Expressions/AddAssign.cs b/src/UiPath.Workflow.Runtime/Expressions/AddAssign.cs
new file mode 100644
index 00000000..ca1261c0
--- /dev/null
+++ b/src/UiPath.Workflow.Runtime/Expressions/AddAssign.cs
@@ -0,0 +1,98 @@
+// This file is part of Core WF which is licensed under the MIT license.
+// See LICENSE file in the project root for full license information.
+
+using System.Activities.Validation;
+using System.ComponentModel;
+using System.Linq.Expressions;
+using System.Numerics;
+
+namespace System.Activities.Expressions
+{
+ ///
+ /// A code activity which incrementally assigns a numeral.
+ ///
+ ///
+ /// int myNum = 5;
+ /// myNum += 5; // 10.
+ ///
+ /// The operand to modify.
+ /// The operand with which to modify .
+ /// The resulting type of hte operation.
+ public sealed class AddAssign : CodeActivity
+#if NET7_0_OR_GREATER
+ where TLeft : INumber
+ where TRight : INumber
+ where TResult : INumber
+#endif
+ {
+ private static Func? checkedOperationFunction = null;
+ private static Func? uncheckedOperationFunction = null;
+
+ ///
+ /// Gets or sets the left operand which will be modified by this operation.
+ ///
+ [RequiredArgument]
+ public InArgument Left { get; set; } = new();
+
+ ///
+ /// Gets or sets the right operand which will be the modifier for this operation.
+ ///
+ [RequiredArgument]
+ public InArgument Right { get; set; } = new();
+
+ ///
+ /// Gets or sets a value indicating whether this operation will happen in a checked or unchecked context.
+ ///
+ [DefaultValue(true)]
+ public bool IsChecked { get; set; } = true;
+
+ ///
+ protected override void CacheMetadata(CodeActivityMetadata metadata)
+ {
+ BinaryExpressionHelper.OnGetArguments(metadata, Left, Right);
+
+ if (IsChecked)
+ {
+ EnsureOperationFunction(metadata, ref checkedOperationFunction, ExpressionType.AddAssignChecked);
+ }
+ else
+ {
+ EnsureOperationFunction(metadata, ref uncheckedOperationFunction, ExpressionType.AddAssign);
+ }
+ }
+
+ private static void EnsureOperationFunction
+ (
+ CodeActivityMetadata metadata,
+ ref Func? operationFunction,
+ ExpressionType operatorType
+ )
+ {
+ if (operationFunction == null)
+ {
+ if (!BinaryExpressionHelper.TryGenerateLinqDelegate(
+ operatorType,
+ out operationFunction,
+ out ValidationError? validationError))
+ {
+ metadata.AddValidationError(validationError);
+ }
+ }
+ }
+
+ ///
+ protected override TResult Execute(CodeActivityContext context)
+ {
+ TLeft leftValue = Left.Get(context);
+ TRight rightValue = Right.Get(context);
+
+ // If user changed checked flag between open and execution, an NRE may be thrown.
+ // This is by design.
+ // Nullability check silenced because the corresponding value is guaranteed to be
+ // non-null
+ return IsChecked
+ ? checkedOperationFunction!(leftValue, rightValue)
+ : uncheckedOperationFunction!(leftValue, rightValue);
+ }
+ }
+}
diff --git a/src/UiPath.Workflow.Runtime/Expressions/BinaryExpressionHelper.cs b/src/UiPath.Workflow.Runtime/Expressions/BinaryExpressionHelper.cs
index 8bec8c78..abc96584 100644
--- a/src/UiPath.Workflow.Runtime/Expressions/BinaryExpressionHelper.cs
+++ b/src/UiPath.Workflow.Runtime/Expressions/BinaryExpressionHelper.cs
@@ -8,8 +8,19 @@
namespace System.Activities.Expressions;
-internal static class BinaryExpressionHelper
+///
+/// Helpers for binary expressions.
+///
+public static class BinaryExpressionHelper
{
+ ///
+ /// Binds metadata when getting arguments.
+ ///
+ /// The type of the left argument.
+ /// The type of the right argument.
+ /// The metadata.
+ /// The left argument.
+ /// The right argument.
public static void OnGetArguments(CodeActivityMetadata metadata, InArgument left, InArgument right)
{
RuntimeArgument rightArgument = new("Right", typeof(TRight), ArgumentDirection.In, true);
@@ -26,6 +37,16 @@ public static void OnGetArguments(CodeActivityMetadata metadata,
});
}
+ ///
+ /// Generates a delegate.
+ ///
+ /// The type of the left argument.
+ /// The type of the right argument.
+ /// The return type of the operation.
+ /// The type of expression.
+ /// The resulting .
+ /// If the operation failed, the error.
+ /// if the operation was successful; otherwise, .
public static bool TryGenerateLinqDelegate(ExpressionType operatorType, out Func function, out ValidationError validationError)
{
function = null;
diff --git a/src/UiPath.Workflow.Runtime/Expressions/Decrement.cs b/src/UiPath.Workflow.Runtime/Expressions/Decrement.cs
new file mode 100644
index 00000000..c9a93dcf
--- /dev/null
+++ b/src/UiPath.Workflow.Runtime/Expressions/Decrement.cs
@@ -0,0 +1,57 @@
+// This file is part of Core WF which is licensed under the MIT license.
+// See LICENSE file in the project root for full license information.
+
+using System.Activities.Validation;
+using System.Linq.Expressions;
+using System.Numerics;
+
+namespace System.Activities.Expressions
+{
+ ///
+ /// A code activity which decrements a numeral.
+ ///
+ /// A numeric value, such as or .
+ public sealed class Decrement : CodeActivity
+#if NET7_0_OR_GREATER
+ where TNumeral : IIncrementOperators
+#endif
+ {
+ private static Func? operationFunction = null!;
+
+ ///
+ /// Gets or sets the numeral value that will be incremented.
+ ///
+ [RequiredArgument]
+ public InOutArgument Numeral { get; set; } = new();
+
+ ///
+ protected override void CacheMetadata(CodeActivityMetadata metadata)
+ {
+ UnaryExpressionHelper.OnGetArguments(metadata, Numeral);
+ EnsureOperationFunction(metadata, ref operationFunction!, ExpressionType.Decrement);
+ }
+
+ private static void EnsureOperationFunction
+ (
+ CodeActivityMetadata metadata,
+ ref Func operationFunction,
+ ExpressionType operatorType
+ )
+ {
+ if (operationFunction is null)
+ {
+ if (!UnaryExpressionHelper.TryGenerateLinqDelegate(operatorType, out operationFunction!, out ValidationError? validationError))
+ {
+ metadata.AddValidationError(validationError);
+ }
+ }
+ }
+
+ ///
+ protected override TNumeral Execute(CodeActivityContext context)
+ {
+ TNumeral value = Numeral.Get(context);
+ return operationFunction!.Invoke(value);
+ }
+ }
+}
diff --git a/src/UiPath.Workflow.Runtime/Expressions/Increment.cs b/src/UiPath.Workflow.Runtime/Expressions/Increment.cs
new file mode 100644
index 00000000..5837056b
--- /dev/null
+++ b/src/UiPath.Workflow.Runtime/Expressions/Increment.cs
@@ -0,0 +1,57 @@
+// This file is part of Core WF which is licensed under the MIT license.
+// See LICENSE file in the project root for full license information.
+
+using System.Activities.Validation;
+using System.Linq.Expressions;
+using System.Numerics;
+
+namespace System.Activities.Expressions
+{
+ ///
+ /// A code activity which increments a numeral.
+ ///
+ /// A numeric value, such as or .
+ public sealed class Increment : CodeActivity
+#if NET7_0_OR_GREATER
+ where TNumeral : IIncrementOperators
+#endif
+ {
+ private static Func? operationFunction = null!;
+
+ ///
+ /// Gets or sets the numeral value that will be incremented.
+ ///
+ [RequiredArgument]
+ public InOutArgument Numeral { get; set; } = new();
+
+ ///
+ protected override void CacheMetadata(CodeActivityMetadata metadata)
+ {
+ UnaryExpressionHelper.OnGetArguments(metadata, Numeral);
+ EnsureOperationFunction(metadata, ref operationFunction!, ExpressionType.Increment);
+ }
+
+ private static void EnsureOperationFunction
+ (
+ CodeActivityMetadata metadata,
+ ref Func operationFunction,
+ ExpressionType operatorType
+ )
+ {
+ if (operationFunction is null)
+ {
+ if (!UnaryExpressionHelper.TryGenerateLinqDelegate(operatorType, out operationFunction!, out ValidationError? validationError))
+ {
+ metadata.AddValidationError(validationError);
+ }
+ }
+ }
+
+ ///
+ protected override TNumeral Execute(CodeActivityContext context)
+ {
+ TNumeral value = Numeral.Get(context);
+ return operationFunction!.Invoke(value);
+ }
+ }
+}
diff --git a/src/UiPath.Workflow.Runtime/Expressions/SubtractAssign.cs b/src/UiPath.Workflow.Runtime/Expressions/SubtractAssign.cs
new file mode 100644
index 00000000..0fe57915
--- /dev/null
+++ b/src/UiPath.Workflow.Runtime/Expressions/SubtractAssign.cs
@@ -0,0 +1,98 @@
+// This file is part of Core WF which is licensed under the MIT license.
+// See LICENSE file in the project root for full license information.
+
+using System.Activities.Validation;
+using System.ComponentModel;
+using System.Linq.Expressions;
+using System.Numerics;
+
+namespace System.Activities.Expressions
+{
+ ///
+ /// A code activity which deccrementally assigns a numeral.
+ ///
+ ///
+ /// int myNum = 5;
+ /// myNum += 5; // 10.
+ ///
+ /// The operand to modify.
+ /// The operand with which to modify .
+ /// The resulting type of hte operation.
+ public sealed class SubtractAssign : CodeActivity
+#if NET7_0_OR_GREATER
+ where TLeft : INumber
+ where TRight : INumber
+ where TResult : INumber
+#endif
+ {
+ private static Func? checkedOperationFunction = null;
+ private static Func? uncheckedOperationFunction = null;
+
+ ///
+ /// Gets or sets the left operand which will be modified by this operation.
+ ///
+ [RequiredArgument]
+ public InArgument Left { get; set; } = new();
+
+ ///
+ /// Gets or sets the right operand which will be the modifier for this operation.
+ ///
+ [RequiredArgument]
+ public InArgument Right { get; set; } = new();
+
+ ///
+ /// Gets or sets a value indicating whether this operation will happen in a checked or unchecked context.
+ ///
+ [DefaultValue(true)]
+ public bool IsChecked { get; set; } = true;
+
+ ///
+ protected override void CacheMetadata(CodeActivityMetadata metadata)
+ {
+ BinaryExpressionHelper.OnGetArguments(metadata, Left, Right);
+
+ if (IsChecked)
+ {
+ EnsureOperationFunction(metadata, ref checkedOperationFunction, ExpressionType.SubtractAssignChecked);
+ }
+ else
+ {
+ EnsureOperationFunction(metadata, ref uncheckedOperationFunction, ExpressionType.SubtractAssign);
+ }
+ }
+
+ private static void EnsureOperationFunction
+ (
+ CodeActivityMetadata metadata,
+ ref Func? operationFunction,
+ ExpressionType operatorType
+ )
+ {
+ if (operationFunction == null)
+ {
+ if (!BinaryExpressionHelper.TryGenerateLinqDelegate(
+ operatorType,
+ out operationFunction,
+ out ValidationError? validationError))
+ {
+ metadata.AddValidationError(validationError);
+ }
+ }
+ }
+
+ ///
+ protected override TResult Execute(CodeActivityContext context)
+ {
+ TLeft leftValue = Left.Get(context);
+ TRight rightValue = Right.Get(context);
+
+ // If user changed checked flag between open and execution, an NRE may be thrown.
+ // This is by design.
+ // Nullability check silenced because the corresponding value is guaranteed to be
+ // non-null
+ return IsChecked
+ ? checkedOperationFunction!(leftValue, rightValue)
+ : uncheckedOperationFunction!(leftValue, rightValue);
+ }
+ }
+}
diff --git a/src/UiPath.Workflow.Runtime/Expressions/UnaryExpressionHelper.cs b/src/UiPath.Workflow.Runtime/Expressions/UnaryExpressionHelper.cs
index 714f1879..977ce3f7 100644
--- a/src/UiPath.Workflow.Runtime/Expressions/UnaryExpressionHelper.cs
+++ b/src/UiPath.Workflow.Runtime/Expressions/UnaryExpressionHelper.cs
@@ -8,8 +8,17 @@
namespace System.Activities.Expressions;
-internal static class UnaryExpressionHelper
+///
+/// Helpers for unary expressions.
+///
+public static class UnaryExpressionHelper
{
+ ///
+ /// Binds the metadata for the argument.
+ ///
+ /// The type of the argument.
+ /// The metadata.
+ /// The argument.
public static void OnGetArguments(CodeActivityMetadata metadata, InArgument operand)
{
RuntimeArgument operandArgument = new("Operand", typeof(TOperand), ArgumentDirection.In, true);
@@ -22,6 +31,33 @@ public static void OnGetArguments(CodeActivityMetadata metadata, InArg
});
}
+ ///
+ /// Binds the metadata for the argument.
+ ///
+ /// The type of the argument.
+ /// The metadata.
+ /// The argument.
+ public static void OnGetArguments(CodeActivityMetadata metadata, InOutArgument operand)
+ {
+ RuntimeArgument operandArgument = new("Operand", typeof(TOperand), ArgumentDirection.InOut, true);
+ metadata.Bind(operand, operandArgument);
+
+ metadata.SetArgumentsCollection(
+ new Collection
+ {
+ operandArgument
+ });
+ }
+
+ ///
+ /// Generates a delegate.
+ ///
+ /// The type of the argument.
+ /// The return type of the operation.
+ /// The type of expression.
+ /// The resulting .
+ /// If the operation failed, the error.
+ /// if the operation was successful; otherwise, .
public static bool TryGenerateLinqDelegate(ExpressionType operatorType, out Func operation, out ValidationError validationError)
{
operation = null;