2021-07-09 21:56:13 +01:00
|
|
|
#include "model.h"
|
|
|
|
#include "compat.h"
|
|
|
|
#include "genericClass.h"
|
|
|
|
#include "intClass.h"
|
|
|
|
#include "arrayClass.h"
|
|
|
|
#include "garbageCollector.h"
|
|
|
|
#include "eval.h"
|
|
|
|
#include "scriptError.h"
|
|
|
|
#include "StringClass.h"
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
u8 anotherOneIntArg[] = { IntClass };
|
|
|
|
u8 oneStringoneFunction[] = { StringClass, FunctionClass };
|
2021-07-09 22:19:10 +01:00
|
|
|
u8 doubleInt[] = {IntClass, IntClass};
|
2021-07-09 21:56:13 +01:00
|
|
|
u8 oneIntOneAny[] = { IntClass, VARARGCOUNT };
|
|
|
|
u8 anotherAnotherOneVarArg[] = { VARARGCOUNT };
|
|
|
|
u8 oneByteArrayClass[] = {ByteArrayClass};
|
|
|
|
u8 oneIntArrayClass[] = {IntArrayClass};
|
|
|
|
|
|
|
|
Variable_t arrayClassGetIdx(Variable_t *caller, s64 idx) {
|
|
|
|
if (caller->variableType == IntArrayClass) {
|
|
|
|
s64* arr = caller->solvedArray.vector.data;
|
|
|
|
return newIntVariable(arr[idx]);
|
|
|
|
}
|
|
|
|
else if (caller->variableType == StringArrayClass) {
|
|
|
|
char** arr = caller->solvedArray.vector.data;
|
|
|
|
Variable_t v = newStringVariable(arr[idx], 1, 0);
|
|
|
|
v.readOnly = 1;
|
|
|
|
v.reference = 1;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
else if (caller->variableType == ByteArrayClass) {
|
|
|
|
u8* arr = caller->solvedArray.vector.data;
|
|
|
|
return newIntVariable(arr[idx]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (Variable_t) { 0 };
|
|
|
|
}
|
|
|
|
|
2021-07-09 22:19:10 +01:00
|
|
|
int arrayClassAdd(Variable_t *caller, Variable_t *add){
|
|
|
|
if (caller->variableType == IntArrayClass) {
|
|
|
|
if (add->variableType != IntClass) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
vecAdd(&caller->solvedArray.vector, add->integer.value);
|
|
|
|
}
|
|
|
|
else if (caller->variableType == StringArrayClass) {
|
|
|
|
if (add->variableType != StringClass) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char* str = CpyStr(add->string.value);
|
|
|
|
vecAdd(&caller->solvedArray.vector, str);
|
|
|
|
}
|
|
|
|
else if (caller->variableType == ByteArrayClass) {
|
|
|
|
if (add->variableType != IntClass) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 val = (u8)(add->integer.value & 0xFF);
|
|
|
|
vecAdd(&caller->solvedArray.vector, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-07-09 21:56:13 +01:00
|
|
|
ClassFunction(getArrayIdx) {
|
|
|
|
s64 getVal = (*args)->integer.value;
|
|
|
|
// Out of bounds
|
|
|
|
if (getVal < 0 || getVal >= caller->solvedArray.vector.count) {
|
|
|
|
SCRIPT_FATAL_ERR("Accessing index %d while array is %d long", (int)getVal, (int)caller->solvedArray.vector.count);
|
|
|
|
}
|
|
|
|
|
|
|
|
Variable_t a = arrayClassGetIdx(caller, getVal);
|
|
|
|
if (a.variableType == None)
|
|
|
|
return NULL;
|
|
|
|
return copyVariableToPtr(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassFunction(getArrayLen) {
|
|
|
|
return newIntVariablePtr(caller->solvedArray.vector.count);
|
|
|
|
}
|
|
|
|
|
2021-07-09 22:19:10 +01:00
|
|
|
ClassFunction(arraySlice) {
|
2021-07-09 21:56:13 +01:00
|
|
|
s64 skipAmount = getIntValue(*args);
|
2021-07-09 22:19:10 +01:00
|
|
|
s64 takeAmount = getIntValue(args[1]);
|
|
|
|
|
|
|
|
if (caller->solvedArray.vector.count < (skipAmount + takeAmount) || skipAmount <= 0 || takeAmount <= 0) {
|
|
|
|
SCRIPT_FATAL_ERR("Slicing out of range of array with len %d", (int)caller->solvedArray.vector.count);
|
2021-07-09 21:56:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Variable_t refSkip = { .variableType = SolvedArrayReferenceClass };
|
|
|
|
refSkip.solvedArray.arrayClassReference = caller;
|
|
|
|
refSkip.solvedArray.offset = skipAmount;
|
2021-07-09 22:19:10 +01:00
|
|
|
refSkip.solvedArray.len = takeAmount;
|
2021-07-09 21:56:13 +01:00
|
|
|
addPendingReference(caller);
|
|
|
|
return copyVariableToPtr(refSkip);
|
|
|
|
}
|
|
|
|
|
2021-07-10 00:12:39 +01:00
|
|
|
// TODO: arrayForEach does not like the new garbage collector
|
2021-07-09 21:56:13 +01:00
|
|
|
ClassFunction(arrayForEach) {
|
|
|
|
Vector_t* v = &caller->solvedArray.vector;
|
|
|
|
|
|
|
|
Callback_SetVar_t setVar = { .isTopLevel = 1, .varName = (*args)->string.value };
|
|
|
|
Variable_t* iter = NULL;
|
|
|
|
iter = copyVariableToPtr(newIntVariable(0));
|
2021-07-10 00:12:39 +01:00
|
|
|
iter->gcDoNotFree = 1;
|
2021-07-09 21:56:13 +01:00
|
|
|
runtimeVariableEdit(&setVar, iter);
|
|
|
|
|
|
|
|
for (int i = 0; i < v->count; i++) {
|
|
|
|
*iter = arrayClassGetIdx(caller, i);
|
2021-07-10 00:12:39 +01:00
|
|
|
iter->gcDoNotFree = 1;
|
2021-07-09 21:56:13 +01:00
|
|
|
|
|
|
|
Variable_t* res = genericCallDirect(args[1], NULL, 0);
|
2021-07-10 13:45:09 +01:00
|
|
|
if (res == NULL) {
|
|
|
|
if (scriptLastError == SCRIPT_BREAK) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
2021-07-09 21:56:13 +01:00
|
|
|
}
|
|
|
|
|
2021-07-10 00:12:39 +01:00
|
|
|
iter->reference = 1;
|
|
|
|
free(iter);
|
|
|
|
|
2021-07-09 21:56:13 +01:00
|
|
|
return &emptyClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassFunction(arrayCopy) {
|
|
|
|
Vector_t* v = &caller->solvedArray.vector;
|
|
|
|
Vector_t copiedArray = vecCopy(v);
|
|
|
|
Variable_t var = { .variableType = caller->variableType, .solvedArray.vector = copiedArray };
|
|
|
|
return copyVariableToPtr(var);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassFunction(arraySet) {
|
|
|
|
s64 idx = getIntValue(*args);
|
|
|
|
Vector_t* v = &caller->solvedArray.vector;
|
2021-07-09 22:19:10 +01:00
|
|
|
if (v->count < idx || idx < 0) {
|
2021-07-09 21:56:13 +01:00
|
|
|
SCRIPT_FATAL_ERR("Accessing index %d while array is %d long", (int)idx, (int)caller->solvedArray.vector.count);
|
|
|
|
}
|
|
|
|
|
2021-07-09 22:19:10 +01:00
|
|
|
u32 oldCount = caller->solvedArray.vector.count;
|
|
|
|
caller->solvedArray.vector.count = idx;
|
|
|
|
if (arrayClassAdd(caller, args[1])){
|
|
|
|
SCRIPT_FATAL_ERR("Adding the wrong type to a typed array");
|
2021-07-09 21:56:13 +01:00
|
|
|
}
|
2021-07-09 22:19:10 +01:00
|
|
|
caller->solvedArray.vector.count = oldCount;
|
2021-07-09 21:56:13 +01:00
|
|
|
|
|
|
|
return &emptyClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassFunction(arrayAdd) {
|
|
|
|
Variable_t* arg = *args;
|
|
|
|
|
2021-07-09 22:19:10 +01:00
|
|
|
if (caller->readOnly) {
|
|
|
|
SCRIPT_FATAL_ERR("Array is read-only");
|
2021-07-09 21:56:13 +01:00
|
|
|
}
|
|
|
|
|
2021-07-09 22:19:10 +01:00
|
|
|
if (arrayClassAdd(caller, arg)){
|
|
|
|
SCRIPT_FATAL_ERR("Adding the wrong type to a typed array");
|
2021-07-09 21:56:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return &emptyClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassFunction(arrayContains) {
|
|
|
|
Vector_t* v = &caller->solvedArray.vector;
|
|
|
|
Variable_t* arg = *args;
|
|
|
|
|
|
|
|
for (int i = 0; i < v->count; i++) {
|
|
|
|
Variable_t iter = arrayClassGetIdx(caller, i);
|
2021-07-24 22:00:05 +01:00
|
|
|
|
|
|
|
if (iter.variableType != arg->variableType){
|
|
|
|
SCRIPT_FATAL_ERR("type of contains does not match");
|
|
|
|
}
|
2021-07-09 21:56:13 +01:00
|
|
|
|
|
|
|
if (caller->variableType == StringArrayClass) {
|
|
|
|
if (!strcmp(arg->string.value, iter.string.value))
|
|
|
|
return newIntVariablePtr(1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (arg->integer.value == iter.integer.value)
|
|
|
|
return newIntVariablePtr(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newIntVariablePtr(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassFunction(arrayMinus) {
|
|
|
|
s64 count = getIntValue(*args);
|
|
|
|
Vector_t* v = &caller->solvedArray.vector;
|
|
|
|
if (v->count < count || count <= 0) {
|
|
|
|
SCRIPT_FATAL_ERR("Accessing index %d while array is %d long", (int)count, (int)caller->solvedArray.vector.count);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (caller->variableType == StringArrayClass) {
|
|
|
|
char** arr = v->data;
|
|
|
|
for (int i = v->count - count; i < count; i++) {
|
|
|
|
FREE(arr[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
v->count -= count;
|
|
|
|
return &emptyClass;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassFunction(bytesToStr) {
|
|
|
|
if (caller->variableType != ByteArrayClass) {
|
2021-07-09 22:19:10 +01:00
|
|
|
SCRIPT_FATAL_ERR("Need a bytearray to convert to str");
|
2021-07-09 21:56:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
char* buff = malloc(caller->solvedArray.vector.count + 1);
|
|
|
|
memcpy(buff, caller->solvedArray.vector.data, caller->solvedArray.vector.count);
|
|
|
|
buff[caller->solvedArray.vector.count] = '\0';
|
|
|
|
return newStringVariablePtr(buff, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassFunction(eqArray){
|
|
|
|
Variable_t *arg = (*args);
|
|
|
|
if (caller->solvedArray.vector.count != arg->solvedArray.vector.count || arg->variableType != caller->variableType){
|
|
|
|
return newIntVariablePtr(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
s64 res = memcmp(caller->solvedArray.vector.data, arg->solvedArray.vector.data, caller->solvedArray.vector.count * caller->solvedArray.vector.elemSz);
|
|
|
|
return newIntVariablePtr(!res);
|
|
|
|
}
|
|
|
|
|
2021-07-21 00:30:08 +01:00
|
|
|
ClassFunction(arrayFind){
|
|
|
|
Variable_t *arg = (*args);
|
|
|
|
if (caller->solvedArray.vector.count <= arg->solvedArray.vector.count || arg->variableType != caller->variableType){
|
|
|
|
return newIntVariablePtr(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
u8 step = (arg->variableType == ByteArrayClass) ? 1 : 8;
|
|
|
|
char *haystack = caller->solvedArray.vector.data;
|
|
|
|
void *needle = arg->solvedArray.vector.data;
|
|
|
|
|
|
|
|
for (int i = 0; i < caller->solvedArray.vector.count - arg->solvedArray.vector.count; i++){
|
|
|
|
if (!memcmp(haystack + (i * step), needle, step * arg->solvedArray.vector.count)){
|
|
|
|
return newIntVariablePtr(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return newIntVariablePtr(-1);
|
|
|
|
}
|
|
|
|
|
2021-07-09 21:56:13 +01:00
|
|
|
ClassFunctionTableEntry_t arrayFunctions[] = {
|
|
|
|
{"get", getArrayIdx, 1, anotherOneIntArg },
|
|
|
|
{"len", getArrayLen, 0, 0},
|
2021-07-09 22:19:10 +01:00
|
|
|
{"slice", arraySlice, 2, doubleInt},
|
2021-07-09 21:56:13 +01:00
|
|
|
{"foreach", arrayForEach, 2, oneStringoneFunction},
|
|
|
|
{"copy", arrayCopy, 0, 0},
|
|
|
|
{"set", arraySet, 2, oneIntOneAny},
|
|
|
|
{"+", arrayAdd, 1, anotherAnotherOneVarArg},
|
2021-07-24 23:54:21 +01:00
|
|
|
{"add", arrayAdd, 1, anotherAnotherOneVarArg},
|
2021-07-09 21:56:13 +01:00
|
|
|
{"-", arrayMinus, 1, anotherOneIntArg},
|
|
|
|
{"contains", arrayContains, 1, anotherAnotherOneVarArg},
|
|
|
|
{"bytestostr", bytesToStr, 0, 0},
|
|
|
|
{"==", eqArray, 1, oneByteArrayClass},
|
|
|
|
{"==", eqArray, 1, oneIntArrayClass},
|
2021-07-21 00:30:08 +01:00
|
|
|
{"find", arrayFind, 1, oneByteArrayClass},
|
|
|
|
{"find", arrayFind, 1, oneIntArrayClass},
|
2021-07-09 21:56:13 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
Variable_t getArrayMember(Variable_t* var, char* memberName) {
|
|
|
|
return getGenericFunctionMember(var, memberName, arrayFunctions, ARRAY_SIZE(arrayFunctions));
|
|
|
|
}
|