Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Expressif.Cli.Tests/BindCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ public async Task Bind_BinaryPredicate_PreservesBothOperands()
});
}

[Test]
public async Task Bind_ClosedFunctionPredicateArgument_ResolvesNestedFunction()
{
var result = await InvokeAsync("bind", "even |or greater-than(45 | add(17))");

Assert.Multiple(() =>
{
Assert.That(result.ExitCode, Is.EqualTo(ExitCodes.Success));
Assert.That(result.StdOut, Does.Contain("Arg[0]: InputExpression"));
Assert.That(result.StdOut, Does.Contain("Function: add"));
Assert.That(result.StdErr, Is.Empty);
});
}

[Test]
public async Task Bind_FieldShorthand_ShowsBinderGeneratedFunction()
{
Expand Down
17 changes: 17 additions & 0 deletions Expressif.Cli.Tests/CliCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,23 @@ public async Task Evaluate_TwoNestedPredicateBranches_ReturnsBoolean(string inpu
});
}

[Test]
public async Task Evaluate_PredicateClosedInputExpression_ResolvesNestedFunction()
{
var result = await InvokeAsync(
"evaluate",
"filter(greater-than(17 | add(17)))",
"--input",
"{10,12,13}");

Assert.Multiple(() =>
{
Assert.That(result.ExitCode, Is.EqualTo(ExitCodes.Success));
Assert.That(result.StdOut.Trim(), Is.EqualTo("{}"));
Assert.That(result.StdErr, Is.Empty);
});
}

[Test]
public async Task Evaluate_MultipleInputOptions_ReturnsClearError()
{
Expand Down
18 changes: 18 additions & 0 deletions Expressif.Testing/Functions/FunctionFactoryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,24 @@ public void Instantiate_FilterWithPredicateExpression_Valid()
Assert.That(predicate, Is.TypeOf<GreaterThan>());
}

[Test]
public void Instantiate_FilterWithClosedPredicateParameter_ResolvesNestedFunction()
{
var reference = new InputExpressionParameter(
new Expressif.Bindings.ClosedExpression(
new LiteralParameter(17m),
[new Function("add", [new LiteralParameter(17m)])]));
var predicate = new Function("greater-than", [reference]);
var filter = new Function(
"filter",
[new OpenExpressionParameter(new OpenExpression([predicate]))]);
var root = new OpenRootExpression(new OpenExpression([filter]));

var function = new FunctionFactory().Instantiate(root, new Context());

Assert.That(function.Evaluate(new object[] { 10, 12, 13 }), Is.Empty);
}

[Test]
public void Instantiate_SliceAlias_Valid()
{
Expand Down
16 changes: 16 additions & 0 deletions Expressif.Testing/Predicates/PredicationFactoryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,20 @@ public void Instantiate_NumericEqualToObjectIndexParameter_Valid()
Assert.That((predicate as EqualTo)!.Reference.Invoke(), Is.EqualTo(4));
});
}

[TestCase(62, false)]
[TestCase(63, true)]
public void Instantiate_ClosedFunctionParameter_ResolvesThroughFunctionRegistry(object value, bool expected)
{
var reference = new InputExpressionParameter(
new Expressif.Bindings.ClosedExpression(
new LiteralParameter(45m),
[new Function("add", [new LiteralParameter(17m)])]));
var predication = new SinglePredication(
new Function("greater-than", [reference]));

var predicate = new PredicationFactory().Instantiate(predication, new Context());

Assert.That(predicate.Evaluate(value), Is.EqualTo(expected));
}
}
6 changes: 6 additions & 0 deletions Expressif/Predicates/PredicationFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ protected override Delegate CreateParameter(IParameter parameter, Type scalarTyp
scalarType)
: base.CreateParameter(parameter, scalarType, context);

protected override Delegate CreateInputExpression(InputExpressionParameter input, Type type, IContext context)
{
var expression = new FunctionFactory().Instantiate(new ClosedRootExpression(input.Expression), context);
return CreateFunctionCast(() => expression.Evaluate(null), type);
}

private sealed class ContextualPredicate(IFunction expression, IContext context) : IPredicate
{
public bool Evaluate(object? value)
Expand Down