diff --git a/newrpl/compiler.c b/newrpl/compiler.c index 48587c1..601b79b 100644 --- a/newrpl/compiler.c +++ b/newrpl/compiler.c @@ -563,17 +563,19 @@ WORDPTR rplCompile(BYTEPTR string,BINT length, BINT addwrapper) if(!previous_tokeninfo || (TI_TYPE(previous_tokeninfo)>TITYPE_OPERATORS)) { // THIS IS A PARENTHESIS FOLLOWING AN OPERATOR // PUSH THE NEW OPERATOR - if(RStkSize<=(InfixOpTop+1-(WORDPTR)RStk)) growRStk(InfixOpTop-(WORDPTR)RStk+RSTKSLACK); + if(RStkSize<=(InfixOpTop+3-(WORDPTR)RStk)) growRStk(InfixOpTop-(WORDPTR)RStk+RSTKSLACK); if(Exceptions) { LAMTop=LAMTopSaved; return 0; } InfixOpTop[0]=CompileEnd-TempObEnd; // SAVE POSITION TO START COUNTING ARGUMENTS InfixOpTop[1]=probe_tokeninfo; - InfixOpTop+=2; + InfixOpTop[2]=Opcode; // SAVE OPCODE TO DISTINGUISH BRACKET TYPES + InfixOpTop[3]=probe_tokeninfo; + InfixOpTop+=4; } else { // THIS IS EITHER MATRIX/VECTOR INDEXING OR A USER FUNCTION CALL // PUSH OPERATOR FUNCEVAL FIRST - if(RStkSize<=(InfixOpTop+3-(WORDPTR)RStk)) growRStk(InfixOpTop-(WORDPTR)RStk+RSTKSLACK); + if(RStkSize<=(InfixOpTop+5-(WORDPTR)RStk)) growRStk(InfixOpTop-(WORDPTR)RStk+RSTKSLACK); if(Exceptions) { LAMTop=LAMTopSaved; return 0; } InfixOpTop[0]=(CMD_OVR_FUNCEVAL); // SAVE POSITION TO START COUNTING ARGUMENTS InfixOpTop[1]=MKTOKENINFO(TI_LENGTH(previous_tokeninfo),TITYPE_FUNCTION,0xf,2); @@ -582,7 +584,9 @@ WORDPTR rplCompile(BYTEPTR string,BINT length, BINT addwrapper) // THEN THE OPENING BRACKET InfixOpTop[0]=CompileEnd-TempObEnd; // SAVE POSITION TO START COUNTING ARGUMENTS InfixOpTop[1]=probe_tokeninfo; - InfixOpTop+=2; + InfixOpTop[2]=Opcode; // SAVE OPCODE TO DISTINGUISH BRACKET TYPES + InfixOpTop[3]=probe_tokeninfo; + InfixOpTop+=4; } @@ -593,7 +597,16 @@ WORDPTR rplCompile(BYTEPTR string,BINT length, BINT addwrapper) // POP ALL OPERATORS OFF THE STACK UNTIL THE OPENING BRACKET IS FOUND while(InfixOpTop>(WORDPTR)ValidateTop){ - if((TI_TYPE(*(InfixOpTop-1))==TITYPE_OPENBRACKET)) break; + if((TI_TYPE(*(InfixOpTop-1))==TITYPE_OPENBRACKET)) { + // CHECK IF THE BRACKET IS THE RIGHT TYPE OF BRACKET + if((TI_TYPE(probe_tokeninfo)==TITYPE_CLOSEBRACKET) &&(*(InfixOpTop-2)!=Opcode)) { + // MISMATCHED BRACKET TYPE + rplError(ERR_MISSINGBRACKET); + LAMTop=LAMTopSaved; + return 0; + } + break; + } // POP OPERATORS OFF THE STACK AND APPLY TO OBJECTS InfixOpTop-=2; if(!rplInfixApply(InfixOpTop[0],TI_NARGS(InfixOpTop[1]))) @@ -614,9 +627,10 @@ WORDPTR rplCompile(BYTEPTR string,BINT length, BINT addwrapper) if(TI_TYPE(probe_tokeninfo)==TITYPE_CLOSEBRACKET) { // COUNT THE NUMBER OF ARGUMENTS WE HAVE // REMOVE THE OPENING BRACKET - InfixOpTop-=2; + InfixOpTop-=4; BINT nargs=0; + WORD brackettype=InfixOpTop[2]; // OPCODE WITH BRACKET TYPE TO DISTINGUISH BRACKETS WORDPTR list=TempObEnd+InfixOpTop[0]; WORDPTR ptr=CompileEnd; @@ -625,8 +639,7 @@ WORDPTR rplCompile(BYTEPTR string,BINT length, BINT addwrapper) // CHECK IF THE TOP OF STACK IS A FUNCTION - if(InfixOpTop>(WORDPTR)ValidateTop) { - if(TI_TYPE(*(InfixOpTop-1))==TITYPE_FUNCTION) { + if((InfixOpTop>(WORDPTR)ValidateTop)&&(TI_TYPE(*(InfixOpTop-1))==TITYPE_FUNCTION)) { BINT needargs=(BINT)TI_NARGS(*(InfixOpTop-1)); if((needargs!=0xf) && (nargs!=needargs)) { rplError(ERR_BADARGCOUNT); @@ -652,7 +665,23 @@ WORDPTR rplCompile(BYTEPTR string,BINT length, BINT addwrapper) } } + else { + // THERE'S NO FUNCTION ON THE STACK, USE THE BRACKET THE MAIN OPERATOR + if((brackettype!=CMD_OPENBRACKET)||(nargs>1)) { + + if(!rplInfixApply(brackettype,nargs)) + { + LAMTop=LAMTopSaved; + return 0; + } + + + + } + + } + } else { // THE PARAMETER IS A COMMA // DO NOTHING FOR NOW @@ -1433,6 +1462,31 @@ end_of_expression: } + case TITYPE_OPENBRACKET: + { + // DECOMPILE THE OPERATOR NOW, THEN ADD PARENTHESIS FOR THE LIST + CurOpcode=MKOPCODE(LIBNUM(*DecompileObject),(flags&DECOMP_EDIT)? OPCODE_DECOMPEDIT:OPCODE_DECOMPILE); + DecompMode=infixmode|(flags<<16); + + RetNum=-1; + if(handler) { + // PROTECT OPERATOR'S STACK FROM BEING OVERWRITTEN + WORDPTR *tmpRSTop=RSTop; + RSTop=(WORDPTR *)InfixOpTop; + + (*handler)(); + RSTop=tmpRSTop; + } + // IGNORE THE RESULT OF DECOMPILATION + if(RetNum!=OK_CONTINUE) { + rplDecompAppendString((BYTEPTR)"##INVALID##"); + } + + ++DecompileObject; + infixmode=INFIX_FUNCARGUMENT; + break; + } + case TITYPE_FUNCTION: default: // DECOMPILE THE OPERATOR NOW, THEN ADD PARENTHESIS FOR THE LIST @@ -1801,11 +1855,41 @@ end_of_expression: WORDPTR EndofExpression = rplSkipOb(*(signed int *)(InfixOpTop-4)+EndOfObject); if(DecompileObject==EndofExpression) { - rplDecompAppendChar(')'); + LIBHANDLER handler; + // ADD THE OPERATOR AFTER THE OPERAND + WORD functype=*(InfixOpTop-1); + + if(TI_TYPE(functype)==TITYPE_OPENBRACKET) { + BINT libnum=LIBNUM(*(InfixOpTop-2)); + WORD closebracket; + closebracket=*(InfixOpTop-2)+1; + DecompileObject=&closebracket; + CurOpcode=MKOPCODE(libnum,(flags&DECOMP_EDIT)? OPCODE_DECOMPEDIT:OPCODE_DECOMPILE); + DecompMode=infixmode|(flags<<16); + handler=rplGetLibHandler(libnum); + RetNum=-1; + + if(handler) { + // PROTECT OPERATOR'S STACK FROM BEING OVERWRITTEN + WORDPTR *tmpRSTop=RSTop; + RSTop=(WORDPTR *)InfixOpTop; + (*handler)(); + RSTop=tmpRSTop; + } + + // IGNORE THE RESULT OF DECOMPILATION + if(RetNum!=OK_CONTINUE) { + rplDecompAppendString((BYTEPTR)"##INVALID##"); + } + } + else rplDecompAppendChar(')'); + // END OF THIS EXPRESSION // POP EXPRESSION FROM THE STACK InfixOpTop-=4; // RESTORE PREVIOUS EXPRESSION STATE + + infixmode=InfixOpTop[1]; DecompileObject=rplSkipOb(*(signed int *)InfixOpTop+EndOfObject); if(!infixmode) rplDecompAppendChar('\''); diff --git a/newrpl/lib-56-symbolic.c b/newrpl/lib-56-symbolic.c index 241f279..84442df 100644 --- a/newrpl/lib-56-symbolic.c +++ b/newrpl/lib-56-symbolic.c @@ -30,7 +30,7 @@ #define COMMAND_LIST \ ECMD(RULESEPARATOR,":→",MKTOKENINFO(2,TITYPE_BINARYOP_LEFT,2,14)), \ - ECMD(OPENBRACKET,"(",MKTOKENINFO(1,TITYPE_OPENBRACKET,0,31)), \ + ECMD(OPENBRACKET,"(",MKTOKENINFO(1,TITYPE_OPENBRACKET,0,1)), \ ECMD(CLOSEBRACKET,")",MKTOKENINFO(1,TITYPE_CLOSEBRACKET,0,31)), \ ECMD(COMMA,"",MKTOKENINFO(1,TITYPE_COMMA,0,31)), \ ECMD(SYMBEVALPRE,"",MKTOKENINFO(0,TITYPE_NOTALLOWED,1,2)), \ @@ -46,8 +46,10 @@ CMD(RULEMATCH,MKTOKENINFO(9,TITYPE_NOTALLOWED,1,2)), \ CMD(RULEAPPLY,MKTOKENINFO(9,TITYPE_NOTALLOWED,1,2)), \ ECMD(TOFRACTION,"→Q",MKTOKENINFO(2,TITYPE_FUNCTION,1,2)), \ - ECMD(SYMBEVAL1CHK,"",MKTOKENINFO(0,TITYPE_NOTALLOWED,1,2)) - + ECMD(SYMBEVAL1CHK,"",MKTOKENINFO(0,TITYPE_NOTALLOWED,1,2)), \ + ECMD(EQUATIONOPERATOR,"=",MKTOKENINFO(1,TITYPE_BINARYOP_LEFT,2,15)), \ + ECMD(LISTOPENBRACKET,"{",MKTOKENINFO(1,TITYPE_OPENBRACKET,0,1)), \ + ECMD(LISTCLOSEBRACKET,"}",MKTOKENINFO(1,TITYPE_CLOSEBRACKET,0,31)) // CMD(TEST,MKTOKENINFO(4,TITYPE_NOTALLOWED,1,2)) @@ -895,6 +897,13 @@ void LIB_HANDLER() rplSetExceptionHandler(IPtr+5); // SET THE EXCEPTION HANDLER TO THE SYMBEVAL1ERR WORD + if((Opcode==CMD_OPENBRACKET) || (Opcode==CMD_LISTOPENBRACKET)) { + // SPECIAL CASE, THESE COMMANDS NEED THE NUMBER OF ARGUMENTS PUSHED ON THE STACK + rplNewBINTPush(newdepth,DECBINT); + + + } + 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 @@ -1494,11 +1503,57 @@ void LIB_HANDLER() case RULESEPARATOR: //@SHORT_DESC=@HIDE + return; case OPENBRACKET: //@SHORT_DESC=@HIDE + { + // OPERATOR USED IN SYMBOLIC NUMBERS, SHOULD CREATE SOME KIND OF SET OF NUMBERS, A LIST FOR NOW + if(rplDepthData()<2) { + rplError(ERR_BADARGCOUNT); + return; + } + + rplCreateList(); + return; + } case CLOSEBRACKET: //@SHORT_DESC=@HIDE - return; + return; + case LISTOPENBRACKET: + //@SHORT_DESC=@HIDE + if(rplDepthData()<1) { + rplError(ERR_BADARGCOUNT); + return; + } + + rplCreateList(); + return; + case LISTCLOSEBRACKET: + //@SHORT_DESC=@HIDE + + case EQUATIONOPERATOR: + //@SHORT_DESC=@HIDE + { + if(rplDepthData()<2) { + rplError(ERR_BADARGCOUNT); + return; + } + + WORDPTR arg1=rplPeekData(2); + WORDPTR arg2=rplPeekData(1); + + + // ALLOW LIST PROCESSING AND MATRIX PROCESSING FIRST + if(ISLIST(*arg1) || ISLIST(*arg2)){ + rplListBinaryDoCmd(arg1,arg2); + return; + } + + // MAKE SURE WE KEEP THE EQUALITY WHEN EVAL'd + rplSymbApplyOperator(CurOpcode,2); + return; + } + // STANDARIZED OPCODES: // -------------------- @@ -1534,7 +1589,7 @@ void LIB_HANDLER() if(*tok==')') { if((TokenLen==1) && (CurrentConstruct==MKPROLOG(DOSYMB,0))) { - rplCompileAppend(MKOPCODE(LIBRARY_NUMBER,CLOSEBRACKET)); + rplCompileAppend(MKOPCODE(LIBRARY_NUMBER,OPENBRACKET)); // INDICATE THE OPENING BRACKET TO MATCH RetNum=OK_CONTINUE; } else RetNum=ERR_NOTMINE; @@ -1549,6 +1604,27 @@ void LIB_HANDLER() return; } + if(*tok=='{') { + if((TokenLen==1)&&(CurrentConstruct==MKPROLOG(DOSYMB,0))) { + rplCompileAppend(MKOPCODE(LIBRARY_NUMBER,LISTOPENBRACKET)); + RetNum=OK_CONTINUE; + } + else RetNum=ERR_NOTMINE; + return; + } + if(*tok=='}') { + if((TokenLen==1)&&(CurrentConstruct==MKPROLOG(DOSYMB,0))) { + // ISSUE A BUILDLIST OPERATOR + rplCompileAppend(MKOPCODE(LIBRARY_NUMBER,LISTOPENBRACKET)); + RetNum=OK_CONTINUE; + } + else RetNum=ERR_NOTMINE; + return; + } + + + + if( (TokenLen==2) && !utf8ncmp2((char *)tok,(char *)BlankStart,":→",2)) { if(CurrentConstruct==MKPROLOG(DOSYMB,0)) { rplCompileAppend(MKOPCODE(LIBRARY_NUMBER,RULESEPARATOR)); @@ -1635,17 +1711,7 @@ void LIB_HANDLER() RetNum= OK_ENDCONSTRUCT_INFIX; return; } -/* - if(*((char *)TokenStart)=='(') { - RetNum= OK_TOKENINFO | MKTOKENINFO(1,TITYPE_OPENBRACKET,0,31); - return; - } - if(*((char *)TokenStart)==')') { - RetNum= OK_TOKENINFO | MKTOKENINFO(1,TITYPE_CLOSEBRACKET,0,31); - return; - } -*/ if((WORD)utf82cp((char *)TokenStart,(char *)BlankStart)==ARG_SEP(Locale)) { RetNum= OK_TOKENINFO | MKTOKENINFO(1,TITYPE_COMMA,0,31); return; diff --git a/newrpl/lib-62-lists.c b/newrpl/lib-62-lists.c index 5a5b414..9497871 100644 --- a/newrpl/lib-62-lists.c +++ b/newrpl/lib-62-lists.c @@ -2967,8 +2967,12 @@ void LIB_HANDLER() // RetNum = OK_TOKENINFO | MKTOKENINFO(...) WITH THE INFORMATION ABOUT THE CURRENT TOKEN // OR RetNum = ERR_NOTMINE IF NO TOKEN WAS FOUND { + if(*((char *)TokenStart)=='}') { + // FOUND END OF LIST WITHIN A SYMBOLIC COMPILATION. JUST IGNORE AND LET THE SYMBOLIC LIBRARY HANDLE IT + RetNum=ERR_NOTMINE; + return; + } libProbeCmds((char **)LIB_NAMES,(BINT *)LIB_TOKENINFO,LIB_NUMBEROFCMDS); - return; }