Getting Fibers promise to fire

I am trying to get a minimal app working on the browser–all it does is send text to the console. I got console.log working from outside Fibers (both the before and after promise calls work), but don’t understand why the code inside the promise doesn’t work, i.e., it doesn’t print anything.

(use-modules (scheme write)
             (hoot ffi)
             (fibers)
             (fibers promises))

(define-foreign console-log
  "window" "log"
  (ref string) -> (ref null extern))

(console-log "Before promise!")

(lambda (resolved rejected)
  (call-with-async-result
   resolved rejected
   (lambda ()
     (console-log "entered promise..."))))

(console-log "After promise!")

The wiring of the console-log function through the FFI is working because I do get console output, and ttt.wasm must be loading as well.

Repository: GitHub - andres-moreno/ttt

Help with this would be greatly appreciated!

1 Like

That lambda needs to be the final expression in your program. When you do Scheme.load_main from JavaScript, you will receive this procedure as the return value. You can then use call_async to call it to launch your async program.

See the JS code at the bottom of the fibers example here: Fibers example (Guile Hoot)

Dave, thanks so much for solving this riddle for me. I made the needed changes and now it works.

I will leave the Github repo out there as a minimal example if anyone needs it.

2 Likes

Dave,

I have a new interesting issue RE: console-log in spawn-fiber in ttt.scm in the repo from the original post,

The ttt.scm file has the following structure:

  1. Module imports
  2. Foreign function definition for console-log
  3. A bunch of code from (ice-9 q) b/c the module is not available for Hoot and I don’t know how to import my own modules yet
  4. the Inbox queues code from Spritely that was shared in the call with minor mods, one of which is to call a function passed as its argument
  5. A procedure called my-threads, called by Inbox where I use spawn-thread
  6. Promise code

Note that my-threads spawns a number of fibers, one of which uses console-log. When looking at the browser console, you’ll see that there is an UncaughtInternalError: too much recursion corresponding to the fiber that uses console-log.

Any ideas on how to solve? No pressure–I understand this Hoot is bleeding edge software.

Interestingly enough, @afm-victoria, I suspect the problem you are experiencing is the same bug in the Hoot runtime I’ve been tracking down in our Goblins+Hoot porting effort which is also a stack overflow. I can’t be sure, having not run your code, but it’s my best guess.

You define the import for console.log like so:

(define-foreign console-log "core" "log" (ref string) -> (ref null extern))

The return type is specified as (ref null extern), but console.log returns undefined, which translates to no return value in Wasm. Try this instead and let me know if the problem goes away:

(define-foreign console-log "core" "log" (ref string) -> none)

Dave,

I cut and pasted your definition for console-log but this caused a compilation error:

afm@mars:~/data/repos/guile/console-log [env]$ make serve
guild compile-wasm -o ttt.wasm ttt.scm
Backtrace:
In language/tree-il/compile-cps.scm:
  2104:10 19 (lp #<transient-intmap 0-59> _ _ (#<tree-il (lambda ()…>))
  2134:11 18 (convert #<transient-intmap 0-59> _ 1 #<hash-table 7f57…>)
  2134:11 17 (convert #<transient-intmap 0-59> _ 1 #<hash-table 7f57…>)
  2104:10 16 (lp #<transient-intmap 0-59> _ _ (#<tree-il (lambda ()…>))
  2134:11 15 (convert #<transient-intmap 0-59> _ 1 #<hash-table 7f57…>)
  2104:10 14 (lp #<transient-intmap 0-59> _ _ (#<tree-il (lambda ()…>))
  2134:11 13 (convert #<transient-intmap 0-59> _ 1 #<hash-table 7f57…>)
  2104:10 12 (lp #<transient-intmap 0-59> _ _ (#<tree-il (lambda ()…>))
   2092:9 11 (convert #<transient-intmap 0-59> _ 1 #<hash-table 7f57…>)
  1746:11 10 (convert #<transient-intmap 0-59> _ 1 _)
  1732:14  9 (convert-clauses #<transient-intmap 0-59> _ 2)
  2104:10  8 (lp #<transient-intmap 0-59> _ _ (#<tree-il (lambda …> …))
  1746:11  7 (convert #<transient-intmap 0-59> _ 12 _)
  1732:14  6 (convert-clauses #<transient-intmap 0-59> _ 13)
   2092:9  5 (convert #<transient-intmap 0-59> _ 13 #<hash-table 7f5…>)
   2092:9  4 (convert #<transient-intmap 0-59> _ 13 #<hash-table 7f5…>)
   2092:9  3 (convert #<transient-intmap 0-59> _ 13 #<hash-table 7f5…>)
   1639:7  2 (convert-arg #<transient-intmap 0-59> #<tree-il (const…> …)
In hoot/inline-wasm.scm:
   325:15  1 (_ #<transient-intmap 0-59> (1748))
    233:7  0 (n-valued-continuation #<transient-intmap 0-59> _ 0 _)

hoot/inline-wasm.scm:233:7: In procedure n-valued-continuation:
unexpected continuation for n-valued result 0
make: *** [Makefile:4: ttt.wasm] Error 1

To reproduce, you can get the repo and run it with guix shell -m manifest, followed by make serve, and the go to the console in the browser to see the issue.

I have also encountered a stack overflow trying to get the car of a message received from a channel.

Do you folks have a guile-hoot-next available in a Guix channel somewhere? It would make sense for me to use the latest version if I am playing with bleeding edge stuff.

Thanks for looking into this.

I think the unexpected continuation for n-valued result 0 error is happening because you have the console-log call as the last expression in a fiber but the fiber is expected to produce a return value. Try returning something, anything after the console-log call like #t or something.

We don’t have any Guix channel currently.

Dave,

Yes, I am now returning 42 from the promise and there are no compilation issues. Thanks!

The console-log recursion bug still persists: no issues if I use display.

I’ll sit tight until this is ironed out.

Happy New Year to you and the team at Spritely!

1 Like

I’m tracking the stack overflow issue here Call stack overflow (#354) · Issues · spritely / Guile Hoot · GitLab

I fixed the call stack overflow problem. Also, I came up with a small program for the n-valued-continuation compilation error and filed an issue. There is indeed a bug there. compilation error for inline-wasm with no return values (#355) · Issues · spritely / Guile Hoot · GitLab

Fixed the n-valued-continuation bug, as well!

Hey @afm-victoria, you inspired me to finally make a Guix channel that contains the latest bleeding edge builds of Goblins and Hoot. Check it out!

Note that we don’t currently have a substitute server so the packages will be built on your own machine.

1 Like

Dave,

Thanks for making this available. I was planning to chill until the next release but this means that I can keep on trying my stuff with the latest cut of the software.

1 Like

Dave,

No good deed goes unpunished! I am encountering an odd issue when running guile-hoot-next:

It complains about

Uncaught (in promise) TypeError: WebAssembly: Response has unsupported MIME type 'text/plain;charset=utf-8' expected 'application/wasm'

when loading ttt.js:

window.addEventListener("load", async ()  => {
  const [proc] = await Scheme.load_main("ttt.wasm", {
    user_imports: {
      core: {
        log(text) { console.log(text); }
      }
    }
  });
  proc.call_async();
});

This works fine when I use guile-hoot from the main Guix repo with no issues if I avoid console-log inside a Fibers thread but breaks catastrophically under guile-hoot-next. I assume that something changed in the compiler output that needs to be reflected in the code that loads the wasm module?

Any hints on what’s causing the issue?

Many thanks!

Hmmm I feel like I’ve seen this before but the root cause escapes me at the moment. Sounds like the web server is returning the wrong MIME type. Not sure why, though. You will need to update your reflect.js, reflect.wasm files if you haven’t done that yet, but I don’t see why forgetting to do so would cause this issue. I’ll reply again if I figure it out.

1 Like

That did it! I am back in business! Thanks!

I’ll go back to the documentation and your articles to make sure I understand what I need to do clearly.

Have a swell weekend!

1 Like

Dave,

Good news: the console-log issue that ate the stack appears to be gone. But a new problem came up where the Hoot runtime gave me an excellent hint:

Uncaught exception:
  1. #<&failed-type-check predicate: string?>
  2. #<&message message: "type check failed">
  3. #<&origin origin: console-log>
  4. #<&irritants irritants: (move)>
  5. #<&source file: "hoot/errors.scm" line: 95 column: 22>

It turns out that display can print symbols but console-log doesn’t know what to do with them, so it got sick when I passed it a symbol. I don’t need console-log because display does what I want and is more capable, so I am going to rip console-log out.

I will go back to my tic-tac-toe stuff to see if I can get it working in the next couple of days.

Thanks for all the support!

1 Like

Yup, you’re right that display is better! Most Scheme values are opaque from JavaScript’s point of view so console.log would mostly print out unhelpful information, anyway.

I feel like I should explain why you got that error because it could be of use to you in the future! It’s because your function definition looks like this:

(define-foreign console-log "core" "log" (ref string) -> none)

This is saying that console-log accepts one argument which must be a string since the type is (ref string). If you want an FFI binding to be able to receive any Scheme value, use (ref eq) as the param type.

1 Like