Discussion:
[Jemacs-info] Implementing eval-last-sexp
Per Bothner
2011-04-27 02:54:17 UTC
Permalink
Hi all,
I'm attempting to implement eval-last-sexp. What I have so far pretty
much works,
but there must be some code somewhere in kawa that does the parsing I've
attempted
in the method evalLastSexp.
Well, I'm not sure where in Kawa you'd find a parser that does what
we need. One problem is that it needs to parse *backwards*. And of course
to be correct, you should check if a paren is inside string quotes or
is part of character literal.

Also note that an sexpr isn't necessary a parenthesis form - it can be
a constant or a symbol. In that case you probably have to scan
backwards for
a delimiter.

So I'm willing to check in your patch as-is (though there are some
indentation
issues), it might be a good idea if you could take a look at Emacs's
implementation - see how they do it. We don't need to be 100% correct, but
having a better idea of what Emacs does seems like a good idea.
Also, since jemacs supports both kawa and
elisp,
should the user be given a way to switch between the two? I've attached
a diff file
of my code, any suggestions would be appreciated.
Yes, perhaps there should be a way to switch languages, but using
the "current language" is probably good enough for now. Regardless,
this may be difficult enough for just one language!
--
--Per Bothner
***@bothner.com http://per.bothner.com/
Shad Gregory
2011-04-27 19:20:13 UTC
Permalink
Thank you for feedback, Per. I would like to work on this weekend or
during my next
bout of insomnia, whichever comes first, incorporating your concerns.
And I guess I
should force myself to take a look at the emacs code. :-)
Post by Per Bothner
Hi all,
I'm attempting to implement eval-last-sexp. What I have so far pretty
much works,
but there must be some code somewhere in kawa that does the parsing I've
attempted
in the method evalLastSexp.
Well, I'm not sure where in Kawa you'd find a parser that does what
we need.  One problem is that it needs to parse *backwards*.  And of course
to be correct, you should check if a paren is inside string quotes or
is part of character literal.
Also note that an sexpr isn't necessary a parenthesis form - it can be
a constant or a symbol.  In that case you probably have to scan backwards for
a delimiter.
So I'm willing to check in your patch as-is (though there are some indentation
issues), it might be a good idea if you could take a look at Emacs's
implementation - see how they do it.  We don't need to be 100% correct, but
having a better idea of what Emacs does seems like a good idea.
 Also, since jemacs supports both kawa and
elisp,
should the user be given a way to switch between the two? I've attached
a diff file
of my code, any suggestions would be appreciated.
Yes, perhaps there should be a way to switch languages, but using
the "current language" is probably good enough for now.  Regardless,
this may be difficult enough for just one language!
--
       --Per Bothner
Shad Gregory
2011-04-29 03:03:05 UTC
Permalink
Here's a second attempt at implementing eval-last-sexp. I'm certain
that this one is a lot closer to the emacs function.
Post by Shad Gregory
Thank you for feedback, Per. I would like to work on this weekend or
during my next
bout of insomnia, whichever comes first, incorporating your concerns.
And I guess I
should force myself to take a look at the emacs code. :-)
Post by Per Bothner
Hi all,
I'm attempting to implement eval-last-sexp. What I have so far pretty
much works,
but there must be some code somewhere in kawa that does the parsing I've
attempted
in the method evalLastSexp.
Well, I'm not sure where in Kawa you'd find a parser that does what
we need.  One problem is that it needs to parse *backwards*.  And of course
to be correct, you should check if a paren is inside string quotes or
is part of character literal.
Also note that an sexpr isn't necessary a parenthesis form - it can be
a constant or a symbol.  In that case you probably have to scan backwards for
a delimiter.
So I'm willing to check in your patch as-is (though there are some indentation
issues), it might be a good idea if you could take a look at Emacs's
implementation - see how they do it.  We don't need to be 100% correct, but
having a better idea of what Emacs does seems like a good idea.
 Also, since jemacs supports both kawa and
elisp,
should the user be given a way to switch between the two? I've attached
a diff file
of my code, any suggestions would be appreciated.
Yes, perhaps there should be a way to switch languages, but using
the "current language" is probably good enough for now.  Regardless,
this may be difficult enough for just one language!
--
       --Per Bothner
Per Bothner
2011-05-01 17:07:36 UTC
Permalink
Post by Shad Gregory
Here's a second attempt at implementing eval-last-sexp. I'm certain
that this one is a lot closer to the emacs function.
Yes, I think that is close enough. I did see a difference when
there is a non-paren form following a paren form: Assume:

345#xff
Then with your patch the result is "345, 255" (two values), but with
emacs only one is returned.

Also:

(setq xx 21)xx

Both are evaluated; only (the second) xx should be evaluated.

However, these are nits - this is certainly good enough to provide
the functionality is a useful way.

However, I'm more concerned that evalLastSexp is a method of SwingBuffer,
but there shouldn't be anything Swing-specific in it. It really
should be a method in Buffer instead. Even better - it really should be
a method of Marker. You can use buffer.charAt(i) to get at the
characters.
--
--Per Bothner
***@bothner.com http://per.bothner.com/
Shad Gregory
2011-05-03 02:09:35 UTC
Permalink
Here's version 3.

-I followed your suggestion and moved evalLastSexp to Marker.java

-I removed the 't' test. It was not necessary.

-I added an 'other' state. This should fix the '(setq xx 21)xx' problem.

-I haven't got a solution for the '345#xff' problem yet. I noticed
that the REPL returns "345 255".
Post by Shad Gregory
Here's a second attempt at implementing eval-last-sexp. I'm certain
that this one is a lot closer to the emacs function.
Yes, I think that is close enough.  I did see a difference when
  345#xff
Then with your patch the result is "345, 255" (two values), but with
emacs only one is returned.
 (setq xx 21)xx
Both are evaluated; only (the second) xx should be evaluated.
However, these are nits - this is certainly good enough to provide
the functionality is a useful way.
However, I'm more concerned that evalLastSexp is a method of SwingBuffer,
but there shouldn't be anything Swing-specific in it.  It really
should be a method in Buffer instead.  Even better - it really should be
a method of Marker.  You can use buffer.charAt(i) to get at the
characters.
--
       --Per Bothner
Per Bothner
2011-05-03 06:50:15 UTC
Permalink
Post by Shad Gregory
Here's version 3.
Thanks! I checked this in, with 2 changes:
(1) The message function returns a string, but showInfoMessage returns void.
I changed it to:
(define (message msg) :: <string>
((window-frame):showInfoMessage msg)
msg)
(2) I removed the System.err.println call in evalLastSexp's catch clause.
Post by Shad Gregory
-I followed your suggestion and moved evalLastSexp to Marker.java
-I removed the 't' test. It was not necessary.
-I added an 'other' state. This should fix the '(setq xx 21)xx' problem.
-I haven't got a solution for the '345#xff' problem yet.
It's not worth stressing over - what we have is ok.
Post by Shad Gregory
I noticed
that the REPL returns "345 255".
The REPL takes multiple SEXPs, evaluates them all, and prints them all.
eval-last-sexp is supposed to just evaluate the "last" sexp.

Consider: (+ 2 3)(* 5 6) ^X^E in this case yields "30" - because it only
evaluates the last sexp. But: (+ 2 3)30 returns "5, 30". Which is a bug.
However, it not an important bug - getting eval-last-sexp 100% correct
is probably more difficult than it is worth. I don't know any clean and
simple way to do it.
--
--Per Bothner
***@bothner.com http://per.bothner.com/
Loading...