Added function call syntax for matrix. Improved functions call safety. Improved error display on symbolic evaluation.

This commit is contained in:
claudiol 2017-12-28 13:09:30 -05:00
parent 3387c6849b
commit 7528134cda
18 changed files with 279 additions and 106 deletions

View file

@ -454,7 +454,9 @@ if(iseval) {
if(RSTop>=RStk+rstksave) {
RSTop=RStk+rstksave;
// BLAME THE ERROR ON THE COMMAND WE CALLED
if(BlameCmd!=0) rplBlameError(BlameCmd);
if(!rplIsTempObPointer(ExceptionPointer)){
if(BlameCmd!=0) rplBlameError(BlameCmd);
}
}
else { rplCleanup(); halFlags&=~(HAL_HALTED|HAL_AUTORESUME|HAL_FASTAUTORESUME); }
if(LAMTop>LAMs+lamsave) LAMTop=LAMs+lamsave;

View file

@ -1452,9 +1452,14 @@ const WORD const text_editor_string[]={
WORDPTR halGetCommandName(WORDPTR NameObject)
{
WORD Opcode=*NameObject;
WORD Opcode=NameObject? *NameObject : 0;
if(Opcode==0) return (WORDPTR)text_editor_string;
if(ISSYMBOLIC(Opcode)) {
NameObject=rplSymbMainOperatorPTR(NameObject);
Opcode=*NameObject;
}
if(ISPROLOG(Opcode)) {
// ONLY ACCEPT IDENTS AND STRINGS AS COMMAND NAMES
if(ISSTRING(Opcode)) return NameObject;

View file

@ -1073,6 +1073,7 @@ void LIB_HANDLER()
}
return;
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
case OVR_XEQ:

View file

@ -1860,6 +1860,7 @@ case TVARSE:
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
case OVR_XEQ:

View file

@ -6367,6 +6367,7 @@ void LIB_HANDLER()
else rplPushData((WORDPTR)one_bint);
return;
}
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
case OVR_XEQ:

View file

@ -108,6 +108,14 @@ ROMOBJECT lamistrue_seco[]={
CMD_SEMI
};
ROMOBJECT lamfunceval_seco[]={
MKPROLOG(DOCOL,5),
MKOPCODE(LIBRARY_NUMBER,LAMEVALPRE),
(CMD_OVR_FUNCEVAL), // DO THE EVAL
MKOPCODE(LIBRARY_NUMBER,LAMEVALPOST), // POST-PROCESS RESULTS AND CLOSE THE LOOP
MKOPCODE(LIBRARY_NUMBER,LAMEVALERR), // ERROR HANDLER
CMD_SEMI
};
// INTERNAL RPL PROGRAM THAT CALLS ABND
ROMOBJECT abnd_prog[]=
@ -297,7 +305,7 @@ void LIB_HANDLER()
rplOverwriteData(1,*(val+1)); // REPLACE THE FIRST LEVEL WITH THE VALUE
rplPushRet(IPtr);
IPtr=(WORDPTR) lameval_seco;
IPtr=(WORDPTR) lamfunceval_seco;
CurOpcode=(CMD_OVR_EVAL);
}
return;
@ -368,6 +376,7 @@ void LIB_HANDLER()
if(!val) {
// INEXISTENT VARIABLE CANNOT BE CONVERTED TO NUMBER
rplError(ERR_UNDEFINEDVARIABLE);
rplBlameError(rplPeekData(1));
return;
}
}
@ -412,6 +421,8 @@ void LIB_HANDLER()
if(!val) {
// INEXISTENT VARIABLE CANNOT BE CONVERTED TO NUMBER
rplError(ERR_UNDEFINEDVARIABLE);
rplBlameError(rplPeekData(1));
return;
}
}
@ -626,6 +637,8 @@ void LIB_HANDLER()
}
else {
rplError(ERR_UNDEFINEDVARIABLE);
rplBlameError(rplPeekData(1));
return;
}
}
@ -682,8 +695,13 @@ void LIB_HANDLER()
return;
}
case LAMEVALERR:
// SAME PROCEDURE AS ENDERR
rplRemoveExceptionHandler();
rplPopRet();
rplUnprotectData();
rplRemoveExceptionHandler();
// JUST CLEANUP AND EXIT
//DSTop=rplUnprotectData();
rplCleanupLAMs(0);
IPtr=rplPopRet();
Exceptions=TrappedExceptions;

View file

@ -157,6 +157,7 @@ void rplCallOvrOperator(WORD op)
// RESPOND TO OVERLOADED OPERATORS LIKE A LIBRARY HANDLER
switch(OPCODE(op))
{
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
case OVR_XEQ:

View file

@ -328,6 +328,68 @@ void LIB_HANDLER()
return;
}
case OVR_FUNCEVAL:
// EVALUATING A MATRIX OR VECTOR AS A FUNCTION GETS THE ELEMENT
{
WORDPTR comp=rplPeekData(1);
WORDPTR posobj;
BINT rows,cols,ndims;
BINT posrow,poscol;
rows=rplMatrixRows(comp);
cols=rplMatrixCols(comp);
if(!rows) {
// THIS IS A VECTOR
ndims=1;
rows=1;
} else ndims=2; // IT'S A 2D MATRIX
if(rplDepthData()<ndims+1) {
rplError(ERR_INVALIDPOSITION);
return;
}
// CHECK IF WE HAVE THE RIGHT POSITION
posobj=rplPeekData(2);
poscol=rplReadNumberAsBINT(posobj);
if(Exceptions) {
rplError(ERR_INVALIDPOSITION);
return;
}
if(ndims==2) {
// READ THE SECOND COORDINATE (COLUMN)
posobj=rplPeekData(3);
posrow=rplReadNumberAsBINT(posobj);
if(Exceptions) {
rplError(ERR_INVALIDPOSITION);
return;
}
} else posrow=1;
// CHECK IF THE POSITION IS WITHIN THE MATRIX
if( (posrow<1) || (posrow>rows) || (poscol<1) || (poscol>cols)) {
rplError(ERR_INDEXOUTOFBOUNDS);
return;
}
WORDPTR item=rplMatrixGet(comp,posrow,poscol);
if(!item) {
rplError(ERR_INDEXOUTOFBOUNDS);
return;
}
rplOverwriteData(1+ndims,item);
rplDropData(ndims);
return;
}
case OVR_EVAL:
// EVAL NEEDS TO SCAN THE MATRIX, EVAL EACH ARGUMENT SEPARATELY AND REBUILD IT.
{

View file

@ -198,6 +198,7 @@ void LIB_HANDLER()
switch(OPCODE(CurOpcode))
{
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
case OVR_XEQ:

View file

@ -268,7 +268,16 @@ void LIB_HANDLER()
if(Exceptions) { rplCleanupLAMs(0); return; }
object++;
if(Opcode) object++;
if(Opcode) {
object++;
if(OPCODE(Opcode)==OVR_FUNCEVAL) {
// DON'T MARK THE LAST OBJECT AS THE END OF OBJECT
WORDPTR lastobj=object;
while(rplSkipOb(lastobj)!=endobject) lastobj=rplSkipOb(lastobj);
endobject=lastobj;
}
}
rplCreateLAM((WORDPTR)nulllam_ident,endobject); // LAM 2 = END OF CURRENT OBJECT
if(Exceptions) { rplCleanupLAMs(0); return; }
@ -304,6 +313,15 @@ void LIB_HANDLER()
return;
}
case OVR_FUNCEVAL:
{
// A SYMBOLIC OBJECT CANNOT BE FUNCEVALED
rplError(ERR_INVALIDUSERDEFINEDFUNCTION);
return;
}
case OVR_EVAL:
// EVAL NEEDS TO SCAN THE SYMBOLIC, EVAL EACH ARGUMENT SEPARATELY AND APPLY THE OPCODE.
{
@ -335,7 +353,16 @@ void LIB_HANDLER()
if(Exceptions) { rplCleanupLAMs(0); return; }
object++;
if(Opcode) object++;
if(Opcode) {
object++;
if(OPCODE(Opcode)==OVR_FUNCEVAL) {
// DON'T MARK THE LAST OBJECT AS THE END OF OBJECT
WORDPTR lastobj=object;
while(rplSkipOb(lastobj)!=endobject) lastobj=rplSkipOb(lastobj);
endobject=lastobj;
}
}
rplCreateLAM((WORDPTR)nulllam_ident,endobject); // LAM 2 = END OF CURRENT OBJECT
if(Exceptions) { rplCleanupLAMs(0); return; }
@ -442,7 +469,16 @@ void LIB_HANDLER()
if(Exceptions) { rplCleanupLAMs(0); return; }
object++;
if(Opcode) object++;
if(Opcode) {
object++;
if(OPCODE(Opcode)==OVR_FUNCEVAL) {
// DON'T MARK THE LAST OBJECT AS THE END OF OBJECT
WORDPTR lastobj=object;
while(rplSkipOb(lastobj)!=endobject) lastobj=rplSkipOb(lastobj);
endobject=lastobj;
}
}
rplCreateLAM((WORDPTR)nulllam_ident,endobject); // LAM 2 = END OF CURRENT OBJECT
if(Exceptions) { rplCleanupLAMs(0); return; }
@ -808,46 +844,73 @@ void LIB_HANDLER()
BINT newdepth=(BINT)(DSTop-prevDStk);
if(Opcode) {
if( (newdepth!=1) || (Opcode!=(CMD_OVR_FUNCEVAL))) {
if(Opcode==(CMD_OVR_FUNCEVAL)) {
// DO MINIMAL TYPE CHECKING, LAST ARGUMENT HAS TO BE
// AN IDENT, OTHERWISE THE RESULT IS INVALID
if(!ISIDENT(*rplPeekData(1))) {
// IT SHOULD ACTUALLY RETURN SOMETHING LIKE "INVALID USER FUNCTION"
DSTop=rplUnprotectData();
rplCleanupLAMs(0);
IPtr=rplPopRet();
rplError(ERR_INVALIDUSERDEFINEDFUNCTION);
CurOpcode=(CMD_OVR_EVAL1);
return;
}
}
// DO SYMBOLIC WRAP ON ALL OBJECTS THAT ARE NOT MATRICES OR LISTS
else rplSymbWrapN(1,newdepth);
// PUSH THE OPERATOR IN THE STACK AND EVAL IT. THIS SHOULD APPLY THE OPERATOR IF THE RESULT IS SYMBOLIC
// OTHERWISE IT WILL CALCULATE IT
rplSetExceptionHandler(IPtr+3); // SET THE EXCEPTION HANDLER TO THE SYMBEVAL1ERR WORD
if((Opcode==CMD_OVR_MUL)||(Opcode==CMD_OVR_ADD)) {
// CHECK FOR FLATTENED LIST, APPLY MORE THAN ONCE IF MORE THAN 2 ARGUMENTS
if(newdepth<=2) rplPutLAMn(1,(WORDPTR)zero_bint); // SIGNAL OPCODE IS DONE
}
else rplPutLAMn(1,(WORDPTR)zero_bint); // SIGNAL OPCODE IS DONE
// PUSH THE NEXT OBJECT IN THE STACK
rplPushData(Opcodeptr);
// AND EXECUTION WILL CONTINUE AT EVAL1
if(Opcode==CMD_OVR_FUNCEVAL) {
// SPECIAL CASE, ALL ARGUMENTS WERE EVALUATED BUT ACTUAL FUNCTION NEEDS TO BE CALLED HERE
rplPushData(endoflist);
++newdepth;
// DO MINIMAL TYPE CHECKING, LAST ARGUMENT HAS TO BE
// AN IDENT, OTHERWISE THE RESULT IS INVALID
if(!ISIDENT(*rplPeekData(1))) {
// IT SHOULD ACTUALLY RETURN SOMETHING LIKE "INVALID USER FUNCTION"
DSTop=rplUnprotectData();
rplCleanupLAMs(0);
IPtr=rplPopRet();
rplError(ERR_INVALIDUSERDEFINEDFUNCTION);
CurOpcode=(CMD_OVR_EVAL);
return;
}
rplSetExceptionHandler(IPtr+3); // SET THE EXCEPTION HANDLER TO THE SYMBEVAL1ERR WORD
// PUSH THE NEXT OBJECT IN THE STACK
rplPushData(Opcodeptr);
rplPutLAMn(1,(WORDPTR)zero_bint); // SIGNAL OPCODE IS DONE
// AND EXECUTION WILL CONTINUE AT EVAL
return;
}
if(newdepth!=1)
// DO SYMBOLIC WRAP ON ALL OBJECTS THAT ARE NOT MATRICES OR LISTS
rplSymbWrapN(1,newdepth);
// PUSH THE OPERATOR IN THE STACK AND EVAL IT. THIS SHOULD APPLY THE OPERATOR IF THE RESULT IS SYMBOLIC
// OTHERWISE IT WILL CALCULATE IT
rplSetExceptionHandler(IPtr+3); // SET THE EXCEPTION HANDLER TO THE SYMBEVAL1ERR WORD
if((Opcode==CMD_OVR_MUL)||(Opcode==CMD_OVR_ADD)) {
// CHECK FOR FLATTENED LIST, APPLY MORE THAN ONCE IF MORE THAN 2 ARGUMENTS
if(newdepth<=2) rplPutLAMn(1,(WORDPTR)zero_bint); // SIGNAL OPCODE IS DONE
}
else rplPutLAMn(1,(WORDPTR)zero_bint); // SIGNAL OPCODE IS DONE
// PUSH THE NEXT OBJECT IN THE STACK
rplPushData(Opcodeptr);
// AND EXECUTION WILL CONTINUE AT EVAL
return;
}
if(newdepth!=1) {
rplCleanupLAMs(0);
IPtr=rplPopRet();
@ -895,6 +958,7 @@ void LIB_HANDLER()
}
case SYMBEVAL1ERR:
// SAME PROCEDURE AS ENDERR
rplBlameError(*rplGetLAMn(4)); // BLAME THE ERROR ON THE LAST OBJECT EVALUATED
rplRemoveExceptionHandler();
rplPopRet();
rplUnprotectData();
@ -907,7 +971,7 @@ void LIB_HANDLER()
IPtr=rplPopRet();
Exceptions=TrappedExceptions;
ErrorCode=TrappedErrorCode;
ExceptionPointer=IPtr;
CurOpcode=(CMD_OVR_EVAL1);
return;
@ -950,32 +1014,44 @@ void LIB_HANDLER()
if(Opcode) {
if( (newdepth!=1) || (Opcode!=(CMD_OVR_FUNCEVAL))) {
if(Opcode==(CMD_OVR_FUNCEVAL)) {
// DO MINIMAL TYPE CHECKING, LAST ARGUMENT HAS TO BE
// AN IDENT, OTHERWISE THE RESULT IS INVALID
if(!ISIDENT(*rplPeekData(1))) {
// IT SHOULD ACTUALLY RETURN SOMETHING LIKE "INVALID USER FUNCTION"
DSTop=rplUnprotectData();
rplCleanupLAMs(0);
IPtr=rplPopRet();
rplError(ERR_INVALIDUSERDEFINEDFUNCTION);
CurOpcode=(CMD_OVR_EVAL);
return;
}
if(Opcode==CMD_OVR_FUNCEVAL) {
// SPECIAL CASE, ALL ARGUMENTS WERE EVALUATED BUT ACTUAL FUNCTION NEEDS TO BE CALLED HERE
rplPushData(endoflist);
++newdepth;
// DO MINIMAL TYPE CHECKING, LAST ARGUMENT HAS TO BE
// AN IDENT, OTHERWISE THE RESULT IS INVALID
if(!ISIDENT(*rplPeekData(1))) {
// IT SHOULD ACTUALLY RETURN SOMETHING LIKE "INVALID USER FUNCTION"
DSTop=rplUnprotectData();
rplCleanupLAMs(0);
IPtr=rplPopRet();
rplError(ERR_INVALIDUSERDEFINEDFUNCTION);
CurOpcode=(CMD_OVR_EVAL);
return;
}
rplSetExceptionHandler(IPtr+3); // SET THE EXCEPTION HANDLER TO THE SYMBEVAL1ERR WORD
// PUSH THE NEXT OBJECT IN THE STACK
rplPushData(Opcodeptr);
rplPutLAMn(1,(WORDPTR)zero_bint); // SIGNAL OPCODE IS DONE
// AND EXECUTION WILL CONTINUE AT EVAL
return;
}
if(newdepth!=1)
// DO SYMBOLIC WRAP ON ALL OBJECTS THAT ARE NOT MATRICES OR LISTS
else rplSymbWrapN(1,newdepth);
rplSymbWrapN(1,newdepth);
// PUSH THE OPERATOR IN THE STACK AND EVAL IT. THIS SHOULD APPLY THE OPERATOR IF THE RESULT IS SYMBOLIC
// OTHERWISE IT WILL CALCULATE IT
rplSetExceptionHandler(IPtr+3); // SET THE EXCEPTION HANDLER TO THE SYMBEVAL1ERR WORD
if((Opcode==CMD_OVR_MUL)||(Opcode==CMD_OVR_ADD)) {
// CHECK FOR FLATTENED LIST, APPLY MORE THAN ONCE IF MORE THAN 2 ARGUMENTS
if(newdepth<=2) rplPutLAMn(1,(WORDPTR)zero_bint); // SIGNAL OPCODE IS DONE
@ -990,19 +1066,6 @@ void LIB_HANDLER()
return;
/*
rplSymbApplyOperator(Opcode,newdepth);
newdepth=(BINT)(DSTop-prevDStk);
if(Exceptions) {
rplCleanupLAMs(0);
IPtr=rplPopRet();
ExceptionPointer=IPtr;
CurOpcode=(CMD_OVR_EVAL);
return;
}
*/
}
}
if(newdepth!=1) {
rplCleanupLAMs(0);
@ -1051,6 +1114,8 @@ void LIB_HANDLER()
}
case SYMBEVALERR:
// SAME PROCEDURE AS ENDERR
rplBlameError(*rplGetLAMn(4)); // BLAME THE ERROR ON THE LAST OBJECT EVALUATED
rplRemoveExceptionHandler();
rplPopRet();
rplUnprotectData();
@ -1062,7 +1127,7 @@ void LIB_HANDLER()
IPtr=rplPopRet();
Exceptions=TrappedExceptions;
ErrorCode=TrappedErrorCode;
ExceptionPointer=IPtr;
CurOpcode=(CMD_OVR_EVAL);
return;
@ -1089,21 +1154,39 @@ void LIB_HANDLER()
if(Opcode) {
if( (newdepth!=1) || (Opcode!=(CMD_OVR_FUNCEVAL))) {
if(Opcode==(CMD_OVR_FUNCEVAL)) {
// DO MINIMAL TYPE CHECKING, LAST ARGUMENT HAS TO BE
// AN IDENT, OTHERWISE THE RESULT IS INVALID
if(!ISIDENT(*rplPeekData(1))) {
// IT SHOULD ACTUALLY RETURN SOMETHING LIKE "INVALID USER FUNCTION"
DSTop=rplUnprotectData();
rplCleanupLAMs(0);
IPtr=rplPopRet();
rplError(ERR_INVALIDUSERDEFINEDFUNCTION);
CurOpcode=(CMD_OVR_NUM);
return;
}
if(Opcode==CMD_OVR_FUNCEVAL) {
// SPECIAL CASE, ALL ARGUMENTS WERE EVALUATED BUT ACTUAL FUNCTION NEEDS TO BE CALLED HERE
rplPushData(endoflist);
++newdepth;
// DO MINIMAL TYPE CHECKING, LAST ARGUMENT HAS TO BE
// AN IDENT, OTHERWISE THE RESULT IS INVALID
if(!ISIDENT(*rplPeekData(1))) {
// IT SHOULD ACTUALLY RETURN SOMETHING LIKE "INVALID USER FUNCTION"
DSTop=rplUnprotectData();
rplCleanupLAMs(0);
IPtr=rplPopRet();
rplError(ERR_INVALIDUSERDEFINEDFUNCTION);
CurOpcode=(CMD_OVR_EVAL);
return;
}
rplSetExceptionHandler(IPtr+3); // SET THE EXCEPTION HANDLER TO THE SYMBEVAL1ERR WORD
// PUSH THE NEXT OBJECT IN THE STACK
rplPushData(Opcodeptr);
rplPutLAMn(1,(WORDPTR)zero_bint); // SIGNAL OPCODE IS DONE
// AND EXECUTION WILL CONTINUE AT EVAL
IPtr+=3;
return;
}
if(newdepth!=1)
// DO SYMBOLIC WRAP ON ALL OBJECTS THAT ARE NOT MATRICES OR LISTS
rplSymbWrapN(1,newdepth);
// PUSH THE OPERATOR IN THE STACK AND EVAL IT. THIS SHOULD APPLY THE OPERATOR IF THE RESULT IS SYMBOLIC
// OTHERWISE IT WILL CALCULATE IT
@ -1114,29 +1197,18 @@ void LIB_HANDLER()
if(newdepth<=2) rplPutLAMn(1,(WORDPTR)zero_bint); // SIGNAL OPCODE IS DONE
}
else rplPutLAMn(1,(WORDPTR)zero_bint); // SIGNAL OPCODE IS DONE
// PUSH THE NEXT OBJECT IN THE STACK
rplPushData(Opcodeptr);
IPtr+=3; // AND EXECUTION WILL CONTINUE AT EVAL
// AND EXECUTION WILL CONTINUE AT EVAL
IPtr+=3;
return;
// DO THE OPERATION
/*WORDPTR *savedstop=DSTop;
rplCallOperator(Opcode);
newdepth=(BINT)(DSTop-prevDStk);
if(Exceptions) {
DSTop=savedstop;
rplCleanupLAMs(0);
IPtr=rplPopRet();
ExceptionPointer=IPtr;
CurOpcode=(CMD_OVR_NUM);
return;
}
*/
}
}
if(newdepth!=1) {
rplCleanupLAMs(0);
IPtr=rplPopRet();
@ -1194,6 +1266,8 @@ void LIB_HANDLER()
}
case SYMBNUMERR:
// SAME PROCEDURE AS ENDERR
rplBlameError(*rplGetLAMn(4)); // BLAME THE ERROR ON THE LAST OBJECT EVALUATED
rplRemoveExceptionHandler();
rplPopRet();
rplUnprotectData();
@ -1210,7 +1284,6 @@ void LIB_HANDLER()
Exceptions=TrappedExceptions;
ErrorCode=TrappedErrorCode;
ExceptionPointer=IPtr;
CurOpcode=(CMD_OVR_EVAL);
return;

View file

@ -440,6 +440,7 @@ void LIB_HANDLER()
}
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
case OVR_XEQ:

View file

@ -670,6 +670,7 @@ void LIB_HANDLER()
// APPLY UNARY OPERATOR DIRECTLY TO THE CONTENTS OF THE VARIABLE
switch(OPCODE(CurOpcode))
{
case OVR_FUNCEVAL:
case OVR_EVAL1:
case OVR_EVAL:
case OVR_XEQ:

View file

@ -629,6 +629,7 @@ void LIB_HANDLER()
}
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
case OVR_XEQ:

View file

@ -1419,6 +1419,7 @@ case SCLVIEW:
}
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
case OVR_XEQ:

View file

@ -789,6 +789,7 @@ void LIB_HANDLER()
case OVR_ISTRUE:
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
// EXECUTE THE OBJECT

View file

@ -121,6 +121,7 @@ void LIB_HANDLER()
return;
}
case OVR_ISTRUE:
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
case OVR_XEQ:

View file

@ -660,6 +660,7 @@ void LIB_HANDLER()
if(!Exceptions) rplCheckResultAndError(&Darg1);
}
return;
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
case OVR_XEQ:

View file

@ -1227,6 +1227,7 @@ void LIB_HANDLER()
op1=-op1;
rplNewBINTPush(op1,LIBNUM(*arg1));
return;
case OVR_FUNCEVAL:
case OVR_EVAL:
case OVR_EVAL1:
case OVR_XEQ: