Skip to content

Commit f346051

Browse files
committed
feat(zscript): ArrayPushAt/ArrayPopAt for arbitrary index push/pop
1 parent 89a17bc commit f346051

File tree

7 files changed

+135
-56
lines changed

7 files changed

+135
-56
lines changed

resources/docs/ZScript_Additions.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3228,6 +3228,22 @@ void DestroyArray(untyped[] arr);
32283228
* Immediately deallocates the specified array, if it is a local array.
32293229
* If the array is a global array, does nothing.
32303230

3231+
bool ArrayPushBack(untyped[] arr, untyped val);
3232+
bool ArrayPushFront(untyped[] arr, untyped val);
3233+
bool ArrayPushAt(untyped[] arr, untyped val, int indx);
3234+
* Increases the size of the array by 1, inserting a new value.
3235+
* The new value can either be inserted at the end, start, or an arbitrary index.
3236+
* An invalid index pushes to the end.
3237+
* Returns false if it fails for any reason (ex: array is at max size already)
3238+
3239+
untyped ArrayPushBack(untyped[] arr);
3240+
untyped ArrayPushFront(untyped[] arr);
3241+
untyped ArrayPushAt(untyped[] arr, int indx);
3242+
* Decreases the size of the array by 1, removing and returning a value.
3243+
* The new value can either be pulled from the end, start, or an arbitrary index.
3244+
* An invalid index pops from the end.
3245+
* Errors if array size is 0, and returns `-1`.
3246+
32313247
void OwnObject([Object] obj);
32323248
* Takes an object (see 'Classes and Objects' above)
32333249
* Transfers ownership of the object to the current script.

src/base/zc_array.h

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ class ZCArrayIterator
127127
pointer _ptr;
128128
};
129129

130-
131130
template <typename T>
132131
class ZCArray
133132
{
@@ -407,7 +406,7 @@ class ZCArray
407406
{
408407
Resize(0, _Y, _X);
409408
}
410-
void Resize(const size_type _Z, const size_type _Y, const size_type _X, const size_type offs = 0)
409+
void Resize(const size_type _Z, const size_type _Y, const size_type _X)
411410
{
412411
if(_SameDimensions(_Z,_Y,_X)) return;
413412
const size_type _OldSize = _size;
@@ -424,16 +423,17 @@ class ZCArray
424423
_ReAssign(_OldSize, _NewSize);
425424
}
426425

427-
void Push(type val, bool front)
426+
void Push(type val, int indx = -1)
428427
{
429-
Resize(_dim[2], _dim[1], _dim[0]+1, front?1:0);
430-
_ptr[front?0:_size-1] = val;
428+
++_dim[0];
429+
_ReAssign(_size, _size+1, indx, val);
431430
}
432431

433-
type Pop(bool front)
432+
type Pop(int indx = -1)
434433
{
435-
type ret = _ptr[front?0:_size-1];
436-
Resize(_dim[2], _dim[1], _dim[0]-1, front?1:0);
434+
type ret = _ptr[(indx<0||indx>=_size) ? _size-1 : indx];
435+
--_dim[0];
436+
_ReAssign(_size, _size-1, indx);
437437
return ret;
438438
}
439439

@@ -511,25 +511,54 @@ class ZCArray
511511
_size = size;
512512
}
513513

514-
void _ReAssign(const size_type _OldSize, const size_type _NewSize, size_type offs = 0)
514+
void _ReAssign(const size_type _OldSize, const size_type _NewSize, int indx = -1, type fillval = 0)
515515
{
516+
if(_NewSize == 0)
517+
{
518+
_Delete();
519+
return;
520+
}
521+
516522
pointer _oldPtr = _ptr;
517523
_ptr = new type[ _NewSize ];
524+
if(indx < 0 || indx > _size) indx = _size;
518525

519526
const size_type _copyRange = (_OldSize < _NewSize ? _OldSize : _NewSize);
520-
const size_type soffs = _OldSize < _NewSize ? 0 : offs;
521-
const size_type doffs = _OldSize < _NewSize ? offs : 0;
527+
const size_type size_diff = zc_max(_OldSize,_NewSize)-zc_min(_OldSize,_NewSize);
522528

523-
for(size_type i(0); i < _copyRange; i++)
524-
_ptr[ i+doffs ] = _oldPtr[ i+soffs ];
529+
if(indx == _size)
530+
{
531+
for(size_type i(0); i < _copyRange; i++)
532+
_ptr[ i ] = _oldPtr[ i ];
533+
if(_OldSize < _NewSize)
534+
Assign(_OldSize, _NewSize, fillval);
535+
}
536+
else if(_OldSize < _NewSize)
537+
{
538+
size_type offs = 0;
539+
for(size_type i(0); i < _copyRange; i++)
540+
{
541+
if(i==indx)
542+
{
543+
offs = size_diff;
544+
Assign(i, i+size_diff, fillval);
545+
}
546+
_ptr[ i+offs ] = _oldPtr[ i ];
547+
}
548+
}
549+
else
550+
{
551+
size_type offs = 0;
552+
for(size_type i(0); i < _copyRange; i++)
553+
{
554+
if(i==indx)
555+
offs = size_diff;
556+
_ptr[ i ] = _oldPtr[ i+offs ];
557+
}
558+
}
525559

526560
_Delete(_oldPtr);
527561
_size = _NewSize;
528-
if(_OldSize < _NewSize)
529-
{
530-
Assign(0, doffs, 0);
531-
Assign(_OldSize+doffs, _NewSize, 0);
532-
}
533562
}
534563

535564
void _Delete()

src/parser/ByteCode.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2465,24 +2465,22 @@ namespace ZScript
24652465
return new OCurrentItemID();
24662466
}
24672467
};
2468-
class OArrayPush : public UnaryOpcode
2468+
class OArrayPush : public Opcode
24692469
{
24702470
public:
2471-
OArrayPush(Argument *A) : UnaryOpcode(A) {}
24722471
std::string toString() const;
24732472
Opcode* clone() const
24742473
{
2475-
return new OArrayPush(a->clone());
2474+
return new OArrayPush();
24762475
}
24772476
};
2478-
class OArrayPop : public UnaryOpcode
2477+
class OArrayPop : public Opcode
24792478
{
24802479
public:
2481-
OArrayPop(Argument *A) : UnaryOpcode(A) {}
24822480
std::string toString() const;
24832481
Opcode* clone() const
24842482
{
2485-
return new OArrayPop(a->clone());
2483+
return new OArrayPop();
24862484
}
24872485
};
24882486
class OResrvdOpEmily17 : public Opcode

src/parser/symbols/GlobalSymbols.cpp

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,12 @@ static AccessorTable GlobalTable[] =
9696
{ "Min", 0, ZTID_UNTYPED, -1, FL_VARG, { ZTID_UNTYPED, ZTID_UNTYPED },{},2 },
9797
{ "Choose", 0, ZTID_UNTYPED, -1, FL_VARG, { ZTID_UNTYPED },{},1 },
9898

99-
{ "ArrayPushBack", 0, ZTID_VOID, -1, 0, { ZTID_UNTYPED, ZTID_UNTYPED },{} },
100-
{ "ArrayPushFront", 0, ZTID_VOID, -1, 0, { ZTID_UNTYPED, ZTID_UNTYPED },{} },
99+
{ "ArrayPushBack", 0, ZTID_BOOL, -1, 0, { ZTID_UNTYPED, ZTID_UNTYPED },{} },
100+
{ "ArrayPushFront", 0, ZTID_BOOL, -1, 0, { ZTID_UNTYPED, ZTID_UNTYPED },{} },
101+
{ "ArrayPushAt", 0, ZTID_BOOL, -1, 0, { ZTID_UNTYPED, ZTID_UNTYPED, ZTID_FLOAT },{} },
101102
{ "ArrayPopBack", 0, ZTID_UNTYPED, -1, 0, { ZTID_UNTYPED },{} },
102103
{ "ArrayPopFront", 0, ZTID_UNTYPED, -1, 0, { ZTID_UNTYPED },{} },
104+
{ "ArrayPopAt", 0, ZTID_UNTYPED, -1, 0, { ZTID_UNTYPED, ZTID_FLOAT },{} },
103105

104106
//Undocumented intentionally - compat only
105107
{ "Rand", 0, ZTID_FLOAT, -1, 0, { ZTID_FLOAT },{} },
@@ -1631,9 +1633,10 @@ void GlobalSymbols::generateCode()
16311633
Function* function = getFunction("ArrayPushFront");
16321634
int32_t label = function->getLabel();
16331635
vector<shared_ptr<Opcode>> code;
1634-
addOpcode2 (code, new OArrayPush(new LiteralArgument(10000)));
1636+
addOpcode2 (code, new OPushImmediate(new LiteralArgument(0)));
16351637
LABELBACK(label);
1636-
POP_ARGS(2,NUL);
1638+
addOpcode2 (code, new OArrayPush());
1639+
POP_ARGS(3,NUL);
16371640
RETURN();
16381641
function->giveCode(code);
16391642
}
@@ -1642,9 +1645,21 @@ void GlobalSymbols::generateCode()
16421645
Function* function = getFunction("ArrayPushBack");
16431646
int32_t label = function->getLabel();
16441647
vector<shared_ptr<Opcode>> code;
1645-
addOpcode2 (code, new OArrayPush(new LiteralArgument(0)));
1648+
addOpcode2 (code, new OPushImmediate(new LiteralArgument(-10000)));
16461649
LABELBACK(label);
1647-
POP_ARGS(2,NUL);
1650+
addOpcode2 (code, new OArrayPush());
1651+
POP_ARGS(3,NUL);
1652+
RETURN();
1653+
function->giveCode(code);
1654+
}
1655+
//void ArrayPushAt(untyped[] arr, untyped val, int indx)
1656+
{
1657+
Function* function = getFunction("ArrayPushAt");
1658+
int32_t label = function->getLabel();
1659+
vector<shared_ptr<Opcode>> code;
1660+
addOpcode2 (code, new OArrayPush());
1661+
LABELBACK(label);
1662+
POP_ARGS(3,NUL);
16481663
RETURN();
16491664
function->giveCode(code);
16501665
}
@@ -1653,9 +1668,10 @@ void GlobalSymbols::generateCode()
16531668
Function* function = getFunction("ArrayPopFront");
16541669
int32_t label = function->getLabel();
16551670
vector<shared_ptr<Opcode>> code;
1656-
addOpcode2 (code, new OArrayPop(new LiteralArgument(10000)));
1671+
addOpcode2 (code, new OPushImmediate(new LiteralArgument(0)));
16571672
LABELBACK(label);
1658-
POP_ARG(NUL);
1673+
addOpcode2 (code, new OArrayPop());
1674+
POP_ARGS(2,NUL);
16591675
RETURN();
16601676
function->giveCode(code);
16611677
}
@@ -1664,9 +1680,21 @@ void GlobalSymbols::generateCode()
16641680
Function* function = getFunction("ArrayPopBack");
16651681
int32_t label = function->getLabel();
16661682
vector<shared_ptr<Opcode>> code;
1667-
addOpcode2 (code, new OArrayPop(new LiteralArgument(0)));
1683+
addOpcode2 (code, new OPushImmediate(new LiteralArgument(-10000)));
16681684
LABELBACK(label);
1669-
POP_ARG(NUL);
1685+
addOpcode2 (code, new OArrayPop());
1686+
POP_ARGS(2,NUL);
1687+
RETURN();
1688+
function->giveCode(code);
1689+
}
1690+
//void ArrayPopAt(untyped[] arr, int indx)
1691+
{
1692+
Function* function = getFunction("ArrayPopAt");
1693+
int32_t label = function->getLabel();
1694+
vector<shared_ptr<Opcode>> code;
1695+
addOpcode2 (code, new OArrayPop());
1696+
LABELBACK(label);
1697+
POP_ARGS(2,NUL);
16701698
RETURN();
16711699
function->giveCode(code);
16721700
}

src/zc/ffscript.cpp

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2580,6 +2580,7 @@ void clearScriptHelperData()
25802580
// Array Helper Functions //
25812581
///---------------------------------------------//
25822582

2583+
#define ZCARRAY_MAX_SIZE 214748
25832584
class ArrayManager
25842585
{
25852586
public:
@@ -2591,8 +2592,8 @@ class ArrayManager
25912592
int32_t size() const;
25922593

25932594
bool resize(size_t newsize);
2594-
void push(int32_t val, bool front = false);
2595-
int32_t pop(bool front = false);
2595+
bool push(int32_t val, int indx = -1);
2596+
int32_t pop(int indx = -1);
25962597

25972598
bool invalid() const {return _invalid;}
25982599
bool internal() const {return !_invalid && !aptr;}
@@ -2959,26 +2960,33 @@ bool ArrayManager::resize(size_t newsize)
29592960
return true;
29602961
}
29612962

2962-
void ArrayManager::push(int32_t val, bool front)
2963+
bool ArrayManager::push(int32_t val, int indx)
29632964
{
2964-
if(_invalid) return;
2965+
if(_invalid) return false;
29652966
if(!aptr)
29662967
{
29672968
Z_scripterrlog("Special internal array '%d' not valid for operation 'Push'\n", ptr);
2968-
return;
2969+
return false;
29692970
}
2970-
aptr->Push(val,front);
2971-
return;
2971+
if(aptr->Size() == ZCARRAY_MAX_SIZE)
2972+
return false;
2973+
aptr->Push(val,indx);
2974+
return true;
29722975
}
2973-
int32_t ArrayManager::pop(bool front)
2976+
int32_t ArrayManager::pop(int indx)
29742977
{
29752978
if(_invalid) return -10000;
29762979
if(!aptr)
29772980
{
29782981
Z_scripterrlog("Special internal array '%d' not valid for operation 'Push'\n", ptr);
29792982
return -10000;
29802983
}
2981-
return aptr->Pop(front);
2984+
if(aptr->Empty())
2985+
{
2986+
Z_scripterrlog("Array %d had nothing to Pop!\n",ptr);
2987+
return -10000;
2988+
}
2989+
return aptr->Pop(indx);
29822990
}
29832991

29842992
std::string ArrayManager::asString(std::function<char const*(int32_t)> formatter, const size_t& limit) const
@@ -32351,19 +32359,19 @@ int32_t run_script_int(bool is_jitted)
3235132359
break;
3235232360
case ARRAYPUSH:
3235332361
{
32354-
bool front = sarg1!=0;
32355-
auto ptr = SH::read_stack(ri->sp + 1) / 10000;
32356-
auto val = SH::read_stack(ri->sp + 0);
32362+
auto ptr = SH::read_stack(ri->sp + 2) / 10000;
32363+
auto val = SH::read_stack(ri->sp + 1);
32364+
auto indx = SH::read_stack(ri->sp + 0) / 10000;
3235732365
ArrayManager am(ptr);
32358-
am.push(val,front);
32366+
ri->d[rEXP1] = am.push(val,indx) ? 10000 : 0;
3235932367
break;
3236032368
}
3236132369
case ARRAYPOP:
3236232370
{
32363-
bool front = sarg1!=0;
32364-
auto ptr = SH::read_stack(ri->sp + 0) / 10000;
32371+
auto ptr = SH::read_stack(ri->sp + 1) / 10000;
32372+
auto indx = SH::read_stack(ri->sp + 0) / 10000;
3236532373
ArrayManager am(ptr);
32366-
ri->d[rEXP1] = 10000 * am.pop(front);
32374+
ri->d[rEXP1] = am.pop(indx);
3236732375
break;
3236832376
}
3236932377

@@ -41583,8 +41591,8 @@ script_command ZASMcommands[NUMCOMMANDS+1]=
4158341591
{ "PRINTFA", 0, 0, 0, 0 },
4158441592
{ "SPRINTFA", 0, 0, 0, 0 },
4158541593
{ "CURRENTITEMID", 0, 0, 0, 0 },
41586-
{ "ARRAYPUSH", 1, 1, 0, 0 },
41587-
{ "ARRAYPOP", 1, 1, 0, 0 },
41594+
{ "ARRAYPUSH", 0, 0, 0, 0 },
41595+
{ "ARRAYPOP", 0, 0, 0, 0 },
4158841596
{ "RESRVD_OP_EMILY_17", 0, 0, 0, 0 },
4158941597
{ "RESRVD_OP_EMILY_18", 0, 0, 0, 0 },
4159041598
{ "RESRVD_OP_EMILY_19", 0, 0, 0, 0 },

src/zq/ffasm.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,8 +1156,8 @@ script_command command_list[NUMCOMMANDS+1]=
11561156
{ "PRINTFA", 0, 0, 0, 0 },
11571157
{ "SPRINTFA", 0, 0, 0, 0 },
11581158
{ "CURRENTITEMID", 0, 0, 0, 0 },
1159-
{ "ARRAYPUSH", 1, 1, 0, 0 },
1160-
{ "ARRAYPOP", 1, 1, 0, 0 },
1159+
{ "ARRAYPUSH", 0, 0, 0, 0 },
1160+
{ "ARRAYPOP", 0, 0, 0, 0 },
11611161
{ "RESRVD_OP_EMILY_17", 0, 0, 0, 0 },
11621162
{ "RESRVD_OP_EMILY_18", 0, 0, 0, 0 },
11631163
{ "RESRVD_OP_EMILY_19", 0, 0, 0, 0 },

webdocs/zsdocs_main.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,8 +1383,8 @@
13831383
"val": "<h3>void OwnArray(untyped[] arr);</h3>\nGrants ownership of the target array to the currently running script.\nIf this array is not a local array, nothing happens.\nIf it is a local array, the array will no longer be destroyed when it reaches the end of its' declaring scope- it will last until the owning script ends, at which point it will be freed.\n\n<h3>void DestroyArray(untyped[] arr);</h3>\nIf 'arr' is a local array, destroys it immediately. Otherwise does nothing."
13841384
},
13851385
{
1386-
"name": "Push / Pop ;; ArrayPushBack / ArrayPushFront / ArrayPopBack / ArrayPopFront",
1387-
"val": "<h3>void ArrayPushBack(untyped[] arr, untyped val);\nvoid ArrayPushFront(untyped[] arr, untyped val);</h3>\n\nIncreases the size of the array by 1, inserting 'val' at the back/front of the array;\n\n<h3>untyped ArrayPopBack(untyped[] arr);\nuntyped ArrayPopFront(untyped[] arr);</h3>\n\nDecreases the size of the array by 1, removing and returning the element at the back/front of the array."
1386+
"name": "Push / Pop ;; ArrayPushBack / ArrayPushFront / ArrayPushAt / ArrayPopBack / ArrayPopFront / ArrayPopAt",
1387+
"val": "<h3>bool ArrayPushBack(untyped[] arr, untyped val);\nbool ArrayPushFront(untyped[] arr, untyped val);\nbool ArrayPushAt(untyped[] arr, untyped val, int indx);</h3>\n\nIncreases the size of the array by 1, inserting 'val' at the back/front/specified index of the array. If an invalid index is passed, the back of the array will be targetted.\nReturns false if it fails for any reason, such as the array being max-sized already.\n\n<h3>untyped ArrayPopBack(untyped[] arr);\nuntyped ArrayPopFront(untyped[] arr);\nuntyped ArrayPopAt(untyped[] arr, int indx);</h3>\n\nDecreases the size of the array by 1, removing and returning the element at the back/front/specified index of the array. If an invalid index is passed, the back of the array will be targetted.\nErrors and returns `-1` if the array is size 0."
13881388
}
13891389
]
13901390
}

0 commit comments

Comments
 (0)