Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • May 14 15:27

    bakpakin on master

    Fix meson.build for older versi… (compare)

  • May 10 14:22
    bakpakin commented #970
  • May 09 18:55
    patranger commented #970
  • May 09 15:29

    bakpakin on v1.22.0

    (compare)

  • May 09 15:28

    bakpakin on v1.22.0

    (compare)

  • May 09 15:28

    bakpakin on master

    Fix version bump. (compare)

  • May 09 15:20

    bakpakin on v1.22.0

    (compare)

  • May 09 15:19

    bakpakin on master

    Prepare for 1.22.0 release. (compare)

  • May 08 13:38
    bakpakin closed #974
  • May 06 00:24

    bakpakin on master

    Add `module/value` function to … (compare)

  • May 05 23:33

    bakpakin on master

    Remove file/popen - address #974 (compare)

  • May 05 23:28
    bakpakin commented #974
  • May 05 23:27

    bakpakin on master

    Use janet_getnat when non-negat… (compare)

  • May 05 13:56
    bakpakin closed #975
  • May 05 13:56

    bakpakin on master

    Fix #975 - null ptr dereference… Merge pull request #976 from ri… (compare)

  • May 05 13:56
    bakpakin closed #976
  • May 05 13:56
    bakpakin commented #976
  • May 05 05:13
    rick2600 opened #976
  • May 05 05:01
    rick2600 edited #975
  • May 05 05:00
    rick2600 opened #975
Levi R. I. Tan Ong
@levitanong
To cement my understanding: If i don't have thru or (choice % 1) I get nil because they don't immediately match the pattern and the engine gives up. Is this correct?
tionis
@tionis:matrix.org
[m]
I'm a bit confused by the documentation, how do I use run-context correctly when i want to execute some code that has access to my current environment/functions?
andrewchambers
@andrewchambers
@tionis:matrix.org can you pass in the output of curenv ?
tionis
@tionis:matrix.org
[m]
I'm more generally confused on how to feed it the string to parse, do i have to wrap it with function that returns chunks or how is this meant to be used?
andrewchambers
@andrewchambers
hmm - don't know off hand and don't have access to my stuff - But a good place to look is just to read boot.janet if you didn't already
tionis
@tionis:matrix.org
[m]
Nevermind, I just read the implementation of eval-string, this helped a bit
I think my mistake is somewhere else
andrewchambers
@andrewchambers
all good
tionis
@tionis:matrix.org
[m]
Is this a bug or intended?
Ok. I found the problem, when compiling the janet script into an executable the code parsed in the runtime doesn't have access to the parent environment functions.
Wait scratch that

Why does this work:

(defn test-func []
  (print "Hello there!"))

(defn test []
  (def test-func-2 (eval-string "(fn [] (test-func))" ))
  (test-func-2))

(test)

but this doesn't?:

(defn test-func []
  (print "Hello there!"))

(defn test []
  (def test-func-2 (eval-string "(fn [] (test-func))" ))
  (test-func-2))

(defn main [& args]
  (test))
1 reply
bakpakin
@bakpakin:matrix.org
[m]
When running as a script (a main function), the environment is basically emptied of various defs and such. This is so that it behaves as if it were compiled.
tionis
@tionis:matrix.org
[m]
Ah I see
bakpakin
@bakpakin:matrix.org
[m]
Janet, unlike many lisps, does not late bind defs and defns by default
tionis
@tionis:matrix.org
[m]
What does late bind mean?
bakpakin
@bakpakin:matrix.org
[m]
I guess not entirely relevant to this particular example, but essentially the redefining things does not update old references.
in this example, the issue is that there is always a "current environment" that contains all dyanmic bindings, as well as avaiable symbol definitions used by the compiler. This environment will be different in the script with main function to better emulate a compiled program
Try adding (pp (curenv)) before (test) in both cases
tionis
@tionis:matrix.org
[m]
Ah yes, now I see it
Is there a good way then to write a program, compile it and then at runtime load some janet-code and execute it with it having access to some internal functions?
Would I have to construct a new environment?
bakpakin
@bakpakin:matrix.org
[m]
A module?
tionis
@tionis:matrix.org
[m]
Well in my use case I'm writing a dotfile managment tool and want to load pre- and postsync hooks a bit like git but written in janet, importing it with import* like a module gave me problems when compiling it
janet complained about non-existant functions, because they were not loaded yet, as they were intended to be loaded in the runtime
bakpakin
@bakpakin:matrix.org
[m]
What problems did you run into?
It seems like you are having issues with early binding
tionis
@tionis:matrix.org
[m]
This was my function that executes the presync hook:
(defn execute_pre_sync_hook []
  (def path_no_extension (string (get_cfg_dir) "/hooks/pre-sync"))
  (if (file_exists? (string path_no_extension ".janet"))
      (do (print "Executing pre-sync-hook...")
          (import* path_no_extension)
          (pre-sync/pre-sync))
      true))
with the error:
error: cfg.janet:138:11: compile error: unknown symbol pre-sync/pre-sync
that's why I then experimented with something like this:
(defn execute_pre_sync_hook []
  (def path (string (get_cfg_dir) "/hooks/pre-sync.janet"))
  (if (file_exists? path)
      (do (print "Executing pre-sync-hook...")
          (def pre-sync (eval-string (slurp path)))
          (pre-sync))
      true))
bakpakin
@bakpakin:matrix.org
[m]

You modify the environment in the middle of a compiled block - the block is compiled before *import is run, because compilation always comes before evaluation. No amount of hacks will fix that. As I said, Janet is (almost) always early bound.

eval-string is not the right solution to your problem though, I can tell you that. Could you not do something like:

(defn load-hooks
   "load pre and post hooks"
   [module-path]
   (def module (require module-path))
   (def pre-sync (get-in module ['pre-sync :value]))
   (pre-sync))
or better than require, dofile if you want to just pass in a bare path
tionis
@tionis:matrix.org
[m]
Ok, thanks for the explanation, this is quite interesting
I will try that!
And also thanks for janet, it is tons of fun to write my system scripts in it 😄
tionis
@tionis:matrix.org
[m]
Hm, still doesn't work. The environment is still cleaned of my internal functions
bakpakin
@bakpakin:matrix.org
[m]
It should work - what do you mean by "internal" functions?
tionis
@tionis:matrix.org
[m]
I mean functions defined on the top level in the parent environment
bakpakin
@bakpakin:matrix.org
[m]

They do work, I just tested locally. I think the issue is you are making use of things like eval and eval-string inside your "hooks" file. These are inherently dependent on the context they are run in - you would have the same issues in any programming language. Using "require" or "dofile" does not just bring all of the bindings from the given path into the current environment, it returns a fully encapsulated module table. Even *import will auto-prefix bindings before bringing them into the current environment table.

Also, the effect of import or *import has no effect until the top level block is executed. You cannot do:

(do
  (import my-mod)
  (my-mod/abc 123))
1 reply
Instead, you would need to separate these into two top level statements:
(import my-mod)
(my-mod/abc 123)
bakpakin
@bakpakin:matrix.org
[m]

This is because Janet use incremental compilation, basically a repl. The first example (using do) has the following flow:

  • Read the form (do (import ...))
  • Compile this form and error because my-mod/abc is undefined.

The second working form has the following flow:

  • Read the form (import my-mod)
  • Compile and execute this form. This will modify the current environment to have my-mod/abc defined.
  • Read the next form (my-mod/abc 123)
  • Compile and execute this form. Since my-mod/abc was defined in the previous form, this evaluates without compilation error.

This incremental compilation is pretty common to Lisps and is not the stringly typed dynamism that is from a language like TCL.

but the incremental part only happens at the top level. Within a top-level block, everything is compiled and executed together
tionis
@tionis:matrix.org
[m]
(defn post-sync []
  (match ((cfg "config" "node.name") :text)
    "citadel" (do (os/execute ["vdirsyncer" "sync"] :p)
                  (os/execute ["wiki" "calendar_commit"] :p)
                  (os/execute ["wiki" "contacts_commit" "--no_pull"] :p))))
this is the post-sync hook code
James Muguira
@muguira-james

I am working c++ (gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1), trying to add a key to a janet table.

I get the table with: JanetTable *tt = janet_table(0); .

I try to add an entry with: janet_table_put(tt, janet_wrap_string("count"), janet_wrap_number(10)); .

The key shows up as "" when I print the table in the repl?

why?
thank you in advance!

bakpakin
@bakpakin:matrix.org
[m]
Use janet_cstringv("count") to wrap the string. Janet wrap string expects an already memory managed string, allocated by the Janet runtime.
1 reply
Levi R. I. Tan Ong
@levitanong
Given that JPM now requires to be built on the machine, does this mean that for CI jobs, we to download and bootstrap jpm each time? If so, this seems a bit wasteful :O
bakpakin
@bakpakin:matrix.org
[m]
I'm not sure why you would need to, although bootstrapping is quick, you are really just paying for the download time
1 reply