jscl icon indicating copy to clipboard operation
jscl copied to clipboard

Catching unbound-variable in JSCL

Open hemml opened this issue 4 years ago • 4 comments

I want to load a code dynamically from remote server via websocket. The idea is to catch unbound-variable and undefined-function conditions and ask remote server for missing variables and functions code.

In SBCL I can use the following code to catch the exception:

(handler-bind
    ((unbound-variable
       (lambda (c)
         (print c)
         (eval `(defvar ,(cell-error-name c) "XXXX"))
         (continue c))))     
  (print "AAA")
  (print x11xxaaa)
  (print "BBB"))

The result is:

"AAA" 
#<UNBOUND-VARIABLE X11XXAAA {100335EA13}> 
"XXXX" 
"BBB" 

But in JSCL this code not working:

"AAA"
ERROR: Variable X11XXAAA is unbound.

I'm tried to use just error instead of unbound-variable (this also works in SBCL):

(handler-bind
    ((error
       (lambda (c)
         (print c)
         (eval `(defvar ,(cell-error-name c) "XXXX"))
         (continue c))))     
  (print "AAA")
  (print x11xxaa)
  (print "BBB"))

but got:

"AAA"
#<structure !condition>
ERROR: Function 'CELL-ERROR-NAME' undefined

Is there a way to catch undefined-variable in JSCL, define a new var and continue execution?

hemml avatar May 16 '20 21:05 hemml

Interesting use case!

Unfortunately, as of now, the error for unbound variables is a generic error:

https://github.com/jscl-project/jscl/blob/master/src/prelude.js#L331-L338

actually, most errors signaled by the implementation are those generic unstructured errors, as the condition system is implemented at the library level.

It does not seem that hard to change though. In case somebody wants to tackle this, what can be done is to define a temporary function in prelude.js. The compiler would generate code to call it when a symbol is unbound. It can be a very simple function initially (for bootstrapping), and then it can be redefined by

https://github.com/jscl-project/jscl/blob/master/src/conditions.lisp

A similar trick is already done with eval_in_lisp in prelude.js.

davazp avatar May 16 '20 22:05 davazp

I looked at the condition.lisp and did not see any code for restarts. There is no way to continue execution after an error?

hemml avatar May 16 '20 22:05 hemml

They are restartable. But only if they are trigger with signal from conditions.lisp.

The way this works is in %handler-bind. By default a handler can just return to continue, or do a non-local exit to abort. restart-case can be implemented on top of this. But it is not there yet, unfortunately.

davazp avatar May 17 '20 08:05 davazp

restart is possible and needs to be implemented. But not right away. Not all Common Lisp design concepts fall on JS

vlad-km avatar May 06 '21 18:05 vlad-km