mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
Added errorOutput to interpreter, moved builtin functions to their own file
This commit is contained in:
416
source/lib_builtin.c
Normal file
416
source/lib_builtin.c
Normal file
@@ -0,0 +1,416 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user