From 603d9d2b06baca9f4d1a4c5e4c114b5a39510774 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Thu, 11 Aug 2022 09:24:13 +0100 Subject: [PATCH] Recursive arrays and dictionaries! --- scripts/example.toy | 3 + scripts/small.toy | 4 +- source/compiler.c | 152 ++++++++++++++++++++++++++++------------- source/literal.c | 17 +++++ source/literal.h | 4 +- source/literal_array.c | 8 +++ 6 files changed, 137 insertions(+), 51 deletions(-) diff --git a/scripts/example.toy b/scripts/example.toy index bbb9b9a..e81025a 100644 --- a/scripts/example.toy +++ b/scripts/example.toy @@ -35,6 +35,9 @@ print ["key":"value"]; print []; print [:]; +//recursive +print [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; + //var arr : [int] = [1, 2, 3, 42]; //var dict : [string, int] = ["hello": 1, "world":2]; diff --git a/scripts/small.toy b/scripts/small.toy index f4d58b7..999b306 100644 --- a/scripts/small.toy +++ b/scripts/small.toy @@ -1,2 +1,2 @@ -print ["foo", "bar"]; -print ["foo":1, "bar":2]; \ No newline at end of file +print [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; +print [["foo":1]:["bar":2]]; diff --git a/source/compiler.c b/source/compiler.c index 1cec0cb..db5b07b 100644 --- a/source/compiler.c +++ b/source/compiler.c @@ -24,6 +24,110 @@ void initCompiler(Compiler* compiler) { pushLiteralArray(&compiler->literalCache, f); } +//separated out, so it can be recursive +static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { + int index = -1; + + //for both, stored as an array + LiteralArray* store = ALLOCATE(LiteralArray, 1); + initLiteralArray(store); + + //emit an array or a dictionary definition + if (node->compound.literalType == LITERAL_DICTIONARY) { + //ensure each literal key and value are in the cache, individually + for (int i = 0; i < node->compound.count; i++) { + //keys + switch(node->compound.nodes[i].pair.left->type) { + case NODE_LITERAL: { + //keys are literals + int key = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.left->atomic.literal); + if (key < 0) { + key = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].pair.left->atomic.literal); + } + + pushLiteralArray(store, TO_INTEGER_LITERAL(key)); + } + break; + + case NODE_COMPOUND: { + int key = writeNodeCompoundToCache(compiler, node->compound.nodes[i].pair.left); + + pushLiteralArray(store, TO_INTEGER_LITERAL(key)); + } + break; + + default: + fprintf(stderr, "[Internal] Unrecognized key node type in writeNodeCompoundToCache()"); + return -1; + } + + //values + switch(node->compound.nodes[i].pair.right->type) { + case NODE_LITERAL: { + //values are literals + int val = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.right->atomic.literal); + if (val < 0) { + val = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].pair.right->atomic.literal); + } + + pushLiteralArray(store, TO_INTEGER_LITERAL(val)); + } + break; + + case NODE_COMPOUND: { + int val = writeNodeCompoundToCache(compiler, node->compound.nodes[i].pair.right); + + pushLiteralArray(store, TO_INTEGER_LITERAL(val)); + } + break; + + default: + fprintf(stderr, "[Internal] Unrecognized value node type in writeNodeCompoundToCache()"); + return -1; + } + } + + //push the store to the cache, with instructions about how pack it + index = pushLiteralArray(&compiler->literalCache, TO_DICTIONARY_LITERAL(store)); + } + else if (node->compound.literalType == LITERAL_ARRAY) { + //ensure each literal value is in the cache, individually + for (int i = 0; i < node->compound.count; i++) { + switch(node->compound.nodes[i].type) { + case NODE_LITERAL: { + //values + int val = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].atomic.literal); + if (val < 0) { + val = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].atomic.literal); + } + + pushLiteralArray(store, TO_INTEGER_LITERAL(val)); + } + break; + + case NODE_COMPOUND: { + int val = writeNodeCompoundToCache(compiler, &node->compound.nodes[i]); + + index = pushLiteralArray(store, TO_INTEGER_LITERAL(val)); + } + break; + + default: + fprintf(stderr, "[Internal] Unrecognized node type in writeNodeCompoundToCache()"); + return -1; + } + } + + //push the store to the cache, with instructions about how pack it + index = pushLiteralArray(&compiler->literalCache, TO_ARRAY_LITERAL(store)); + } + else { + fprintf(stderr, "[Internal] Unrecognized compound type in writeNodeCompoundToCache()"); + } + + return index; +} + void writeCompiler(Compiler* compiler, Node* node) { //grow if the bytecode space is too small if (compiler->capacity < compiler->count + 1) { @@ -95,53 +199,7 @@ void writeCompiler(Compiler* compiler, Node* node) { break; case NODE_COMPOUND: { - int index = -1; - - //for both, stored as an array - LiteralArray* store = ALLOCATE(LiteralArray, 1); - initLiteralArray(store); - - //emit an array or a dictionary definition - if (node->compound.literalType == LITERAL_DICTIONARY) { - //ensure each literal key and value are in the cache, individually - for (int i = 0; i < node->compound.count; i++) { - //keys - int key = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.left->atomic.literal); - if (key < 0) { - key = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].pair.left->atomic.literal); - } - - //values - int val = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].pair.right->atomic.literal); - if (val < 0) { - val = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].pair.right->atomic.literal); - } - - pushLiteralArray(store, TO_INTEGER_LITERAL(key)); - pushLiteralArray(store, TO_INTEGER_LITERAL(val)); - } - - //push the store to the cache, with instructions about how pack it - index = pushLiteralArray(&compiler->literalCache, TO_DICTIONARY_LITERAL(store)); - } - else if (node->compound.literalType == LITERAL_ARRAY) { - //ensure each literal value is in the cache, individually - for (int i = 0; i < node->compound.count; i++) { - //values - int val = findLiteralIndex(&compiler->literalCache, node->compound.nodes[i].atomic.literal); - if (val < 0) { - val = pushLiteralArray(&compiler->literalCache, node->compound.nodes[i].atomic.literal); - } - - pushLiteralArray(store, TO_INTEGER_LITERAL(val)); - } - - //push the store to the cache, with instructions about how pack it - index = pushLiteralArray(&compiler->literalCache, TO_ARRAY_LITERAL(store)); - } - else { - fprintf(stderr, "[Internal] Unrecognized compound type in writeCompiler()"); - } + int index = writeNodeCompoundToCache(compiler, node); //push the node opcode to the bytecode if (index >= 256) { diff --git a/source/literal.c b/source/literal.c index 014bee7..46b3222 100644 --- a/source/literal.c +++ b/source/literal.c @@ -271,6 +271,23 @@ int hashLiteral(Literal lit) { case LITERAL_STRING: return hashString(AS_STRING(lit), STRLEN(lit)); + case LITERAL_ARRAY: { + unsigned int res = 0; + for (int i = 0; i < AS_DICTIONARY(lit)->count; i++) { + res += hashLiteral(AS_ARRAY(lit)->literals[i]); + } + return hash(res); + } + + case LITERAL_DICTIONARY: { + unsigned int res = 0; + for (int i = 0; i < AS_DICTIONARY(lit)->count; i++) { + res += hashLiteral(AS_DICTIONARY(lit)->entries[i].key); + res += hashLiteral(AS_DICTIONARY(lit)->entries[i].value); + } + return hash(res); + } + case LITERAL_IDENTIFIER: return hashString(AS_IDENTIFIER(lit), STRLEN_I(lit)); diff --git a/source/literal.h b/source/literal.h index 7ea320e..dcced93 100644 --- a/source/literal.h +++ b/source/literal.h @@ -56,8 +56,8 @@ typedef struct { #define AS_INTEGER(value) ((value).as.integer) #define AS_FLOAT(value) ((value).as.number) #define AS_STRING(value) ((value).as.string.ptr) -#define AS_ARRAY(value) ((value).as.array) -#define AS_DICTIONARY(value) ((value).as.dictionary) +#define AS_ARRAY(value) ((LiteralArray*)((value).as.array)) +#define AS_DICTIONARY(value) ((LiteralDictionary*)((value).as.dictionary)) // #define AS_FUNCTION(value) #define AS_IDENTIFIER(value) ((value).as.identifier.ptr) diff --git a/source/literal_array.c b/source/literal_array.c index 1ef1aef..c2f0319 100644 --- a/source/literal_array.c +++ b/source/literal_array.c @@ -87,6 +87,14 @@ int findLiteralIndex(LiteralArray* array, Literal literal) { } continue; + // case LITERAL_ARRAY: + // // + // continue; + + // case LITERAL_DICTIONARY: + // // + // continue; + default: fprintf(stderr, "[Internal] Unexpected literal type in findLiteralIndex(): %d\n", literal.type); }