mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-18 00:04:09 +10:00
416 lines
10 KiB
C
416 lines
10 KiB
C
#include "lib_builtin.h"
|
|
|
|
#include "memory.h"
|
|
|
|
int _set(Interpreter* interpreter, LiteralArray* arguments) {
|
|
//if wrong number of arguments, fail
|
|
if (arguments->count != 3) {
|
|
interpreter->errorOutput("Incorrect number of arguments to _set\n");
|
|
return -1;
|
|
}
|
|
|
|
Literal idn = arguments->literals[0];
|
|
Literal obj = arguments->literals[0];
|
|
Literal key = arguments->literals[1];
|
|
Literal val = arguments->literals[2];
|
|
|
|
if (!IS_IDENTIFIER(idn)) {
|
|
interpreter->errorOutput("Expected identifier in _set\n");
|
|
return -1;
|
|
}
|
|
|
|
parseIdentifierToValue(interpreter, &obj);
|
|
|
|
bool freeKey = false;
|
|
if (IS_IDENTIFIER(key)) {
|
|
parseIdentifierToValue(interpreter, &key);
|
|
freeKey = true;
|
|
}
|
|
|
|
bool freeVal = false;
|
|
if (IS_IDENTIFIER(val)) {
|
|
parseIdentifierToValue(interpreter, &val);
|
|
freeVal = true;
|
|
}
|
|
|
|
switch(obj.type) {
|
|
case LITERAL_ARRAY: {
|
|
Literal typeLiteral = getScopeType(interpreter->scope, key);
|
|
|
|
if (AS_TYPE(typeLiteral).typeOf == LITERAL_ARRAY) {
|
|
Literal subtypeLiteral = ((Literal*)(AS_TYPE(typeLiteral).subtypes))[0];
|
|
|
|
if (AS_TYPE(subtypeLiteral).typeOf != LITERAL_ANY && AS_TYPE(subtypeLiteral).typeOf != val.type) {
|
|
interpreter->errorOutput("Bad argument type in _set\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
if (!IS_INTEGER(key)) {
|
|
interpreter->errorOutput("Expected integer index in _set\n");
|
|
return -1;
|
|
}
|
|
|
|
if (AS_ARRAY(obj)->count <= AS_INTEGER(key) || AS_INTEGER(key) < 0) {
|
|
interpreter->errorOutput("Index out of bounds in _set\n");
|
|
return -1;
|
|
}
|
|
|
|
//don't use pushLiteralArray, since we're setting
|
|
freeLiteral(AS_ARRAY(obj)->literals[AS_INTEGER(key)]); //BUGFIX: clear any existing data first
|
|
AS_ARRAY(obj)->literals[AS_INTEGER(key)] = copyLiteral(val);
|
|
|
|
if (!setScopeVariable(interpreter->scope, idn, obj, true)) {
|
|
interpreter->errorOutput("Incorrect type assigned to array in _set: \"");
|
|
printLiteralCustom(val, interpreter->errorOutput);
|
|
interpreter->errorOutput("\"\n");
|
|
return -1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case LITERAL_DICTIONARY: {
|
|
Literal typeLiteral = getScopeType(interpreter->scope, key);
|
|
|
|
if (AS_TYPE(typeLiteral).typeOf == LITERAL_DICTIONARY) {
|
|
Literal keySubtypeLiteral = ((Literal*)(AS_TYPE(typeLiteral).subtypes))[0];
|
|
Literal valSubtypeLiteral = ((Literal*)(AS_TYPE(typeLiteral).subtypes))[1];
|
|
|
|
if (AS_TYPE(keySubtypeLiteral).typeOf != LITERAL_ANY && AS_TYPE(keySubtypeLiteral).typeOf != key.type) {
|
|
interpreter->printOutput("bad argument type in _set\n");
|
|
return -1;
|
|
}
|
|
|
|
if (AS_TYPE(valSubtypeLiteral).typeOf != LITERAL_ANY && AS_TYPE(valSubtypeLiteral).typeOf != val.type) {
|
|
interpreter->printOutput("bad argument type in _set\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
setLiteralDictionary(AS_DICTIONARY(obj), key, val);
|
|
|
|
if (!setScopeVariable(interpreter->scope, idn, obj, true)) {
|
|
interpreter->errorOutput("Incorrect type assigned to dictionary in _set: \"");
|
|
printLiteralCustom(val, interpreter->errorOutput);
|
|
interpreter->errorOutput("\"\n");
|
|
return -1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
interpreter->errorOutput("Incorrect compound type in _set: ");
|
|
printLiteralCustom(obj, interpreter->errorOutput);
|
|
interpreter->errorOutput("\"\n");
|
|
return -1;
|
|
}
|
|
|
|
freeLiteral(obj);
|
|
|
|
if (freeKey) {
|
|
freeLiteral(key);
|
|
}
|
|
|
|
if (freeVal) {
|
|
freeLiteral(val);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int _get(Interpreter* interpreter, LiteralArray* arguments) {
|
|
//if wrong number of arguments, fail
|
|
if (arguments->count != 2) {
|
|
interpreter->errorOutput("Incorrect number of arguments to _get");
|
|
return -1;
|
|
}
|
|
|
|
Literal obj = arguments->literals[0];
|
|
Literal key = arguments->literals[1];
|
|
|
|
bool freeObj = false;
|
|
if (IS_IDENTIFIER(obj)) {
|
|
parseIdentifierToValue(interpreter, &obj);
|
|
freeObj = true;
|
|
}
|
|
|
|
bool freeKey = false;
|
|
if (IS_IDENTIFIER(key)) {
|
|
parseIdentifierToValue(interpreter, &key);
|
|
freeKey = true;
|
|
}
|
|
|
|
switch(obj.type) {
|
|
case LITERAL_ARRAY: {
|
|
if (!IS_INTEGER(key)) {
|
|
interpreter->errorOutput("Expected integer index in _get\n");
|
|
return -1;
|
|
}
|
|
|
|
if (AS_ARRAY(obj)->count <= AS_INTEGER(key) || AS_INTEGER(key) < 0) {
|
|
interpreter->errorOutput("Index out of bounds in _get\n");
|
|
return -1;
|
|
}
|
|
|
|
pushLiteralArray(&interpreter->stack, AS_ARRAY(obj)->literals[AS_INTEGER(key)]);
|
|
|
|
if (freeObj) {
|
|
freeLiteral(obj);
|
|
}
|
|
|
|
if (freeKey) {
|
|
freeLiteral(key);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
case LITERAL_DICTIONARY: {
|
|
Literal dict = getLiteralDictionary(AS_DICTIONARY(obj), key);
|
|
pushLiteralArray(&interpreter->stack, dict);
|
|
freeLiteral(dict);
|
|
|
|
if (freeObj) {
|
|
freeLiteral(obj);
|
|
}
|
|
|
|
if (freeKey) {
|
|
freeLiteral(key);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
default:
|
|
interpreter->errorOutput("Incorrect compound type in _get \"");
|
|
printLiteralCustom(obj, interpreter->errorOutput);
|
|
interpreter->errorOutput("\"\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int _push(Interpreter* interpreter, LiteralArray* arguments) {
|
|
//if wrong number of arguments, fail
|
|
if (arguments->count != 2) {
|
|
interpreter->errorOutput("Incorrect number of arguments to _push\n");
|
|
return -1;
|
|
}
|
|
|
|
Literal idn = arguments->literals[0];
|
|
Literal obj = arguments->literals[0];
|
|
Literal val = arguments->literals[1];
|
|
|
|
if (!IS_IDENTIFIER(idn)) {
|
|
interpreter->errorOutput("Expected identifier in _push\n");
|
|
return -1;
|
|
}
|
|
|
|
parseIdentifierToValue(interpreter, &obj);
|
|
|
|
bool freeVal = false;
|
|
if (IS_IDENTIFIER(val)) {
|
|
parseIdentifierToValue(interpreter, &val);
|
|
freeVal = true;
|
|
}
|
|
|
|
switch(obj.type) {
|
|
case LITERAL_ARRAY: {
|
|
Literal typeLiteral = getScopeType(interpreter->scope, val);
|
|
|
|
if (AS_TYPE(typeLiteral).typeOf == LITERAL_ARRAY) {
|
|
Literal subtypeLiteral = ((Literal*)(AS_TYPE(typeLiteral).subtypes))[0];
|
|
|
|
if (AS_TYPE(subtypeLiteral).typeOf != LITERAL_ANY && AS_TYPE(subtypeLiteral).typeOf != val.type) {
|
|
interpreter->errorOutput("Bad argument type in _push");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
pushLiteralArray(AS_ARRAY(obj), val);
|
|
|
|
if (!setScopeVariable(interpreter->scope, idn, obj, true)) { //TODO: could definitely be more efficient than overwriting the whole original object
|
|
interpreter->errorOutput("Incorrect type assigned to array in _push: \"");
|
|
printLiteralCustom(val, interpreter->errorOutput);
|
|
interpreter->errorOutput("\"\n");
|
|
return -1;
|
|
}
|
|
|
|
freeLiteral(obj);
|
|
|
|
if (freeVal) {
|
|
freeLiteral(val);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
default:
|
|
interpreter->errorOutput("Incorrect compound type in _push: ");
|
|
printLiteralCustom(obj, interpreter->errorOutput);
|
|
interpreter->errorOutput("\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int _pop(Interpreter* interpreter, LiteralArray* arguments) {
|
|
//if wrong number of arguments, fail
|
|
if (arguments->count != 1) {
|
|
interpreter->errorOutput("Incorrect number of arguments to _pop\n");
|
|
return -1;
|
|
}
|
|
|
|
Literal idn = arguments->literals[0];
|
|
Literal obj = arguments->literals[0];
|
|
|
|
if (!IS_IDENTIFIER(idn)) {
|
|
interpreter->errorOutput("Expected identifier in _pop\n");
|
|
return -1;
|
|
}
|
|
|
|
parseIdentifierToValue(interpreter, &obj);
|
|
|
|
switch(obj.type) {
|
|
case LITERAL_ARRAY: {
|
|
Literal lit = popLiteralArray(AS_ARRAY(obj));
|
|
pushLiteralArray(&interpreter->stack, lit);
|
|
freeLiteral(lit);
|
|
|
|
if (!setScopeVariable(interpreter->scope, idn, obj, true)) { //TODO: could definitely be more efficient than overwriting the whole original object
|
|
interpreter->errorOutput("Incorrect type assigned to array in _pop: ");
|
|
printLiteralCustom(obj, interpreter->errorOutput);
|
|
interpreter->errorOutput("\n");
|
|
return -1;
|
|
}
|
|
|
|
freeLiteral(obj);
|
|
|
|
return 1;
|
|
}
|
|
|
|
default:
|
|
interpreter->errorOutput("Incorrect compound type in _pop: ");
|
|
printLiteralCustom(obj, interpreter->errorOutput);
|
|
interpreter->errorOutput("\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int _length(Interpreter* interpreter, LiteralArray* arguments) {
|
|
//if wrong number of arguments, fail
|
|
if (arguments->count != 1) {
|
|
interpreter->errorOutput("Incorrect number of arguments to _get\n");
|
|
return -1;
|
|
}
|
|
|
|
Literal obj = arguments->literals[0];
|
|
|
|
bool freeObj = false;
|
|
if (IS_IDENTIFIER(obj)) {
|
|
parseIdentifierToValue(interpreter, &obj);
|
|
freeObj = true;
|
|
}
|
|
|
|
switch(obj.type) {
|
|
case LITERAL_ARRAY: {
|
|
Literal lit = TO_INTEGER_LITERAL( AS_ARRAY(obj)->count );
|
|
pushLiteralArray(&interpreter->stack, lit);
|
|
freeLiteral(lit);
|
|
break;
|
|
}
|
|
|
|
case LITERAL_DICTIONARY: {
|
|
Literal lit = TO_INTEGER_LITERAL( AS_DICTIONARY(obj)->count );
|
|
pushLiteralArray(&interpreter->stack, lit);
|
|
freeLiteral(lit);
|
|
break;
|
|
}
|
|
|
|
case LITERAL_STRING: {
|
|
Literal lit = TO_INTEGER_LITERAL( strlen(AS_STRING(obj)) );
|
|
pushLiteralArray(&interpreter->stack, lit);
|
|
freeLiteral(lit);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
interpreter->errorOutput("Incorrect compound type in _length: ");
|
|
printLiteralCustom(obj, interpreter->errorOutput);
|
|
interpreter->errorOutput("\n");
|
|
return -1;
|
|
}
|
|
|
|
if (freeObj) {
|
|
freeLiteral(obj);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int _clear(Interpreter* interpreter, LiteralArray* arguments) {
|
|
//if wrong number of arguments, fail
|
|
if (arguments->count != 1) {
|
|
interpreter->errorOutput("Incorrect number of arguments to _clear\n");
|
|
return -1;
|
|
}
|
|
|
|
Literal idn = arguments->literals[0];
|
|
Literal obj = arguments->literals[0];
|
|
|
|
if (!IS_IDENTIFIER(idn)) {
|
|
interpreter->errorOutput("expected identifier in _clear\n");
|
|
return -1;
|
|
}
|
|
|
|
parseIdentifierToValue(interpreter, &obj);
|
|
|
|
//NOTE: just pass in new compounds
|
|
|
|
switch(obj.type) {
|
|
case LITERAL_ARRAY: {
|
|
LiteralArray* array = ALLOCATE(LiteralArray, 1);
|
|
initLiteralArray(array);
|
|
|
|
Literal obj = TO_ARRAY_LITERAL(array);
|
|
|
|
if (!setScopeVariable(interpreter->scope, idn, obj, true)) {
|
|
interpreter->errorOutput("Incorrect type assigned to array in _clear: ");
|
|
printLiteralCustom(obj, interpreter->errorOutput);
|
|
interpreter->errorOutput("\n");
|
|
return -1;
|
|
}
|
|
|
|
freeLiteral(obj);
|
|
|
|
break;
|
|
}
|
|
|
|
case LITERAL_DICTIONARY: {
|
|
LiteralDictionary* dictionary = ALLOCATE(LiteralDictionary, 1);
|
|
initLiteralDictionary(dictionary);
|
|
|
|
Literal obj = TO_DICTIONARY_LITERAL(dictionary);
|
|
|
|
if (!setScopeVariable(interpreter->scope, idn, obj, true)) {
|
|
interpreter->errorOutput("Incorrect type assigned to dictionary in _clear: ");
|
|
printLiteralCustom(obj, interpreter->errorOutput);
|
|
interpreter->errorOutput("\n");
|
|
return -1;
|
|
}
|
|
|
|
freeLiteral(obj);
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
interpreter->errorOutput("Incorrect compound type in _clear: ");
|
|
printLiteralCustom(obj, interpreter->errorOutput);
|
|
interpreter->errorOutput("\n");
|
|
return -1;
|
|
}
|
|
|
|
freeLiteral(obj);
|
|
return 1;
|
|
} |