Gambit hits a mark

(see, the X-Men Gambit has perfect aim and a stupid accent, which still makes him more interesting than Hawkeye; and of course I’m Mark and so is Marc)

With much appreciated help from Marc Feeley, got maintest running.

A couple of lessons: I very much think include paths should include the path of the main source doing the including. Chibi’s default is correct, Gambit’s default is wrong and requires fixing in every user program. It’s “more secure”, but if you’re running source code from a directory, you can probably trust whatever else is in that dir.

main was frustrating: Gambit manual 2.6 (highlighting mine)

After the script is loaded the procedure main is called with the command line arguments. The way this is done depends on the language specifying token. For scheme-r4rs, scheme-r5rs, scheme-ieee-1178-1990, and scheme-srfi-0, the main procedure is called with the equivalent of (main (cdr (command-line))) and main is expected to return a process exit status code in the range 0 to 255. This conforms to the “Running Scheme Scripts on Unix SRFI” (SRFI 22). For gsi-script and six-script the main procedure is called with the equivalent of (apply main (cdr (command-line))) and the process exit status code is 0 (main’s result is ignored). The Gambit system has a predefined main procedure which accepts any number of arguments and returns 0, so it is perfectly valid for a script to not define main and to do all its processing with top-level expressions (examples are given in the next section).

So your code that looks fine with 1 arg will break with 2, depending on the version. (main . argv) works. I’m in the process of making sure every one of my maintests parses args consistently, and every Scheme disagrees.

Gambit’s compiler worked very simply once I got the library on the command line; it doesn’t seek out & include them the way Chez does, even though it takes what looks like a search path.

The upside of all this is at least now there’s one maintained, fast, R7-compatible Scheme compiler. I’m sticking with Chez (R6) for my code, but it’s nice having something 100x faster (gut feeling, not benchmarked) than Chibi to test R7 code on.

2 thoughts on “Gambit hits a mark”

  1. To be clear, let me explain the bad behaviour I had in mind when I said (in your previous blog post) that . should not be in the module search path by default. The CWD is generally not the same as the directory containing the script being executed. In fact when a script is installed in a central location like /usr/local/bin the CWD when executing the script will surely not be the same. In the following example Chibi is loading the wrong (device) library:

    $ cat main.scm
    (import (scheme base) (scheme write) (device))
    (display "running main.scm\n")
    (init)
    $ cat device.sld
    (define-library (device)
    (import (scheme base) (scheme write))
    (export init)
    (begin (define (init) (display "device initialized\n"))))
    $ chibi-scheme main.scm
    running main.scm
    device initialized
    $ cd foobar
    $ cat device.sld
    (define-library (device)
    (import (scheme base) (scheme write))
    (export init)
    (begin (define (init) (display "3 2 1 ***BOOM***\n"))))
    $ chibi-scheme ../main.scm
    running main.scm
    3 2 1 ***BOOM***

    For the record Gambit does support (include path) and the path is relative to the current source file containing the include. But modules are a very different thing because they are accessed during two phases: expansion/compile time (when a module is parsed to know what it exports) and run time (when the code is loaded to execute it). It is important that the two searches find the same module otherwise program execution will be unreliable (as the above example shows). In particular the system must allow compiling programs with the module’s source code laid out in a way that is convenient for development, and executing programs with the modules laid out in the filesystem in a way that is convenient for the end user environment. The source code location at compile time is not very useful for execution time.

    1. For a compiled program, I expect the module to be compiled into the binary; there’s dylib cases where that’s not true, and that’s always a nightmare to deploy. gsc works correctly there, I can invoke main from anywhere now.

      . isn’t quite the right thing, but I would mostly expect a script to be run in its working directory, it’ll likely have support files there anyway. An imports-relative-to-main default would be ideal for both security and convenience.

Comments are closed.