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]

docstrings in Guile!


I'm happy to report that I had a productive weekend hacking Guile.  To
give you an idea where we're at now:

% ./guile
guile> (documentation 'library-dir)
(library-dir)
Return the directory where the Guile Scheme library files are installed.
E.g., may return "/usr/share/guile/1.3.5".
[load.c:207]
#t

Lots of things are not in a mature form yet, but the basics are there.  

I ended up doing a massive software engineering restructuring -- about
30,000 lines of diffs that I'm still reviewing to check for mistaken
changes (i.e., bugs that I introduced in the process).  I know I found 
a bunch of bugs, and some questionable issues.  Many are now marked with 
GJB:FIXME:: (following Scwm's FIXME conventions).  

As an extra bonus, I replaced (nearly?) all K&R prototypes for functions
with ANSI C equivalents.  I also replaced constructs like

f? SCM_BOOL_T : SCM_BOOL_F

with

SCM_BOOL(f)

(and similarly w/ SCM_NEGATE_BOOL for f? SCM_BOOL_F : SCM_BOOL_T)

As an example of how I've improved the primitives and added docstrings,
consider `substring-move!' from strop.c:

SCM_PROC(s_substring_move_x, "substring-move!", 5, 0, 0, scm_substring_move_x);

SCM
scm_substring_move_x (SCM str1, SCM start1, SCM end1, 
                      SCM str2, SCM start2)    
{
  long s1, s2, e, len;

  SCM_ASSERT (SCM_NIMP (str1) && SCM_STRINGP (str1), str1, 
              SCM_ARG1, s_substring_move_x);
  SCM_ASSERT (SCM_INUMP (start1), start1, SCM_ARG2, s_substring_move_x);
  SCM_ASSERT (SCM_INUMP (end1), end1, SCM_ARG3, s_substring_move_x);
  SCM_ASSERT (SCM_NIMP (str2) && SCM_STRINGP (str2), str2, 
              SCM_ARG4, s_substring_move_x);
  SCM_ASSERT (SCM_INUMP (start2), start2, SCM_ARG5, s_substring_move_x);

  s1 = SCM_INUM (start1), s2 = SCM_INUM (start2), e = SCM_INUM (end1);
  len = e - s1;
  SCM_ASSERT (len >= 0, end1, SCM_OUTOFRANGE, s_substring_move_x);
  SCM_ASSERT (s1 <= SCM_LENGTH (str1) && s1 >= 0, start1, 
              SCM_OUTOFRANGE, s_substring_move_x);
  SCM_ASSERT (s2 <= SCM_LENGTH (str2) && s2 >= 0, start2, 
              SCM_OUTOFRANGE, s_substring_move_x);
  SCM_ASSERT (e <= SCM_LENGTH (str1) && e >= 0, end1, 
              SCM_OUTOFRANGE, s_substring_move_x);
  SCM_ASSERT (len+s2 <= SCM_LENGTH (str2), start2, 
              SCM_OUTOFRANGE, s_substring_move_x);

  SCM_SYSCALL(memmove((void *)(&(SCM_CHARS(str2)[s2])),
                      (void *)(&(SCM_CHARS(str1)[s1])),
                      len));
  
  return scm_return_first(SCM_UNSPECIFIED, str1, str2);
}


It now looks like this:

GUILE_PROC(scm_substring_move_x, "substring-move!", 5, 0, 0, 
           (SCM str1, SCM start1, SCM end1, SCM str2, SCM start2),
"Copy the substring of @var{str1} bounded by @var{start1} and @var{end1}
into @var{str2} beginning at position @var{end2}.
@code{substring-move-right!} begins copying from the rightmost character
and moves left, and @code{substring-move-left!} copies from the leftmost
character moving right.

It is useful to have two functions that copy in different directions so
that substrings can be copied back and forth within a single string.  If
you wish to copy text from the left-hand side of a string to the
right-hand side of the same string, and the source and destination
overlap, you must be careful to copy the rightmost characters of the
text first, to avoid clobbering your data.  Hence, when @var{str1} and
@var{str2} are the same string, you should use
@code{substring-move-right!} when moving text from left to right, and
@code{substring-move-left!}  otherwise.  If @code{str1} and @samp{str2}
are different strings, it does not matter which function you use.")
#define FUNC_NAME s_scm_substring_move_x
{
  long s1, s2, e, len;

  SCM_VALIDATE_STRING(1,str1);
  SCM_VALIDATE_INT_COPY(2,start1,s1);
  SCM_VALIDATE_INT_COPY(3,end1,e);
  SCM_VALIDATE_STRING(4,str2);
  SCM_VALIDATE_INT_COPY(5,start2,s2);
  len = e - s1;
  SCM_ASSERT_RANGE (3,end1,len >= 0);
  SCM_ASSERT_RANGE (2,start1,s1 <= SCM_LENGTH (str1) && s1 >= 0);
  SCM_ASSERT_RANGE (5,start2,s2 <= SCM_LENGTH (str2) && s2 >= 0);
  SCM_ASSERT_RANGE (3,end1,e <= SCM_LENGTH (str1) && e >= 0);
  SCM_ASSERT_RANGE (5,start2,len+s2 <= SCM_LENGTH (str2));

  SCM_SYSCALL(memmove((void *)(&(SCM_CHARS(str2)[s2])),
		      (void *)(&(SCM_CHARS(str1)[s1])),
		      len));
  
  return scm_return_first(SCM_UNSPECIFIED, str1, str2);
}
#undef FUNC_NAME


I've moved all the documentation for primitives from
guile-doc/ref/{appendices,posix,scheme}.texi into the source code.  This
leaves about half of the primitives undocumented.  Also, all the markup
is currently still texinfo.  I don't have a problem with texinfo per se,
but the markup is not very descriptive or accurate.

guile-doc-snarf is the new way to create foo.x and foo.doc from foo.c;
the foo.doc's are then all catted together (they should probably be
sorted, etc.) by Makefile.am and stuck in guile-procedures.txt which
should get installed in pkgdatadir where the (ice-9 doc) module (ripped
off from Scwm) looks for it.  Obviously we need to do better w/
integrating with `procedure-documentation'.

Also, I don't do anything yet w/ generating a manual; I've been focusing
on extracting the docstrings and exposing them to the interpreter.  Not
all of the software-artifacts are yet checked -- e.g., the FUNC_NAME
dependence and the argument validation macro matching the formal
parameter name are not done yet.  

I'm sure there will be build problems, etc.  Please report them here,
but *first* tell me how great this is! :-) I've literally spent 20 hours
in the last two days trying to make Guile ready for the 21st century! :-)

Enjoy!

Greg

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