Recursive arrays and dictionaries!

This commit is contained in:
2022-08-11 09:24:13 +01:00
parent 380b7a3699
commit 603d9d2b06
6 changed files with 137 additions and 51 deletions

View File

@@ -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) {

View File

@@ -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));

View File

@@ -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)

View File

@@ -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);
}