Failure (was: Joy inbuilt editor)
John Cowan — 2001-05-16 13:20:46
Manfred von Thun wrote:
> You know a lot more about setjmp than I do. I have only used
> it for "escape from error, back to main", the sort of thing
> which in Pascal tends to be a simple "GOTO 1", where the label 1
> is in the main program.
Setjmp and longjmp are rather like labels and gotos, except
that the jmp_buf is a fully reified continuation. Thus
one can have code something like this:
static jmp_buf fail_buf;
...
exeterm() {
jmp_buf local_fail_buf;
/* local_fail_buf = fail_buf does not work */
memcpy(local_fail_buf, fail_buf, sizeof(fail_buf));
if (setjmp(fail_buf)) {
/* fail invoked */ }
else {
/* normal execution */ }
/* fail_buf = local_fail_buf does not work */
memcpy(fail_buf, local_fail_buf, sizeof(fail_buf));
}
fail() {
longjmp(fail_buf, 1);
}
Invoking "fail" will cause the setjmp at the most recent
dynamic instance of exeterm to be resumed in the "true"
path of the "if setjmp" conditional.
--
There is / one art || John Cowan <
jcowan@...>
no more / no less ||
http://www.reutershealth.com
to do / all things ||
http://www.ccil.org/~cowan
with art- / lessness \\ -- Piet Hein
Manfred von Thun — 2001-05-17 01:33:26
This is my wishlist for additions to John Cowan's Joy 1.0 beta
I am sending it to the group in case anyone wants to update
their own version of my prototype Joy 0.0
The additions concern seven new operators for shuffling
the top elements of the stack.
The first new operator is "rotate" for interchanging the
first and third element of the stack. The other new operators
are variants of the (now 6) ordinary stack shuffling operators.
For X = (pop,dup,swap,rollup,rolldown,rotate), a variant
is introduced called "Xd", with the "d" for "dipped".
For example "swapd" would be the same as "[swap] dip".
See the new online manual entries below for details.
The first reason for the additions is to make the naming of the
variants more systematic than what I have in the standard library.
The other reason is to make these variants more efficient.
The additions are just inside the main interpreter file interp.c
(John will know that the four cases of ->u.num will have to be
changed for his Joy 1.0 beta.)
- Manfred
--- There are just two consecutive additions to interp.c
--- The first is for the code, the second for the online manual.
--- insert this just after "rollup" and "rolldown"
--- This is a new operator "rotate" and a new macro for defining
--- "dipped" versions of the principal stack shuffling operators
PRIVATE void rotate_()
{
THREEPARAMS("rotate");
SAVESTACK;
TERNARY(SAVED1->op,SAVED1->u.num);
NULLARY(SAVED2->op,SAVED2->u.num);
NULLARY(SAVED3->op,SAVED3->u.num);
POP(dump);
}
#define DIPPED(PROCEDURE,NAME,PARAMCOUNT,ARGUMENT) \
PRIVATE void PROCEDURE() \
{ PARAMCOUNT(NAME); \
SAVESTACK; \
POP(stk); \
ARGUMENT(); \
NULLARY(SAVED1->op,SAVED1->u.num); \
POP(dump); \
}
DIPPED(popd_,"popd",TWOPARAMS,pop_)
DIPPED(dupd_,"dupd",TWOPARAMS,dup_)
DIPPED(swapd_,"swapd",THREEPARAMS,swap_)
DIPPED(rolldownd_,"rolldownd",FOURPARAMS,rolldown_)
DIPPED(rollupd_,"rollupd",FOURPARAMS,rollup_)
DIPPED(rotated_,"rotated",FOURPARAMS,rotate_)
--- END of fist insertion just after "rollup" and "rolldown"
--- insert the following in the online manual section
--- just after the entries for "rollup" and "rolldown"
{"rotate", rotate_, "X Y Z -> Z Y X",
"Interchanges X and Z"},
{"popd", popd_, "Y Z -> Z",
"As if defined by: popd == [pop] dip "},
{"dupd", dupd_, "Y Z -> Y Y Z",
"As if defined by: dupd == [dup] dip"},
{"swapd", swapd_, "X Y Z -> Y X Z",
"As if defined by: swapd == [swap] dip"},
{"rollupd", rollupd_, "X Y Z W -> Z X Y W",
"As if defined by: rollupd == [rollup] dip"},
{"rolldownd", rolldownd_, "X Y Z W -> Y Z X W",
"As if defined by: rolldownd == [rolldown] dip "},
{"rotated", rotated_, "X Y Z W -> Z Y X W",
"As if defined by: rotated == [rotate] dip"},
--- END of second insertion
Manfred von Thun — 2001-05-17 01:46:15
On Wed, 16 May 2001, John Cowan wrote:
> Setjmp and longjmp are rather like labels and gotos, except
> that the jmp_buf is a fully reified continuation. Thus
> one can have code something like this:
>
> static jmp_buf fail_buf;
> ...
> exeterm() {
> jmp_buf local_fail_buf;
>
> /* local_fail_buf = fail_buf does not work */
> memcpy(local_fail_buf, fail_buf, sizeof(fail_buf));
>
> if (setjmp(fail_buf)) {
> /* fail invoked */ }
> else {
> /* normal execution */ }
>
> /* fail_buf = local_fail_buf does not work */
> memcpy(fail_buf, local_fail_buf, sizeof(fail_buf));
> }
Wow ! I haven't used such sophisticated versions of jmpbuf, and
have not seen any description of such wizardry. One obvious
concern: if this is inside exeterm() , will the memcpy have
to be executed for every instruction (even the simplest operators
such as dup ?). I take it that this would slow down execution
for everything, but I do not know by how much. Also, do these
buffers get allocated on the stack or elsewhere, do they need
GC? I am completely lost about these matters.
- Manfred