schemeorg-community / try.scheme.org

Try Scheme - Run a Scheme REPL in the browser
https://try.scheme.org
2 stars 0 forks source link

Interface proposal #1

Open jcubic opened 3 years ago

jcubic commented 3 years ago

First thing that we need to agree before adding Scheme interpreter code and front-end REPL. In need to be generic and allow to change Scheme implementation and maybe also the REPL.

In my interpreter I have two ports stdout nad stdin in global scope that was used to write and read and also interpreter exposed eval and function that could be called from JavaScript. That was my main interface. In recent version I've hidden those ports because user was able to overwrite those names.

stdout, stdin and stderr need be hidden, but I'm not sure how this would look like in Gambit.

The other idea is to make eval and read JavaScript functions that call scheme functions.

There is one issue that I'm worried about (but it's working in gambit-in-browser) that read need to be async function. It can't block the thread like Emscripten default behavior (I'm not sure if it changed, but c read function invoked prompt ugly window). In my interpreter I've solved the issue by making everything is async. read return JavaScript promise and eval may or may not return a promise (exec main API always do that), but promises are hidden from the users. They are resolved automagically.

I was looking into gambit-in-the-browser intf.js file and I've seen some setTimeouts loops, I'm not sure if would be e

Just my ideas, you have any please write them below.

jcubic commented 3 years ago

from @feeley in mailing list.

I’ve added some files to the try.scheme.org github repo to show how a barebones Scheme interpreter webapp can be created using Gambit. It is a makefile and a 45 line Scheme source file.

The interpreter is only “barebones” in its UI. It currently runs a REPL using the JavaScript “prompt” function that allows showing the last few lines of output and allowing the next line of input to be entered. Very minimal but often good enough to start developing webapps.

The I/O for the interpreter’s console can be redirected elsewhere by redefining the JavaScript functions g_console_input_add and g_console_output_add. I’m confident an interface to JQueryTerminal would be easy to achieve with minimal work. For Gambit-in-the-browser I had used Terminus (https://github.com/breuleux/terminus) another JavaScript terminal emulator,with lots of interesting features by the way. I expect JQueryTerminal to be similarly easy to interface to.

File I/O would have to be improved to support editing files in the browser. Currently open-input-file will use AJAX to read files from the web server, which is useful for accessing libraries and other resources.

jcubic commented 3 years ago

Great starting point. I've stared writing issue on GitHub but I didn't add it, I'm not sure if should. I was proposing adding proper API that should be simple that can be connecting Scheme implementation with REPL.

To add I/O files we can use BrowserFS I was planing on adding this to my Scheme implementation, I have issue created. I can try to think something about this.

The one issue with I/O in Emscripten is prompt for read from stdin. I was impress that your gambit in browser support real (read) in terminal. It's not something easy to create and replace the default prompt that is blocking and replace with async code.

I can check the code you've added, but probably will need help to make the (read) async to add it to jQuery Terminal. With LIPS I was using Promises that is best way to make sync code.

Gambit in browser have:

_user_interrupt TTY.register(FS.makedev(6, 0), ops);

_heartbeat_interrupt(); _cleanup();

and setTimeout

That don't look very promising in creating simple API, but maybe something can be added and make simple API. that will be more generic and allow to change the implementation.

feeley commented 3 years ago

Having non-blocking input (for the console but also ajax, websockets, etc) is really important to me and is why this is implemented in the Gambit-in-the-browser webapp. It is a required feature for allowing multiple Scheme threads to do I/O without blocking other threads. This has been working in Gambit for many years.

When Scheme code is compiled to JavaScript by Gambit the runtime system provides a trampoline that allows leaving the Scheme code to give time for the browser to process events, then the trampoline can be called again to resume the execution of the Scheme code. The API needs to provide this functionality.

Gambit's JavaScript runtime system has a class that represents a "device" (the G_Device class). Moreover each device has a "condition variable" for blocking threads that try to get data from a device and the data is not yet available. So the I/O subsystem can keep track of which condition variable needs to be "signaled" when an I/O operation is now possible on that device and this will cause the waiting thread to be resumed by the Scheme thread scheduler. The thread will attempt the same operation again, and this will succeed (or not)... allowing the data to be processed by the thread.

Here's for example the function for reading data from a device:

g_os_device_stream_read = function (dev_condvar_scm, buffer_scm, lo_scm, hi_scm) { ... };

All the parameters are Scheme objects. The first is the device and condition variable, the second is the u8vector buffer for getting the data, and finally there are lo and hi indices of the section of the buffer that receives the data. The function returns the number of bytes read with the special case 0 for end-of-file, and -35 for "operation would block" (EAGAIN if you know Unix system calls).

The details are rather Gambit specific, but the general idea could be used to create a general purpose API that can be applied to other Scheme implementations including Gambit.

The important point is that the underlying I/O subsystem (in JavaScript) can keep track of the set of objects (dev_condvar_scm in the above example) that need to receive the notifications that the I/O operation should be attempted once more. The details of the notification would be specific to the Scheme implementation. A Scheme implementation that doesn't want to bother with the notifications (and threads, etc) could simply retry the I/O operation after a short delay to basically implement a busy-wait.

lassik commented 3 years ago

Any new thoughts on this issue?

jcubic commented 3 years ago

This is explanation part of the Gambit system but I have no clue how this is related to the code in https://feeley.github.io/gambit-in-the-browser/intf.js I don't see any g_os_device_stream_read in that file so I don't see how this is related. Is _user_interrupt function defined by user coder code and related to device. Do we need to defined devices for stdin stdout stderr? I don't understand how this works so I'm not able to implement the interface for Gambit to be used with jQuery Terminal.

I would need to see example that is non blocking. prompt based code is like any other emscripten compilation and it's not even close to solution done for gambit-in-browser.

From what I see it's really expensive in CPU to run Gambit in browser, because it run in the setTimeout loop even if it do nothing. It consume 19% of CPU even that it do nothing. It do complex computation when idle. I'm not sure how it would work on mobile, and yes applications run on mobile and I think try.scheme.org should also work on mobile. People may want to run mobile version to test something. My REPL works fine on Android.

To think about, it's in 2020 and people still care if they make size of the page smaller by 50KB. I've tested the gambit in browser in lighthouse (integrated with Chrome dev tools) and performance is 5% which is less then really bad.

jcubic commented 3 years ago

Maybe it would be good idea to first write documentation how GambitJS works and how to use it. Maybe it would be good idea to write article "how to use Gambit Scheme in browser". Since there not much pages in https://www.google.com/search?hl=pl&q=scheme%20in%20browser.

The only result is BiwaScheme and no one know any other option of Scheme in browser. So if Gambit can run it browser maybe it's worth explaining how to use it.

feeley commented 3 years ago

The gambit-in-the-browser system is based on the normal "C" distribution of Gambit compiled to JS by emscripten. This was done a few years ago (Gambit v4.7.0) and things have evolved quite a bit since then (Gambit is now at v4.9.3).

The more interesting option for try.scheme.org is the version of Gambit compiled to JS using the "universal" backend. It has a tighter coupling to JS and doesn't depend on emscripten, so it is more compact and has better performance. I'm not sure what you are talking about when you say that Gambit's performance is 5%. In any case if you care about performance you should read my "Compiling for multi-language task migration" paper which shows that Gambit-JS is up to 2 to 3 orders of magnitude (100x to 1000x) faster than Spock and Scheme2JS, the two other fairly mature Scheme to JS compilers.

Gambit JS can definitely run on mobile platforms. What I was saying in a previous message is that mobile platforms should not be the main target users for try.scheme.org . The user experience will be suboptimal because of the UI constraints (hard to use virtual keyboard and small screen size on phones).

I fear that using a minimalistic Scheme interpreter for try.scheme.org will not give a good impression of Scheme's abilities and power. Here are the features I think are essential in the try.scheme.org REPL to allow users to get a good understanding of what Scheme is:

Gambit JS has all of these requirements and many other features, including threads, hash-tables, pretty printer, JS FFI, fast execution, and the ability to compile Scheme apps to JS and run them in the browser or nodejs. These advanced features are also interesting to show off in examples even if they are not essential features.

I think we should agree on the requirements of the try.scheme.org REPL before moving forward. Do you agree with the above requirements?

lassik commented 3 years ago

Gambit-JS is 2 to 3 orders of magnitude (100x to 1000x) faster than Spock and Scheme2JS, the two other fairly mature Scheme to JS compilers.

Awesome job!

Here are the features I think are essential in the try.scheme.org REPL

Definitely can't hurt to have them.

  • 100% conformance is too much to ask because very few systems are at 100% currently

As far as I know, there are none. Chibi-Scheme may be closest, but it's interpreter-only, needs to be compiled with Emscripten and doesn't have a debugger.

arthurgleckler commented 3 years ago

On Sat, Jan 2, 2021 at 3:20 PM Lassi Kortela notifications@github.com wrote:

Here are the features I think are essential in the try.scheme.org REPL

Definitely can't hurt to have them.

I agree with Marc. If we're trying to show off the language, we should insist upon as complete an implementation of one of the recent standards, i.e. R6RS or R7RS, as possible.

lassik commented 3 years ago

I think we should give every implementation space on try.scheme.org that can reasonably run in the browser. But the default choice should be something full-featured and performant.

As for which order to do things in, I'm a believer in letting the people who do the work pick the order.

feeley commented 3 years ago

@lassik it may be "politically correct" to make space for multiple Scheme's on try.scheme.org . However if try.scheme.org is more than a link to a Scheme REPL running in the browser, such as having specific examples and a tutorial, then it becomes a mess to limit examples to the lowest common denominator or to explain in the tutorial that the following example only runs on Scheme X.

My point of view is that try.scheme.org will become the principal way to give a first impression of Scheme to newcomers. Giving them the impression that there are many many incompatible versions of Scheme is not the best image to leave them with, even if it is reality.

lassik commented 3 years ago

Unfortunately, one of the main goals with scheme.org has to be figuring out how to avoid political splits. I'm optimistic that a good compromise between usability and political stability can be found.

I agree that it's best if try.scheme.org immediately brings up the default REPL, and the other REPLs are in a pull-down menu or something.

It's worth thinking about how to organize tutorials and other documentation with respect to the REPLs. It's useful to have a REPL at hand while reading documentation. But maybe the REPL shouldn't be visible or loaded by default in that case; the user would have to click a button to bring it up or something -- people consulting reference documentation likely already have a REPL running in Emacs or a terminal window.

Anyway, we should definitely have try.scheme.org as something that immediately offers a REPL, but it probably is useful if we can embed REPLs into other parts of scheme.org as well.

arthurgleckler commented 3 years ago

This may not be a good idea, but I'll bring it up just in case, since it was popular in the early days of the web: There's no particular reason that try.scheme.org has to run Scheme directly in the browser. If it's suitably sandboxed and rate-limited, we could run a Scheme REPL on a server and provide remote access to it through the browser. That would significantly reduce client-side overhead, and would allow us to run full-fledged Schemes at full speed.

I'll also note that the startup repl.it supports Scheme, and that they do it using BiwaScheme, so there's already a minimal Scheme available for people to try for free. That means that there's less pressure on us to deploy something that's just a subset of Scheme.

lassik commented 3 years ago

A server-side REPL is definitely possible, but is a substantial performance and security concern.

@feeley pointed out that Emscripten should be able to compile many Schemes for use in the browser with reasonably few modifications. With modern browsers, that could be a more promising approach to REPLs for many of them.

For the default REPL, a JS-native Scheme would probably be better than an Emscripten-based one.

feeley commented 3 years ago

@arthurgleckler I would advise against a server-side REPL... a big can of worms. A web based Scheme REPL can be feature rich, be usable offline, have a persistent file system, and have reasonably good performance while avoiding security issues and logins to some form of "user accounts".

I'm not against supporting multiple Scheme systems in the long term. In the short term however it adds another level of complexity to make it easy to add a JavaScript Scheme implementation as a "plugin" (because existing JS Scheme implementations may not have a design suitable for this).

One interface that works well for Gambit JS is a hook in the stdin and stdout ports. These ports are used for the REPL I/O (reading expressions, writing results and error messages and reading debugger commands). The user's typing events feed the stdin port, and the output to stdout feeds the "console" (which could be a plain "textarea", a CodeMirror instance, a ymacs instance, etc). So the API is essentially at the stream level.

This may not be suitable for JavaScript Scheme implementations designed around an "eval" function which receives a string and returns a string (the result), and raises a JS exception when the evaluation causes an error. With this sort of API it is much harder to have a feature rich debugger, because it needs its own debugger API (how to display error messages, how to show backtraces, how to continue or single step the code, etc).

So I propose starting with a stream based API (basically hooks into stdin/stdout) and those JS Scheme implementations with stream based REPLs should be adaptable relatively easily to be used as plugins to try.scheme.org .

feeley commented 3 years ago

@feeley pointed out that Emscripten should be able to compile many Schemes for use in the browser with reasonably few modifications. With modern browsers, that could be a more promising approach to REPLs for many of them.

I didn't quite say that... I said that "in principle" any Scheme implementation written in portable C code should be compilable to JS by emscripten. However, in practice it may be a very different story (in part because it is common practice to use C tricks to implement some things and these might ruin portability to emscripten). You really have to try it for each Scheme implementation and either it works out of the box (very unlikely) or there is some adaptation required (that may take hours to months of work to implement).

For example, emscripten used to compile Gambit fine in the past (including January 2020), but I just tried again a few days ago and the C compiler crashes when compiling Gambit (due to some bug in LLVM). I managed to avoid the bug by compiling with -O0 optimization level, but haven't resolved other issues and don't have much time to spend on this (I was just interested in doing a quick check).

jcubic commented 3 years ago

BTW: 5% Performance is from lighthouse tool in Chrome that is used to test few metrics about the website: lighthouse

The tools say that most people will abandon the website because of performance (but that's just estimation). This performance is for mobile, which is lighthouse default. Desktop test is little higher at 15%.

Note that this metrics is not about Gambit itself only about the website gambit in browser.

lassik commented 3 years ago

@jcubic Interesting, thanks for computing those metrics! feeley.github.io runs the Emscripten version of Gambit. I wonder what Lighthouse would say about the gsc -target js version.

lassik commented 3 years ago

I didn't quite say that... I said that "in principle" any Scheme implementation written in portable C code should be compilable to JS by emscripten. However, in practice it may be a very different story (in part because it is common practice to use C tricks to implement some things and these might ruin portability to emscripten).

Sorry about misquoting you.

It seems this discussion is converging on the issue of defining a common JavaScript interface to which different Scheme implementations can conform to show a REPL. If we can define such an interface, that works well for Gambit and Lips to start with, then we could leave it as other implementors' responsibility to support that interface if they want to add their REPL.

lassik commented 3 years ago

Ideally the common interface would be something that can be supported by an Emscripten-based implementation as well. I haven't looked at what kind of JS FFI Emscripten has.

feeley commented 3 years ago

A stream based interface seems a natural fit for the traditional Scheme interpreter REPL "read-eval-print" metaphor, where the read is from stdin and the print is to stdout. The rest of the human interface (for debugging) is text based. So this would allow all non-JS Scheme implementations to be adapted to work (by compiling with emscripten), and also Gambit-JS, but I'm not sure about the other JS Scheme implementations.

feeley commented 3 years ago

In addition to a stdin/stdout interface it would be good to support a user-interrupt (ctrl-C) to interrupt the execution. This will be useful especially for newcomers that create infinite loops without knowing it.

jcubic commented 3 years ago

@feeley is it possible to make CTRL+C break loop in Gambit? It would be awesome if it do. I wonder if I could add something like this to my interpreter. As for common interface it's mostly because it would be easy to integrate with jQuery Terminal. Right now don't care much try.scheme.org will work with LIPS I only would like to implement all the features that I already have in my REPL. like colors, auto indent, pretty printing on copy paste or completion. Probably not all features would be able to create in GambitJS like in LIPS can get all functions from environment and can use it create completion and each procedure/macro have doc string in code and I can show it to the users when he hover over procedure or macro. If gambit don't store that information maybe we can use docs from somewhere else. maybe docs.scheme.org.

feeley commented 3 years ago

Yes this is implemented in the gambit-in-the-browser REPL. Here's an example interrupting a long recursive computation and asking for a backtrace using the REPL's ",b" command:

image

This can also be made to work with the Gambit JS system (it is a question of implementing the UI).

As for documentation, Gambit has the help procedure to open the documentation in the browser. This works in the normal Gambit system if you want to try it out. It used to work in the gambit-in-the-browser REPL, but unfortunately the URL of the Gambit documentation is no longer valid so you will get a 404 error.

In what language do you propose implementing the features you describe (auto-indent, pretty-printing, auto-completion)? I suspect you have JS in mind but it would be nice to implement this in Scheme (for example as a module loaded by the Scheme implementation) so that it is well integrated to the specific Scheme implementation being used. For example Gambit already has a pretty-printer with specific layout style and also symbol completion and it would be good for the UI to use the existing conventions of the Scheme implementation.

feeley commented 3 years ago

Let me also mention here my codeBoot project which is an online IDE for JavaScript and Python which supports single stepping. It is possible to create signed URLs which start codeBoot in a given state (content of file editors and state of execution). This provides a nice way to refer to specific code examples in web pages, PDF documents, etc. Here's an example of a small Python program being single-stepped (click the "play 1" button to advance by one step): example.py

I'll be adding support for Scheme (based on Gambit JS). So perhaps this would be another way to offer an online Scheme REPL.

Your thoughts?

jcubic commented 3 years ago

@feeley looks great. The stepper is pretty awesome. Is it full python or some proof of concept (because in REPL if I call again load smae file it throw error that load is not defined, and yield throws syntax error). There is one existing Python in JS which is Brython that is very good, I have simple REPL with syntax highlighting at trypython.jcubic.pl but it don't have lot of features like my Scheme REPL (the latest one is at https://jcubic.github.io/lips-test/ it's WIP for new website, the REPL on the page have little bit of lag, because the code is written in Scheme and it wait for Scheme to load the std library, maybe I will try to bundle JS and Scheme files together, so it will load faster).

feeley commented 3 years ago

codeBoot is a WIP and is designed for teaching programming to novices, so it covers a subset of Python. Nevertheless the subset is quite rich including classes and exceptions and there's also an interface to the DOM.

The load(...) at the REPL is a fake operation that is used to indicate that a program was executed at that point (using the "play" button while the focus is in a code editor window). You can use the Python import ... statement if you want to load a file.

Concerning the REPL interface I have an idea how to structure the system. We could use two JS classes: Console and Interpreter. The Console has a method to "connect" it to an Interpreter so that user interaction at the console will send notifications to the connected interpreter using these public methods:

A Console maintains a queue of lines that were entered by the user. A Console has these public methods:

So an Interpreter's console_readable(cons) method is called any time some data is added to the connected Console's queue. The Interpreter can then retrieve the data from the console by calling the read() method, either immediately or sometime later. It is important to decouple the notification of available data and the actual reading of the data because the Interpreter may be busy at that moment.

The interface could eliminate the Console's read() method and do the queuing in the Interpreter. However I like that the Console has both a read and write method because that is closer to the way TTY's are implemented in Unix (so the interface might be easier to use for other Scheme implementations that have a TTY interface).

Here's how a Console and Interpreter can be created and connected:

function init() {
    var cons = new Console(document.querySelector('#repl'));
    var interp = new Interpreter();
    cons.connect(interp);
}

The advantage of a separate connect method is that it allows multiple Consoles to feed a single Interpreter, which might be useful for a page with multiple examples. It could also be used to dynamically change which Console is connected to which Interpreter.

jcubic commented 3 years ago

Two questions:

Example in Kawa:

#|kawa:1|# (read)
#|kawa:2|# xxx (+ 1 2)
xxx3

Gambit do similar:

> (read)
xxx (+ 1 2)
xxx
> 3

Or will Scheme (GambitJS) just get the line and do what is should?

feeley commented 3 years ago

I think it would be good to implement the same "stream" interface as when a Scheme interpreter is executed from the unix shell (i.e. what you show above). That way newcomers will get the same experience when they move to a "desktop" environment and also it makes it more likely that a non-JS implementation of Scheme can be adapted to the try.scheme.org REPL.

I have a prototype implementation of the Console class based on CodeMirror (~ 250 lines of code). How hard would it be to write a version of the Console class based on JQuery Terminal?

jcubic commented 3 years ago

You can upload the files to some directory in git I can check how it works with CodeMirror. If you have something that works without prompt it probably will be easy to ad jQuery Terminal integration.

I probably will need help if we will want to implement all the features I have in my REPL. They can be written in Scheme: The features that wound be nice to have:

feeley commented 3 years ago

OK I'll create a makefile to build a proof of concept.

jcubic commented 3 years ago

Was playing with REPL and written simple code that works in standard Scheme including Kawa, Guile and Gambit, it don't work in Gauche and my interpreter though.

(let ((repl (lambda ()
              (let ((env (interaction-environment))
                    (void (if #f #f)))
                (let iter ()
                  (display "scheme> ")
                  (let ((input (read)))
                     (if (eof-object? input)
                         (newline)
                         (let ((result (eval input env)))
                           (if (not (eq? result void))
                               (begin
                                 (display result)
                                 (newline)))
                           (iter)))))))))
  (repl))

It would be awesome if this would work in try.scheme.org it would very be nice example how Scheme works (if someone look at the code). All what's required is stdin and stdout. Maybe also need handling errors to show stack trace and allow Gambit interupt.

feeley commented 3 years ago

There is now a demo here: http://gambitscheme.org/try/

As you can see I have removed the Gambit banner so that the REPL takes less space on the page. Moreover, I think it is more "politically acceptable" to not advertise up-front the specific implementation of Scheme that is being used.

I've just pushed the files to the try.scheme.org repo. Just look at the file try/makefile for instructions on how to build it. The interesting files are try/Console.js and try/Interpreter.scm . You will need to update Gambit first because some of my recent changes to the runtime system are needed (all I/O is now asynchronous and user-interrupts with ctrl-C are supported).

arthurgleckler commented 3 years ago

On Tue, Jan 5, 2021 at 12:05 PM Marc Feeley notifications@github.com wrote:

There is now a demo here: http://gambitscheme.org/try/

This is truly amazing. Bignums, threads, and everything!

jcubic commented 3 years ago

It's awesome, and gambitJS is really amazing factorial of 10 000 with little bit over ~1.3 seconds on my machine.

feeley commented 3 years ago

Performance of execution has always been an important goal of Gambit. The factorial function is not the best benchmark for a Scheme system because it mainly tests the speed of bignum multiplication (interestingly Gambit's bignums are all implemented in Scheme yet performance is good).

If you take the doubly recursive fibonacci function as a benchmark and compute (fib 25) here are the execution times on my machine and the Safari browser:

15.000 seconds: lips beta 1
 0.550 seconds: Gambit-JS (interpreted at the REPL)
 0.011 seconds: Gambit-JS (fib function compiled by gsc to JS code with full type checking)

So the Gambit-JS based REPL is about 30x faster than lips (while at the same time offering full symbolic debugging and the ability to interrupt the code with ctrl-C). And a Scheme webapp needing high performance can be compiled to JS by the Gambit compiler and the code will be on the order of 1400x faster than the lips interpreter.

The Gambit-JS REPL running in the browser is still about 10x slower than the native Gambit REPL (i.e. gsi). However I think the performance is sufficient to give a good impression of Scheme for the try.scheme.org site.

jcubic commented 3 years ago

Yes, LIPS is pretty slow, so I think that the only real use case for it is for learning Scheme, it's not good for actual application where performance is important, but this can be solved by implementing slow part of the code in JavaScript, I need to document this problem (I already have issue on GitHub, where I'm testing performance). Each function or macro used in expression make the whole code run much slower. I wonder how faster it would be when I implement proper expansion time, right now everything is expanded at runtime.

feeley commented 3 years ago

I have added to the REPL a better implementation of the documentation browser. For example (help help) will open in the browser the documentation of the help procedure. Also the REPL's ,h command will open the appropriate documentation for the procedure that last caused an error. For example the following will open the documentation of path-expand:

> (path-expand 123)
*** ERROR IN (console)@1.1 -- (Argument 1) STRING expected
(path-expand 123)
1> ,h

Unfortunately the Gambit manual does not contain the documentation for the standard procedures of R7RS like car, +, etc. So either the R7RS document could be integrated to the Gambit manual, or the r7rs.html document could be opened.

I didn't mention this previously but another nice feature of the Gambit JS REPL is the ability to treat URLs as files:

> (load "/http://gambitscheme.org/try/test.scm")
"test.scm says hello!"
"/http://gambitscheme.org/try/test.scm"

This opens up the possibility of loading R7RS libraries directly from repositories on the web (this needs special configuration to allow CORS, but it is relatively easy to do). In the specific case of libraries hosted on scheme.org there would be no need for special CORS considerations.

So what are the next steps for the try.scheme.org REPL? I think the Gambit-JS based REPL currently provides a good user experience and could be used in its current state. Do you see anything lacking? The (non essential) improvements I'd like to see in the future are:

lassik commented 3 years ago

Great work @feeley! URLs and threads are really nice.

Now replicated at https://try.scheme.org Runs all the examples. I added make targets to download codemirror, and to upload to the site

lassik commented 3 years ago

This is the only example that currently fails (on both try.scheme.org and gambitscheme.org/try):

(import (srfi 28))

Causes the REPL to hang so it does not accept further input. JS
console has the following error:

Uncaught ReferenceError: g_os_uri_encode is not defined
    at g_os_file_info (Interpreter.min.js:154)
    at g_bb1__23__23_os_2d_file_2d_info (Interpreter.min.js:3187)
    at g_bb6__23__23_file_2d_info_2d_aux (Interpreter.min.js:43753)
    at Array.g_bb3__23__23_file_2d_info_2d_aux (Interpreter.min.js:43752)
    at g_bb86__23__23_default_2d_path_2d_expand (Interpreter.min.js:44192)
    at g_bb85__23__23_default_2d_path_2d_expand (Interpreter.min.js:44194)
    at g_trampoline (Interpreter.min.js:44)
    at g_os_condvar_select_resume (Interpreter.min.js:173)
    at g_os_condvar_ready_set (Interpreter.min.js:173)
    at a.console_readable (Interpreter.min.js:73)
feeley commented 3 years ago

Refresh your browser cache. I fixed the problem this morning.

lassik commented 3 years ago

Unfortunately the Gambit manual does not contain the documentation for the standard procedures of R7RS like car, +, etc. So either the R7RS document could be integrated to the Gambit manual, or the r7rs.html document could be opened.

I continue to implore that you should split the Texinfo manual into one file per chapter, and we should improve it instead of the wiki :)

lassik commented 3 years ago

Refresh your browser cache. I fixed the problem this morning.

Some files are still missing on the server:

$ curl https://gambitscheme.org/try/lib/srfi/_setup_.scm
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.19.6</center>
</body>
</html>
lassik commented 3 years ago

Should the .scm/.sld files from the lib directory be copied onto the server? It would seem that they should.

lassik commented 3 years ago

As you can see I have removed the Gambit banner so that the REPL takes less space on the page. Moreover, I think it is more "politically acceptable" to not advertise up-front the specific implementation of Scheme that is being used.

On the contrary, I think it's fine to say which implementation is being used. Scheme implementations are to some degree incompatible anyway, and have different user interfaces (e.g. debugger commands) and other features. So it knowing the implementation helps users, and gives deserved credit to the implementor.

What I think is essential (over the long term, not immediately) is to allow other implementations to host REPLs as well. But it's reasonable to have a good default, and to have each implementation do the work to add its own REPL.

feeley commented 3 years ago

I think removing the banner of the Scheme implementation gives:

But don't worry... I have put the banner in the output generated by ,help !

A new version is now available that redirects the current input/output port to the console (by default Gambit JS uses the JS console for the current output port which will be unexpected for newcomers).

curl https://gambitscheme.org/try/lib/srfi/_setup_.scm

I'm not sure what you expect... that file does not exist in the Gambit distribution. As a quick hack I simply copied everything from Gambit's installed ~~lib to http://gambitscheme.org/try/lib so if you want other files you need to copy them manually.

lassik commented 3 years ago

Hiding the banner and putting it in the help is a good compromise. And if try.scheme.org eventually has a drop-down menu for switching implementations, the name of the current implementation will naturally show as the selected item in the dropdown; maybe that's good enough.

We could change the background color of the REPL as a subtle hint to make it easier to notice which implementation is selected. It would be fun if each implementation has a kind of theme color. For example, Gauche's homepage is brown. Gambit has yellow logo. Kawa's website uses light blue and beige. Obviously, for bright colors we can use a light, unobtrusive shade of that color as the background.

If implementation documentation is ever aggregated at the scheme.org doc browser, we could use the background colors there as well, so it would be easier to notice which implementation's documentation one is reading.

lassik commented 3 years ago

I'm not sure what you expect... that file does not exist in the Gambit distribution.

Typing (import (srfi 28)) into the gambitscheme.org/try console causes the following errors to show up in the browser's JS console:

Interpreter.min.js:150 HEAD http://gambitscheme.org/try/lib/_define-library/%40 404 (Not Found)
Interpreter.min.js:150 GET http://gambitscheme.org/try/lib/_define-library/define-library-expand/define-library-expand.sld 404 (Not Found)
Interpreter.min.js:150 GET http://gambitscheme.org/try/lib/_define-library/define-library-expand/define-library-expand.scm 404 (Not Found)
Interpreter.min.js:150 GET http://gambitscheme.org/try/lib/_define-library/define-library-expand/define-library-expand.six 404 (Not Found)
Interpreter.min.js:150 GET http://gambitscheme.org/try/lib/_define-library/define-library-expand.sld 404 (Not Found)
Interpreter.min.js:150 GET http://gambitscheme.org/try/_setup_.scm 404 (Not Found)
Interpreter.min.js:150 GET http://gambitscheme.org/try/_setup_.scm 404 (Not Found)
Interpreter.min.js:150 HEAD http://gambitscheme.org/try/lib/srfi/%40 404 (Not Found)
Interpreter.min.js:150 GET http://gambitscheme.org/try/lib/srfi/28/_setup_.scm 404 (Not Found)
Interpreter.min.js:150 GET http://gambitscheme.org/try/lib/srfi/_setup_.scm 404 (Not Found)
Interpreter.min.js:150 GET http://gambitscheme.org/try/lib/_setup_.scm 404 (Not Found)
Interpreter.min.js:150 HEAD http://gambitscheme.org/try/lib/srfi/%40 404 (Not Found)
feeley commented 3 years ago

Those errors are caused by the library search algorithm that pokes around the "filesystem" to find the library. The amount of poking around could be reduced by putting the files in the first location that is searched, and to put empty files for the _setup_.scm files.

In the case of (import (srfi 28)) it is necessary to first load the (_define-library define-library-expand) library (this library contains the implementation of the import form) before loading the (srfi 28) library. It was implemented this way mostly as a proof of concept that even parts of the library system could be put in dynamically loaded libraries. An alternative would be to link the (_define-library define-library-expand) library into the preloaded runtime library. All of this is (important but not yet finalized) engineering.

feeley commented 3 years ago

I'm not convinced about using colours to distinguish the implementations of Scheme... some people are colour-blind and with 50+ implementations of Scheme many colours will look alike...