Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spec confusion about 'sigerr' #9

Closed
masak opened this issue Aug 22, 2020 · 3 comments
Closed

Spec confusion about 'sigerr' #9

masak opened this issue Aug 22, 2020 · 3 comments

Comments

@masak
Copy link

masak commented Aug 22, 2020

This:

> (bel '(a . b))
malformed

Is correct/expected, I believe.

It happens because of the (no (proper e)) condition in ev:

(def ev (((e a) . s) r m)
  (aif (literal e)            (mev s (cons e r) m)
       (variable e)           (vref e a s r m)
       (no (proper e))        (sigerr 'malformed s r m)
       (get (car e) forms id) ((cdr it) (cdr e) a s r m)
                              (evcall e a s r m)))

So sigerr gets called. Its definition confuses the heck out of me:

(def sigerr (msg s r m)
  (aif (binding 'err s)
       (applyf (cdr it) (list msg) nil s r m)
       (err 'no-err)))

Can we agree that the (binding 'err s) condition will be false at this point? s at this point is nil, because the only thing that was on the expression stack was (a . b), which ev took off.

What could reasonably have put an err binding in the expression stack? In "The Bel Language": "If there isn't a binding for err, then there's an error in the interpreter itself, and we call err about it." It makes it sounds like it was the interpreter's job to establish a binding for err. But where; how? There really isn't much code happening between the initialization of the one-element expression stack in bel, and this point in sigerr. Does that mean the interpreter is erroneous as specified?

I think bel.bel is wrong here. Maybe this would fix it:

 (def bel (e (o g globe))
-  (ev (list (list e nil))
+  (ev (list (list e nil)
+            (list (list smark 'bind (cons 'err err)) nil))
       nil
       (list nil g)))
@masak
Copy link
Author

masak commented Aug 24, 2020

Having thought about it overnight, I now feel that this is a better/saner fix:

 (def sigerr (msg s r m)
   (aif (binding 'err s)
        (applyf (cdr it) (list msg) nil s r m)
-       (err 'no-err)))
+       (applyf err (list msg) nil s r m)))

That is, the underlying implementation always at least has a global err defined — both your implementation and mine already defines one globally — and it's called with the same convention as a dynamically overriding one.

The only small issue I see with this is that, according to "The Bel Language": "Errors are signalled by calling err with one argument describing the error." But with a bit of squinting, one can take that to mean "one argument describing the error", plus optionally a bunch of others detailing the evaluator's state.

@masak
Copy link
Author

masak commented Sep 1, 2020

Closing this one, since this is a bug in the spec, not in chime.

I expect I'll implement sigerr with the diff above applied (which is effectively what you've done also) — and maybe the user documentation can end up with a note that sigerr is most likely mis-specified and implementations deviate from it.

@masak masak closed this as completed Sep 1, 2020
@masak
Copy link
Author

masak commented Jul 14, 2022

The only small issue I see with this is that, according to "The Bel Language": "Errors are signalled by calling err with one argument describing the error." But with a bit of squinting, one can take that to mean "one argument describing the error", plus optionally a bunch of others detailing the evaluator's state.

No, that's just me being confused; the err function does get exactly one argument; the other arguments are to the (interpreter-internal) function applyf.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant