Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use library for functions? #259

Open
alexec opened this issue Sep 13, 2022 · 2 comments
Open

How to use library for functions? #259

alexec opened this issue Sep 13, 2022 · 2 comments

Comments

@alexec
Copy link

alexec commented Sep 13, 2022

How can I convert the "greet" example into a lib please?

This does not work:

import org.projectnessie.cel.EnvOption;
import org.projectnessie.cel.Library;
import org.projectnessie.cel.ProgramOption;
import org.projectnessie.cel.checker.Decls;
import org.projectnessie.cel.interpreter.functions.Overload;

import java.util.List;

import static org.projectnessie.cel.common.types.StringT.stringOf;

public class GreetLib implements Library {
    @Override
    public List<EnvOption> getCompileOptions() {
        return List.of(
                EnvOption.declarations(
                        List.of(
                                Decls.newVar("i", Decls.String),
                                Decls.newVar("you", Decls.String),
                                Decls.newFunction(
                                        "greet",
                                        Decls.newInstanceOverload(
                                                "string_greet_string", List.of(Decls.String, Decls.String), Decls.String)))
                )
        );
    }

    @Override
    public List<ProgramOption> getProgramOptions() {
        return List.of(
                ProgramOption.functions(
                        Overload.binary(
                                "string_greet_string",
                                (lhs, rhs) ->
                                        stringOf(String.format("Hello %s! Nice to meet you, I'm %s.\n", rhs,
                                                lhs))))

        );
    }
}
    @Test
    void merge() throws Exception {
        String greeting = ScriptHost
                .newBuilder()
                .build()
                .buildScript("i.greet(you)")
                .withLibraries(new GreetLib())
                .build()
                .execute(String.class, Map.of("i", "alex", "you", "you"));

        assertEquals("hello alex", greeting);
    }

Results in:

org.projectnessie.cel.tools.ScriptExecutionException: no such overload: string.greet[](string)

	at org.projectnessie.cel.tools.Script.evaluate(Script.java:59)
	at org.projectnessie.cel.tools.Script.execute(Script.java:45)
	at com.intuit.pavedroad.apimanagement.exteventingestorapp.rest.services.cel.GreetLibTest.merge(GreetLibTest.java:33)
	
@alexec
Copy link
Author

alexec commented Sep 13, 2022

Looks like it might be a bug:

List<ProgramOption> programOptions = new ArrayList<>();

Where is the call to getProgramOptions this func should contain?

@snazy thoughts? Is this a bug?

@XN137
Copy link
Contributor

XN137 commented Nov 11, 2022

getProgramOptions is used here:

static EnvOption Lib(Library l) {
return e -> {
for (EnvOption opt : l.getCompileOptions()) {
e = opt.apply(e);
if (e == null) {
throw new NullPointerException(
String.format("env option of type '%s' returned null", opt.getClass().getName()));
}
}
e.addProgOpts(l.getProgramOptions());
return e;
};
}

which gets used here in ScriptHost:

envOptions.addAll(libraries.stream().map(Library::Lib).collect(Collectors.toList()));
Env env = newCustomEnv(registry, envOptions);

also note that we have a test for ScriptHost with a custom library here:

@Test
void library() throws Exception {
class MyLib implements Library {
@Override
public List<EnvOption> getCompileOptions() {
return Collections.singletonList(
EnvOption.declarations(
Decls.newFunction(
"foo", Decls.newOverload("foo_void", Collections.emptyList(), Decls.Int))));
}
@Override
public List<ProgramOption> getProgramOptions() {
return Collections.singletonList(
ProgramOption.functions(Overload.function("foo", e -> IntT.intOf(42))));
}
}
ScriptHost scriptHost = ScriptHost.newBuilder().build();
Script script = scriptHost.buildScript("foo()").withLibraries(new MyLib()).build();
assertThat(script.execute(Integer.class, Collections.emptyMap())).isEqualTo(42);
}

from that example i am guessing you should be using "greet" instead of "string_greet_string" in your getProgramOptions() ?
if not, feel free to extend the testcase with a failing example and possible fix in a PR please

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants