Work in progress - new RPL exception handlers

This commit is contained in:
claudiol 2016-12-02 17:05:17 -05:00
parent d0c5373d5e
commit 32daa580f4
6 changed files with 140 additions and 26 deletions

View file

@ -429,7 +429,7 @@ rplSetEntryPoint(obj);
rplRun();
// DISCARD ANY ERRORS DURING EXECUTION, IDEALLY IT HIT THE BREAKPOINT
if(Exceptions!=EX_BKPOINT) {
if(Exceptions!=EX_HALT) {
// THERE WAS SOME OTHER ERROR DURING EXECUTION, DISCARD ALL OUTPUT FROM THE FAILED PROGRAM
rplClearData();
}
@ -4081,22 +4081,23 @@ void halOuterLoop()
}
// DO OTHER IDLE PROCESSING HERE
isidle=1;
halSetBusyHandler();
if (halCheckSystemAlarm()) {
jobdone=isidle=0;
halTriggerAlarm();
}
} else {
jobdone=isidle=0;
halSetBusyHandler();
}
// DO OTHER IDLE PROCESSING HERE
isidle=1;
} else { jobdone=isidle=0; }
halSetBusyHandler();
} while(!halProcessKey(keymsg));

View file

@ -240,7 +240,7 @@ LIBS += -L/usr/local/lib
DISTFILES +=
QMAKE_CFLAGS += -Wno-duplicate-decl-specifier
#QMAKE_CFLAGS += -Wno-duplicate-decl-specifier

View file

@ -69,16 +69,26 @@ void rplCatchException()
Exceptions=0; // RESET THE EXCEPTIONS TO ALLOW HANDLER TO RUN
// SET INSTRUCTION POINTER AND CONTINUE EXECUTION AT THE ERROR HANDLER
IPtr=ErrorHandler-1; // MAKE SURE THE FIRST OBJECT AT THE ERROR HANDLER IS NOT SKIPPED
CurOpcode=0;
if(ISPROLOG(*ErrorHandler) && (LIBNUM(*ErrorHandler)==DOCOL)) {
// SPECIAL LOW-LEVEL ERROR HANDLER
// SPECIAL LOW-LEVEL TRANSPARENT ERROR HANDLER
// DO NOT CLEANUP ANYTHING OR REMOVE THE HANDLER
rplPushRet(IPtr); // PUSH THE OFFENDING OPCODE TO RESUME AFTER THE ERROR HANDLER FINISHED
rplSetExceptionHandler((WORDPTR)error_reenter_seco);
// TRANSPARENT ERROR HANDLERS MUST ENSURE ALL STACK, RSTACK AND LOCALS ARE LEFT INTACT
rplPushRet((WORDPTR)exiterror_seco); // UPON NORMAL RETURN
IPtr=ErrorHandler; // SKIP THE PROLOG OF THE SECO, SO THAT SEMI RETURNS DIRECTLY TO exiterror_seco
CurOpcode=0;
} else {
rplRemoveExceptionHandler();
// SET INSTRUCTION POINTER AND CONTINUE EXECUTION AT THE ERROR HANDLER
IPtr=ErrorHandler-1; // MAKE SURE THE FIRST OBJECT AT THE ERROR HANDLER IS NOT SKIPPED
CurOpcode=0;
}
} else rplRemoveExceptionHandler();
}

View file

@ -33,6 +33,8 @@
CMD(XEQSECO,MKTOKENINFO(7,TITYPE_NOTALLOWED,1,2)), \
ECMD(SEMI,";",MKTOKENINFO(1,TITYPE_NOTALLOWED,1,2)), \
CMD(EVAL1NEXT,MKTOKENINFO(9,TITYPE_NOTALLOWED,1,2)), \
ECMD(ERROR_EXIT,"",MKTOKENINFO(0,TITYPE_NOTALLOWED,1,2)), \
CMD(RESUME,MKTOKENINFO(6,TITYPE_NOTALLOWED,1,2)), \
CMD(DOERR,MKTOKENINFO(5,TITYPE_NOTALLOWED,1,2)), \
CMD(ERRN,MKTOKENINFO(4,TITYPE_NOTALLOWED,1,2)), \
CMD(ERRM,MKTOKENINFO(4,TITYPE_NOTALLOWED,1,2)), \
@ -63,6 +65,11 @@ ROMOBJECT errormsg_ident[]={
TEXT2WORD('r','M','s','g')
};
ROMOBJECT exiterror_seco[]={
CMD_ERROR_EXIT
};
// EXTERNAL EXPORTED OBJECT TABLE
// UP TO 64 OBJECTS ALLOWED, NO MORE
const WORDPTR const ROMPTR_TABLE[]={
@ -86,7 +93,7 @@ void LIB_HANDLER()
rplException(EX_EXITRPL);
return;
case BKPOINT:
rplException(EX_BKPOINT);
rplException(EX_HALT);
return;
case XEQSECO:
// IF THE NEXT OBJECT IN THE SECONDARY
@ -119,6 +126,98 @@ void LIB_HANDLER()
// SINCE IPtr POINTS TO THE NEXT OBJECT, IT WILL BE SKIPPED
return;
case ERROR_EXIT:
// THIS IS CALLED ONLY WHEN INSIDE AN ERROR HANDLER TO CLEANUP AND EXIT
// JUST LIKE A NORMAL ERROR HANDLER WOULD
// THE RETURN STACK CAN NEVER BE EMPTY (CHECK THAT) AND IT SHOULD HAVE:
// ON NORMAL RETURN FROM AN ERROR HANDLER:
// 1: ... SPECIAL ERROR HANDLER ... 4: IPtr TO RESUME 5: ... OLD ERROR HANDLER
{
if(rplDepthRet()<5) {
// THIS OPCODE WAS NOT CALLED FROM WITHIN AN ERROR HANDLER, JUST DO EXITRPL
rplException(EX_EXITRPL);
return;
}
if(ErrorHandler!=(WORDPTR)error_reenter_seco) {
// NOT WITHIN AN ERROR HANDLER
rplException(EX_EXITRPL);
return;
}
rplRemoveExceptionHandler(); // REMOVE THE REENTRANT EXCEPTION HANDLER
IPtr=rplPopRet(); // GET THE CALLER ADDRESS
if(IPtr) CurOpcode=*IPtr; // SET THE WORD SO MAIN LOOP SKIPS THIS OBJECT, AND THE NEXT ONE IS EXECUTED
rplRemoveExceptionHandler();
return; // AND CONTINUE EXECUTION AS IF SEMI WAS EXECUTED
}
if((rplDepthRet()<11)||(rplPeekRet(5)!=(WORDPTR)errorexit_seco)) {
// THIS OPCODE WAS NOT CALLED AS AN ERROR WITHIN AN ERROR HANDLER, JUST DO EXITRPL
rplException(EX_EXITRPL);
return;
}
// ERROR IN THE ERROR HANDLER?
rplRemoveExceptionHandler(); // REMOVE THE ERROR HANDLER WITHIN THE ERROR HANDLER
rplPopRet(); // REMOVE THE errorexit HANDLER
rplPopRet(); // REMOVE THE RESUME ADDRESS
rplRemoveExceptionHandler(); // REMOVE THE OLD EXCEPTION HANDLER
// AND DO SEMI, WHICH WILL PUT IPtr TO EXECUTE THE ENDERR WORD
IPtr=rplPopRet(); // GET THE CALLER ADDRESS
if(IPtr) CurOpcode=*IPtr; // SET THE WORD SO MAIN LOOP SKIPS THIS OBJECT, AND THE NEXT ONE IS EXECUTED
return;
}
case RESUME:
// THIS IS CALLED ONLY WHEN INSIDE AN ERROR HANDLER TO "RESUME" THE ORIGINAL CODE
// JUST AFTER THE OPCODE THAT CAUSED THE EXCEPTION
// THE RETURN STACK CAN NEVER BE EMPTY (CHECK THAT) AND IT SHOULD HAVE:
// ON NORMAL RETURN FROM AN ERROR HANDLER:
// 1: errorexit_seco, 2: IPtr, 3: ... OLD ERROR HANDLER ...
{
if(rplDepthRet()<7) {
// THIS OPCODE WAS NOT CALLED FROM WITHIN AN ERORR HANDLER, JUST DO EXITRPL
rplException(EX_EXITRPL);
return;
}
if(rplPeekRet(1)==(WORDPTR)errorexit_seco) {
// THIS OPCODE WAS CALLED AS A NORMAL RETURN FROM AN ERROR HANDLER
rplPopRet(); // REMOVE THE errorexit HANDLER
rplPopRet(); // REMOVE THE RESUME ADDRESS
rplRemoveExceptionHandler(); // REMOVE THE OLD EXCEPTION HANDLER
IPtr=rplPopRet(); // GET THE CALLER ADDRESS
if(IPtr) CurOpcode=*IPtr; // SET THE WORD SO MAIN LOOP SKIPS THIS OBJECT, AND THE NEXT ONE IS EXECUTED
return; // AND CONTINUE EXECUTION AS IF SEMI WAS EXECUTED
}
if((rplDepthRet()<11)||(rplPeekRet(5)!=(WORDPTR)errorexit_seco)) {
// THIS OPCODE WAS NOT CALLED AS AN ERROR WITHIN AN ERROR HANDLER, JUST DO EXITRPL
rplException(EX_EXITRPL);
return;
}
// ERROR IN THE ERROR HANDLER?
rplRemoveExceptionHandler(); // REMOVE THE ERROR HANDLER WITHIN THE ERROR HANDLER
rplPopRet(); // REMOVE THE errorexit HANDLER
rplPopRet(); // REMOVE THE RESUME ADDRESS
rplRemoveExceptionHandler(); // REMOVE THE OLD EXCEPTION HANDLER
// AND DO SEMI, WHICH WILL PUT IPtr TO EXECUTE THE ENDERR WORD
IPtr=rplPopRet(); // GET THE CALLER ADDRESS
if(IPtr) CurOpcode=*IPtr; // SET THE WORD SO MAIN LOOP SKIPS THIS OBJECT, AND THE NEXT ONE IS EXECUTED
return;
}
case DOERR:
// THROW AN ERROR BY EITHER A STRING OR ERROR CODE
{

View file

@ -178,8 +178,9 @@ void rplClearErrors();
void rplBlameUserCommand();
void rplBlameError(WORDPTR command);
#define CLEAN_RUN 0
#define NEEDS_CLEANUP 1
#define CODE_HALTED 2
// ENVIRONMENT FUNCTIONS IN RUNSTREAM.C
void rplInit();
@ -708,7 +709,7 @@ void rplSkipNextAlarm();
// DEFINED EXCEPTIONS
#define EX_EXITRPL 1
#define EX_BKPOINT 2
#define EX_HALT 2
#define EX_OUTOFMEM 4
#define EX_ERRORCODE 8
#define EX_POWEROFF 16

View file

@ -255,25 +255,28 @@ BINT rplRun(void)
else {
rplError(ERR_MISSINGLIBRARY);
// INVALID OPCODE = END OF EXECUTION (CANNOT BE TRAPPED BY HANDLER)
return 1;
return NEEDS_CLEANUP;
}
if(Exceptions) {
// HARD EXCEPTIONS FIRST, DO NOT ALLOW ERROR HANDLERS TO CATCH THESE ONES
if(Exceptions&EX_EXITRPL) {
Exceptions=0;
rplClearRStk(); // CLEAR THE RETURN STACK
rplClearLAMs(); // CLEAR ALL LOCAL VARIABLES
ErrorHandler=0;
return 0; // DON'T ALLOW HANDLER TO TRAP THIS EXCEPTION
return CLEAN_RUN; // DON'T ALLOW HANDLER TO TRAP THIS EXCEPTION
}
if(Exceptions&EX_HALT) { rplSkipNext(); return CODE_HALTED; } // PREPARE TO RESUME ON NEXT CALL
if(Exceptions&EX_POWEROFF) { rplSkipNext(); return CODE_HALTED; } // PREPARE AUTORESUME
if(ErrorHandler) {
// ERROR WAS TRAPPED BY A HANDLER
rplCatchException();
}
else {
// THERE IS NO ERROR HANDLER --> UNTRAPPED ERROR
if(Exceptions&EX_BKPOINT) rplSkipNext(); // PREPARE TO RESUME ON NEXT CALL
if(Exceptions&EX_POWEROFF) { rplSkipNext(); return 2; }
return 1; // END EXECUTION IMMEDIATELY IF AN UNHANDLED EXCEPTION IS THROWN
return NEEDS_CLEANUP; // END EXECUTION IMMEDIATELY IF AN UNHANDLED EXCEPTION IS THROWN
}
}