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

Embedding section incomplete? #117

Open
monkey-w1n5t0n opened this issue Apr 20, 2021 · 3 comments
Open

Embedding section incomplete? #117

monkey-w1n5t0n opened this issue Apr 20, 2021 · 3 comments

Comments

@monkey-w1n5t0n
Copy link

The Embedding section of the C API chapter explains some basic ways of running Janet code embedded in a C program, such as janet_dobytes, janet_dostring, or janet_call.

It is mentioned multiple times that these ways are mostly meant for running "simple, short running logic" or for running code once. There is a mention of the existence of more efficient options (under the entry for janet_dobytes), but there's no info on what those options actually are.

What are these more efficient ways of running Janet code optimally when embedded in a C program?

@sogaiu
Copy link
Contributor

sogaiu commented Feb 4, 2022

Not sure what the text was like at the time of the original post.

Although janet_call has the associated text:

Try to put mostly simple, short running logic here as this suspends the garbage collector for the duration of the call.

I don't see that kind of text for janet_continue:

Resumes a new or suspended fiber. Returns a signal that corresponds to the status of the fiber after execution, and places the return/signal value in out. When resuming a fiber, the value to resume with should be in the argument in, which corresponds to the second argument to the Janet resume function.

nor for janet_pcall:

Invoke a function in a protected manner, catching any panics raised. Returns the resulting status code, as well as placing the return value in *out. The fiber pointer f is a pointer to a fiber pointer will contain the fiber used to run the function fun. If f is NULL, a new fiber will be created. Otherwise, Janet will use the fiber pointed to by f to run fun.

If no panics are raised, will return JANET_SIGNAL_OK. If an error is raised, will return JANET_SIGNAL_ERROR. Other signals will be returned as expected.

May be it's one or both of these that was being hinted at?

@monkey-w1n5t0n
Copy link
Author

I can't remember whether the text was any different at the time either. I do recall the janet_call text contributing to the confusion and, more importantly, the following from janet_dobytes:

Use this function to compile and run some Janet source code from C. If you plan on running the code multiple times, there are more efficient options. However, for code that will only run once, this is a useful function.

Perhaps the issue here is that "there are more efficient options" doesn't actually do anything to point the reader to those options; something as simple as naming them would suffice.

A few more points:

  1. By virtue of its name, I would expect janet_call to be the way of calling Janet code. Its "I'm the one you're looking for" name is contradicted by its documentation asking the user to restrict its usage to "mostly simple code, short running logic", causing some cognitive dissonance as to whether it's "the main one" or a "lightweight, restricted version".
  2. Again by looking at just the name, one would expect janet_pcall to be a superset of, or otherwise very tightly coupled with, janet_call (janet protected call reads like "janet call but with some extra steps for protection"). If janet_pcall is more efficient/capable of handling more complex logic than janet_call, then that's not made clear by neither the name nor the documentation.
  3. janet_do_bytes, by virtue of having bytes in its name, initially had me thinking that it's meant for evaluating code that has already been compiled to bytecode, which Janet clearly states it's capable of, reinforcing that initial impression. Since bytecode execution is generally expected to be faster than simply calling a not-yet-compiled string of code, then the statement "there are more efficient options" adds further dissonance.
  4. One would not assume that janet_continue is the name of a procedure meant for running/calling code, but rather something to do with continuing execution.

I'm happy to discuss possible solutions to the above, but some would require changes to the method names in addition to amendments to the documentation. Is the project open to such changes?

@sogaiu
Copy link
Contributor

sogaiu commented Feb 5, 2022

I looked at the current definitions for:

Roughly, it looks to me like:

  • janet_call calls run_vm (the main bytecode interpreter loop)
  • janet_continue calls janet_continue_no_check which in turn calls run_vm
  • janet_dobytes creates at least one fiber and then calls janet_continue
  • janet_dostring is a wrapper around janet_dobytes
  • janet_pcall sometimes creates a fiber (reuses an existing one in some cases) and then calls janet_continue

Based on these observations and the original text, my current guess is that of the mentioned functions, janet_continue is likely to be one of the more efficient options that doesn't involve GC suspension, while if suspending GC is not such a concern (presumably for "simple, short running logic"), then janet_call is also a "more efficient option".

If confirmation is obtained on the above, I wouldn't be surprised if an appropriate PR for updating the text to explicitly mention these as "the more efficient options" got accepted.

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