by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Sep 20 13:02
    Windows-mingw build of CI run 263695210 failed
  • Sep 20 12:33

    feeley on debug-serial-numbers

    (compare)

  • Sep 20 12:33

    feeley on master

    Add serial numbers on truncated… Merge pull request #637 from ga… (compare)

  • Sep 20 12:33
    feeley closed #637
  • Sep 20 11:45
    Windows-mingw build of CI run 263636775 failed
  • Sep 20 11:20
    feeley opened #637
  • Sep 20 11:19

    feeley on debug-serial-numbers

    Add serial numbers on truncated… (compare)

  • Sep 16 21:11
    jxy opened #636
  • Sep 07 15:52
    Negdayen edited #635
  • Sep 07 15:25
    Negdayen opened #635
  • Sep 06 17:20
    R1ck77 commented #634
  • Sep 06 17:20
    R1ck77 closed #634
  • Sep 06 17:20
    R1ck77 commented #634
  • Sep 06 17:19
    R1ck77 commented #634
  • Sep 03 17:00
    R1ck77 opened #634
  • Sep 03 02:52
    gambiteer opened #633
  • Aug 27 21:50
    brunerdm commented #632
  • Aug 27 21:50
    brunerdm closed #632
  • Aug 27 19:42
    gambiteer commented #632
  • Aug 27 18:38
    brunerdm opened #632
amirouche
@amirouche

Here is the script that I devised:

% cat scheme2javascript.sh
#!/bin/sh

set -e

cp $1 /tmp/app.scm
echo "(declare (standard-bindings) (extended-bindings) (not safe) (not run-time-bindings))\n\n(define (main) (println \"hello world\"))(app#)" > /tmp/lib.scm
gsc -target js -c /tmp/lib.scm
gsc -target js -c /tmp/app.scm
gsc -target js -link -l /tmp/lib /tmp/app.js
cat /tmp/app_.js /tmp/lib.js /tmp/app.js  > "$1.js"

The code should go inside a app.scm and that file must be passed as first argument of the above script.

amirouche
@amirouche

We just built a new version of the unofficial docker container that includes the necessary file to compile to javascript with gambit runtime, here is a test run:

% echo "(println 42)" > main.scm
% docker run --rm -ti -P -v "$PWD":/mnt schemers/gambit:head bash
root@fe73d55b688a:/# apt update > /dev/null && apt install -y nodejs > /dev/null
...
root@fe73d55b688a:/# cd /mnt/
root@fe73d55b688a:/mnt# nodejs --version
v10.21.0
root@fe73d55b688a:/mnt# gsc -target js -exe main.scm
root@fe73d55b688a:/mnt# nodejs main
42
root@fe73d55b688a:/mnt#

Do not forget to run docker pull schemers/gambit:head to have the latest image :)

amirouche
@amirouche
How can I call javascript from scheme?
amirouche
@amirouche
using fgrep through gambit repo gave me a hint, the gist of the idea is to use the form ##inline-host-expression
with g_scm2host et al.
Marc Feeley
@feeley
@amirouche You’ll find some more information on interfacing Scheme and JS in the browser with Gambit in this web app which was created with Gambit : https://udem-dlteam.github.io/webapp-tutorial
Over the summer I supervised a student (@roropincho) who started developing an interface to the DOM using Gambit… it is quite preliminary but perhaps you can get some ideas from it and improve it : https://github.com/roropincho/scm2js/blob/master/js/js.scm (in particular the g_host2foreign and g_foreign2host that allow any JS object, such as DOM elements, to be manipulated in the Scheme code… a Scheme “foreign” object is simply a box containing an object of the host language, JS in this case)
Marc Feeley
@feeley
@R1ck77 When you interface to C code and a c-lambda returns a C string (e.g. the type char-string), the C string is copied to its Scheme representation… there is no sharing of the memory block containing the C string. If however you use a type like (pointer char), equivalent to the C char* type, then a “foreign” object is created that points to the C characters. You can specify a “release function” with your (pointer char) type so that when the Scheme world no longer has a reference to the foreign object, the release function is called (which in this case should probably do a free(ptr)). This could be achieved with the type (pointer char (char*) “free”) assuming your string was allocated with malloc. The use of the ___AT_END macro allows a clean separation between the C and Scheme memory management but it may be less efficient due to the copying of a (potentially long) string.
@lucaregini You are welcome to use my code in your blog. Please share the link when it is posted.
@fare There is no predefined modular exponentiation procedure. A simple algorithm is not too hard to write in Scheme thanks to the bignum support.
François-René Rideau
@fare
If a continuation is made of activation frames, itself made of data plus code, what do you call the code part of the frame? The "code pointer"? The "proc"?
"frame code" vs "frame data"? "code block"?
amirouche
@amirouche
@feeley Thanks for the input, it is very much appreciated.

Looking at the code, I see the following define-procedure:

(define-procedure (foreign->js (obj foreign))
  (##inline-host-expression "g_foreign2host(@1@);" obj))

What is define-procedure ?

Also, I do something similar in my code, where I bypass the procedure2scm et al. to do the conversion myself, because reactjs synthetic dom event can not translated with host2scm so I pass the original "JavaScript Object" around and add procedures with ##inline-host-expression to interact with it.
amirouche
@amirouche
Tomorrow I will slack a bit ;)
Bradley Lucier
@gambiteer

For an example, see the code for SRFI 41: 41.scm contains

(define-procedure
  (stream-car (strm stream))
    (if (stream-null? strm)
        (error-stream-null 'stream-car))
        (stream-force (stream-car* (stream-force strm))))

which expands to

(define stream-car
  (lambda (%strm) (if (stream? %strm) (begin (if (stream-null? %strm) (##error 'stream-car "null-stream argument") #!void) (stream-force (stream-car* (stream-force %strm)))) (##fail-check-stream '(1 . strm) stream-car %strm))))

It's a poor man's way to automatically add type checks to the arguments of a procedure.

amirouche
@amirouche
Got it, thanks!
Riccardo Di Meo
@R1ck77
@feeley thank you very much!
amirouche
@amirouche
what are the namespaces or procedures available in javascript runtime?
when I type (apropos) in the normal REPL I get some procedure names, but I am not sure which one is available in js runtime
Marc Feeley
@feeley

@amirouche I’m not sure what you mean by the “normal REPL” but if you execute (apropos) in the web app REPL then you will get the procedures defined in the web app’s Scheme library. Unfortunately the web app’s REPL will only show the last few lines of output, so you might want to evaluate this instead (tested on the last page of https://udem-dlteam.github.io/webapp-tutorial):

(define (show thunk)
  (host-exec
    "var text = g_scm2host(@1@);
     var parent = document.querySelector('.slide.present') || document.body;
     var elem = document.createElement('textarea');
     elem.style = 'position: absolute; font-family: monospace; font-size: 10px; height: 500px; width: 500px; left: 0px; top: 0px; z-index: 99999; overflow-y: scroll;';
     elem.value = text;
     elem.addEventListener('dblclick', function (event) { event.target.parentNode.removeChild(event.target); });
     parent.appendChild(elem);"
    (with-output-to-string thunk)))

(show (lambda () (apropos "" (current-output-port))))

You’ll see that most of the procedures of the C backend’s Gambit library are available. Obviously some “desktop OS specific” functionality is not implemented :

> (shell-command "ls")
unimplemented ##os-environ called
*** ERROR IN (console)@1.1 -- Unknown error
(shell-command "ls")
amirouche
@amirouche
Thanks!
amirouche
@amirouche
I do not have the procedure host-exec on my side
Marc Feeley
@feeley
host-exec is a macro that is specific to the universal library. Look for "Host FFI" in lib/_univlib.scm. There is an implementation for the JS and Python backends (languages that have a run time eval construct). If you want to avoid host-exec then use ##inline-host-expression which has the same API but is static (you can’t (eval '(##inline-host-expression …)))
amirouche
@amirouche
I do not understand, because it does not work on my side...
% cat index.scm
(define (show thunk)
  (host-exec
    "var text = g_scm2host(@1@);
     var parent = document.querySelector('.slide.present') || document.body;
     var elem = document.createElement('textarea');
     elem.style = 'position: absolute; font-family: monospace; font-size: 10px; height: 500px; width: 500px; left: 0px; top: 0px; z-index: 99999; overflow-y: scroll;';
     elem.value = text;
     elem.addEventListener('dblclick', function (event) { event.target.parentNode.removeChild(event.target); });
     parent.appendChild(elem);"
    (with-output-to-string thunk)))

(show (lambda () (apropos "" (current-output-port))))
% cat ../../scm2js.sh
#!/bin/sh

docker run -v $(pwd):/mnt --rm -it schemers/gambit:head gsc -target js -exe /mnt/$1
tail -n +2 $(basename $1 .scm) > "$(basename $1 .scm).js"
rm -f $(basename $1 .scm)
% ../../scm2js.sh index.scm
% node index.js
*** ERROR -- Operator is not a PROCEDURE
(#!void
 "var text = g_scm2host(@1@);\n     var parent = document.querySelector('.sl...
 "\"##\" namespace:\n  *, *2, +, |+2|, -, |-2|, /, /2, <, <2, <=, =, =2, >, ...
)
>
*** EOF again to exit
%
Marc Feeley
@feeley
Did you (eval ‘(host-exec “…”)) or do (host-exec “…”) in the web app’s REPL? It won’t work in compiled code… you need to use (##inline-host-statement “…”) for that.
amirouche
@amirouche
ah ! ok :)
host-exec is usable only in eval
Good thing eval works :)
Marc Feeley
@feeley
or in the REPL, which hides eval… ideally the two forms should be unified
François-René Rideau
@fare
How good is the JS backend, and could I reasonably have my DApp runtime run on top of it?
How much work would be required to bring the backend up to shape?
François-René Rideau
@fare
Another parameter question: it looks like (define foo (make-parameter #f)) creates a global binding that is side-effected rather than thread-locally shadowed by a (foo 'bar) unless I first use (parameterize ((foo #f)) ...) in the thread. Is that expected behavior?
François-René Rideau
@fare
This interesting makes parameters more like special variables in SBCL, and less like parameters in Racket.
François-René Rideau
@fare
the most "interesting" to me is to spawn a thread within a parameterize, then the threads inherit the cell, not the value, and can concurrently edit that shared cell.
François-René Rideau
@fare
is there a way to access the list of currently bound parameters? The equivalent of CL's PROGV ?
François-René Rideau
@fare
... the answer is a list of parameter-binding procedures.
François-René Rideau
@fare
and call parameterize on each one in a loop around the internal thunk.
amirouche
@amirouche
@fare JS backend is definitely usable!
I was planning to do a clone of slack, but the target application is little bit different than "corporate chat", so I am experimenting with a conversation that ressembles a tree.
François-René Rideau
@fare
@amirouche nice!
I'll need some chat capability in my app manager... after all, players have to be able to find each other.
Jason Felice
@eraserhd
I just discovered that (equal? (make-table) (make-table test: equal?)) ;=> #f, and it's probably because (equal? equal? ##equal?) ;=> #f. This is non-obvious from the docs, is it bad?
amirouche
@amirouche
re javascript backend: that said I stumbled upon an error that says something along the lines of r1 register undefined... Next time I will try to pin point a simple way to reproduce, I mostly debug with print but before convert argument to string with write
The error I mentioned above is a javascript error, 99 time out of 100 the error raise a popup with a REPL with where the error is.
Marc Feeley
@feeley
@eraserhd nice catch! yes definitely what I consider to be a bug… will come up with a fix...