[plt-scheme] Code for catching exceptions in embedding applications
At Mon, 3 Nov 2008 11:14:07 +0300, "Sergey Khorev" wrote:
>
> environment = scheme_basic_env();
> declare_modules(environment);
At this point, `environment' is set up ok.
> env = (Scheme_Env *)scheme_make_namespace(0, NULL);
> declare_modules(env);
But then you create another namespace...
Solution 1:
If you don't actually need a second namespace, just set `env' to
`environment'.
The other solutions below assume that you do need a second namespace.
Solution 2 (incomplete):
It turns out that declare_modules() doesn't use its `env' argument.
Instead, it declares modules in the current environment, which is
`environment'. I'll adjust the docs to clarify this.
Even if you reverse the order of the declare and parameter assignment,
like this:
env = (Scheme_Env *)scheme_make_namespace(0, NULL);
scheme_set_param(scheme_current_config(), MZCONFIG_ENV, env);
declare_modules(env);
then it doesn't work, because the empty namespace doesn't have some
built-in modules that are needed for the `scheme/base' declarations.
You could attach the built-in declarations from `environment' to `env',
but it's best just to attach `scheme/base' itself, as in Solution 3.
Solution 3 (works with latest in SVN):
To create a separate `env', it's best to call `make-base-namespace'
from `scheme/base' instead of scheme_make_namespace(). That operation
attaches the declared modules from the original namespace, instead of
redeclaring them.
The C code looks like this:
a[0] = scheme_intern_symbol("scheme/base");
a[1] = scheme_intern_symbol("make-base-namespace");
p = scheme_dynamic_require(2, a);
env = scheme_apply(p, 0, NULL);
However, this didn't work previously, because the namespace-attaching
operation didn't transfer module-name mappings. That is, in the new
namespace, the module resolver didn't track that `scheme/base' was
pre-declared.
In SVN, I've adjusted the module renamer created by `mzc --c-mods' to
correctly track attaches, so that this approach works. The code below
works with the latest in SVN.
----------------------------------------
#define MZ_PRECISE_GC 1
#include <scheme.h>
#include "base.c"
static Scheme_Env *environment = NULL;
static int
scheme_main(void *data)
{
char *e =
"(lambda (thunk) "
"(with-handlers ([void (lambda (exn) (cons #f exn))]) "
"(cons #t (thunk))))";
Scheme_Env *env = NULL;
Scheme_Object *exn_catching_apply = NULL;
Scheme_Object *p = NULL, *a[2] = { NULL, NULL };
MZ_GC_DECL_REG(6);
MZ_GC_VAR_IN_REG(0, env);
MZ_GC_VAR_IN_REG(1, exn_catching_apply);
MZ_GC_VAR_IN_REG(2, p);
MZ_GC_ARRAY_VAR_IN_REG(3, a, 2);
MZ_GC_REG();
MZ_REGISTER_STATIC(environment);
environment = scheme_basic_env();
declare_modules(environment);
a[0] = scheme_intern_symbol("scheme/base");
a[1] = scheme_intern_symbol("make-base-namespace");
p = scheme_dynamic_require(2, a);
env = scheme_apply(p, 0, NULL);
scheme_set_param(scheme_current_config(), MZCONFIG_ENV,
(Scheme_Object *)env);
scheme_namespace_require(a[0]);
exn_catching_apply = scheme_eval_string(e, env);
MZ_GC_UNREG();
a[1] = scheme_intern_symbol("read-eval-print-loop");
p = scheme_dynamic_require(2, a);
p = scheme_dynamic_require(2, a);
env = scheme_apply(p, 0, NULL);
return 1;
}
int main()
{
return scheme_main_stack_setup(1, scheme_main, NULL);
}