janet-lang / janet

A dynamic language and bytecode vm
https://janet-lang.org
MIT License
3.43k stars 221 forks source link

curenv doesn't work when embedded in C #1290

Closed iacore closed 11 months ago

iacore commented 11 months ago

Janet version: 1.30.0-bfb60fdb

When calling (make-image (curenv)) when embedded, the output buffer is wrong.

1. embedded in C

#include <janet.h>

int main(int argc, const char *argv[]) {
    // Initialize the virtual machine. Do this before any calls to Janet functions.
    janet_init();

    // Get the core janet environment. This contains all of the C functions in the core
    // as well as the code in src/boot/boot.janet.
    JanetTable *env = janet_core_env(NULL);

    // One of several ways to begin the Janet vm.
    janet_dostring(env, "(def abcdefg 1)  (pp (make-image (curenv)))", "main.janet", NULL);

    // Use this to free all resources allocated by Janet.
    janet_deinit();
    return 0;
}

Output: (The output is wrong)

❯ gcc test.c -ljanet && ./a.out
@"\xD8\broot-env"

2. script

this is correct

Output:

❯ cat /tmp/a.janet
(def abcdefg 1)  (pp (make-image (curenv)))
user@x17 ~/c/s/chargrid (main)
❯ janet /tmp/a.janet 
@"\xD4\x04\xD8\broot-env\xCF\aabcdefg\xD3\x02\xD0\nsource-map\xD2\x03\0\xCE\f/tmp/a.janet\x01\x01\xD0\x05value\x01\xD8\x06*args*\xD1\x01\xDA\x05\xD8\x0E*current-file*\xDA\x05\xD0\x06source\xDA\x05"

3. REPL

This is also correct.

❯ janet
Janet 1.30.0-bfb60fdb linux/x64/gcc - '(doc)' for help
repl:1:> (def abcdefg 1)  (pp (make-image (curenv)))
1
@"\xD4\x02\xD8\broot-env\xCF\x01_\xD3\x01\xD0\x05value\x01\xCF\aabcdefg\xD3\x02\xD0\nsource-map\xD2\x03\0\xCE\x04repl\x01\x01\xDA\x04\x01"
nil
sogaiu commented 11 months ago

In the embedded example, it looks like (curenv) and root-env evaluate to the same value. hash returns the same value for both and (= root-env (curenv)) returns true too.

IIUC, that may contribute to the if succeeding here (during marshalling):

https://github.com/janet-lang/janet/blob/a1b848ad76563ca2960507949a9b93a41735b697/src/core/marsh.c#L478-L485

...resulting in an early return and hence the buffer result of (make-image (curenv)) being @"\xD8\broot-env".

For the non-embedded cases, root-env and (curenv) evaluate to different tables and the if does not appear to succeed.

Within boot.janet / the janet executable, there often appears to be an environment constructed via make-env involved in evaluating code (whereas that doesn't appear to be occurring in the embedded case here). Perhaps this is part why the behaviors differ.

iacore commented 11 months ago

So the correct usage should be setting the prototype of a new table as core_env, and use that as environment?

bakpakin commented 11 months ago

You are running the environment table return from janet_core_env(), which is the root environment.

iacore commented 11 months ago

Should I update the first example here? Since running code directly in core_env is not the best practice.