mirror of
https://git.code.sf.net/p/newrpl/sources
synced 2024-11-16 19:51:25 +01:00
370 lines
9.2 KiB
C
370 lines
9.2 KiB
C
// LIBRARY ZERO HAS SPECIAL RUNSTREAM OPERATORS
|
|
|
|
#include "newrpl.h"
|
|
#include "libraries.h"
|
|
#include "hal.h"
|
|
// THERE'S ONLY ONE EXTERNAL FUNCTION: THE LIBRARY HANDLER
|
|
// ALL OTHER FUNCTIONS ARE LOCAL
|
|
// LIB0 PROVIDES EXIT FROM RPL, BREAKPOINTS AND RUNSTREAM MANIPULATION OPCODES
|
|
|
|
// MAIN LIBRARY NUMBER, CHANGE THIS FOR EACH LIBRARY
|
|
#define LIBRARY_NUMBER 26
|
|
#define LIB_ENUM lib26_enum
|
|
#define LIB_NAMES lib26_names
|
|
#define LIB_HANDLER lib26_handler
|
|
#define LIB_NUMBEROFCMDS LIB26_NUMBEROFCMDS
|
|
|
|
// LIST OF COMMANDS EXPORTED, CHANGE FOR EACH LIBRARY
|
|
#define CMD_LIST \
|
|
CMD(PUT), \
|
|
CMD(PUTI), \
|
|
CMD(GET), \
|
|
CMD(GETI), \
|
|
CMD(HEAD), \
|
|
CMD(TAIL)
|
|
|
|
// ADD MORE OPCODES HERE
|
|
|
|
|
|
// EXTRA LIST FOR COMMANDS WITH SYMBOLS THAT ARE DISALLOWED IN AN ENUM
|
|
// THE NAMES AND ENUM SYMBOLS ARE GIVEN SEPARATELY
|
|
#define CMD_EXTRANAME \
|
|
"}", \
|
|
"->LIST", \
|
|
"OBJ->"
|
|
|
|
#define CMD_EXTRAENUM \
|
|
ENDLIST, \
|
|
TOLIST, \
|
|
INNERCOMP
|
|
|
|
//
|
|
|
|
// INTERNAL DECLARATIONS
|
|
|
|
|
|
// CREATE AN ENUM WITH THE OPCODE NAMES FOR THE DISPATCHER
|
|
#define CMD(a) a
|
|
enum LIB_ENUM { CMD_LIST , CMD_EXTRAENUM , LIB_NUMBEROFCMDS };
|
|
#undef CMD
|
|
|
|
// AND A LIST OF STRINGS WITH THE NAMES FOR THE COMPILER
|
|
#define CMD(a) #a
|
|
char *LIB_NAMES[]= { CMD_LIST , CMD_EXTRANAME };
|
|
#undef CMD
|
|
|
|
|
|
// EXPAND A COMPOSITE IN THE STACK AND STORES THE NUMBER OF ELEMENTS AT THE END
|
|
// USES 2 SCRATCH POINTERS
|
|
|
|
BINT rplExplodeList(WORDPTR composite)
|
|
{
|
|
BINT count=0;
|
|
ScratchPointer1=composite+1;
|
|
ScratchPointer2=composite+OBJSIZE(*composite); // POINT TO THE END MARKER
|
|
while(ScratchPointer1<ScratchPointer2) {
|
|
rplPushData(ScratchPointer1);
|
|
ScratchPointer1=rplSkipOb(ScratchPointer1);
|
|
++count;
|
|
}
|
|
rplNewBINTPush(count,DECBINT);
|
|
return count;
|
|
}
|
|
|
|
// CREATE A NEW LIST. STACK LEVEL 1 = NUMBER OF ELEMENTS, LEVELS 2.. N+1 = OBJECTS
|
|
// USES 1 SCRATCH POINTER
|
|
void rplCreateList()
|
|
{
|
|
// NO ARGUMENT CHECKING
|
|
BINT64 num=rplReadNumberAsBINT(rplPeekData(1));
|
|
if(rplDepthData()<num+1) {
|
|
Exceptions|=EX_BADARGCOUNT;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
BINT size=1; // 1 WORD FOR THE END MARKER
|
|
BINT count;
|
|
for(count=0;count<num;++count) {
|
|
size+=rplObjSize(rplPeekData(2+count));
|
|
}
|
|
|
|
// ALLOCATE MEMORY
|
|
WORDPTR list=rplAllocTempOb(size);
|
|
if(!list) {
|
|
Exceptions|=EX_OUTOFMEM;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
|
|
// CONSTRUCT THE OBJECT
|
|
WORDPTR objptr=list+1;
|
|
*list=MKPROLOG(LIBRARY_NUMBER,size);
|
|
for(count=num;count>0;--count) {
|
|
rplCopyObject(objptr,rplPeekData(count+1));
|
|
objptr+=rplObjSize(objptr);
|
|
}
|
|
*objptr=MKOPCODE(LIBRARY_NUMBER,ENDLIST);
|
|
|
|
rplDropData(num);
|
|
rplOverwriteData(1,list);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void LIB_HANDLER()
|
|
{
|
|
if(ISPROLOG(CurOpcode)) {
|
|
// PROVIDE BEHAVIOR OF EXECUTING THE OBJECT HERE
|
|
rplPushData(IPtr);
|
|
return;
|
|
}
|
|
|
|
switch(OPCODE(CurOpcode))
|
|
{
|
|
case PUT:
|
|
{
|
|
// CHECK ARGUMENTS
|
|
if(rplDepthData()<3) {
|
|
Exceptions|=EX_BADARGCOUNT;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
|
|
WORDPTR list=rplPeekData(3);
|
|
WORDPTR *var=0;
|
|
if(ISIDENT(*list)) {
|
|
var=rplFindLAM(list);
|
|
if(!var) {
|
|
var=rplFindGlobal(list,1);
|
|
if(!var) {
|
|
Exceptions|=EX_BADARGTYPE;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
|
|
}
|
|
list=*(var+1);
|
|
}
|
|
if(!ISLIST(*list)) {
|
|
Exceptions|=EX_BADARGTYPE;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
|
|
if(!ISNUMBER(*rplPeekData(2))) {
|
|
Exceptions|=EX_BADARGTYPE;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
|
|
BINT nitems=rplExplodeList(list);
|
|
BINT position=rplReadNumberAsBINT(rplPeekData(nitems+3));
|
|
if(Exceptions) return;
|
|
|
|
if(position<1 || position>nitems) {
|
|
Exceptions|=EX_BADARGVALUE;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
rplOverwriteData(nitems+2-position,rplPeekData(nitems+2));
|
|
|
|
rplCreateList();
|
|
|
|
rplOverwriteData(4,rplPeekData(1));
|
|
rplDropData(3);
|
|
|
|
if(var) {
|
|
*(var+1)=rplPopData();
|
|
}
|
|
|
|
}
|
|
return;
|
|
case PUTI:
|
|
return;
|
|
|
|
case GET:
|
|
{
|
|
// CHECK ARGUMENTS
|
|
if(rplDepthData()<2) {
|
|
Exceptions|=EX_BADARGCOUNT;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
WORDPTR list=rplPeekData(2);
|
|
WORDPTR *var=0;
|
|
if(ISIDENT(*list)) {
|
|
var=rplFindLAM(list);
|
|
if(!var) {
|
|
var=rplFindGlobal(list,1);
|
|
if(!var) {
|
|
Exceptions|=EX_BADARGTYPE;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
|
|
}
|
|
list=*(var+1);
|
|
}
|
|
if(!ISLIST(*list)) {
|
|
Exceptions|=EX_BADARGTYPE;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
|
|
if(!ISNUMBER(*rplPeekData(1))) {
|
|
Exceptions|=EX_BADARGTYPE;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
|
|
BINT nitems=rplExplodeList(list);
|
|
BINT position=rplReadNumberAsBINT(rplPeekData(nitems+2));
|
|
if(Exceptions) return;
|
|
if(position<1 || position>nitems) {
|
|
Exceptions|=EX_BADARGVALUE;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
rplOverwriteData(nitems+3,rplPeekData(nitems+2-position));
|
|
rplDropData(nitems+2);
|
|
}
|
|
return;
|
|
|
|
|
|
|
|
case GETI:
|
|
case HEAD:
|
|
case TAIL:
|
|
return;
|
|
case ENDLIST:
|
|
return;
|
|
case TOLIST:
|
|
if(rplDepthData()<1) {
|
|
Exceptions|=EX_BADARGCOUNT;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
if(!ISNUMBER(*rplPeekData(1))) {
|
|
Exceptions|=EX_BADARGTYPE;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
|
|
rplCreateList();
|
|
|
|
return;
|
|
case INNERCOMP:
|
|
if(rplDepthData()<1) {
|
|
Exceptions|=EX_BADARGCOUNT;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
if(!ISLIST(*rplPeekData(1))) {
|
|
Exceptions|=EX_BADARGTYPE;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
}
|
|
|
|
rplExplodeList(rplPopData());
|
|
|
|
return;
|
|
|
|
|
|
// ADD MORE OPCODES HERE
|
|
|
|
// STANDARIZED OPCODES:
|
|
// --------------------
|
|
// LIBRARIES ARE FORCED TO ALWAYS HANDLE THE STANDARD OPCODES
|
|
|
|
|
|
case OPCODE_COMPILE:
|
|
// COMPILE RECEIVES:
|
|
// TokenStart = token string
|
|
// TokenLen = token length
|
|
// BlankStart = token blanks afterwards
|
|
// BlanksLen = blanks length
|
|
// CurrentConstruct = Opcode of current construct/WORD of current composite
|
|
|
|
// COMPILE RETURNS:
|
|
// RetNum = enum CompileErrors
|
|
|
|
// CHECK IF THE TOKEN IS THE OPEN BRACKET
|
|
|
|
if((TokenLen==1) && (!strncmp((char * )TokenStart,"{",1)))
|
|
{
|
|
rplCompileAppend((WORD) MKPROLOG(LIBRARY_NUMBER,0));
|
|
RetNum=OK_STARTCONSTRUCT;
|
|
return;
|
|
}
|
|
// CHECK IF THE TOKEN IS THE CLOSING BRACKET
|
|
|
|
if(((TokenLen==1) && (!strncmp((char *)TokenStart,"}",1))))
|
|
{
|
|
if(CurrentConstruct!=MKPROLOG(LIBRARY_NUMBER,0)) {
|
|
RetNum=ERR_SYNTAX;
|
|
return;
|
|
}
|
|
rplCompileAppend(MKOPCODE(LIBRARY_NUMBER,ENDLIST));
|
|
RetNum=OK_ENDCONSTRUCT;
|
|
return;
|
|
}
|
|
|
|
// THIS STANDARD FUNCTION WILL TAKE CARE OF COMPILATION OF STANDARD COMMANDS GIVEN IN THE LIST
|
|
// NO NEED TO CHANGE THIS UNLESS CUSTOM OPCODES
|
|
libCompileCmds(LIBRARY_NUMBER,LIB_NAMES,NULL,LIB_NUMBEROFCMDS);
|
|
|
|
// SINCE THIS IS THE LAST LIBRARY TO BE EVALUATED, DO ONE LAST PASS TO COMPILE IT AS AN IDENT
|
|
// EITHER LAM OR IN USEROB
|
|
return;
|
|
|
|
case OPCODE_DECOMPILE:
|
|
// DECOMPILE RECEIVES:
|
|
// DecompileObject = Ptr to WORD of object to decompile
|
|
// DecompStringEnd = Ptr to the end of decompile string
|
|
|
|
//DECOMPILE RETURNS
|
|
// RetNum = enum DecompileErrors
|
|
|
|
if(ISPROLOG(*DecompileObject)) {
|
|
rplDecompAppendString((BYTEPTR)" { ");
|
|
RetNum=OK_STARTCONSTRUCT;
|
|
return;
|
|
}
|
|
|
|
|
|
// THIS STANDARD FUNCTION WILL TAKE CARE OF DECOMPILING STANDARD COMMANDS GIVEN IN THE LIST
|
|
// NO NEED TO CHANGE THIS UNLESS THERE ARE CUSTOM OPCODES
|
|
libDecompileCmds(LIB_NAMES,NULL,LIB_NUMBEROFCMDS);
|
|
return;
|
|
case OPCODE_VALIDATE:
|
|
// VALIDATE RECEIVES OPCODES COMPILED BY OTHER LIBRARIES, TO BE INCLUDED WITHIN A COMPOSITE OWNED BY
|
|
// THIS LIBRARY. EVERY COMPOSITE HAS TO EVALUATE IF THE OBJECT BEING COMPILED IS ALLOWED INSIDE THIS
|
|
// COMPOSITE OR NOT. FOR EXAMPLE, A REAL MATRIX SHOULD ONLY ALLOW REAL NUMBERS INSIDE, ANY OTHER
|
|
// OPCODES SHOULD BE REJECTED AND AN ERROR THROWN.
|
|
// TokenStart = token string
|
|
// TokenLen = token length
|
|
// ArgNum2 = Opcode/WORD of object
|
|
|
|
// VALIDATE RETURNS:
|
|
// RetNum = enum CompileErrors
|
|
|
|
|
|
|
|
return;
|
|
}
|
|
// BY DEFAULT, ISSUE A BAD OPCODE ERROR
|
|
Exceptions|=EX_BADOPCODE;
|
|
ExceptionPointer=IPtr;
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|