unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
From: prj@po.cwru.edu (Paul Jarc)
Subject: Scheme-defined smobs
Date: Mon, 03 Nov 2003 12:39:38 -0500	[thread overview]
Message-ID: <m38ymx9wr3.fsf@multivac.cwru.edu> (raw)

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1027 bytes --]

It seems pointless at first, but I think it might be useful.  The
attached file (tested as an extension with 1.6.4) provides Scheme
bindings for defining smobs - i.e., the "print" and "equalp" functions
can be defined in Scheme.  This might be useful for adding
user-defined cases to equal?.  But I admit my real motivation for
writing this was to enable this gruesome hack:

guile> (define (printer smob-data port state) (system smob-data))
guile> (define generator (make-smob-type "smob-name" printer #f))
guile> (define ls (generator "ls"))
guile> (ls)
"ls"
guile> (ls "ls -a")
guile> (ls)
"ls -a"
guile> ls

... which shows me the output of "ls -a".  So I can use Guile as a
shell with a bit less typing.

Is there interest in adding this to libguile?  (Regardless, I think
the three snarfing macros at the top (along with corresponding
SCM_SMOB_FREE, SCM_SMOB_PRINT, and SCM_SMOB_EQUALP) would be useful
additions to smob.h, though perhaps the name SCM_ SMOB_APPLY is too
similar to the existing SCM_SMOB_APPLY_*.)


paul

[-- Attachment #2: dynsmob.c --]
[-- Type: TEXT/PLAIN, Size: 3096 bytes --]

#include <libguile.h>

#define SCM_SMOB(c_name, scheme_name, size) \
  SCM_SNARF_HERE(static scm_t_bits scm_##c_name##_tag) \
  SCM_SNARF_INIT(scm_##c_name##_tag=scm_make_smob_type((scheme_name), size);)
#define SCM_SMOB_MARK(c_name, arg) \
  SCM_SNARF_HERE(static SCM scm_##c_name##_mark(SCM arg)) \
  SCM_SNARF_INIT(scm_set_smob_mark(scm_##c_name##_tag, scm_##c_name##_mark);)
#define SCM_SMOB_APPLY(c_name, args, req, opt, rest) \
  SCM_SNARF_HERE(static SCM scm_##c_name##_apply args) \
  SCM_SNARF_INIT(scm_set_smob_apply(scm_##c_name##_tag, scm_##c_name##_apply, \
                                    req, opt, rest);)

/* define one static smob, to be used as a generator */

SCM_SMOB(dynsmob_static, "dynsmob", 0);

SCM_SMOB_MARK(dynsmob_static, s_smob)
{
  scm_gc_mark(SCM_CELL_OBJECT_2(s_smob));
  return SCM_CELL_OBJECT_3(s_smob);
}

SCM_SMOB_APPLY(dynsmob_static, (SCM s_smob, SCM s_data), 1, 0, 0)
{
  SCM_RETURN_NEWSMOB2(SCM_CELL_WORD_1(s_smob), s_smob, SCM_UNPACK(s_data));
}

/* these are for Scheme-defined smobs */

static SCM mark_dynsmob(SCM s_smob) {
  SCM const s_type=SCM_CELL_OBJECT_1(s_smob);
  SCM const s_data=SCM_CELL_OBJECT_2(s_smob);
  scm_gc_mark(s_type);
  return s_data;
}

static int print_dynsmob(SCM s_smob, SCM s_port, scm_print_state* pstate) {
  SCM const s_type   =SCM_CELL_OBJECT_1(s_smob);
  SCM const s_printer=SCM_CELL_OBJECT_2(s_type);
  SCM const s_data   =SCM_CELL_OBJECT_2(s_smob);
  (void)pstate; /* silence "unused parameter" warning */
  scm_call_3(s_printer, s_data, s_port, SCM_UNSPECIFIED/*pstate*/);
  return 1;
}

static SCM equalp_dynsmob(SCM s_smob1, SCM s_smob2) {
  SCM const s_type  =SCM_CELL_OBJECT_1(s_smob1);
  SCM const s_equalp=SCM_CELL_OBJECT_3(s_type);
  SCM const s_data1 =SCM_CELL_OBJECT_2(s_smob1);
  SCM const s_data2 =SCM_CELL_OBJECT_2(s_smob2);
  return scm_call_2(s_equalp, s_data1, s_data2);
}

static SCM apply_dynsmob(SCM s_smob, SCM s_newdata) {
  if (SCM_UNBNDP(s_newdata)) {
    SCM const s_data=SCM_CELL_OBJECT_2(s_smob);
    return s_data;
  }
  SCM_SET_CELL_OBJECT_2(s_smob, s_newdata);
  return SCM_UNSPECIFIED;
}

#define FUNC_NAME s_scm_dynsmob_make_smob_type
SCM_DEFINE(scm_dynsmob_make_smob_type, "make-smob-type", 3, 0, 0,
           (SCM s_name, SCM s_printer, SCM s_equalp),
           "Define a new smob type and return a generator for it.")
{
  scm_t_bits tag;
  SCM_VALIDATE_STRING(SCM_ARG1, s_name);
  if (!SCM_FALSEP(s_printer)) SCM_VALIDATE_PROC(SCM_ARG2, s_printer);
  if (!SCM_FALSEP(s_equalp )) SCM_VALIDATE_PROC(SCM_ARG3, s_equalp);
  SCM_STRING_COERCE_0TERMINATION_X(s_name);
  tag=scm_make_smob_type(SCM_STRING_CHARS(s_name), 0);
  scm_set_smob_mark(tag, mark_dynsmob);
  if (!SCM_FALSEP(s_printer)) scm_set_smob_print (tag, print_dynsmob);
  if (!SCM_FALSEP(s_equalp )) scm_set_smob_equalp(tag, equalp_dynsmob);
  scm_set_smob_apply(tag, apply_dynsmob, 0, 1, 0);
  SCM_RETURN_NEWSMOB3(scm_dynsmob_static_tag, tag, SCM_UNPACK(s_printer),
                      SCM_UNPACK(s_equalp));
}
#undef FUNC_NAME

void dynsmob__load__init(void) {
#ifndef SCM_MAGIC_SNARFER
#include "dynsmob.x"
#endif
}

[-- Attachment #3: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Guile-devel mailing list
Guile-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/guile-devel

             reply	other threads:[~2003-11-03 17:39 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-11-03 17:39 Paul Jarc [this message]
2003-11-03 23:58 ` Scheme-defined smobs Rob Browning
2003-11-04  0:16   ` Paul Jarc
2003-11-05 17:13 ` Marius Vollmer
2003-11-06 16:25   ` Paul Jarc
2003-11-13 19:24     ` Marius Vollmer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/guile/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m38ymx9wr3.fsf@multivac.cwru.edu \
    --to=prj@po.cwru.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).