Giter VIP home page Giter VIP logo

Comments (16)

bakpakin avatar bakpakin commented on June 13, 2024 2

Ah, my bad. What I mean is that you need to have some kind of mechanism to timeout if there are no events in the queue, ev/deadline is one such mechanism.
Another idea is to have "heartbeat" events that will prevent the queue from locking up.

Like adding:

(ev/spawn-thread
    (while true
        (os/sleep 0.1)
        (ev/give thread-channel :heart-beat)))

from jaylib.

honix avatar honix commented on June 13, 2024 1

Yo, @rpherman, there is better version, and seems I fixed all things:

(use jaylib)

# function to hot-reload
(varfn draw [] 
    (begin-drawing) 
    (clear-background [1 0 1]) 
    (end-drawing))

(defn game []
    (init-window 100 100 "Test Game")
    (while (not (window-should-close))
        (if-let [s (try (thread/receive 0) ([err] nil))]
            (try (eval-string s) ([err] (print err))))
        (draw))
    (close-window))
    
# like getline but waits for matching count of parenthesis
(defn getform [&opt prompt]
    (if prompt (file/write stdout prompt))
    (var s "")
    (var n 0)
    (while (or (and (empty? s) (zero? n)) 
               (and (not (empty? s)) (not (zero? n))))
        (let [l (file/read stdin :line)]
            (set n (+ n (length (string/find-all "(" l))))
            (set n (- n (length (string/find-all ")" l))))
            (set s (string/join @[s l] "\n"))))
    s)

(defn repl-thread [parent]
    (os/sleep 1) # let jaylib to print all the things
    (while true
        (thread/send parent (getform "game-repl>"))))

(thread/new repl-thread)
(game)

from jaylib.

honix avatar honix commented on June 13, 2024
(defn repl-thread [parent]
    (repl))

(thread/new repl-thread)

Throws:

in thread <core/thread 0x7F7A98002CA0>: error: arity mismatch, expected at most 2, got 3
  in getline
  in <anonymous> [boot.janet] on line 2177, column 31
  in run-context [boot.janet] (tailcall) on line 1863, column 5

from jaylib.

pepe avatar pepe commented on June 13, 2024

On the thread, you can run only code which Janet can marshal. cfuncs are not marshalable.

from jaylib.

kurayama avatar kurayama commented on June 13, 2024

@honix That was fixed in janet-lang/janet@f5433dc

from jaylib.

honix avatar honix commented on June 13, 2024

Thanks for the signal. I'll try my repl trick in some of next days.

from jaylib.

honix avatar honix commented on June 13, 2024

Ah.. New error appears.
My actions (doing this in janet-code for vscode), but really it is simple terminal session:

  • Start janet, load basic jaylib sketch (black window):
(base) [honix@honix-pc prog]$ janet -s
Janet 1.9.0-dev-63812c9  Copyright (C) 2017-2020 Calvin Rose
janet:1:> (use jaylib)

(defn draw []
    (use jaylib)
    (begin-drawing)
    (clear-background [0 0 0])
    (end-drawing))

(defn game []
    (init-window 100 100 "Test Game")
    (while (not (window-should-close))
        (draw))
    (close-window))

(defn repl-thread [parent]
    (repl))

(thread/new repl-thread)
(game)


nil
janet:2:> janet:3:> janet:4:(> janet:5:(> janet:6:(> janet:7:(> <function draw>
janet:8:> janet:9:> janet:10:(> janet:11:(> janet:12:((> janet:13:(> <function game>
janet:14:> janet:15:> janet:16:(> <function repl-thread>
janet:17:> janet:18:> <core/thread 0x5594CCA0D9A0>
janet:19:> INFO: Initializing raylib 2.6-dev
repl:1:> repl:2:> repl:3:> INFO: Display device initialized successfully
**** many INFO output from jaylib itself ****
  • Trying to update draw function (red window will appear):
(defn draw []
    (begin-drawing)
    (clear-background [1 0 0])
    (end-drawing))
repl:4:(> repl:5:(> repl:6:(> repl:7:(> compile error: unknown symbol begin-drawing on line 5, column 5 while compiling repl
  • Another one (trying use jaylib line):
repl:8:> (defn draw []
    (use jaylib)
    (begin-drawing)
    (clear-background [0 1 0])
    (end-drawing))
repl:9:(> repl:10:(> repl:11:(> repl:12:(> compile error: unknown symbol begin-drawing on line 10, column 5 while compiling repl
repl:13:> 

If @pepe is right about marshaling, how hotswap can be done in runtime?

from jaylib.

bakpakin avatar bakpakin commented on June 13, 2024

So due to the way Janet compiles, bindings creates with def and defn cannot be mutated after creation, even in repls. To get around this, you can use var or varfn as a stand in replacement. A second invocation of varfn will replace the first, where the second invocation of var will create a new var, so be aware.

from jaylib.

bakpakin avatar bakpakin commented on June 13, 2024

There also seems to be some misunderstanding of how threads work - two threads do not share a janet interpreter.

If I were you, I would use the second thread to only call getline, and send the result back to the main thread with thread/send. The main thread would then use (thread/receive 0) to get the result - if that fails with a timeout - no line is ready, you could yield to the next frame to avoid blocking. This functionality could be put in the β€˜chunk’ function argument to repl, which determines how the repl gets chunks of source code.

from jaylib.

honix avatar honix commented on June 13, 2024

Thanks for the guide! It a bit complicated compared to my common lisp experience, but it looks like it will do the job.

from jaylib.

rpherman avatar rpherman commented on June 13, 2024

@honix Did you get it to work, because I am seriously interested in using Janet to do game dev and as an embedded scripting language. I wish I could help, but I am ignorant on these matters (but I am trying to catch up!). Also, it would be cool to make an NP++ macro to do it in NP++ to keep Raylib cohesive. I like VS Code too.

from jaylib.

honix avatar honix commented on June 13, 2024

@rpherman I did the test. Here is code I end up with:

(use jaylib)

# function to hot-reload
# this function will be oneliner since we use getline for reading
(varfn draw [] (begin-drawing) (clear-background [1 0 0]) (end-drawing))

(defn game []
    (init-window 100 100 "Test Game")
    (while (not (window-should-close))
        (try
            (do
                (eval-string (thread/receive 0)))
            ([err] 
                # thread/receive will throw err every tick do we ignore all the errors
                #(print err)
                ))
        (draw))
    (close-window))

(defn repl-thread [parent]
    (os/sleep 1) # let jaylib to print all the things
    (while true
        (thread/send parent (getline "game-repl> "))))

(thread/new repl-thread)
(game)

It works, except some things that I can't find solution in my time:

  • Reloaded function will be injected as oneliner (one newline at the end) as I can't find alternative to getline (getline stops on first newline)
  • thread/receive throws string as error object, so I can't check is it error from thread/receive or from eval-string or from evaluated form itself, only solution I can imagine is string comparasion

I will close issue as original problem is solved with bakpakin's notes. rpherman, we can continue conversation here if you want to.

from jaylib.

rpherman avatar rpherman commented on June 13, 2024

Thank you so much! I'll give it a spin after my work day has ended.

from jaylib.

paines avatar paines commented on June 13, 2024

Almost exactly 2 years later ....

I updated @honix snippet in order to have it working with latest Janet + Jayli, as threading seem to have changed quite a lot.
I tested the code from within VS Code with the vscode-janet extension where you would eval the file via alt+l and then alter the draw function, e.g. different clear color and eval only that function via alt+e. It works but after evaluation a window will pop-up asking if the app should be killed as it seems not to be responding. Discard that message a couple of times and after that you can develop. It usually disapears then. Not sure if this is a gnome-shell thing.

(use jaylib)

# function to hot-reload
(varfn draw [] 
    (begin-drawing) 
    (clear-background [1 1 1]) 
    (end-drawing))

(def thread-channel (ev/thread-chan 10))
(defn game []
    (init-window 500 500 "Test Game")
    (while (not (window-should-close))
        (if-let [s (try (ev/take thread-channel) ([err] nil))]
            (try (eval-string s) ([err] (print err))))
        (draw))
    (close-window))
    
# like getline but waits for matching count of parenthesis
(defn getform [&opt prompt]
    (if prompt (file/write stdout prompt))
    (var s "")
    (var n 0)
    (while (or (and (empty? s) (zero? n)) 
               (and (not (empty? s)) (not (zero? n))))
        (let [l (file/read stdin :line)]
            (set n (+ n (length (string/find-all "(" l))))
            (set n (- n (length (string/find-all ")" l))))
            (set s (string/join @[s l] "\n"))))
    s)

(ev/spawn-thread
    (while true
        (os/sleep 0.2)
        (ev/give thread-channel (getform "game-repl>"))))

(game)

from jaylib.

bakpakin avatar bakpakin commented on June 13, 2024

I think you would need to pass a timeout value to ev/take, otherwise it will hang.

from jaylib.

paines avatar paines commented on June 13, 2024

I think you would need to pass a timeout value to ev/take, otherwise it will hang.

Not sure what you mean. ev/take does not have a timeout, at least from what I see in the docs.

from jaylib.

Related Issues (19)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.