shirok / Gauche

Scheme Scripting Engine
https://practical-scheme.net/gauche
Other
823 stars 82 forks source link

How to call script main in R7RS mode? #563

Open lassik opened 4 years ago

lassik commented 4 years ago

With the script: (define (main args) (display "Hello\n") 0)

This runs the main procedure: gosh test.scm

How do you make this work with R7RS imports? If you add (import (scheme base)) or (import (gauche base)) at the start of the script, gosh test.scm no longer runs main. gosh -r 7 test.scm does not run main either. Adding -m or -m r7rs.user doesn't help.

lassik commented 4 years ago

Wait, this works :)

(import (scheme base) (scheme write))
(define (main args) (display "Hello\n") 0)

And then gosh -r 7 -m r7rs.user test.scm

However, should -m r7rs.user be the default in -r 7 mode?

shirok commented 4 years ago

It is intentional.

Calling main is SRFI-22, which unfortunately wasn't adopted to R7RS. "R7RS programs" don't have concept of main---just toplevel expressions are evaluated sequentially (R7RS 5.1). So portable R7RS progarms don't expect main to be called automatically, and doing so will break the program.

Personally I prefer SRFI-22 way; it allows me to load the script into REPL without actually executing the script.

One option is that if a R7RS script says (import (srfi 22)) we'd run r7rs.user#main. It's still Gauche specific (importing (srfi 22) won't actually import any bindings; but the loaded library can do some special wiring to make main run.)

pclouds commented 4 years ago

Calling main is SRFI-22, which unfortunately wasn't adopted to R7RS

Is srfi-22 in r7rs-large agenda? Probably best handled there, I think.

lassik commented 4 years ago

"R7RS programs" don't have concept of main---just toplevel expressions are evaluated sequentially (R7RS 5.1).

That section is quite vague, probably intentionally since R7RS has to work in many kinds of environments.

So portable R7RS progarms don't expect main to be called automatically, and doing so will break the program.

Most of those programs don't define main. But you're right that it is possible to write a script that defines main and calls it manually. If main was also called automatically, it would be called twice.

Personally I prefer SRFI-22 way; it allows me to load the script into REPL without actually executing the script.

I agree.

Is srfi-22 in r7rs-large agenda? Probably best handled there, I think.

Good question. @johnwcowan should know.

IMHO the SRFI 22 requirement that main returns an integer is archaic. Returning integers to represent errors is idiomatic in C. It's easy to forget to do it in Scheme and it would be clearer to use (raise ...) or (exit #t/#f/<n>) to signal an error. If main does not call exit or raise an exception, Scheme would then simply ignore the return value of main and do a successful exit.

pclouds commented 4 years ago

IMHO the SRFI 22 requirement that main returns an integer is archaic. Returning integers to represent errors is idiomatic in C.

This may be related to the POSIX SRFI actually (and exit should be provided in the posix srfi but I didn't check). Other OSes may not require this (but then I can't remember what Windows programs are supposed to do here). Java's main function does not let you return an exit code either.

lassik commented 4 years ago

R7RS-small has a nicely specified exit procedure. The SRFI 170 (POSIX) will have some language specifying exit in more detail while remaining compatible with R7RS. (I can't remember whether that part of the SRFI is written already.)

Plan 9 has "exit strings" - the process exit code is a string instead of an integer, a blank string indicates success. Probably all other OSes use integers, including Windows.

I suspect SRFI 22 uses an integer because it was published a few years before R6RS. R5RS did not have standardized exception handling. I guess SRFI 22 could still have relied on exit though.

johnwcowan commented 4 years ago

On Mon, Jan 6, 2020 at 8:56 AM Lassi Kortela notifications@github.com wrote:

R7RS-small has a nicely specified exit procedure.

So nicely in fact (toot, toot!) that I see no need to add exit to SRFI 170 at all. It says that (exit #f) returns failure to the calling environment, (exit #t) returns the simplest form of success, any object that matches the calling environment's idea of an exit code (strings on Plan 9, small integers on Posix and Windows, as Lassi says) is returned directly, and all other objects have implementation-dependent interpretations. There is also emergency-exit, which corresponds to Posix and Windows _exit(), and does not flush buffers or unwind the dynamic environment.

Note that the meaning of integers is not standardized: Posix guarantees that (exit 0) returns success and specifies some literal constants for various types of failure which actual Posix programs may or may not use, but that's all. On VMS, 0 is "undefined error" and success is 2.

John Cowan http://vrici.lojban.org/~cowan cowan@ccil.org "Make a case, man; you're full of naked assertions, just like Nietzsche." "Oh, i suffer from that, too. But you know, naked assertions or GTFO." --heard on #scheme, sorta

pclouds commented 4 years ago

@johnwcowan what about srfi-22 and r7rs? Specifically the main function to be called automatically when an r7rs file is run as a script.

johnwcowan commented 4 years ago

Oh yes. I don't intend to propose SRFI-22 for R7RS-large standardization, but others can if they want and I'll add it to the ballot if there's enough interest.

On Mon, Jan 6, 2020 at 6:54 PM Duy Nguyen notifications@github.com wrote:

@johnwcowan https://github.com/johnwcowan what about srfi-22 and r7rs? Specifically the main function to be called automatically when an r7rs file is run as a script.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/shirok/Gauche/issues/563?email_source=notifications&email_token=AANPPBQZNKCVOGX5EFL36MDQ4PAEHA5CNFSM4KC3Z3XKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIHF7QA#issuecomment-571367360, or unsubscribe https://github.com/notifications/unsubscribe-auth/AANPPBXVSEUPUU5THQUWLE3Q4PAEHANCNFSM4KC3Z3XA .

pclouds commented 4 years ago

Um.. I read srfi-22 again. It requires the shebang line which is not here (at least in Lassik's original report). I think without that line, it's gauche behavior and up to Shiro to decide. But anyway, there's this piece in ChangeLog

2017-06-11  Shiro Kawai  <shiro@acm.org>

        * src/main.c: If the interpreter basename is "scheme-r7rs", we assume
          the script is in R7RS and invoked under SRFI-22 convention, and calls
          r7rs.user#main.

and if I add #!/usr/bin/env scheme-r7rs line then the script runs as expected (directly from shell, not running "gosh script.scm"). So in a way srfi-22+r7rs is actually supported by gauche (whether that's the official interpretation of the srfi is a different story)

The only thing that may be lacking is gauche does not provide this scheme-r7rs symlink by default. Which is understandable, if you install multiple scheme implementations then it's probably distro's job to create that link (to the chosen impl)

lassik commented 4 years ago

I see no need to add exit to SRFI 170 at all.

It's probably useful to at least raise an error if given a value outside 0..255 on Posix. Thread: https://srfi-email.schemers.org/srfi-170/msg/11950151/

    * src/main.c: If the interpreter basename is "scheme-r7rs", we assume
      the script is in R7RS and invoked under SRFI-22 convention, and calls
      r7rs.user#main.

and if I add #!/usr/bin/env scheme-r7rs line then the script runs as expected (directly from shell, not running "gosh script.scm"). So in a way srfi-22+r7rs is actually supported by gauche (whether that's the official interpretation of the srfi is a different story)

Ah, there it is. Thank for finding that :) As far as I can tell, Gauche's behavior here is exactly in line with SRFI 22.

The only thing that may be lacking is gauche does not provide this scheme-r7rs symlink by default. Which is understandable, if you install multiple scheme implementations then it's probably distro's job to create that link (to the chosen impl)

That's right. Those executable names are not that useful since people tend to install multiple Schemes. They could be symlinks to a launcher program that can switch between implementations. But at present, non-trivial Scheme programs are also very picky about which implementation(s) they run on, so it would be better if it's something more sophisticated. I have an idea for a scheme-script executable that would be portable but I'm not sure if anyone would like it.

Um.. I read srfi-22 again. It requires the shebang line

Nope, it's optional (note the question mark in the grammar):

Script Syntax

Githubissues.
  • Githubissues is a development platform for aggregating issues.