mirror of
https://git.code.sf.net/p/newrpl/sources
synced 2024-11-16 19:51:25 +01:00
175 lines
4.2 KiB
C
175 lines
4.2 KiB
C
/*
|
|
* Copyright (c) 2014, Claudio Lapilli and the newRPL Team
|
|
* All rights reserved.
|
|
* This file is released under the 3-clause BSD license.
|
|
* See the file LICENSE.txt that shipped with this distribution.
|
|
*/
|
|
|
|
|
|
#include "libraries.h"
|
|
#include "newrpl.h"
|
|
|
|
|
|
#define ENDLIST 0 // NOTE: COORDINATE THIS WITH LIBRARY 26, FIRST OPCODE MUST BE ENDLIST
|
|
|
|
// 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;
|
|
}
|
|
|
|
BINT rplListLength(WORDPTR composite)
|
|
{
|
|
BINT count=0;
|
|
WORDPTR ptr=composite+1;
|
|
WORDPTR end=composite+OBJSIZE(*composite); // POINT TO THE END MARKER
|
|
while(ptr<end) {
|
|
ptr=rplSkipOb(ptr);
|
|
++count;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
|
|
|
|
// RETURN THE LENGTH OF A "FLAT" LIST, AS IF LISTS INSIDE THE LIST WERE EXPLODED
|
|
BINT rplListLengthFlat(WORDPTR composite)
|
|
{
|
|
BINT count=0,depth=0;
|
|
WORDPTR ptr=composite+1;
|
|
WORDPTR end=composite+OBJSIZE(*composite); // POINT TO THE END MARKER
|
|
while(ptr<end) {
|
|
if(ISLIST(*ptr)) {
|
|
++depth;
|
|
++ptr;
|
|
} else {
|
|
ptr=rplSkipOb(ptr);
|
|
if(*ptr==MKOPCODE(DOLIST,ENDLIST)) {
|
|
++ptr;
|
|
--depth;
|
|
}
|
|
++count;
|
|
}
|
|
}
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
// GET AN ELEMENT FROM A "FLAT" VIEW OF THE LIST
|
|
|
|
WORDPTR rplGetListElementFlat(WORDPTR composite, BINT pos)
|
|
{
|
|
BINT count=1;
|
|
WORDPTR ptr=composite+1;
|
|
WORDPTR end=composite+OBJSIZE(*composite); // POINT TO THE END MARKER
|
|
while(ptr<end && count<=pos) {
|
|
if(ISLIST(*ptr)) {
|
|
++ptr;
|
|
} else {
|
|
if(count==pos) break;
|
|
ptr=rplSkipOb(ptr);
|
|
if(*ptr==MKOPCODE(DOLIST,ENDLIST)) {
|
|
++ptr;
|
|
}
|
|
++count;
|
|
}
|
|
}
|
|
if(ptr==end) return NULL;
|
|
return ptr;
|
|
}
|
|
|
|
WORDPTR rplGetListElement(WORDPTR composite, BINT pos)
|
|
{
|
|
BINT count=1;
|
|
WORDPTR ptr=composite+1;
|
|
WORDPTR end=composite+OBJSIZE(*composite); // POINT TO THE END MARKER
|
|
while(ptr<end && count<pos) {
|
|
ptr=rplSkipOb(ptr);
|
|
++count;
|
|
}
|
|
if(ptr==end) return NULL;
|
|
return ptr;
|
|
}
|
|
|
|
// RETURNS FALSE (0) IF THE ELEMENT IS NOT AT THE END OF A SUBLIST IN A "FLAT" LIST
|
|
// OTHERWISE RETURNS THE POSITION OF THE FIRST ELEMENT IN THE LIST THAT CONTAINS THE OBJECT
|
|
|
|
BINT rplIsLastElementFlat(WORDPTR composite, BINT pos)
|
|
{
|
|
BINT count=1,depth=0,startpos=1;
|
|
WORDPTR ptr=composite+1;
|
|
WORDPTR end=composite+OBJSIZE(*composite); // POINT TO THE END MARKER
|
|
while(ptr<end && count<pos) {
|
|
if(ISLIST(*ptr)) {
|
|
++depth;
|
|
++ptr;
|
|
startpos=pos;
|
|
} else {
|
|
ptr=rplSkipOb(ptr);
|
|
if(*ptr==MKOPCODE(DOLIST,ENDLIST)) {
|
|
--depth;
|
|
++ptr;
|
|
}
|
|
++count;
|
|
}
|
|
}
|
|
|
|
if(ptr<end) {
|
|
ptr=rplSkipOb(ptr);
|
|
if(*ptr==MKOPCODE(DOLIST,ENDLIST)) return startpos;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
// 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(DOLIST,size);
|
|
for(count=num;count>0;--count) {
|
|
rplCopyObject(objptr,rplPeekData(count+1));
|
|
objptr+=rplObjSize(objptr);
|
|
}
|
|
*objptr=MKOPCODE(DOLIST,ENDLIST);
|
|
|
|
rplDropData(num);
|
|
rplOverwriteData(1,list);
|
|
}
|
|
|