From 574a864dd0b88d75eddb930fa82e57a7f2ba23c7 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Wed, 17 Aug 2022 17:39:29 +0100 Subject: [PATCH] Reworked the type system, types now have a single value --- docs/TODO.txt | 2 + scripts/small.toy | 7 +- source/compiler.c | 53 ++++----- source/interpreter.c | 31 +++-- source/literal.c | 261 ++++++++++++++++++------------------------- source/literal.h | 33 ++---- source/node.h | 2 +- source/parser.c | 38 +++---- source/scope.c | 28 +++-- 9 files changed, 201 insertions(+), 254 deletions(-) diff --git a/docs/TODO.txt b/docs/TODO.txt index d231ad6..0c37d39 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -1,3 +1,5 @@ +DONE: rework type system + TODO: type casting TODO: const without a type TODO: increment & decrement operators diff --git a/scripts/small.toy b/scripts/small.toy index 663da06..f2e4d27 100644 --- a/scripts/small.toy +++ b/scripts/small.toy @@ -1,5 +1,6 @@ +var arr : [int] = [1, 2, 3, 42]; +var dict : [string, int] = ["hello": 1, "world":2]; - - -var dict : [string, int] = ["hello" : 1, "world" : 2]; \ No newline at end of file +print arr; +print dict; \ No newline at end of file diff --git a/source/compiler.c b/source/compiler.c index dbde911..3a35449 100644 --- a/source/compiler.c +++ b/source/compiler.c @@ -15,15 +15,6 @@ void initCompiler(Compiler* compiler) { compiler->bytecode = NULL; compiler->capacity = 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 @@ -130,34 +121,27 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { return index; } -static int writeLiteralTypeToCache(LiteralArray* parent, Literal literal) { - int index = -1; - - //for now, stored as an array +static int writeLiteralTypeToCache(LiteralArray* literalCache, Literal literal) { + //I don't like storing types in an array, but it's the easiest and most straight forward method LiteralArray* store = ALLOCATE(LiteralArray, 1); initLiteralArray(store); - //save the mask to the store, at index 0 - int maskIndex = findLiteralIndex(store, TO_INTEGER_LITERAL(AS_TYPE(literal).mask)); - if (maskIndex < 0) { - maskIndex = pushLiteralArray(store, TO_INTEGER_LITERAL(AS_TYPE(literal).mask)); - } + //store the base literal in the store + pushLiteralArray(store, literal); - //if it's a compound type, recurse - if (AS_TYPE(literal).mask & (MASK_ARRAY|MASK_DICTIONARY)) { + //if it's a compound type, recurse and store the results + if (AS_TYPE(literal).typeOf == LITERAL_ARRAY || AS_TYPE(literal).typeOf == LITERAL_DICTIONARY) { for (int i = 0; i < AS_TYPE(literal).count; i++) { //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)); } } //push the store to the cache, tweaking the type Literal lit = TO_ARRAY_LITERAL(store); - lit.type = LITERAL_TYPE; //TODO: tweaking the type isn't a good idea - index = pushLiteralArray(parent, lit); - - return index; + lit.type = LITERAL_TYPE; //NOTE: tweaking the type usually isn't a good idea + return pushLiteralArray(literalCache, lit); } void writeCompiler(Compiler* compiler, Node* node) { @@ -463,6 +447,8 @@ unsigned char* collateCompiler(Compiler* compiler, int* size) { } break; + //TODO: function + case 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 - //length of the array, as a short - emitShort(&collation, &capacity, &count, ptr->count); //count is the array size + //the base literal + Literal typeLiteral = ptr->literals[0]; - //each element of the array - for (int i = 0; i < ptr->count; i++) { - emitShort(&collation, &capacity, &count, (unsigned short)AS_INTEGER(ptr->literals[i])); //shorts representing the indexes of the values + //what type this literal represents + emitByte(&collation, &capacity, &count, AS_TYPE(typeLiteral).typeOf); + 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); diff --git a/source/interpreter.c b/source/interpreter.c index 2555a4f..a8faf10 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -589,28 +589,25 @@ void runInterpreter(Interpreter* interpreter, unsigned char* bytecode, int lengt break; 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) - unsigned short count = readShort(interpreter->bytecode, &interpreter->count) - 1; + Literal typeLiteral = TO_TYPE_LITERAL(literalType, constant); - // read the mask - unsigned char mask = readShort(interpreter->bytecode, &interpreter->count); + //if it's an array type + if (AS_TYPE(typeLiteral).typeOf == LITERAL_ARRAY) { + unsigned short vt = readShort(interpreter->bytecode, &interpreter->count); - //create the literal - typeLiteral = TO_TYPE_LITERAL(mask); + TYPE_PUSH_SUBTYPE(&typeLiteral, interpreter->literalCache.literals[vt]); + } - //if it's got subtypes, grab them from the existing cache - if (count > 0) { - AS_TYPE(typeLiteral).subtypes = ALLOCATE(Literal, count); - AS_TYPE(typeLiteral).capacity = count; - AS_TYPE(typeLiteral).count = count; + if (AS_TYPE(typeLiteral).typeOf == LITERAL_DICTIONARY) { + unsigned short kt = readShort(interpreter->bytecode, &interpreter->count); + unsigned short vt = readShort(interpreter->bytecode, &interpreter->count); - for (int i = 0; i < AS_TYPE(typeLiteral).count; i++) { - //read each index - int index = readShort(interpreter->bytecode, &interpreter->count); - ((Literal*)(AS_TYPE(typeLiteral).subtypes))[i] = interpreter->literalCache.literals[index]; - } + TYPE_PUSH_SUBTYPE(&typeLiteral, interpreter->literalCache.literals[kt]); + TYPE_PUSH_SUBTYPE(&typeLiteral, interpreter->literalCache.literals[vt]); } //save the type diff --git a/source/literal.c b/source/literal.c index f1fcfca..94305b4 100644 --- a/source/literal.c +++ b/source/literal.c @@ -32,9 +32,6 @@ static void printToBuffer(const char* str) { globalPrintCount += strlen(str); } -//BUGFIX: is handled oddly for specific reasons, so this flag is for the debug output of the type -bool printTypeMarker = true; - //hash util functions static unsigned int hashString(const char* string, int length) { unsigned int hash = 2166136261u; @@ -98,7 +95,7 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) { case LITERAL_ARRAY: { LiteralArray* ptr = AS_ARRAY(literal); - //hold potential parent-call buffers + //hold potential parent-call buffers on the C stack char* cacheBuffer = globalPrintBuffer; globalPrintBuffer = NULL; int cacheCapacity = globalPrintCapacity; @@ -137,7 +134,7 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) { case LITERAL_DICTIONARY: { LiteralDictionary* ptr = AS_DICTIONARY(literal); - //hold potential parent-call buffers + //hold potential parent-call buffers on the C stack char* cacheBuffer = globalPrintBuffer; globalPrintBuffer = NULL; int cacheCapacity = globalPrintCapacity; @@ -186,6 +183,8 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) { quotes = 0; } break; + + //TODO: functions case LITERAL_IDENTIFIER: { char buffer[256]; @@ -195,7 +194,7 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) { break; case LITERAL_TYPE: { - //hold potential parent-call buffers + //hold potential parent-call buffers on the C stack char* cacheBuffer = globalPrintBuffer; globalPrintBuffer = NULL; int cacheCapacity = globalPrintCapacity; @@ -203,109 +202,74 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) { int cacheCount = globalPrintCount; globalPrintCount = 0; - //print the type - int iterations = 0; - if (printTypeMarker) { - printToBuffer("<"); - } + //print the type correctly + printToBuffer("<"); - for (int i = 1; i < 8; i ++) { //0th bit is const - //zero mask = any type, anys can't be const - if (AS_TYPE(literal).mask == MASK_ANY) { + switch(AS_TYPE(literal).typeOf) { + case LITERAL_BOOLEAN: + 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"); - break; - } + break; - if (AS_TYPE(literal).mask & MASK(i)) { - //pretty print - if (iterations++ > 0) { - 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 - } - } + default: + //should never be seen + fprintf(stderr, "[Internal] Unrecognized literal type in print type: %d\n", literal.type); } //const (printed last) - if (AS_TYPE(literal).mask & MASK_CONST) { - if (iterations++ > 0) { - printToBuffer(" "); - } - printToBuffer("const"); + if (AS_TYPE(literal).constant) { + printToBuffer(" const"); } - if (printTypeMarker) { - printToBuffer(">"); - } + printToBuffer(">"); //swap the parent-call buffer back into place char* printBuffer = globalPrintBuffer; @@ -335,6 +299,15 @@ void freeLiteral(Literal literal) { 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)) { FREE_ARRAY(char, AS_IDENTIFIER(literal), STRLEN_I(literal)); return; @@ -353,14 +326,15 @@ bool _isTruthy(Literal x) { } 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) { - 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) { int oldCapacity = AS_TYPE(*lit).capacity; @@ -369,11 +343,12 @@ Literal* _typePushSubtype(Literal* lit, unsigned char submask) { } //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 ]; } char* copyString(char* original, int length) { + //make a local copy of the char array char* buffer = ALLOCATE(char, length + 1); strncpy(buffer, original, length); buffer[length] = '\0'; @@ -381,6 +356,7 @@ char* copyString(char* original, int length) { } bool literalsAreEqual(Literal lhs, Literal rhs) { + //utility for other things if (lhs.type != rhs.type) { // ints and floats are compatible 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) { + //NOTE: null covered by check at the top of the function + case LITERAL_BOOLEAN: 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)); case LITERAL_ARRAY: + //mismatched sizes if (AS_ARRAY(lhs)->count != AS_ARRAY(rhs)->count) { return false; } + + //mismatched elements (in order) for (int i = 0; i < AS_ARRAY(lhs)->count; i++) { if (!literalsAreEqual( AS_ARRAY(lhs)->literals[i], AS_ARRAY(rhs)->literals[i] )) { return false; @@ -437,76 +418,47 @@ bool literalsAreEqual(Literal lhs, Literal rhs) { } } } + return true; //TODO: functions case LITERAL_IDENTIFIER: + //check shortcuts if (HASH_I(lhs) != HASH_I(rhs) && STRLEN_I(lhs) != STRLEN_I(rhs)) { return false; } + return !strncmp(AS_IDENTIFIER(lhs), AS_IDENTIFIER(rhs), STRLEN_I(lhs)); 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; } + //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) { return false; } - //TODO: array & dictionaries (slot 0 is an array collection, slot 1 is a dictionary collection) - if ((AS_TYPE(lhs).mask & (MASK_ARRAY|MASK_DICTIONARY)) == (MASK_ARRAY|MASK_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) { + //check array|dictionary signatures are the same (in order) + if (AS_TYPE(lhs).typeOf == LITERAL_ARRAY || AS_TYPE(lhs).typeOf == LITERAL_DICTIONARY) { for (int i = 0; i < AS_TYPE(lhs).count; i++) { - bool match = false; - 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) { + if (!literalsAreEqual(((Literal*)(AS_TYPE(lhs).subtypes))[i], ((Literal*)(AS_TYPE(rhs).subtypes))[i])) { 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; + //NOTE: any covered by check at the top of the function + default: //should never bee seen fprintf(stderr, "[Internal] Unrecognized literal type in equality: %d\n", lhs.type); @@ -550,9 +502,18 @@ int hashLiteral(Literal lit) { return hash(res); } + // case LITERAL_FUNCTION: + // // + case LITERAL_IDENTIFIER: return HASH_I(lit); //pre-computed + // case LITERAL_TYPE: + // //not needed + + // case LITERAL_ANY: + // //not needed + default: //should never bee seen fprintf(stderr, "[Internal] Unrecognized literal type in hash: %d\n", lit.type); diff --git a/source/literal.h b/source/literal.h index 6ea241b..7170945 100644 --- a/source/literal.h +++ b/source/literal.h @@ -12,9 +12,12 @@ typedef enum { LITERAL_STRING, LITERAL_ARRAY, 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_TYPE, + LITERAL_ANY, //used by the type system only } LiteralType; typedef struct { @@ -40,7 +43,8 @@ typedef struct { } identifier; struct { - unsigned char mask; + LiteralType typeOf; //no longer a mask + bool constant; void* subtypes; //for nested types caused by compounds int capacity; int count; @@ -78,26 +82,7 @@ typedef struct { #define TO_DICTIONARY_LITERAL(value) ((Literal){LITERAL_DICTIONARY, { .dictionary = value }}) // #define TO_FUNCTION_LITERAL #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 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 +#define TO_TYPE_LITERAL(value, c) ((Literal){ LITERAL_TYPE, { .type.typeOf = value, .type.constant = c, .type.subtypes = NULL, .type.capacity = 0, .type.count = 0 }}) //utils void printLiteral(Literal literal); @@ -109,13 +94,13 @@ void freeLiteral(Literal literal); #define STRLEN(lit) ((lit).as.string.length) #define STRLEN_I(lit) ((lit).as.identifier.length) #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 bool _isTruthy(Literal x); Literal _toStringLiteral(char* str); Literal _toIdentifierLiteral(char* str, int length); -Literal* _typePushSubtype(Literal* lit, unsigned char submask); +Literal* _typePushSubtype(Literal* lit, Literal subtype); //utils char* copyString(char* original, int length); diff --git a/source/node.h b/source/node.h index 8f22210..c66e6c3 100644 --- a/source/node.h +++ b/source/node.h @@ -15,7 +15,7 @@ typedef enum NodeType { NODE_BLOCK, //contains a sub-node array NODE_COMPOUND, //contains a sub-node array 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_CONDITIONAL, //three children: conditional, then path, else path } NodeType; diff --git a/source/parser.c b/source/parser.c index 88edf13..9a828eb 100644 --- a/source/parser.c +++ b/source/parser.c @@ -798,23 +798,23 @@ static void statement(Parser* parser, Node** nodeHandle) { static Literal readTypeToLiteral(Parser* parser) { advance(parser); - Literal literal = TO_TYPE_LITERAL(MASK_ANY); + Literal literal = TO_NULL_LITERAL; switch(parser->previous.type) { case TOKEN_BOOLEAN: - AS_TYPE(literal).mask |= MASK_BOOLEAN; + AS_TYPE(literal).typeOf = LITERAL_BOOLEAN; break; case TOKEN_INTEGER: - AS_TYPE(literal).mask |= MASK_INTEGER; + AS_TYPE(literal).typeOf = LITERAL_INTEGER; break; case TOKEN_FLOAT: - AS_TYPE(literal).mask |= MASK_FLOAT; + AS_TYPE(literal).typeOf = LITERAL_FLOAT; break; case TOKEN_STRING: - AS_TYPE(literal).mask |= MASK_STRING; + AS_TYPE(literal).typeOf = LITERAL_STRING; break; //array, dictionary - read the sub-types @@ -824,24 +824,15 @@ static Literal readTypeToLiteral(Parser* parser) { if (match(parser, TOKEN_COMMA)) { Literal r = readTypeToLiteral(parser); - AS_TYPE(literal).subtypes = ALLOCATE(Literal, 2); - AS_TYPE(literal).capacity = 2; - AS_TYPE(literal).count = 2; + TYPE_PUSH_SUBTYPE(&literal, l); + TYPE_PUSH_SUBTYPE(&literal, r); - ((Literal*)(AS_TYPE(literal).subtypes))[0] = l; - ((Literal*)(AS_TYPE(literal).subtypes))[1] = r; - - AS_TYPE(literal).mask |= MASK_DICTIONARY; + AS_TYPE(literal).typeOf = LITERAL_DICTIONARY; } else { - AS_TYPE(literal).subtypes = ALLOCATE(Literal, 1); - AS_TYPE(literal).capacity = 1; - AS_TYPE(literal).count = 1; + TYPE_PUSH_SUBTYPE(&literal, l); - //append the "l" literal - ((Literal*)(AS_TYPE(literal).subtypes))[0] = l; - - AS_TYPE(literal).mask |= MASK_ARRAY; + AS_TYPE(literal).typeOf = LITERAL_ARRAY; } consume(parser, TOKEN_BRACKET_RIGHT, "Expected ']' at end of type definition"); @@ -850,6 +841,10 @@ static Literal readTypeToLiteral(Parser* parser) { //TODO: function + case TOKEN_ANY: + AS_TYPE(literal).typeOf = LITERAL_ANY; + break; + default: error(parser, parser->previous, "Bad type signature"); return TO_NULL_LITERAL; @@ -857,7 +852,7 @@ static Literal readTypeToLiteral(Parser* parser) { //const follows the type if (match(parser, TOKEN_CONST)) { - AS_TYPE(literal).mask |= MASK_CONST; + AS_TYPE(literal).constant = true; } return literal; @@ -877,7 +872,8 @@ static void varDecl(Parser* parser, Node** nodeHandle) { typeLiteral = readTypeToLiteral(parser); } else { - typeLiteral = TO_TYPE_LITERAL(MASK_ANY); + //default any + typeLiteral = TO_TYPE_LITERAL(LITERAL_ANY, false); } //variable definition is an expression diff --git a/source/scope.c b/source/scope.c index 7e2a8f1..068dfc7 100644 --- a/source/scope.c +++ b/source/scope.c @@ -24,28 +24,33 @@ static void freeAncestorChain(Scope* scope) { //return false if invalid type static bool checkType(Literal typeLiteral, Literal value) { //for any types - if (AS_TYPE(typeLiteral).mask == MASK_ANY) { + if (AS_TYPE(typeLiteral).typeOf == LITERAL_ANY) { return true; } //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; } - if ((AS_TYPE(typeLiteral).mask & MASK_INTEGER) && !IS_INTEGER(value)) { + if (AS_TYPE(typeLiteral).typeOf == LITERAL_INTEGER && !IS_INTEGER(value)) { return false; } - if ((AS_TYPE(typeLiteral).mask & MASK_FLOAT) && !IS_FLOAT(value)) { + if (AS_TYPE(typeLiteral).typeOf == LITERAL_FLOAT && !IS_FLOAT(value)) { return false; } - if ((AS_TYPE(typeLiteral).mask & MASK_STRING) && !IS_STRING(value)) { + if (AS_TYPE(typeLiteral).typeOf == LITERAL_STRING && !IS_STRING(value)) { 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 for (int i = 0; i < AS_ARRAY(value)->count; 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 for (int i = 0; i < AS_DICTIONARY(value)->capacity; i++) { //only assigned and non-tombstoned keys @@ -70,6 +80,8 @@ static bool checkType(Literal typeLiteral, Literal value) { } } + //TODO: functions + return true; } @@ -144,7 +156,7 @@ bool setScopeVariable(Scope* scope, Literal key, Literal value, bool constCheck) } //const check - if (constCheck && (AS_TYPE(typeLiteral).mask & MASK_CONST)) { + if (constCheck && (AS_TYPE(typeLiteral).constant)) { return false; }