This is the mail archive of the guile@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]

Transition from guile-ii to 1.2


I've been using guile-ii for some time now and I am finally looking at
making the transition to 1.2.  I've been lurking in this group for some
time now simply because most of the issues never pertained to me... now
they do :-)

I have a number of issues and questions regarding my transition:

1) when an error occured during a "load" guile-ii would give the line
number at which the error was detected.  For example with the following
file:

   > (let ((x 3))
   >     (foopy)
   > )   
   
   guile-ii gave:
   
   > guile> (load "/tmp/y.scm")
   > "/tmp/y.scm", line 3: ERROR: unbound variable:  foopy
   > ; in expression: (... foopy)
   > ; in scope:
   > ;   x
   
   Guile 1.2 does this:
   
   > guile> (load "/tmp/y.scm")y.scm")
   > ERROR: Unbound variable: foopy
   > ABORT: (misc-error)

2) To do a sort, I used something like:

    > (require 'sort)
    > (sort! '("hello" "there" "testing" "one") string<?)

   This no longer works and I cannot find *any* sort function in the
guile-1.2 distribution.  Is there some other place I should be going for
"extras" like this?

3) I am using guile as an embedded language for a C++ program that has
its own notion of "commands".  I have a central dispatch routine for all
entry from scheme into my commands.  The previous engineer had done a
*lot* of tweaking of guile-ii to make this work.

My take on this, for each internal command, create a closure in which I
reference the one dispatch routine and pass as data the pointer to the
C++ command object.  Here's my code:

    > #define DISPATCH_CCLO_CMD(cclo) (SCM_VELTS(cclo)[1])
    > 
    > static SCM
    > dispatch(SCM args)
    > {
    >     SCM cclo = SCM_CAR(args);
    >     args = SCM_CDR(args);
    > 
    >     Cmd *cmd = (Cmd *)(SCM_INUM(DISPATCH_CCLO_CMD(cclo)) << 2);
    > 
    >     // convert args into internal format
    > 
    >     cmd->exec(...)
    > }
    > 
    > // can this be local to RegisterCommand and not mess up GC?
    > static SCM dispatch_proc = SCM_UNDEFINED;
    > 
    > void RegisterCommand( Cmd *cmd )
    > {
    >     if (dispatch_proc == SCM_UNDEFINED) {
    >         // This seems to have the desired effect of creating the
    >         // "$my-dispatch" procedure object without making the name
    >         // visible to the user so he/she cannot directly access
    >         // this internal procedure.
    > 
    >   dispatch_proc = scm_make_subr_opt( "$my-dispatch",
scm_tc7_lsubr,
    >                                     (SCM (*)())dispatch, 0 );
    > 
    >     }
    > 
    >     SCM cclo = scm_makcclo( dispatch_proc, 2 );
    > 
    >     // stuff my command pointer into an integer so that guile
garbage
    >     // collection doesn't try to do anything with it.  takes
advantage
    >     // of fact that Cmd's will always be aligned on word boundary
or
    >     // bigger (need to shift right 2 since MAKINUM shifts left 2)
    >     DISPATCH_CCLO_CMD(cclo) = SCM_MAKINUM(((long)cmd) >> 2);
    > 
    >     // register the closure with global symbol table
    >     // ugh, const cast
    >     scm_sysintern( (char *)cmd->getName(), cclo );
    > }

So, my questions are...

	a) Does anybody see any problems that might come up with this
particularly with garbage collection?  In the past, we had some really
nasty problems debugging problems with garbage collection so I'm a
little gun shy.

	b) I'd like to ensure that users cannot directly run ($my-dispatch)
since it is an internal routine and will likely cause nastiness if
directly invoked.  The code above seems to do the trick (by using
"scm_make_subr_opt") but I felt a little nervous about using this
routine not really knowing its real purpose.

	c) Is there a "better" way to save the pointer to the Cmd object.  I
don't really like doing casts of pointers to ints and back (it seems
sort of a hack).  I simply want to save the pointer but *not* have the
garbage collector mess with it.  I tried just storing the pointer
directly in the SCM, but, of course, that caused problems.

	d) Every once in a while I run into problems with "const-correctness"
of the library.  Routines that conceptually should use "const char *"
declared as "char *" ("scm_sysintern", above, is an example).  Is there
any fundamental reason going through the library and making these const
won't work?

4) I have some C++ code which writes to a scheme port.  I used to use
"gscm_fwrite" which would return the number of chars written.  The only
public routine I can find to do the same thing is "scm_gen_write" which
does not return the char count.  Is there some other routine I should
use?

5) When in interactive mode, "(let ((x 3)) (write foopy))" gives:

    > ERROR: While evaluating arguments to write in expression (write
foopy):
    > ERROR: Unbound variable: foopy
    > ABORT: (misc-error)

    in non-interactive mode I just get:

    > guile: Unbound variable: foopy

    Obviously the interactive version of the message is much more
useful.  Is there a way to get the whole message regardless of mode?

6) How do I expand a procedure?  In guile-ii I could just type the
procedure name and it would give a (somewhat) readable representation of
the procedure.  In guile-1.2, I just get "#<procedure blah args>".

7) As an example, the procedure "debug-enable" doesn't actually show up
in the main symbol table.  However, it is defined.  Is this an example
of the new module system?  Can someone point me to some docs on how the
module system works? 

---

A bunch of other things I've noted.  Most of these you all probably know
but I'll state them in case I'm doing something wrong.

1) "#f" used to mean empty list (in addition to "()").  As such:
	a. (cons 1 #f) used to return a proper list; now it returns
	   a dotted pair.  The fix is to use "()" instead.
	b. (null? #f) used to return #t; now it returns #f.  In some
	   cases (badly written) code was using "null?" instead of "not".
	   The fix is to use "not"

2) "defined?" used to be a macro so that (defined? goober) was legit.
	Now, one must use (defined? 'goober)

3) "print" routine is gone... have to use (write obj) and (newline)
instead

Well, that's all for now...  I have some other comments about things
like "readline" support and giving a prompt which shows how deeply
indented one is (two things we did in our guile-ii support), but I'll
send that under separate cover.

Thanks,
Rob

-- 
------------------------------------------------------------------------
Rob Engle                                      grenoble@spimageworks.com
Sony Pictures Imageworks                             voice: 310-840-8203
9050 West Washington Boulevard                         fax: 310-840-8567
Culver City, CA  90232
------------------------------------------------------------------------