diff --git a/scripts/small.toy b/scripts/small.toy index 920f5d1..2af1cec 100644 --- a/scripts/small.toy +++ b/scripts/small.toy @@ -1 +1,2 @@ -var name : [string const, int] = ["foo" : 42]; \ No newline at end of file +var name : [string const, int] = ["foo" : 42]; +var something = 0; diff --git a/source/compiler.c b/source/compiler.c index e83b3ce..b57c8d2 100644 --- a/source/compiler.c +++ b/source/compiler.c @@ -88,7 +88,7 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { } //push the store to the cache, with instructions about how pack it - index = pushLiteralArray(&compiler->literalCache, TO_DICTIONARY_LITERAL(store)); //pushed as an array, so below can recognize it + index = pushLiteralArray(&compiler->literalCache, TO_ARRAY_LITERAL(store)); //WARNING: pushed as a dictionary, so below can recognize it } else if (node->compound.literalType == LITERAL_ARRAY) { //ensure each literal value is in the cache, individually @@ -135,24 +135,25 @@ static int writeLiteralTypeToCache(LiteralArray* parent, Literal literal) { LiteralArray* store = ALLOCATE(LiteralArray, 1); initLiteralArray(store); - //save the mask to the store - int maskIndex = findLiteralIndex(parent, TO_INTEGER_LITERAL(AS_TYPE(literal).mask)); + //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(parent, TO_INTEGER_LITERAL(AS_TYPE(literal).mask)); + maskIndex = pushLiteralArray(store, TO_INTEGER_LITERAL(AS_TYPE(literal).mask)); } - pushLiteralArray(store, TO_INTEGER_LITERAL(maskIndex)); - //if it's a compound type, recurse if (AS_TYPE(literal).mask & (MASK_ARRAY|MASK_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]); pushLiteralArray(store, TO_INTEGER_LITERAL(subIndex)); } } - //push the store to the parent - index = pushLiteralArray(parent, TO_ARRAY_LITERAL(store)); + //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; } diff --git a/source/interpreter.c b/source/interpreter.c index a53f5bf..413046b 100644 --- a/source/interpreter.c +++ b/source/interpreter.c @@ -80,14 +80,14 @@ static char* readString(unsigned char* tb, int* count) { static void consumeByte(unsigned char byte, unsigned char* tb, int* count) { if (byte != tb[*count]) { - printf("[internal] Failed to consume the correct byte\n"); + printf("[internal] Failed to consume the correct byte (expected %u, found %u)\n", byte, tb[*count]); } *count += 1; } static void consumeShort(unsigned short bytes, unsigned char* tb, int* count) { if (bytes != *(unsigned short*)(tb + *count)) { - printf("[internal] Failed to consume the correct bytes\n"); + printf("[internal] Failed to consume the correct bytes (expected %u, found %u)\n", bytes, *(unsigned short*)(tb + *count)); } *count += 2; } @@ -497,7 +497,7 @@ void runInterpreter(Interpreter* interpreter) { pushLiteralArray(&interpreter->literalCache, identifier); if (command.verbose) { - printf("(identifier %s)\n", AS_IDENTIFIER(identifier)); + printf("(identifier %s (%d))\n", AS_IDENTIFIER(identifier), identifier.as.identifier.hash); } } break; @@ -505,22 +505,36 @@ void runInterpreter(Interpreter* interpreter) { case LITERAL_TYPE: { Literal typeLiteral; - // read the mask - unsigned char mask = 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; + // read the mask + unsigned char mask = readShort(interpreter->bytecode, &interpreter->count); + + //create the literal typeLiteral = TO_TYPE_LITERAL(mask); - AS_TYPE(typeLiteral).count = readShort(interpreter->bytecode, &interpreter->count); - //if it's got subtypes, grab them from the existing cache - if (AS_TYPE(typeLiteral).count > 0) { - AS_TYPE(typeLiteral).subtypes = ALLOCATE(Literal, AS_TYPE(typeLiteral).count); + if (count > 0) { + AS_TYPE(typeLiteral).subtypes = ALLOCATE(Literal, count); + AS_TYPE(typeLiteral).capacity = count; + AS_TYPE(typeLiteral).count = 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]; } } + + //save the type + pushLiteralArray(&interpreter->literalCache, typeLiteral); + + if (command.verbose) { + printf("(type "); + printLiteral(typeLiteral); + printf(")\n"); + } } break; } diff --git a/source/literal.c b/source/literal.c index e840ddd..411c69a 100644 --- a/source/literal.c +++ b/source/literal.c @@ -149,7 +149,7 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) { int delimCount = 0; printToBuffer("["); for (int i = 0; i < ptr->capacity; i++) { - if (ptr->entries[i].key.type == LITERAL_NULL) { + if (IS_NULL(ptr->entries[i].key)) { continue; } @@ -211,7 +211,7 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) { 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 == 0) { + if (AS_TYPE(literal).mask == MASK_ANY) { printToBuffer("any"); break; } @@ -222,7 +222,7 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) { printToBuffer(" | "); } - //special case for array & dictionary + //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; @@ -357,8 +357,8 @@ 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), .identifier.hash=hashString(str, 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)}}); } Literal* _typePushSubtype(Literal* lit, unsigned char submask) { diff --git a/source/literal.h b/source/literal.h index d8935b5..6ea241b 100644 --- a/source/literal.h +++ b/source/literal.h @@ -77,7 +77,7 @@ typedef struct { #define TO_ARRAY_LITERAL(value) ((Literal){LITERAL_ARRAY, { .array = value }}) #define TO_DICTIONARY_LITERAL(value) ((Literal){LITERAL_DICTIONARY, { .dictionary = value }}) // #define TO_FUNCTION_LITERAL -#define TO_IDENTIFIER_LITERAL(value) _toIdentifierLiteral(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 MASK(x) (1 << (x)) @@ -114,7 +114,7 @@ void freeLiteral(Literal literal); //BUGFIX: macros are not functions bool _isTruthy(Literal x); Literal _toStringLiteral(char* str); -Literal _toIdentifierLiteral(char* str); +Literal _toIdentifierLiteral(char* str, int length); Literal* _typePushSubtype(Literal* lit, unsigned char submask); //utils diff --git a/source/literal_array.c b/source/literal_array.c index c2f0319..8276ed6 100644 --- a/source/literal_array.c +++ b/source/literal_array.c @@ -20,10 +20,13 @@ int pushLiteralArray(LiteralArray* array, Literal literal) { array->literals = GROW_ARRAY(Literal, array->literals, oldCapacity, array->capacity); } - //if it's a string, make a local copy + //if it's a string or an identifier, make a local copy if (IS_STRING(literal)) { literal = TO_STRING_LITERAL(copyString(AS_STRING(literal), STRLEN(literal))); } + if (IS_IDENTIFIER(literal)) { + literal = TO_IDENTIFIER_LITERAL(copyString(AS_IDENTIFIER(literal), STRLEN_I(literal))); + } array->literals[array->count] = literal; return array->count++; @@ -58,45 +61,9 @@ int findLiteralIndex(LiteralArray* array, Literal literal) { continue; } - //matching type, compare values - switch(array->literals[i].type) { - case LITERAL_NULL: - return i; - - case LITERAL_BOOLEAN: - if (AS_BOOLEAN(array->literals[i]) == AS_BOOLEAN(literal)) { - return i; - } - continue; - - case LITERAL_INTEGER: - if (AS_INTEGER(array->literals[i]) == AS_INTEGER(literal)) { - return i; - } - continue; - - case LITERAL_FLOAT: - if (AS_FLOAT(array->literals[i]) == AS_FLOAT(literal)) { - return i; - } - continue; - - case LITERAL_STRING: - if (strncmp(AS_STRING(array->literals[i]), AS_STRING(literal), STRLEN(literal)) == 0) { - return i; - } - continue; - - // case LITERAL_ARRAY: - // // - // continue; - - // case LITERAL_DICTIONARY: - // // - // continue; - - default: - fprintf(stderr, "[Internal] Unexpected literal type in findLiteralIndex(): %d\n", literal.type); + //types match? + if (literalsAreEqual(array->literals[i], literal)) { + return i; } } diff --git a/source/literal_array.h b/source/literal_array.h index 29a7e24..625dc63 100644 --- a/source/literal_array.h +++ b/source/literal_array.h @@ -3,9 +3,9 @@ #include "literal.h" typedef struct LiteralArray { + Literal* literals; int capacity; int count; - Literal* literals; } LiteralArray; void initLiteralArray(LiteralArray* array); diff --git a/source/literal_dictionary.c b/source/literal_dictionary.c index 7c524d6..f907709 100644 --- a/source/literal_dictionary.c +++ b/source/literal_dictionary.c @@ -107,6 +107,21 @@ static bool setEntryArray(_entry** dictionaryHandle, int* capacityPtr, int count _entry* entry = getEntryArray(*dictionaryHandle, *capacityPtr, key, hash, false); + //if it's a string or an identifier, make a local copy + if (IS_STRING(key)) { + key = TO_STRING_LITERAL(copyString(AS_STRING(key), STRLEN(key))); + } + if (IS_IDENTIFIER(key)) { + key = TO_IDENTIFIER_LITERAL(copyString(AS_IDENTIFIER(key), STRLEN_I(key))); + } + + if (IS_STRING(value)) { + value = TO_STRING_LITERAL(copyString(AS_STRING(value), STRLEN(value))); + } + if (IS_IDENTIFIER(value)) { + value = TO_IDENTIFIER_LITERAL(copyString(AS_IDENTIFIER(value), STRLEN_I(value))); + } + //true = count increase if (IS_NULL(entry->key)) { setEntryValues(entry, key, value); diff --git a/source/parser.c b/source/parser.c index df79dee..9cc6b2b 100644 --- a/source/parser.c +++ b/source/parser.c @@ -760,26 +760,24 @@ static Literal readTypeToLiteral(Parser* parser) { if (match(parser, TOKEN_COMMA)) { Literal r = readTypeToLiteral(parser); - //dictionary - Literal* dict = TYPE_PUSH_SUBTYPE(&literal, MASK_DICTIONARY); + AS_TYPE(literal).subtypes = ALLOCATE(Literal, 2); + AS_TYPE(literal).capacity = 2; + AS_TYPE(literal).count = 2; - AS_TYPE(*dict).subtypes = ALLOCATE(Literal, 2); - AS_TYPE(*dict).capacity = 2; - AS_TYPE(*dict).count = 2; + ((Literal*)(AS_TYPE(literal).subtypes))[0] = l; + ((Literal*)(AS_TYPE(literal).subtypes))[1] = r; - ((Literal*)(AS_TYPE(*dict).subtypes))[0] = l; - ((Literal*)(AS_TYPE(*dict).subtypes))[1] = r; + AS_TYPE(literal).mask |= MASK_DICTIONARY; } else { - //array - Literal* arr = TYPE_PUSH_SUBTYPE(&literal, MASK_ARRAY); - - AS_TYPE(*arr).subtypes = ALLOCATE(Literal, 1); - AS_TYPE(*arr).capacity = 1; - AS_TYPE(*arr).count = 1; + AS_TYPE(literal).subtypes = ALLOCATE(Literal, 1); + AS_TYPE(literal).capacity = 1; + AS_TYPE(literal).count = 1; //append the "l" literal - ((Literal*)(AS_TYPE(*arr).subtypes))[0] = l; + ((Literal*)(AS_TYPE(literal).subtypes))[0] = l; + + AS_TYPE(literal).mask |= MASK_ARRAY; } consume(parser, TOKEN_BRACKET_RIGHT, "Expected ']' at end of type definition"); @@ -806,14 +804,17 @@ static void varDecl(Parser* parser, Node** nodeHandle) { consume(parser, TOKEN_IDENTIFIER, "Expected identifier after var keyword"); Token identifierToken = parser->previous; - Literal identifier = TO_IDENTIFIER_LITERAL(identifierToken.lexeme); - identifier.as.identifier.length = identifierToken.length; //BUGFIX + char* cpy = copyString(identifierToken.lexeme, identifierToken.length); + Literal identifier = _toIdentifierLiteral(cpy, strlen(cpy)); //BUGFIX: use this instead of the macro //read the type, if present Literal typeLiteral; if (match(parser, TOKEN_COLON)) { typeLiteral = readTypeToLiteral(parser); } + else { + typeLiteral = TO_TYPE_LITERAL(MASK_ANY); + } //variable definition is an expression Node* expressionNode = NULL; diff --git a/source/repl_main.c b/source/repl_main.c index 253ce06..c7c033b 100644 --- a/source/repl_main.c +++ b/source/repl_main.c @@ -106,17 +106,40 @@ void runBinary(unsigned char* tb, size_t size) { initInterpreter(&interpreter, tb, size); runInterpreter(&interpreter); - //DEBUG - Literal lit; + // //DEBUG + // { + // printf("testing name\n"); + // Literal lit; - printf("DEBUG> "); - if (getScopeVariable(interpreter.scope, TO_IDENTIFIER_LITERAL("name"), &lit)) { - printLiteral(lit); - } - else { - printf("Failed"); - } - printf("\n"); + // printf("VALUE: "); + // if (getScopeVariable(interpreter.scope, TO_IDENTIFIER_LITERAL("name"), &lit)) { + // printLiteral(lit); + + // printf("\nTYPE: "); + // printLiteral(getLiteralDictionary(&interpreter.scope->types, TO_IDENTIFIER_LITERAL("name"))); + // } + // else { + // printf("Failed"); + // } + // printf("\n\n"); + // } + + // { + // printf("testing something\n"); + // Literal lit; + + // printf("VALUE: "); + // if (getScopeVariable(interpreter.scope, TO_IDENTIFIER_LITERAL("something"), &lit)) { + // printLiteral(lit); + + // printf("\nTYPE: "); + // printLiteral(getLiteralDictionary(&interpreter.scope->types, TO_IDENTIFIER_LITERAL("something"))); + // } + // else { + // printf("Failed"); + // } + // printf("\n\n"); + // } freeInterpreter(&interpreter); } @@ -262,32 +285,5 @@ int main(int argc, const char* argv[]) { repl(); - // //testing the types, improving on them as I go - // Literal root = TO_TYPE_LITERAL( MASK_ARRAY | MASK_DICTIONARY | MASK_INTEGER | MASK_FLOAT ); - // Literal* arr = TYPE_PUSH_SUBTYPE(&root, MASK_ARRAY ); - // Literal* dict = TYPE_PUSH_SUBTYPE(&root, MASK_DICTIONARY ); - - // TYPE_PUSH_SUBTYPE(arr, MASK_INTEGER ); - // TYPE_PUSH_SUBTYPE(arr, MASK_FLOAT ); - // TYPE_PUSH_SUBTYPE(arr, MASK_INTEGER | MASK_FLOAT ); - - // TYPE_PUSH_SUBTYPE(dict, MASK_STRING | MASK_CONST ); - // TYPE_PUSH_SUBTYPE(dict, MASK_FLOAT ); - - // TYPE_PUSH_SUBTYPE(dict, MASK_STRING | MASK_CONST ); - // TYPE_PUSH_SUBTYPE(dict, MASK_INTEGER ); - - // TYPE_PUSH_SUBTYPE(dict, MASK_STRING | MASK_CONST ); - // TYPE_PUSH_SUBTYPE(dict, MASK_INTEGER | MASK_FLOAT ); - - // printLiteral(root); - // printf("\n"); - - // Literal any = TO_TYPE_LITERAL(MASK_ANY); - - // printLiteral(any); - - //output: - return 0; } diff --git a/source/scope.c b/source/scope.c index 1520ed1..20ca8fb 100644 --- a/source/scope.c +++ b/source/scope.c @@ -16,6 +16,7 @@ static void freeAncestorChain(Scope* scope) { } freeLiteralDictionary(&scope->variables); + freeLiteralDictionary(&scope->types); FREE(Scope, scope); } @@ -25,6 +26,7 @@ Scope* pushScope(Scope* ancestor) { Scope* scope = ALLOCATE(Scope, 1); scope->ancestor = ancestor; initLiteralDictionary(&scope->variables); + initLiteralDictionary(&scope->types); //tick up all scope reference counts scope->references = 0; @@ -46,7 +48,7 @@ Scope* popScope(Scope* scope) { //returns false if error bool declareScopeVariable(Scope* scope, Literal key, Literal type) { //store the type, for later checking on assignment - //TODO + setLiteralDictionary(&scope->types, key, type); //don't redefine a variable within this scope if (existsLiteralDictionary(&scope->variables, key)) { @@ -64,6 +66,8 @@ bool setScopeVariable(Scope* scope, Literal key, Literal value) { return false; } + //TODO: type checking + //if it's not in this scope, keep searching up the chain if (!existsLiteralDictionary(&scope->variables, key)) { return setScopeVariable(scope->ancestor, key, value); diff --git a/source/scope.h b/source/scope.h index 906f105..8e7afec 100644 --- a/source/scope.h +++ b/source/scope.h @@ -4,6 +4,7 @@ typedef struct Scope { LiteralDictionary variables; //only allow identifiers as the keys + LiteralDictionary types; //the types, indexed by identifiers struct Scope* ancestor; int references; //how many scopes point here } Scope;