Reworked the type system, types now have a single value

This commit is contained in:
2022-08-17 17:39:29 +01:00
parent bde07f6c12
commit 574a864dd0
9 changed files with 201 additions and 254 deletions

View File

@@ -1,3 +1,5 @@
DONE: rework type system
TODO: type casting TODO: type casting
TODO: const without a type TODO: const without a type
TODO: increment & decrement operators TODO: increment & decrement operators

View File

@@ -1,5 +1,6 @@
var arr : [int] = [1, 2, 3, 42];
var dict : [string, int] = ["hello": 1, "world":2];
print arr;
print dict;
var dict : [string, int] = ["hello" : 1, "world" : 2];

View File

@@ -15,15 +15,6 @@ void initCompiler(Compiler* compiler) {
compiler->bytecode = NULL; compiler->bytecode = NULL;
compiler->capacity = 0; compiler->capacity = 0;
compiler->count = 0; compiler->count = 0;
//default atomic literals (commented out, because not needed atm - might need them later)
// Literal n = TO_NULL_LITERAL;
// Literal t = TO_BOOLEAN_LITERAL(true);
// Literal f = TO_BOOLEAN_LITERAL(false);
// pushLiteralArray(&compiler->literalCache, n);
// pushLiteralArray(&compiler->literalCache, t);
// pushLiteralArray(&compiler->literalCache, f);
} }
//separated out, so it can be recursive //separated out, so it can be recursive
@@ -130,34 +121,27 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) {
return index; return index;
} }
static int writeLiteralTypeToCache(LiteralArray* parent, Literal literal) { static int writeLiteralTypeToCache(LiteralArray* literalCache, Literal literal) {
int index = -1; //I don't like storing types in an array, but it's the easiest and most straight forward method
//for now, stored as an array
LiteralArray* store = ALLOCATE(LiteralArray, 1); LiteralArray* store = ALLOCATE(LiteralArray, 1);
initLiteralArray(store); initLiteralArray(store);
//save the mask to the store, at index 0 //store the base literal in the store
int maskIndex = findLiteralIndex(store, TO_INTEGER_LITERAL(AS_TYPE(literal).mask)); pushLiteralArray(store, literal);
if (maskIndex < 0) {
maskIndex = pushLiteralArray(store, TO_INTEGER_LITERAL(AS_TYPE(literal).mask));
}
//if it's a compound type, recurse //if it's a compound type, recurse and store the results
if (AS_TYPE(literal).mask & (MASK_ARRAY|MASK_DICTIONARY)) { if (AS_TYPE(literal).typeOf == LITERAL_ARRAY || AS_TYPE(literal).typeOf == LITERAL_DICTIONARY) {
for (int i = 0; i < AS_TYPE(literal).count; i++) { for (int i = 0; i < AS_TYPE(literal).count; i++) {
//write the values to the cache, and the indexes to the store //write the values to the cache, and the indexes to the store
int subIndex = writeLiteralTypeToCache(parent, ((Literal*)(AS_TYPE(literal).subtypes))[i]); int subIndex = writeLiteralTypeToCache(literalCache, ((Literal*)(AS_TYPE(literal).subtypes))[i]);
pushLiteralArray(store, TO_INTEGER_LITERAL(subIndex)); pushLiteralArray(store, TO_INTEGER_LITERAL(subIndex));
} }
} }
//push the store to the cache, tweaking the type //push the store to the cache, tweaking the type
Literal lit = TO_ARRAY_LITERAL(store); Literal lit = TO_ARRAY_LITERAL(store);
lit.type = LITERAL_TYPE; //TODO: tweaking the type isn't a good idea lit.type = LITERAL_TYPE; //NOTE: tweaking the type usually isn't a good idea
index = pushLiteralArray(parent, lit); return pushLiteralArray(literalCache, lit);
return index;
} }
void writeCompiler(Compiler* compiler, Node* node) { void writeCompiler(Compiler* compiler, Node* node) {
@@ -463,6 +447,8 @@ unsigned char* collateCompiler(Compiler* compiler, int* size) {
} }
break; break;
//TODO: function
case LITERAL_IDENTIFIER: { case LITERAL_IDENTIFIER: {
emitByte(&collation, &capacity, &count, LITERAL_IDENTIFIER); emitByte(&collation, &capacity, &count, LITERAL_IDENTIFIER);
@@ -481,12 +467,19 @@ unsigned char* collateCompiler(Compiler* compiler, int* size) {
LiteralArray* ptr = AS_ARRAY(compiler->literalCache.literals[i]); //used an array for storage above LiteralArray* ptr = AS_ARRAY(compiler->literalCache.literals[i]); //used an array for storage above
//length of the array, as a short //the base literal
emitShort(&collation, &capacity, &count, ptr->count); //count is the array size Literal typeLiteral = ptr->literals[0];
//each element of the array //what type this literal represents
for (int i = 0; i < ptr->count; i++) { emitByte(&collation, &capacity, &count, AS_TYPE(typeLiteral).typeOf);
emitShort(&collation, &capacity, &count, (unsigned short)AS_INTEGER(ptr->literals[i])); //shorts representing the indexes of the values emitByte(&collation, &capacity, &count, AS_TYPE(typeLiteral).constant); //if it's constant
//each element of the array, If they exist, representing sub-types already in the cache
if (AS_TYPE(typeLiteral).typeOf == LITERAL_ARRAY || AS_TYPE(typeLiteral).typeOf == LITERAL_DICTIONARY) {
//the type will represent how many to expect in the array
for (int i = 1; i < ptr->count; i++) {
emitShort(&collation, &capacity, &count, (unsigned short)AS_INTEGER(ptr->literals[i])); //shorts representing the indexes of the types
}
} }
freeLiteralArray(ptr); freeLiteralArray(ptr);

View File

@@ -589,28 +589,25 @@ void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int lengt
break; break;
case LITERAL_TYPE: { case LITERAL_TYPE: {
Literal typeLiteral; //what the literal represents
LiteralType literalType = (LiteralType)readByte(interpreter->bytecode, &interpreter->count);
unsigned char constant = readByte(interpreter->bytecode, &interpreter->count);
//read the array count (subtract 1, because mask is always present) Literal typeLiteral = TO_TYPE_LITERAL(literalType, constant);
unsigned short count = readShort(interpreter->bytecode, &interpreter->count) - 1;
// read the mask //if it's an array type
unsigned char mask = readShort(interpreter->bytecode, &interpreter->count); if (AS_TYPE(typeLiteral).typeOf == LITERAL_ARRAY) {
unsigned short vt = readShort(interpreter->bytecode, &interpreter->count);
//create the literal TYPE_PUSH_SUBTYPE(&typeLiteral, interpreter->literalCache.literals[vt]);
typeLiteral = TO_TYPE_LITERAL(mask); }
//if it's got subtypes, grab them from the existing cache if (AS_TYPE(typeLiteral).typeOf == LITERAL_DICTIONARY) {
if (count > 0) { unsigned short kt = readShort(interpreter->bytecode, &interpreter->count);
AS_TYPE(typeLiteral).subtypes = ALLOCATE(Literal, count); unsigned short vt = readShort(interpreter->bytecode, &interpreter->count);
AS_TYPE(typeLiteral).capacity = count;
AS_TYPE(typeLiteral).count = count;
for (int i = 0; i < AS_TYPE(typeLiteral).count; i++) { TYPE_PUSH_SUBTYPE(&typeLiteral, interpreter->literalCache.literals[kt]);
//read each index TYPE_PUSH_SUBTYPE(&typeLiteral, interpreter->literalCache.literals[vt]);
int index = readShort(interpreter->bytecode, &interpreter->count);
((Literal*)(AS_TYPE(typeLiteral).subtypes))[i] = interpreter->literalCache.literals[index];
}
} }
//save the type //save the type

View File

@@ -32,9 +32,6 @@ static void printToBuffer(const char* str) {
globalPrintCount += strlen(str); globalPrintCount += strlen(str);
} }
//BUGFIX: <array | dictionary> is handled oddly for specific reasons, so this flag is for the debug output of the type
bool printTypeMarker = true;
//hash util functions //hash util functions
static unsigned int hashString(const char* string, int length) { static unsigned int hashString(const char* string, int length) {
unsigned int hash = 2166136261u; unsigned int hash = 2166136261u;
@@ -98,7 +95,7 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) {
case LITERAL_ARRAY: { case LITERAL_ARRAY: {
LiteralArray* ptr = AS_ARRAY(literal); LiteralArray* ptr = AS_ARRAY(literal);
//hold potential parent-call buffers //hold potential parent-call buffers on the C stack
char* cacheBuffer = globalPrintBuffer; char* cacheBuffer = globalPrintBuffer;
globalPrintBuffer = NULL; globalPrintBuffer = NULL;
int cacheCapacity = globalPrintCapacity; int cacheCapacity = globalPrintCapacity;
@@ -137,7 +134,7 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) {
case LITERAL_DICTIONARY: { case LITERAL_DICTIONARY: {
LiteralDictionary* ptr = AS_DICTIONARY(literal); LiteralDictionary* ptr = AS_DICTIONARY(literal);
//hold potential parent-call buffers //hold potential parent-call buffers on the C stack
char* cacheBuffer = globalPrintBuffer; char* cacheBuffer = globalPrintBuffer;
globalPrintBuffer = NULL; globalPrintBuffer = NULL;
int cacheCapacity = globalPrintCapacity; int cacheCapacity = globalPrintCapacity;
@@ -186,6 +183,8 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) {
quotes = 0; quotes = 0;
} }
break; break;
//TODO: functions
case LITERAL_IDENTIFIER: { case LITERAL_IDENTIFIER: {
char buffer[256]; char buffer[256];
@@ -195,7 +194,7 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) {
break; break;
case LITERAL_TYPE: { case LITERAL_TYPE: {
//hold potential parent-call buffers //hold potential parent-call buffers on the C stack
char* cacheBuffer = globalPrintBuffer; char* cacheBuffer = globalPrintBuffer;
globalPrintBuffer = NULL; globalPrintBuffer = NULL;
int cacheCapacity = globalPrintCapacity; int cacheCapacity = globalPrintCapacity;
@@ -203,109 +202,74 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) {
int cacheCount = globalPrintCount; int cacheCount = globalPrintCount;
globalPrintCount = 0; globalPrintCount = 0;
//print the type //print the type correctly
int iterations = 0; printToBuffer("<");
if (printTypeMarker) {
printToBuffer("<");
}
for (int i = 1; i < 8; i ++) { //0th bit is const switch(AS_TYPE(literal).typeOf) {
//zero mask = any type, anys can't be const case LITERAL_BOOLEAN:
if (AS_TYPE(literal).mask == MASK_ANY) { printToBuffer("bool");
break;
case LITERAL_INTEGER:
printToBuffer("int");
break;
case LITERAL_FLOAT:
printToBuffer("float");
break;
case LITERAL_STRING:
printToBuffer("string");
break;
case LITERAL_ARRAY:
//print all in the array
printToBuffer("[");
for (int i = 0; i < AS_TYPE(literal).count; i++) {
printLiteralCustom(((Literal*)(AS_TYPE(literal).subtypes))[i], printToBuffer);
}
printToBuffer("]");
break;
case LITERAL_DICTIONARY:
printToBuffer("[");
for (int i = 0; i < AS_TYPE(literal).count; i += 2) {
printLiteralCustom(((Literal*)(AS_TYPE(literal).subtypes))[i], printToBuffer);
printToBuffer(":");
printLiteralCustom(((Literal*)(AS_TYPE(literal).subtypes))[i + 1], printToBuffer);
}
printToBuffer("]");
break;
case LITERAL_FUNCTION:
printToBuffer("function");
//TODO
break;
case LITERAL_IDENTIFIER:
printToBuffer("identifier");
break;
case LITERAL_TYPE:
printToBuffer("type");
break;
case LITERAL_ANY:
printToBuffer("any"); printToBuffer("any");
break; break;
}
if (AS_TYPE(literal).mask & MASK(i)) { default:
//pretty print //should never be seen
if (iterations++ > 0) { fprintf(stderr, "[Internal] Unrecognized literal type in print type: %d\n", literal.type);
printToBuffer(" | ");
}
//special case for array AND dictionary
if (i == TYPE_ARRAY) {
if ((AS_TYPE(literal).mask & (MASK_ARRAY|MASK_DICTIONARY)) == (MASK_ARRAY|MASK_DICTIONARY)) {
int pCache = printTypeMarker;
printTypeMarker = false;
printLiteralCustom(((Literal*)(AS_TYPE(literal).subtypes))[0], printToBuffer);
printTypeMarker = pCache;
continue;
}
}
if (i == TYPE_DICTIONARY) {
if ((AS_TYPE(literal).mask & (MASK_ARRAY|MASK_DICTIONARY)) == (MASK_ARRAY|MASK_DICTIONARY)) {
int pCache = printTypeMarker;
printTypeMarker = false;
printLiteralCustom(((Literal*)(AS_TYPE(literal).subtypes))[1], printToBuffer);
printTypeMarker = pCache;
continue;
}
}
switch(i) {
case TYPE_BOOLEAN:
printToBuffer("bool");
break;
case TYPE_INTEGER:
printToBuffer("int");
break;
case TYPE_FLOAT:
printToBuffer("float");
break;
case TYPE_STRING:
printToBuffer("string");
break;
case TYPE_ARRAY: {
//print all in the array
printToBuffer("[");
int it = 0;
for (int a = 0; a < AS_TYPE(literal).count; a++) {
if (it++ > 0) {
printToBuffer("] | [");
}
printLiteralCustom(((Literal*)(AS_TYPE(literal).subtypes))[a], printToBuffer);
}
printToBuffer("]");
}
break;
case TYPE_DICTIONARY: {
printToBuffer("[");
int it = 0;
for (int a = 0; a < AS_TYPE(literal).count; a += 2) {
if (it++ > 0) {
printToBuffer("] | [");
}
printLiteralCustom(((Literal*)(AS_TYPE(literal).subtypes))[a], printToBuffer);
printToBuffer(":");
printLiteralCustom(((Literal*)(AS_TYPE(literal).subtypes))[a + 1], printToBuffer);
}
printToBuffer("]");
}
break;
//TODO: function
}
}
} }
//const (printed last) //const (printed last)
if (AS_TYPE(literal).mask & MASK_CONST) { if (AS_TYPE(literal).constant) {
if (iterations++ > 0) { printToBuffer(" const");
printToBuffer(" ");
}
printToBuffer("const");
} }
if (printTypeMarker) { printToBuffer(">");
printToBuffer(">");
}
//swap the parent-call buffer back into place //swap the parent-call buffer back into place
char* printBuffer = globalPrintBuffer; char* printBuffer = globalPrintBuffer;
@@ -335,6 +299,15 @@ void freeLiteral(Literal literal) {
return; return;
} }
//TODO: are these needed? I wish i had valgrind
// if (IS_ARRAY(literal)) {
// freeLiteralArray(((LiteralArray*)(AS_ARRAY(literal))));
// }
// if (IS_DICTIONARY(literal)) {
// freeLiteralDictionary(((LiteralDictionary*)(AS_DICTIONARY(literal))));
// }
if (IS_IDENTIFIER(literal)) { if (IS_IDENTIFIER(literal)) {
FREE_ARRAY(char, AS_IDENTIFIER(literal), STRLEN_I(literal)); FREE_ARRAY(char, AS_IDENTIFIER(literal), STRLEN_I(literal));
return; return;
@@ -353,14 +326,15 @@ bool _isTruthy(Literal x) {
} }
Literal _toStringLiteral(char* str) { Literal _toStringLiteral(char* str) {
return ((Literal){LITERAL_STRING, {.string.ptr = (char*)str, .string.length = strlen((char*)str)}}); return ((Literal){LITERAL_STRING, { .string.ptr = (char*)str, .string.length = strlen((char*)str) }});
} }
Literal _toIdentifierLiteral(char* str, int length) { Literal _toIdentifierLiteral(char* str, int length) {
return ((Literal){LITERAL_IDENTIFIER,{.identifier.ptr = (char*)str,.identifier.length = length, .identifier.hash = hashString(str, length)}}); return ((Literal){LITERAL_IDENTIFIER,{ .identifier.ptr = (char*)str, .identifier.length = length, .identifier.hash = hashString(str, length) }});
} }
Literal* _typePushSubtype(Literal* lit, unsigned char submask) { Literal* _typePushSubtype(Literal* lit, Literal subtype) {
//grow the subtype array
if (AS_TYPE(*lit).count + 1 > AS_TYPE(*lit).capacity) { if (AS_TYPE(*lit).count + 1 > AS_TYPE(*lit).capacity) {
int oldCapacity = AS_TYPE(*lit).capacity; int oldCapacity = AS_TYPE(*lit).capacity;
@@ -369,11 +343,12 @@ Literal* _typePushSubtype(Literal* lit, unsigned char submask) {
} }
//actually push //actually push
((Literal*)(AS_TYPE(*lit).subtypes))[ AS_TYPE(*lit).count++ ] = TO_TYPE_LITERAL( submask ); ((Literal*)(AS_TYPE(*lit).subtypes))[ AS_TYPE(*lit).count++ ] = subtype;
return &((Literal*)(AS_TYPE(*lit).subtypes))[ AS_TYPE(*lit).count - 1 ]; return &((Literal*)(AS_TYPE(*lit).subtypes))[ AS_TYPE(*lit).count - 1 ];
} }
char* copyString(char* original, int length) { char* copyString(char* original, int length) {
//make a local copy of the char array
char* buffer = ALLOCATE(char, length + 1); char* buffer = ALLOCATE(char, length + 1);
strncpy(buffer, original, length); strncpy(buffer, original, length);
buffer[length] = '\0'; buffer[length] = '\0';
@@ -381,6 +356,7 @@ char* copyString(char* original, int length) {
} }
bool literalsAreEqual(Literal lhs, Literal rhs) { bool literalsAreEqual(Literal lhs, Literal rhs) {
//utility for other things
if (lhs.type != rhs.type) { if (lhs.type != rhs.type) {
// ints and floats are compatible // ints and floats are compatible
if ((IS_INTEGER(lhs) || IS_FLOAT(lhs)) && (IS_INTEGER(rhs) || IS_FLOAT(rhs))) { if ((IS_INTEGER(lhs) || IS_FLOAT(lhs)) && (IS_INTEGER(rhs) || IS_FLOAT(rhs))) {
@@ -396,6 +372,8 @@ bool literalsAreEqual(Literal lhs, Literal rhs) {
} }
switch(lhs.type) { switch(lhs.type) {
//NOTE: null covered by check at the top of the function
case LITERAL_BOOLEAN: case LITERAL_BOOLEAN:
return AS_BOOLEAN(lhs) == AS_BOOLEAN(rhs); return AS_BOOLEAN(lhs) == AS_BOOLEAN(rhs);
@@ -412,9 +390,12 @@ bool literalsAreEqual(Literal lhs, Literal rhs) {
return !strncmp(AS_STRING(lhs), AS_STRING(rhs), STRLEN(lhs)); return !strncmp(AS_STRING(lhs), AS_STRING(rhs), STRLEN(lhs));
case LITERAL_ARRAY: case LITERAL_ARRAY:
//mismatched sizes
if (AS_ARRAY(lhs)->count != AS_ARRAY(rhs)->count) { if (AS_ARRAY(lhs)->count != AS_ARRAY(rhs)->count) {
return false; return false;
} }
//mismatched elements (in order)
for (int i = 0; i < AS_ARRAY(lhs)->count; i++) { for (int i = 0; i < AS_ARRAY(lhs)->count; i++) {
if (!literalsAreEqual( AS_ARRAY(lhs)->literals[i], AS_ARRAY(rhs)->literals[i] )) { if (!literalsAreEqual( AS_ARRAY(lhs)->literals[i], AS_ARRAY(rhs)->literals[i] )) {
return false; return false;
@@ -437,76 +418,47 @@ bool literalsAreEqual(Literal lhs, Literal rhs) {
} }
} }
} }
return true; return true;
//TODO: functions //TODO: functions
case LITERAL_IDENTIFIER: case LITERAL_IDENTIFIER:
//check shortcuts
if (HASH_I(lhs) != HASH_I(rhs) && STRLEN_I(lhs) != STRLEN_I(rhs)) { if (HASH_I(lhs) != HASH_I(rhs) && STRLEN_I(lhs) != STRLEN_I(rhs)) {
return false; return false;
} }
return !strncmp(AS_IDENTIFIER(lhs), AS_IDENTIFIER(rhs), STRLEN_I(lhs)); return !strncmp(AS_IDENTIFIER(lhs), AS_IDENTIFIER(rhs), STRLEN_I(lhs));
case LITERAL_TYPE: case LITERAL_TYPE:
if (AS_TYPE(lhs).mask != AS_TYPE(rhs).mask) { //check types
if (AS_TYPE(lhs).typeOf != AS_TYPE(rhs).typeOf) {
return false; return false;
} }
//const don't match
if (AS_TYPE(lhs).constant != AS_TYPE(rhs).constant) {
return false;
}
//check subtypes
if (AS_TYPE(lhs).count != AS_TYPE(rhs).count) { if (AS_TYPE(lhs).count != AS_TYPE(rhs).count) {
return false; return false;
} }
//TODO: array & dictionaries (slot 0 is an array collection, slot 1 is a dictionary collection) //check array|dictionary signatures are the same (in order)
if ((AS_TYPE(lhs).mask & (MASK_ARRAY|MASK_DICTIONARY)) == (MASK_ARRAY|MASK_DICTIONARY)) { if (AS_TYPE(lhs).typeOf == LITERAL_ARRAY || AS_TYPE(lhs).typeOf == LITERAL_DICTIONARY) {
//check arrays
if (!literalsAreEqual(((Literal*)(AS_TYPE(lhs).subtypes))[0], ((Literal*)(AS_TYPE(rhs).subtypes))[0])) {
return false;
}
//check dictionaries
if (!literalsAreEqual(((Literal*)(AS_TYPE(lhs).subtypes))[1], ((Literal*)(AS_TYPE(rhs).subtypes))[1])) {
return false;
}
}
//TODO: arrays (out of order)
if (AS_TYPE(lhs).mask & MASK_ARRAY) {
for (int i = 0; i < AS_TYPE(lhs).count; i++) { for (int i = 0; i < AS_TYPE(lhs).count; i++) {
bool match = false; if (!literalsAreEqual(((Literal*)(AS_TYPE(lhs).subtypes))[i], ((Literal*)(AS_TYPE(rhs).subtypes))[i])) {
for (int j = 0; j < AS_TYPE(rhs).count; j++) {
//compare
if (literalsAreEqual( ((Literal*)(AS_TYPE(lhs).subtypes))[i], ((Literal*)(AS_TYPE(rhs).subtypes))[j] )) {
match = true;
break;
}
}
if (!match) {
return false; return false;
} }
} }
} }
//TODO: dictionaries (out of order)
if (AS_TYPE(lhs).mask & MASK_DICTIONARY) {
for (int i = 0; i < AS_TYPE(lhs).count; i += 2) {
bool match = false;
for (int j = 0; j < AS_TYPE(rhs).count; j += 2) {
//compare
if (literalsAreEqual( ((Literal*)(AS_TYPE(lhs).subtypes))[i], ((Literal*)(AS_TYPE(rhs).subtypes))[j] ) && literalsAreEqual( ((Literal*)(AS_TYPE(lhs).subtypes))[i + 1], ((Literal*)(AS_TYPE(rhs).subtypes))[j + 1] )) {
match = true;
break;
}
}
if (!match) {
return false;
}
}
}
return true; return true;
//NOTE: any covered by check at the top of the function
default: default:
//should never bee seen //should never bee seen
fprintf(stderr, "[Internal] Unrecognized literal type in equality: %d\n", lhs.type); fprintf(stderr, "[Internal] Unrecognized literal type in equality: %d\n", lhs.type);
@@ -550,9 +502,18 @@ int hashLiteral(Literal lit) {
return hash(res); return hash(res);
} }
// case LITERAL_FUNCTION:
// //
case LITERAL_IDENTIFIER: case LITERAL_IDENTIFIER:
return HASH_I(lit); //pre-computed return HASH_I(lit); //pre-computed
// case LITERAL_TYPE:
// //not needed
// case LITERAL_ANY:
// //not needed
default: default:
//should never bee seen //should never bee seen
fprintf(stderr, "[Internal] Unrecognized literal type in hash: %d\n", lit.type); fprintf(stderr, "[Internal] Unrecognized literal type in hash: %d\n", lit.type);

View File

@@ -12,9 +12,12 @@ typedef enum {
LITERAL_STRING, LITERAL_STRING,
LITERAL_ARRAY, LITERAL_ARRAY,
LITERAL_DICTIONARY, LITERAL_DICTIONARY,
// LITERAL_FUNCTION, LITERAL_FUNCTION, //TODO: to be implemented later; the type is still handled for the most part
//these are meta-level types
LITERAL_IDENTIFIER, LITERAL_IDENTIFIER,
LITERAL_TYPE, LITERAL_TYPE,
LITERAL_ANY, //used by the type system only
} LiteralType; } LiteralType;
typedef struct { typedef struct {
@@ -40,7 +43,8 @@ typedef struct {
} identifier; } identifier;
struct { struct {
unsigned char mask; LiteralType typeOf; //no longer a mask
bool constant;
void* subtypes; //for nested types caused by compounds void* subtypes; //for nested types caused by compounds
int capacity; int capacity;
int count; int count;
@@ -78,26 +82,7 @@ typedef struct {
#define TO_DICTIONARY_LITERAL(value) ((Literal){LITERAL_DICTIONARY, { .dictionary = value }}) #define TO_DICTIONARY_LITERAL(value) ((Literal){LITERAL_DICTIONARY, { .dictionary = value }})
// #define TO_FUNCTION_LITERAL // #define TO_FUNCTION_LITERAL
#define TO_IDENTIFIER_LITERAL(value) _toIdentifierLiteral(value, strlen(value)) #define TO_IDENTIFIER_LITERAL(value) _toIdentifierLiteral(value, strlen(value))
#define TO_TYPE_LITERAL(value) ((Literal){ LITERAL_TYPE, { .type.mask = value, .type.subtypes = NULL, .type.capacity = 0, .type.count = 0 }}) #define TO_TYPE_LITERAL(value, c) ((Literal){ LITERAL_TYPE, { .type.typeOf = value, .type.constant = c, .type.subtypes = NULL, .type.capacity = 0, .type.count = 0 }})
#define MASK(x) (1 << (x))
#define TYPE_CONST 0
#define TYPE_BOOLEAN 1
#define TYPE_INTEGER 2
#define TYPE_FLOAT 3
#define TYPE_STRING 4
#define TYPE_ARRAY 5
#define TYPE_DICTIONARY 6
#define TYPE_FUNCTION 7
#define MASK_CONST (MASK(TYPE_CONST))
#define MASK_BOOLEAN (MASK(TYPE_BOOLEAN))
#define MASK_INTEGER (MASK(TYPE_INTEGER))
#define MASK_FLOAT (MASK(TYPE_FLOAT))
#define MASK_STRING (MASK(TYPE_STRING))
#define MASK_ARRAY (MASK(TYPE_ARRAY))
#define MASK_DICTIONARY (MASK(TYPE_DICTIONARY))
#define MASK_FUNCTION (MASK(TYPE_FUNCTION))
#define MASK_ANY 0
//utils //utils
void printLiteral(Literal literal); void printLiteral(Literal literal);
@@ -109,13 +94,13 @@ void freeLiteral(Literal literal);
#define STRLEN(lit) ((lit).as.string.length) #define STRLEN(lit) ((lit).as.string.length)
#define STRLEN_I(lit) ((lit).as.identifier.length) #define STRLEN_I(lit) ((lit).as.identifier.length)
#define HASH_I(lit) ((lit).as.identifier.hash) #define HASH_I(lit) ((lit).as.identifier.hash)
#define TYPE_PUSH_SUBTYPE(lit, submask) _typePushSubtype(lit, submask) #define TYPE_PUSH_SUBTYPE(lit, subtype) _typePushSubtype(lit, subtype)
//BUGFIX: macros are not functions //BUGFIX: macros are not functions
bool _isTruthy(Literal x); bool _isTruthy(Literal x);
Literal _toStringLiteral(char* str); Literal _toStringLiteral(char* str);
Literal _toIdentifierLiteral(char* str, int length); Literal _toIdentifierLiteral(char* str, int length);
Literal* _typePushSubtype(Literal* lit, unsigned char submask); Literal* _typePushSubtype(Literal* lit, Literal subtype);
//utils //utils
char* copyString(char* original, int length); char* copyString(char* original, int length);

View File

@@ -15,7 +15,7 @@ typedef enum NodeType {
NODE_BLOCK, //contains a sub-node array NODE_BLOCK, //contains a sub-node array
NODE_COMPOUND, //contains a sub-node array NODE_COMPOUND, //contains a sub-node array
NODE_PAIR, //contains a left and right NODE_PAIR, //contains a left and right
NODE_VAR_TYPES, //contains a type mask and a sub-node array for compound types NODE_VAR_TYPES, //contains a type and a sub-node array for compound types
NODE_VAR_DECL, //contains identifier literal, typenode, expression definition NODE_VAR_DECL, //contains identifier literal, typenode, expression definition
// NODE_CONDITIONAL, //three children: conditional, then path, else path // NODE_CONDITIONAL, //three children: conditional, then path, else path
} NodeType; } NodeType;

View File

@@ -798,23 +798,23 @@ static void statement(Parser* parser, Node** nodeHandle) {
static Literal readTypeToLiteral(Parser* parser) { static Literal readTypeToLiteral(Parser* parser) {
advance(parser); advance(parser);
Literal literal = TO_TYPE_LITERAL(MASK_ANY); Literal literal = TO_NULL_LITERAL;
switch(parser->previous.type) { switch(parser->previous.type) {
case TOKEN_BOOLEAN: case TOKEN_BOOLEAN:
AS_TYPE(literal).mask |= MASK_BOOLEAN; AS_TYPE(literal).typeOf = LITERAL_BOOLEAN;
break; break;
case TOKEN_INTEGER: case TOKEN_INTEGER:
AS_TYPE(literal).mask |= MASK_INTEGER; AS_TYPE(literal).typeOf = LITERAL_INTEGER;
break; break;
case TOKEN_FLOAT: case TOKEN_FLOAT:
AS_TYPE(literal).mask |= MASK_FLOAT; AS_TYPE(literal).typeOf = LITERAL_FLOAT;
break; break;
case TOKEN_STRING: case TOKEN_STRING:
AS_TYPE(literal).mask |= MASK_STRING; AS_TYPE(literal).typeOf = LITERAL_STRING;
break; break;
//array, dictionary - read the sub-types //array, dictionary - read the sub-types
@@ -824,24 +824,15 @@ static Literal readTypeToLiteral(Parser* parser) {
if (match(parser, TOKEN_COMMA)) { if (match(parser, TOKEN_COMMA)) {
Literal r = readTypeToLiteral(parser); Literal r = readTypeToLiteral(parser);
AS_TYPE(literal).subtypes = ALLOCATE(Literal, 2); TYPE_PUSH_SUBTYPE(&literal, l);
AS_TYPE(literal).capacity = 2; TYPE_PUSH_SUBTYPE(&literal, r);
AS_TYPE(literal).count = 2;
((Literal*)(AS_TYPE(literal).subtypes))[0] = l; AS_TYPE(literal).typeOf = LITERAL_DICTIONARY;
((Literal*)(AS_TYPE(literal).subtypes))[1] = r;
AS_TYPE(literal).mask |= MASK_DICTIONARY;
} }
else { else {
AS_TYPE(literal).subtypes = ALLOCATE(Literal, 1); TYPE_PUSH_SUBTYPE(&literal, l);
AS_TYPE(literal).capacity = 1;
AS_TYPE(literal).count = 1;
//append the "l" literal AS_TYPE(literal).typeOf = LITERAL_ARRAY;
((Literal*)(AS_TYPE(literal).subtypes))[0] = l;
AS_TYPE(literal).mask |= MASK_ARRAY;
} }
consume(parser, TOKEN_BRACKET_RIGHT, "Expected ']' at end of type definition"); consume(parser, TOKEN_BRACKET_RIGHT, "Expected ']' at end of type definition");
@@ -850,6 +841,10 @@ static Literal readTypeToLiteral(Parser* parser) {
//TODO: function //TODO: function
case TOKEN_ANY:
AS_TYPE(literal).typeOf = LITERAL_ANY;
break;
default: default:
error(parser, parser->previous, "Bad type signature"); error(parser, parser->previous, "Bad type signature");
return TO_NULL_LITERAL; return TO_NULL_LITERAL;
@@ -857,7 +852,7 @@ static Literal readTypeToLiteral(Parser* parser) {
//const follows the type //const follows the type
if (match(parser, TOKEN_CONST)) { if (match(parser, TOKEN_CONST)) {
AS_TYPE(literal).mask |= MASK_CONST; AS_TYPE(literal).constant = true;
} }
return literal; return literal;
@@ -877,7 +872,8 @@ static void varDecl(Parser* parser, Node** nodeHandle) {
typeLiteral = readTypeToLiteral(parser); typeLiteral = readTypeToLiteral(parser);
} }
else { else {
typeLiteral = TO_TYPE_LITERAL(MASK_ANY); //default any
typeLiteral = TO_TYPE_LITERAL(LITERAL_ANY, false);
} }
//variable definition is an expression //variable definition is an expression

View File

@@ -24,28 +24,33 @@ static void freeAncestorChain(Scope* scope) {
//return false if invalid type //return false if invalid type
static bool checkType(Literal typeLiteral, Literal value) { static bool checkType(Literal typeLiteral, Literal value) {
//for any types //for any types
if (AS_TYPE(typeLiteral).mask == MASK_ANY) { if (AS_TYPE(typeLiteral).typeOf == LITERAL_ANY) {
return true; return true;
} }
//for each type, if a mismatch is found, return false //for each type, if a mismatch is found, return false
if ((AS_TYPE(typeLiteral).mask & MASK_BOOLEAN) && !IS_BOOLEAN(value)) { if (AS_TYPE(typeLiteral).typeOf == LITERAL_BOOLEAN && !IS_BOOLEAN(value)) {
return false; return false;
} }
if ((AS_TYPE(typeLiteral).mask & MASK_INTEGER) && !IS_INTEGER(value)) { if (AS_TYPE(typeLiteral).typeOf == LITERAL_INTEGER && !IS_INTEGER(value)) {
return false; return false;
} }
if ((AS_TYPE(typeLiteral).mask & MASK_FLOAT) && !IS_FLOAT(value)) { if (AS_TYPE(typeLiteral).typeOf == LITERAL_FLOAT && !IS_FLOAT(value)) {
return false; return false;
} }
if ((AS_TYPE(typeLiteral).mask & MASK_STRING) && !IS_STRING(value)) { if (AS_TYPE(typeLiteral).typeOf == LITERAL_STRING && !IS_STRING(value)) {
return false; return false;
} }
if ((AS_TYPE(typeLiteral).mask & MASK_ARRAY) && IS_ARRAY(value)) { if (IS_ARRAY(value)) {
//check value's type
if (AS_TYPE(typeLiteral).typeOf != LITERAL_ARRAY) {
return false;
}
//check children //check children
for (int i = 0; i < AS_ARRAY(value)->count; i++) { for (int i = 0; i < AS_ARRAY(value)->count; i++) {
if (!checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[0], AS_ARRAY(value)->literals[i])) { if (!checkType(((Literal*)(AS_TYPE(typeLiteral).subtypes))[0], AS_ARRAY(value)->literals[i])) {
@@ -54,7 +59,12 @@ static bool checkType(Literal typeLiteral, Literal value) {
} }
} }
if ((AS_TYPE(typeLiteral).mask & MASK_DICTIONARY) && IS_DICTIONARY(value)) { if (IS_DICTIONARY(value)) {
//check value's type
if (AS_TYPE(typeLiteral).typeOf != LITERAL_DICTIONARY) {
return false;
}
//check children //check children
for (int i = 0; i < AS_DICTIONARY(value)->capacity; i++) { for (int i = 0; i < AS_DICTIONARY(value)->capacity; i++) {
//only assigned and non-tombstoned keys //only assigned and non-tombstoned keys
@@ -70,6 +80,8 @@ static bool checkType(Literal typeLiteral, Literal value) {
} }
} }
//TODO: functions
return true; return true;
} }
@@ -144,7 +156,7 @@ bool setScopeVariable(Scope* scope, Literal key, Literal value, bool constCheck)
} }
//const check //const check
if (constCheck && (AS_TYPE(typeLiteral).mask & MASK_CONST)) { if (constCheck && (AS_TYPE(typeLiteral).constant)) {
return false; return false;
} }