This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Translators again (Re: Python transformer for Guile?)


Lalo Martins writes:

   On Sat, Jan 22, 2000 at 02:24:32PM +0000, Neil Jerram wrote:
   > Lalo Martins writes:
   > 
   > 1. The result of "translation" is a stream of Scheme expressions (as
   > though returned by "read") that are to be evaluated in a specified
   > environment.

   I believe the original design was to munch the whole thing and
   return the corresponding guile-scheme code.

I don't see how this contradicts "a stream of Scheme expressions".
For some languages, it may certainly be the case that the translator
has to slurp the whole source file before it can return even the first
expression.  It may also be the case that the "stream" is actually a
single (begin ...) expression.  What precisely do you mean by "return
the corresponding guile-scheme code"?

(Afterthought...) Perhaps you are suggesting that there are languages
for which it would be impossible to separate the read from the eval?

   >    1: how are translated scripts executed?
   > 
   > Normally they are translated and evaluated at the same time, by
   > "load".

   Is this a good idea? I think ``load'' should be left pure-r*rs.
   Anything else would probably piss off a lot of scheme-heads :-)

   One good way to still use ``load'' is using generics - if it
   has an extra argument (for language, with some special flag for
   autodetection) then it's the translation-powered version,
   otherwise it's the r*rs scheme-only traditional one.

Good point.  My "load" should probably be called something else.

   >       Is the ``client'' application responsible to finding out the
   >       language, or is it Guile (libguile)? [...]
   > 
   > This is a detail, IMO.  We can implement any reasonable combination of
   > -    client specification
   > -    looking at file extensions
   > -    simple source code analysis.

   It's an important detail. Try to design an application that
   supports translation without knowing this detail and you'll
   see. :-)

Sure - sorry, I didn't mean to belittle your point.  I think that it's
a fundamental problem, but one that we can solve acceptably in
practice.

   Still, I think you give the best answer. I'd futher boil it to:

   1: the client chooses the language, but it can choose ``detect''

   2: the detector first tries to search for a string in the first
   few lines (bytes?).

   3: if that fails, it looks at the filename suffix (extension).

   4: if even that fails, should it issue an error (exception) or
      return ``scheme''?

Sounds good.  In my proposal, you could implement this sort of
strategy by

 - defaulting to <autodetect-reader> (rather than
   <scm-reader>) if no reader class is specified

 - writing an <autodetect-reader> implementation that performs
   the steps above and then instantiates the appropriate
   <LANG-reader> as a proxy to slurp the source file.

   >    3: and what form should translators ship in. I suggest a module
   >       with a well-defined API (there isn't a lot to it actually,
   >       IIRC it's a ``magic-string'' variable or somesuch and a
   >       ``translate'' procedure).
   > 
   > Well in my suggestion it's a module containing a reader class
   > implementation for the target language.  The module can of course be
   > partly written in C.

   I'm all for OOP. But isn't it overkill for this task? As I
   said, all we need is a procedure, a string to search for, and
   now a filename suffix (or a list of suffixes).

   Using OOP could give us the benefit of abstracting the check;
   instead of passing a string (both for first-few-bytes (FFB) or
   filename), the translator can provide methods. Still, I'm not
   sure it's an OOP case; there is nearly no need for inheritance,
   nearly no chance for code reuse, and AFAICS no need for
   polymorphism (there isn't really a lot of instance data involved).

I think there are two points here.

(specific) In my proposal, the reader classes don't just detect the
source language, they do the whole translation thing.  A class
provides a very convenient way of encapsulating the various bits of
internal translation and read state that the reader would probably
need while translating its source.  And polymorphism _is_ happening
here, in "(read reader)".

(general) I think it's generally true that most things that cry out
for OOP in lesser languages can be achieved in Scheme using simple
closures.  For example, the reader argument in my proposal could be
replaced by a thunk that, when called, returns the next expression to
evaluate.  In other words, instead of

  (define-class <elisp-reader> (<reader>)
    read-state1
    read-state2
    ...)

  (define-method read ((reader <elisp-reader>))
    ;; Return next expression, using reader slots
    ;; to track and preserve translation state
    )

  (let ((reader (make <elisp-reader> ...)))
    ...
    (read reader)
    ...)

you could equally have

  (define (make-reader ...)
    (let (read-state1
          read-state2
          ...)
      (lambda ()
        ;; Return next expression, using closure vars
        ;; to track and preserve translation state
        )))

  (let ((reader (make-reader ...)))
    ...
    (reader)
    ...)

However, my personal opinion is that, when the code starts getting
complicated, the OOP representation imposes a known structure that
makes things easier to follow.  The GOOPS representation gives me a
framework for several little things that I would otherwise have to
reinvent in R5RS, such as

  - passing init args to the <elisp-reader> using an init keyword

  - separating initialize time processing from read time processing by
    using an initialize method

  - probably other stuff that escapes me right now.

There's not a lot of inheritance going on, but inheritance isn't
the only reason for OOP.

   []s,
                                                  |alo
                                                  +----

Regards,

        Neil

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]