ecls-list

Hello
I'm planing on using ECL for gameplay logic and would like to know how to
handle all errors on my own.
Example:
I have an SDL window with some kind of ingame GUI. The user writes some LISP
and presses Save.
Boom, the program freezes and some weird things are displayed on stdout.
Now, I know why I get presented a top level prompt - but what I want to know
is how I can handle the errors myself like this:
cl_load / si_eval_with_env / whatnot returns some kind of error object and
provides me with a way to
get a string with a human readable error message ("The function XXXX is
undefined"). Also, it should not try to handle
signals.
In short, ECL should be a library - not a program.
Is this possible?
P.S. Where can I find more information about all the functions and
cl_objects? At the moment I've resorted
to reading the source code and browsing the mailinglist but surely there
must be something else somewhere? D.S
Greetings,
--
Christian Svensson
Command Systems

On Thu, Sep 11, 2008 at 9:44 PM, Christian Svensson <info@...> wrote:
> if( type_of( result ) == t_symbol )
> {
> printf( "- Loading result: %s\n", cl_symbol_value( result ) );
> }
>
Hi Christian, first of all sorry that programming embedded ECL seems so
difficult, but believe me: it is not.
The key to understand how ECL works is to grasp that it is just a C library
providing _all_ of Common Lisp. Hence, to know how to program ECL you cannot
avoid learning some Common Lisp, but at the same time if you know Common
Lisp you will know how to manipulate data in C without resorting to low
level hacks.
Given this, the statements above are wrong. Most functions with prefix cl_
are functions defined in the Common Lisp CL or COMMON-LISP package. In
particular cl_symbol_value is the C equivalent of SYMBOL-VALUE which returns
the value of a variable
http://www.lispworks.com/documentation/HyperSpec/Body/f_symb_5.htm
Hence, when your program reaches this point it has read the form
(DEFUN NO-FUNC ....)
and it has evaluated this form which results in an output value
NO-FUNC
This is the same as if I type the previous statement in a Common Lisp: the
output will be the symbol that names the function I have defined. However,
NO-FUNC is not a variable and if you type (SYMBOL-VALUE 'NO-FUNC) in
whatever Lisp it will complain.
Unfortunately there is not yet a simple way to protect yourself from
mistakes in the C program because there are no simple C constructs to
capture errors. There are some macros defined in the ECL C headers but I do
not want to recommend them because they are prone to change.
BTW, this other statement is also wrong
result = si_safe_eval( 3, c_string_to_object( "(my-test-function 1)" ),
Cnil, OBJNULL );
if( result == OBJNULL )
{
printf( "Calling of function failed\n" );
return 1;
}
This is because your cl_read() statement only reads 1 form and not the 2nd
form which contains the definition for MY-TEST-FUNCTION. You would be better
off using cl_load().
Hope this helps you get started,
Juanjo
--
Instituto de Física Fundamental
CSIC, Serrano, 113, Madrid 28040 (Spain)
http://juanjose.garciaripoll.googlepages.com

Hello, thanks for your answer.
The problem with cl_load as I've experienced it is that it will throw me a
top-level prompt if there are any errors in the file.
I don't want that.
Is there any time plan to provide this kind of support? Or is it an "issue"
at all?
Greetings,
On Fri, Sep 12, 2008 at 9:55 PM, Juan Jose Garcia-Ripoll <
juanjose.garciaripoll@...> wrote:
> On Thu, Sep 11, 2008 at 9:44 PM, Christian Svensson <info@...> wrote:
>
>> if( type_of( result ) == t_symbol )
>> {
>> printf( "- Loading result: %s\n", cl_symbol_value( result ) );
>> }
>>
>
> Hi Christian, first of all sorry that programming embedded ECL seems so
> difficult, but believe me: it is not.
>
> The key to understand how ECL works is to grasp that it is just a C library
> providing _all_ of Common Lisp. Hence, to know how to program ECL you cannot
> avoid learning some Common Lisp, but at the same time if you know Common
> Lisp you will know how to manipulate data in C without resorting to low
> level hacks.
>
> Given this, the statements above are wrong. Most functions with prefix cl_
> are functions defined in the Common Lisp CL or COMMON-LISP package. In
> particular cl_symbol_value is the C equivalent of SYMBOL-VALUE which returns
> the value of a variable
> http://www.lispworks.com/documentation/HyperSpec/Body/f_symb_5.htm
>
> Hence, when your program reaches this point it has read the form
> (DEFUN NO-FUNC ....)
> and it has evaluated this form which results in an output value
> NO-FUNC
> This is the same as if I type the previous statement in a Common Lisp: the
> output will be the symbol that names the function I have defined. However,
> NO-FUNC is not a variable and if you type (SYMBOL-VALUE 'NO-FUNC) in
> whatever Lisp it will complain.
>
> Unfortunately there is not yet a simple way to protect yourself from
> mistakes in the C program because there are no simple C constructs to
> capture errors. There are some macros defined in the ECL C headers but I do
> not want to recommend them because they are prone to change.
>
> BTW, this other statement is also wrong
>
> result = si_safe_eval( 3, c_string_to_object( "(my-test-function 1)" ),
> Cnil, OBJNULL );
> if( result == OBJNULL )
> {
> printf( "Calling of function failed\n" );
> return 1;
> }
>
> This is because your cl_read() statement only reads 1 form and not the 2nd
> form which contains the definition for MY-TEST-FUNCTION. You would be better
> off using cl_load().
>
> Hope this helps you get started,
>
> Juanjo
>
> --
> Instituto de Física Fundamental
> CSIC, Serrano, 113, Madrid 28040 (Spain)
> http://juanjose.garciaripoll.googlepages.com
>
--
Christian Svensson
Command Systems

On Sat, Sep 13, 2008 at 11:06 AM, Christian Svensson <info@...> wrote:
> Hello, thanks for your answer.
>
> The problem with cl_load as I've experienced it is that it will throw me a
> top-level prompt if there are any errors in the file.
> I don't want that.
>
> Is there any time plan to provide this kind of support? Or is it an "issue"
> at all?
>
Christian, can you be more specific? I showed that your code was wrong, so
there is no support issue about that. Are you perhaps talking about cl_load?
There is a standard way of deactivating the debugger in Common Lisp
(*debugger-hook*). Again, this is not ECL related, but Common Lisp.
Juanjo
--
Instituto de Física Fundamental
CSIC, Serrano, 113, Madrid 28040 (Spain)
http://juanjose.garciaripoll.googlepages.com

Hello.
Ah, I see.
How would one proceed to set *debugger-hook* to a user specified function
globally to catch errors in cl_load?
I've tried with si_safe_eval( 3, c_string_to_object( "(setq *debugger-hook*
nil)", Cnil, OBJNULL ) but that makes no change
- is NIL a valid value? Do I need to specify an environment for it to work?
Is the setq function correct?
Many questions, but I feel that this might work after all :-)
Thanks in advance,
On Sat, Sep 13, 2008 at 1:26 PM, Juan Jose Garcia-Ripoll <
juanjose.garciaripoll@...> wrote:
>
>
> On Sat, Sep 13, 2008 at 11:06 AM, Christian Svensson <info@...> wrote:
>
>> Hello, thanks for your answer.
>>
>> The problem with cl_load as I've experienced it is that it will throw me
>> a top-level prompt if there are any errors in the file.
>> I don't want that.
>>
>> Is there any time plan to provide this kind of support? Or is it an
>> "issue" at all?
>>
>
> Christian, can you be more specific? I showed that your code was wrong, so
> there is no support issue about that. Are you perhaps talking about cl_load?
> There is a standard way of deactivating the debugger in Common Lisp
> (*debugger-hook*). Again, this is not ECL related, but Common Lisp.
>
> Juanjo
>
> --
> Instituto de Física Fundamental
> CSIC, Serrano, 113, Madrid 28040 (Spain)
> http://juanjose.garciaripoll.googlepages.com
>
--
Christian Svensson
Command Systems

On Sun, Sep 14, 2008 at 2:02 PM, Christian Svensson <info@...> wrote:
> Hello.
>
> Ah, I see.
> How would one proceed to set *debugger-hook* to a user specified function
> globally to catch errors in cl_load?
>
> I've tried with si_safe_eval( 3, c_string_to_object( "(setq *debugger-hook*
> nil)", Cnil, OBJNULL ) but that makes no change
> - is NIL a valid value? Do I need to specify an environment for it to work?
> Is the setq function correct?
>
Google: clhs *debugger-hook* -->
http://www.lispworks.com/documentation/HyperSpec/Body/v_debugg.htm
Read all about it on the web. As Juan pointed out: you need to learn
Common Lisp if you want to do this.
Bye,
Erik.

Hello,
Yes, I've looked at that page before.
You'll have to excuse me, I'm not very experienced with LISP programming yet
but I know
my way around the general language.
I'm having problems seeing how using a let-statement inside the LISP file
would set
the debugger-hook for cl_load to use.
Earlier in this thread I was told that cl_* is the same as the commands in
LISP.
Therefor I test this both in "ecl" and using si_safe_eval:
(let ((*debugger-hook* nil)) (load "test.lisp"))
I get thrown to the top-level anyway.
I've also tried with:
*test-debug.lisp*
(defun test-debug( c m )
(print c))
*main.c*
...
cl_load( 1, "test-debug.lisp" );
..
si_safe_eval( 3, "(let ((*debugger-hook* #'test-debug)) (load
\"test.lisp\"))", Cnil, OBJNULL );
..
where *test.lisp *is riddled with syntax errors - it should fail to load,
which it does
but it throws me to top-level anyway. I does however execute (print c).
Am I missing some kind of function call inside my debug function to stop the
evaluation
or anything of the kind?
Thanks in advance and for your patience.
On Sun, Sep 14, 2008 at 2:35 PM, Erik Huelsmann <ehuels@...> wrote:
> On Sun, Sep 14, 2008 at 2:02 PM, Christian Svensson <info@...> wrote:
> > Hello.
> >
> > Ah, I see.
> > How would one proceed to set *debugger-hook* to a user specified function
> > globally to catch errors in cl_load?
> >
> > I've tried with si_safe_eval( 3, c_string_to_object( "(setq
> *debugger-hook*
> > nil)", Cnil, OBJNULL ) but that makes no change
> > - is NIL a valid value? Do I need to specify an environment for it to
> work?
> > Is the setq function correct?
> >
>
> Google: clhs *debugger-hook* -->
> http://www.lispworks.com/documentation/HyperSpec/Body/v_debugg.htm
>
> Read all about it on the web. As Juan pointed out: you need to learn
> Common Lisp if you want to do this.
>
> Bye,
>
> Erik.
>
--
Christian Svensson
Command Systems

On Sun, Sep 14, 2008 at 4:25 PM, Christian Svensson <info@...> wrote:
>
> Earlier in this thread I was told that cl_* is the same as the commands in LISP.
> Therefor I test this both in "ecl" and using si_safe_eval:
>
> (let ((*debugger-hook* nil)) (load "test.lisp"))
>
> I get thrown to the top-level anyway.
*DEBUGGER-HOOK* may contain a function for the user to intercept all
calls to the debugger. Now if you set this to NIL you are telling the
Common Lisp environment that you do not want to install any debugger
hook, so the ordinary prompt is activated
Look at the lisp definition fi si::safe-eval
(defun safe-eval (form env err-value)
(catch 'si::protect-tag
(let* ((*debugger-hook*
#'(lambda (condition old-hooks)
(throw 'si::protect-tag condition))))
(return-from safe-eval (eval-with-env form env))))
err-value)
You said that you want to capture the error and learn what happens.
This can be coded in Common Lisp as follows
(defun my-safe-eval (form env)
(handler-case (values (eval-with-env form env) nil)
(error (c) (return-from my-safe-eval (values nil c)))))
This function returns two values: the output of your form and an
optional second value with any error that might get signaled. The main
value is directly output by the function, while the second value may
be retrieved using VALUES(1). Beware that the code below was directly
typed into this email and may have typos, errors, etc, but you
probably get the general idea.
cl_object aux = c_string_to_object( "(defun my-safe-eval (form env)
(handler-case (values (eval-with-env form env) nil)
(error (c) (return-from my-safe-eval (values nil c)))))");
cl_object function_name = cl_eval(1, aux);
cl_object form = c_string_to_object("(LOAD ... ");
cl_object output = cl_funcall(3, function_name, form, Cnil);
cl_object error = VALUES(1);
if (error != Cnil) {
...
}
Note also that condition objects may be printed with various degrees
of precision: by default you only get a #<... >, but in pretty print
form you wil get the full error message.
Juanjo
--
Instituto de Física Fundamental
CSIC, Serrano, 113, Madrid 28040 (Spain)
http://juanjose.garciaripoll.googlepages.com

Hello.
Many thanks, that cleared up many things.
Works like a charm, thanks to all of you!
Greetings,
On Sun, Sep 14, 2008 at 5:03 PM, Juan Jose Garcia-Ripoll <
juanjose.garciaripoll@...> wrote:
> On Sun, Sep 14, 2008 at 4:25 PM, Christian Svensson <info@...> wrote:
> >
> > Earlier in this thread I was told that cl_* is the same as the commands
> in LISP.
> > Therefor I test this both in "ecl" and using si_safe_eval:
> >
> > (let ((*debugger-hook* nil)) (load "test.lisp"))
> >
> > I get thrown to the top-level anyway.
>
> *DEBUGGER-HOOK* may contain a function for the user to intercept all
> calls to the debugger. Now if you set this to NIL you are telling the
> Common Lisp environment that you do not want to install any debugger
> hook, so the ordinary prompt is activated
>
> Look at the lisp definition fi si::safe-eval
>
> (defun safe-eval (form env err-value)
> (catch 'si::protect-tag
> (let* ((*debugger-hook*
> #'(lambda (condition old-hooks)
> (throw 'si::protect-tag condition))))
> (return-from safe-eval (eval-with-env form env))))
> err-value)
>
> You said that you want to capture the error and learn what happens.
> This can be coded in Common Lisp as follows
>
> (defun my-safe-eval (form env)
> (handler-case (values (eval-with-env form env) nil)
> (error (c) (return-from my-safe-eval (values nil c)))))
>
> This function returns two values: the output of your form and an
> optional second value with any error that might get signaled. The main
> value is directly output by the function, while the second value may
> be retrieved using VALUES(1). Beware that the code below was directly
> typed into this email and may have typos, errors, etc, but you
> probably get the general idea.
>
> cl_object aux = c_string_to_object( "(defun my-safe-eval (form env)
> (handler-case (values (eval-with-env form env) nil)
> (error (c) (return-from my-safe-eval (values nil c)))))");
>
> cl_object function_name = cl_eval(1, aux);
> cl_object form = c_string_to_object("(LOAD ... ");
> cl_object output = cl_funcall(3, function_name, form, Cnil);
> cl_object error = VALUES(1);
> if (error != Cnil) {
> ...
> }
>
> Note also that condition objects may be printed with various degrees
> of precision: by default you only get a #<... >, but in pretty print
> form you wil get the full error message.
>
> Juanjo
>
> --
> Instituto de Física Fundamental
> CSIC, Serrano, 113, Madrid 28040 (Spain)
> http://juanjose.garciaripoll.googlepages.com
>
--
Christian Svensson
Command Systems

On Sun, Sep 14, 2008 at 8:23 PM, Christian Svensson <info@...> wrote:
> While the error handling works like a charm, I would still like to
> disable ECLs signal handling - at least for SIGINT and the like.
(SI:UNCATCH-BAD-SIGNALS)
Juanjo
--
Instituto de Física Fundamental
CSIC, Serrano, 113, Madrid 28040 (Spain)
http://juanjose.garciaripoll.googlepages.com

On Sun, Sep 14, 2008 at 10:19 PM, Christian Svensson <info@...> wrote:
> Yes - I'm already using that but it does not remove the SIGINT handler.
Well, until I code a function for that particular case you can install
your own signal handler after calling cl_boot(), or use the default
one. It is not that difficult and ECL will not override your choice if
you do it as I say: after cl_boot().
Juanjo
--
Instituto de Física Fundamental
CSIC, Serrano, 113, Madrid 28040 (Spain)
http://juanjose.garciaripoll.googlepages.com