guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

PHP to GUILE


From: Vorfeed Canal
Subject: PHP to GUILE
Date: Mon, 26 Sep 2005 01:50:37 +0400

After latest PHP fiasco (when "maintenance release" PHP 5.0.5 broke
most PHP programs) I decided that "enough is enough - I need to change
language for future projects".

I've checked with few alternatives and found that I like SXML better
then other packages (Perl, Python, etc). Thus GUILE - it's "official"
implementation of Scheme for GNU system, right.

Unfortunatelly while support for XML in scheme (and guile) is
excellent this is not the only thing needed for web-programming. I
found some problems with GUILE core and lack of usefull modules
(perhaps two problems are related?).

Problems with GUILE core:

1. All C extension files can only be put in /usr/lib - there are no
sane way to change libtool's searchpath and there are no sane default.
Very annoying.

2. No way to use standard (for modern languages like C++, PHP or Java)
scheme with throw/catch and EXCEPTIONS HIERARCHY.

Problems with GUILE extesions:

1. Good MySQL binding: both SimpleSQL and Guile-DBI do not give you
access to even basic stuff like mysql_insert_id. Guile-PG looks
promising but is not compatible with Guile 1.7.x (and earlier versions
do not support SMP)...

2. No GD/ImageMagick bindings (or are there ones?).

3. GuileFCGI is not compatible with GUILE 1.6.x or GUILE 1.7.x. There
are mod_lisp (with GUILE module) but it does not support responses
without known length (and it's not always feasible to create answer in
"one go"). What are advantages of mod_lisp over mod_fastcgi ?

While problems with GUILE extensions are not critical (I'll be happy
if someone will show me good MySQL or ImageMagick bindings but I can
write them myself if there will be no other choice) problems with
GUILE core are other story.

About first problem: default extensions load path ONLY includes three
directories: "/lib", "/usr/lib" and "." (in this order). You can
change it from scheme with (setenv "LTDL_LIBRARY_PATH"
"/usr/local/blah") but there are no standard place to put extensions
while normal script languages have one or two (like Perl's site_perl
vs vendor_perl). It can de fixed with simple patch (see below), so
real question is "why the hell it was not done five years ago?" ...

About second problem. GNU Kawa (if we are talking about GNU GUILE it
makes sense to borrow from GNU Kawa, right?) has the following
solution to this problem:

http://per.bothner.com/tmp/kawa/Exceptions.html

primitive-throw exception

    Throws the exception, which must be an instance of a sub-class of
<java.lang.Throwable>.

Syntax: try-finally body handler

    Evaluate body, and return its result. However, before it returns,
evaluate handler. Even if body returns abnormally (by throwing an
exception), handler is evaluated.

    (This is implemented just like Java's try-finally.)

Syntax: try-catch body handler ...

    Evaluate body, in the context of the given handler specifications.
Each handler has the form:

    var type exp ...

    If an exception is thrown in body, the first handler is selected
such that the thrown exception is an instance of the handler's type.
If no handler is selected, the exception is propagated through the
dynamic execution context until a matching handler is found. (If no
matching handler is found, then an error message is printed, and the
computation terminated.)

    Once a handler is selected, the var is bound to the thrown
exception, and the exp in the handler are executed. The result of the
try-catch is the result of body if no exception is thrown, or the
value of the last exp in the selected handler if an exception is
thrown.

    (This is implemented just like Java's try-catch.)

Kawa does not support GOOPS-style overloading so may be it's better to
just remake throw and catch as "primitive with generic", declare
"try-finally" and "try-catch" as aliases to "catch", "primitive-throw"
as alias to "throw" and then make default exceptions catchable via
GOOPS exceptions classes ? This way "normal" catch/throw semantics
will not be affected but when GOOPS is loaded you'll get
sane^H^H^H^Hmodern exceptions handling...

This is part where I do not know how change to core should look in the
end (one thing is clear: exceptions without hierarchy are not very
usefull), but with search path it's obvious: it should be something
like this:

diff -uNr guile-1.7.2.orig/guile-config/guile.m4
guile-1.7.2/guile-config/guile.m4
--- guile-1.7.2.orig/guile-config/guile.m4      2003-04-05
23:01:16.000000000 +0400
+++ guile-1.7.2/guile-config/guile.m4   2005-09-18 23:15:30.000000000 +0400
@@ -110,6 +110,24 @@
   AC_SUBST(GUILE_SITE)
  ])

+# GUILE_SITELIB_DIR -- find path to Guile "site" lirbraries directory
+#
+# Usage: GUILE_SITELIB_DIR
+#
+# This looks for Guile's "site" libraries directory, usually something
+# like PREFIX/lib/guile/site, and sets var @var{GUILE_SITELIB} to the path.
+# Note that the var name is different from the macro name.
+#
+# The variable is marked for substitution, as by @code{AC_SUBST}.
+#
+AC_DEFUN([GUILE_SITELIB_DIR],
+ [AC_REQUIRE([GUILE_PROGS])dnl
+  AC_MSG_CHECKING(for Guile site libraries directory)
+  GUILE_SITE=`[$GUILE_CONFIG] info pkglibdir`/site
+  AC_MSG_RESULT($GUILE_SITEDIR)
+  AC_SUBST(GUILE_SITEDIR)
+ ])
+
 # GUILE_CHECK -- evaluate Guile Scheme code and capture the return value
 #
 # Usage: GUILE_CHECK_RETVAL(var,check)
diff -uNr guile-1.7.2.orig/libguile/dynl.c guile-1.7.2/libguile/dynl.c
--- guile-1.7.2.orig/libguile/dynl.c    2005-03-04 01:12:31.000000000 +0300
+++ guile-1.7.2/libguile/dynl.c 2005-09-18 23:51:56.000000000 +0400
@@ -52,9 +52,37 @@
 #include "libguile/lang.h"
 #include "libguile/validate.h"
 #include "libguile/dynwind.h"
+#include "libguile/srfi-13.h"
+#include "libguile/load.h"
+#include "libguile/libpath.h"

 #include <ltdl.h>

+/* List of names of directories we search for files to load.  */
+static SCM *scm_loc_load_path;
+
+/* Initialize the global variable %load-libpath, given the value of the
+   SCM_SITELIB_DIR and SCM_LIB_DIR preprocessor symbols and the
+   GUILE_LOAD_LIBPATH environment variable.  */
+static void
+scm_init_load_libpath ()
+{
+  char *env;
+  SCM path = SCM_EOL;
+
+#ifdef SCM_LIB_DIR
+  path = scm_list_3 (scm_from_locale_string (SCM_SITELIB_DIR),
+                     scm_from_locale_string (SCM_LIB_DIR),
+                     scm_from_locale_string (SCM_PKGLIB_DIR));
+#endif /* SCM_LIB_DIR */
+
+  env = getenv ("GUILE_LOAD_LIBPATH");
+  if (env)
+    path = scm_parse_path (scm_from_locale_string (env), path);
+
+  *scm_loc_load_path = path;
+}
+
 /*
   From the libtool manual: "Note that libltdl is not threadsafe,
   i.e. a multithreaded application has to use a mutex for libltdl.".
@@ -68,8 +95,16 @@
 static void *
 sysdep_dynl_link (const char *fname, const char *subr)
 {
-  lt_dlhandle handle;
-  handle = lt_dlopenext (fname);
+  lt_dlhandle handle = NULL;
+  SCM scm_search_path = scm_string_join (*scm_loc_load_path,
+                                        scm_from_locale_string (":"),
+                                        SCM_UNDEFINED/*scm_sym_infix*/);
+  char * search_path = scm_to_locale_string (scm_search_path);
+  scm_frame_free (search_path);
+  if (!lt_dlsetsearchpath (search_path))
+    {
+      handle = lt_dlopenext (fname);
+    }
   if (NULL == handle)
     {
       SCM fn;
@@ -314,6 +349,8 @@
   scm_tc16_dynamic_obj = scm_make_smob_type ("dynamic-object", 0);
   scm_set_smob_mark (scm_tc16_dynamic_obj, dynl_obj_mark);
   scm_set_smob_print (scm_tc16_dynamic_obj, dynl_obj_print);
+  scm_loc_load_path = SCM_VARIABLE_LOC (scm_c_define
("%load-libpath", SCM_EOL));
+  scm_init_load_libpath ();
   sysdep_dynl_init ();
 #include "libguile/dynl.x"
 }
diff -uNr guile-1.7.2.orig/libguile/Makefile.am guile-1.7.2/libguile/Makefile.am
--- guile-1.7.2.orig/libguile/Makefile.am       2005-03-08
02:03:23.000000000 +0300
+++ guile-1.7.2/libguile/Makefile.am    2005-09-18 23:23:44.000000000 +0400
@@ -234,6 +234,9 @@
        @echo '#define SCM_PKGDATA_DIR "$(pkgdatadir)"' >> libpath.tmp
        @echo '#define SCM_LIBRARY_DIR
"$(pkgdatadir)/$(GUILE_EFFECTIVE_VERSION)"'>>libpath.tmp
        @echo '#define SCM_SITE_DIR "$(pkgdatadir)/site"' >> libpath.tmp
+       @echo '#define SCM_PKGLIB_DIR "$(pkglibdir)"' >> libpath.tmp
+       @echo '#define SCM_LIB_DIR
"$(pkglibdir)/$(GUILE_EFFECTIVE_VERSION)"'>>libpath.tmp
+       @echo '#define SCM_SITELIB_DIR "$(pkglibdir)/site"' >> libpath.tmp
        @echo '#define SCM_BUILD_INFO { \' >> libpath.tmp
        @echo ' { "srcdir", "'"`cd @srcdir@; pwd`"'" }, \' >> libpath.tmp
        @echo ' { "top_srcdir",    "@top_srcdir_absolute@" }, \' >> libpath.tmp
diff -uNr guile-1.7.2.orig/libguile/Makefile.in guile-1.7.2/libguile/Makefile.in
--- guile-1.7.2.orig/libguile/Makefile.in       2005-03-08
03:42:07.000000000 +0300
+++ guile-1.7.2/libguile/Makefile.in    2005-09-18 23:23:50.000000000 +0400
@@ -1898,6 +1898,9 @@
        @echo '#define SCM_PKGDATA_DIR "$(pkgdatadir)"' >> libpath.tmp
        @echo '#define SCM_LIBRARY_DIR
"$(pkgdatadir)/$(GUILE_EFFECTIVE_VERSION)"'>>libpath.tmp
        @echo '#define SCM_SITE_DIR "$(pkgdatadir)/site"' >> libpath.tmp
+       @echo '#define SCM_PKGLIB_DIR "$(pkglibdir)"' >> libpath.tmp
+       @echo '#define SCM_LIB_DIR
"$(pkglibdir)/$(GUILE_EFFECTIVE_VERSION)"'>>libpath.tmp
+       @echo '#define SCM_SITELIB_DIR "$(pkglibdir)/site"' >> libpath.tmp
        @echo '#define SCM_BUILD_INFO { \' >> libpath.tmp
        @echo ' { "srcdir", "'"`cd @srcdir@; pwd`"'" }, \' >> libpath.tmp
        @echo ' { "top_srcdir",    "@top_srcdir_absolute@" }, \' >> libpath.tmp




reply via email to

[Prev in Thread] Current Thread [Next in Thread]