mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
This is an incomplete process. It's supposed to be robust enough to support the types of arrays and dictionaries, but arrays and dictionaries aren't implemented in the literals yet, so that's my next task. I'll come back to variable declarations later.
174 lines
3.8 KiB
C
174 lines
3.8 KiB
C
#include "literal.h"
|
|
#include "memory.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
static void stdoutWrapper(const char* output) {
|
|
fprintf(stdout, output);
|
|
}
|
|
|
|
void printLiteral(Literal literal) {
|
|
printLiteralCustom(literal, stdoutWrapper);
|
|
}
|
|
|
|
void printLiteralCustom(Literal literal, void (printFn)(const char*)) {
|
|
switch(literal.type) {
|
|
case LITERAL_NULL:
|
|
printFn("null");
|
|
break;
|
|
|
|
case LITERAL_BOOLEAN:
|
|
printFn(AS_BOOLEAN(literal) ? "true" : "false");
|
|
break;
|
|
|
|
case LITERAL_INTEGER: {
|
|
char buffer[256];
|
|
snprintf(buffer, 256, "%d", AS_INTEGER(literal));
|
|
printFn(buffer);
|
|
}
|
|
break;
|
|
|
|
case LITERAL_FLOAT: {
|
|
char buffer[256];
|
|
snprintf(buffer, 256, "%g", AS_FLOAT(literal));
|
|
printFn(buffer);
|
|
}
|
|
break;
|
|
|
|
case LITERAL_STRING: {
|
|
char buffer[256];
|
|
snprintf(buffer, 256, "%.*s", STRLEN(literal), AS_STRING(literal));
|
|
printFn(buffer);
|
|
}
|
|
break;
|
|
|
|
case LITERAL_IDENTIFIER: {
|
|
char buffer[256];
|
|
snprintf(buffer, 256, "%.*s", STRLEN_I(literal), AS_IDENTIFIER(literal));
|
|
printFn(buffer);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
//should never bee seen
|
|
fprintf(stderr, "[Internal] Unrecognized literal type in print: %d\n", literal.type);
|
|
}
|
|
}
|
|
|
|
void freeLiteral(Literal literal) {
|
|
if (IS_STRING(literal)) {
|
|
FREE(char, AS_STRING(literal));
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool _isTruthy(Literal x) {
|
|
return (IS_NULL(x) || (IS_BOOLEAN(x) && AS_BOOLEAN(x)) || (IS_INTEGER(x) && AS_INTEGER(x) != 0) || (IS_FLOAT(x) && AS_FLOAT(x) != 0));
|
|
}
|
|
|
|
Literal _toStringLiteral(char* str) {
|
|
return ((Literal){LITERAL_STRING, {.string.ptr = (char*)str, .string.length = strlen((char*)str)}});
|
|
}
|
|
|
|
Literal _toIdentifierLiteral(char* str) {
|
|
return ((Literal){LITERAL_IDENTIFIER,{.identifier.ptr = (char*)str,.identifier.length = strlen((char*)str)}});
|
|
}
|
|
|
|
char* copyString(char* original, int length) {
|
|
char* buffer = ALLOCATE(char, length + 1);
|
|
strncpy(buffer, original, length);
|
|
buffer[length] = '\0';
|
|
return buffer;
|
|
}
|
|
|
|
bool literalsAreEqual(Literal lhs, Literal rhs) {
|
|
if (lhs.type != rhs.type) {
|
|
// ints and floats are compatible
|
|
if ((IS_INTEGER(lhs) || IS_FLOAT(lhs)) && (IS_INTEGER(rhs) || IS_FLOAT(rhs))) {
|
|
if (IS_INTEGER(lhs)) {
|
|
return AS_INTEGER(lhs) + AS_FLOAT(rhs);
|
|
}
|
|
else {
|
|
return AS_FLOAT(lhs) + AS_INTEGER(rhs);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
switch(lhs.type) {
|
|
case LITERAL_BOOLEAN:
|
|
return AS_BOOLEAN(lhs) == AS_BOOLEAN(rhs);
|
|
|
|
case LITERAL_INTEGER:
|
|
return AS_INTEGER(lhs) == AS_INTEGER(rhs);
|
|
|
|
case LITERAL_FLOAT:
|
|
return AS_FLOAT(lhs) == AS_FLOAT(rhs);
|
|
|
|
case LITERAL_STRING:
|
|
if (STRLEN(lhs) != STRLEN(rhs)) {
|
|
return false;
|
|
}
|
|
return !strncmp(AS_STRING(lhs), AS_STRING(rhs), STRLEN(lhs));
|
|
|
|
case LITERAL_IDENTIFIER:
|
|
if (STRLEN_I(lhs) != STRLEN_I(rhs)) {
|
|
return false;
|
|
}
|
|
return !strncmp(AS_IDENTIFIER(lhs), AS_IDENTIFIER(rhs), STRLEN_I(lhs));
|
|
|
|
default:
|
|
//should never bee seen
|
|
fprintf(stderr, "[internal] Unrecognized literal type: %d\n", lhs.type);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//hash functions
|
|
static unsigned int hashString(const char* string, int length) {
|
|
unsigned int hash = 2166136261u;
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
hash *= string[i];
|
|
hash *= 16777619;
|
|
}
|
|
|
|
return hash;
|
|
}
|
|
|
|
static unsigned int hash(unsigned int x) {
|
|
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
|
x = ((x >> 16) ^ x) * 0x45d9f3b;
|
|
x = (x >> 16) ^ x;
|
|
return x;
|
|
}
|
|
|
|
int hashLiteral(Literal lit) {
|
|
switch(lit.type) {
|
|
case LITERAL_NULL:
|
|
return 0;
|
|
|
|
case LITERAL_BOOLEAN:
|
|
return AS_BOOLEAN(lit) ? 1 : 0;
|
|
|
|
case LITERAL_INTEGER:
|
|
return hash((unsigned int)AS_INTEGER(lit));
|
|
|
|
case LITERAL_FLOAT:
|
|
return hash(*(unsigned int*)(&AS_FLOAT(lit)));
|
|
|
|
case LITERAL_STRING:
|
|
return hashString(AS_STRING(lit), STRLEN(lit));
|
|
|
|
case LITERAL_IDENTIFIER:
|
|
return hashString(AS_IDENTIFIER(lit), STRLEN_I(lit));
|
|
|
|
default:
|
|
//should never bee seen
|
|
fprintf(stderr, "[Internal] Unrecognized literal type in hash: %d\n", lit.type);
|
|
return 0;
|
|
}
|
|
}
|