From 53f0996fd14481b2be65ecabc2e0679b03557ea3 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 12 Aug 2022 15:06:41 +0100 Subject: [PATCH] Types are being read into the variable declaration, not yet used --- scripts/small.toy | 3 +- source/compiler.c | 72 ++++++++++++++++++++++++++++++++++++---- source/literal.c | 6 ++++ source/literal.h | 2 +- source/node.c | 28 +++++----------- source/node.h | 11 +++--- source/opcodes.h | 8 +++-- source/parser.c | 83 +++++++++++++++++++++------------------------- source/repl_main.c | 37 ++++++++++++--------- 9 files changed, 150 insertions(+), 100 deletions(-) diff --git a/scripts/small.toy b/scripts/small.toy index 999b306..ba7b476 100644 --- a/scripts/small.toy +++ b/scripts/small.toy @@ -1,2 +1 @@ -print [[1, 2, 3], [4, 5, 6], [7, 8, 9]]; -print [["foo":1]:["bar":2]]; +var a : int const = 42; \ No newline at end of file diff --git a/source/compiler.c b/source/compiler.c index 92e172d..c8a0e91 100644 --- a/source/compiler.c +++ b/source/compiler.c @@ -128,6 +128,35 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) { return index; } +static int writeLiteralTypeToCache(Compiler* compiler, Literal literal) { + int index = -1; + + //for now, stored as an array + LiteralArray* store = ALLOCATE(LiteralArray, 1); + initLiteralArray(store); + + //save the mask to the store + int maskIndex = findLiteralIndex(store, TO_INTEGER_LITERAL(AS_TYPE(literal).mask)); + if (maskIndex < 0) { + 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++) { + int subIndex = writeLiteralTypeToCache(compiler, ((Literal*)(AS_TYPE(literal).subtypes))[i]); + pushLiteralArray(store, TO_INTEGER_LITERAL(subIndex)); + } + } + + //push the store to the compiler + index = pushLiteralArray(&compiler->literalCache, TO_ARRAY_LITERAL(store)); + + return index; +} + void writeCompiler(Compiler* compiler, Node* node) { //grow if the bytecode space is too small if (compiler->capacity < compiler->count + 1) { @@ -221,17 +250,28 @@ void writeCompiler(Compiler* compiler, Node* node) { fprintf(stderr, "[Internal] NODE_PAIR encountered in writeCompiler()"); break; - // case NODE_VAR_TYPES: - // //TODO: OP_TYPE_DECL + case NODE_VAR_TYPES: { + int index = writeLiteralTypeToCache(compiler, node->varTypes.typeLiteral); - // //find the type declaration in the cache, or create it if it doesn't exist - // break; + //embed the info into the bytecode + if (index >= 256) { + //push a "long" index + compiler->bytecode[compiler->count++] = OP_TYPE_DECL_LONG; //1 byte + *((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)index; //2 bytes + + compiler->count += sizeof(unsigned short); + } + else { + //push the index + compiler->bytecode[compiler->count++] = OP_TYPE_DECL; //1 byte + compiler->bytecode[compiler->count++] = (unsigned char)index; //1 byte + } + } + break; // case NODE_VAR_DECL: // //TODO: OP_VAR_DECL + OP_VAR_ASSIGN // break; - - //TODO: more } } @@ -371,7 +411,7 @@ unsigned char* collateCompiler(Compiler* compiler, int* size) { } break; - case LITERAL_DICTIONARY: + case LITERAL_DICTIONARY: { emitByte(&collation, &capacity, &count, LITERAL_DICTIONARY); LiteralArray* ptr = AS_ARRAY(compiler->literalCache.literals[i]); //used an array for storage above @@ -385,6 +425,24 @@ unsigned char* collateCompiler(Compiler* compiler, int* size) { } freeLiteralArray(ptr); + } + break; + + case LITERAL_TYPE: { + emitByte(&collation, &capacity, &count, LITERAL_TYPE); + + 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 + + //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 + } + + freeLiteralArray(ptr); + } break; default: diff --git a/source/literal.c b/source/literal.c index f649ece..e840ddd 100644 --- a/source/literal.c +++ b/source/literal.c @@ -210,6 +210,12 @@ 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) { + printToBuffer("any"); + break; + } + if (AS_TYPE(literal).mask & MASK(i)) { //pretty print if (iterations++ > 0) { diff --git a/source/literal.h b/source/literal.h index dde3a9f..d8935b5 100644 --- a/source/literal.h +++ b/source/literal.h @@ -97,7 +97,7 @@ typedef struct { #define MASK_ARRAY (MASK(TYPE_ARRAY)) #define MASK_DICTIONARY (MASK(TYPE_DICTIONARY)) #define MASK_FUNCTION (MASK(TYPE_FUNCTION)) -#define MASK_ANY (MASK_BOOLEAN|MASK_INTEGER|MASK_FLOAT|MASK_STRING|MASK_ARRAY|MASK_DICTIONARY|MASK_FUNCTION) +#define MASK_ANY 0 //utils void printLiteral(Literal literal); diff --git a/source/node.c b/source/node.c index f240244..ddd97eb 100644 --- a/source/node.c +++ b/source/node.c @@ -53,15 +53,12 @@ void freeNode(Node* node) { break; case NODE_VAR_TYPES: - for (int i = 0; i < node->varTypes.count; i++) { - freeNode(node->varTypes.nodes + 1); - } - FREE_ARRAY(Node, node->varTypes.nodes, node->varTypes.capacity); + freeLiteral(node->varTypes.typeLiteral); break; case NODE_VAR_DECL: freeLiteral(node->varDecl.identifier); - freeNode(node->varDecl.varType); + freeLiteral(node->varDecl.typeLiteral); freeNode(node->varDecl.expression); break; } @@ -137,24 +134,21 @@ void emitNodePair(Node** nodeHandle, Node* left, Node* right) { *nodeHandle = tmp; } -void emitNodeVarTypes(Node** nodeHandle, unsigned char mask) { +void emitNodeVarTypes(Node** nodeHandle, Literal literal) { Node* tmp = ALLOCATE(Node, 1); tmp->type = NODE_VAR_TYPES; - tmp->varTypes.mask = mask; - tmp->varTypes.nodes = NULL; - tmp->varTypes.capacity = 0; - tmp->varTypes.count = 0; + tmp->varTypes.typeLiteral = literal; *nodeHandle = tmp; } -void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Node* varType, Node* expression) { +void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Literal type, Node* expression) { Node* tmp = ALLOCATE(Node, 1); tmp->type = NODE_VAR_DECL; tmp->varDecl.identifier = identifier; - tmp->varDecl.varType = varType; + tmp->varDecl.typeLiteral = type; tmp->varDecl.expression = expression; *nodeHandle = tmp; @@ -223,20 +217,14 @@ void printNode(Node* node) { break; case NODE_VAR_TYPES: - printf("type[\n"); - - for (int i = 0; i < node->varTypes.count; i++) { - printNode(&(node->varTypes.nodes[i])); - } - - printf("]\n"); + printLiteral(node->varTypes.typeLiteral); break; case NODE_VAR_DECL: printf("vardecl("); printLiteral(node->varDecl.identifier); printf("; "); - printNode(node->varDecl.varType); + printLiteral(node->varDecl.typeLiteral); printf("; "); printNode(node->varDecl.expression); printf(")"); diff --git a/source/node.h b/source/node.h index 5b51549..8f22210 100644 --- a/source/node.h +++ b/source/node.h @@ -66,16 +66,13 @@ typedef struct NodePair { typedef struct NodeVarTypes { NodeType type; - unsigned char mask; //the type mask - Node* nodes; - int capacity; - int count; + Literal typeLiteral; } NodeVarTypes; typedef struct NodeVarDecl { NodeType type; Literal identifier; - Node* varType; + Literal typeLiteral; Node* expression; } NodeVarDecl; @@ -100,8 +97,8 @@ void emitNodeGrouping(Node** nodeHandle); void emitNodeBlock(Node** nodeHandle); void emitNodeCompound(Node** nodeHandle, LiteralType literalType); void emitNodePair(Node** nodeHandle, Node* left, Node* right); -void emitNodeVarTypes(Node** nodeHandle, unsigned char mask); -void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Node* varType, Node* expression); +void emitNodeVarTypes(Node** nodeHandle, Literal literal); +void emitNodeVarDecl(Node** nodeHandle, Literal identifier, Literal type, Node* expression); void printNode(Node* node); diff --git a/source/opcodes.h b/source/opcodes.h index f13a91b..f6f7697 100644 --- a/source/opcodes.h +++ b/source/opcodes.h @@ -25,9 +25,11 @@ typedef enum Opcode { OP_SCOPE_BEGIN, OP_SCOPE_END, - OP_TYPE_DECL, //declare a type to be used - OP_VAR_DECL, //stack: literal name, literal type (referenced by array index) - OP_VAR_ASSIGN, //stack: literal name, literal value + OP_TYPE_DECL, //declare a type to be used (as a literal) + OP_TYPE_DECL_LONG, //declare a type to be used (as a long literal) + + // OP_VAR_DECL, //stack: literal name, literal type (referenced by array index) + // OP_VAR_ASSIGN, //stack: literal name, literal value //meta OP_SECTION_END, diff --git a/source/parser.c b/source/parser.c index 3075995..2fd519b 100644 --- a/source/parser.c +++ b/source/parser.c @@ -731,83 +731,76 @@ static void statement(Parser* parser, Node* node) { } //declarations and definitions -static void readVarType(Parser* parser, Node** nodeHandle) { - //TODO: custom types with the "type" keyword +static Literal readTypeToLiteral(Parser* parser) { advance(parser); - unsigned char typeMask = 0; - - Node* left = NULL; - Node* right = NULL; + Literal literal = TO_TYPE_LITERAL(MASK_ANY); switch(parser->previous.type) { case TOKEN_BOOLEAN: - typeMask |= MASK_BOOLEAN; + AS_TYPE(literal).mask |= MASK_BOOLEAN; break; case TOKEN_INTEGER: - typeMask |= MASK_INTEGER; + AS_TYPE(literal).mask |= MASK_INTEGER; break; case TOKEN_FLOAT: - typeMask |= MASK_FLOAT; + AS_TYPE(literal).mask |= MASK_FLOAT; break; case TOKEN_STRING: - typeMask |= MASK_STRING; + AS_TYPE(literal).mask |= MASK_STRING; break; //array, dictionary - read the sub-types - case TOKEN_BRACKET_LEFT: - //at least 1 type required - readVarType(parser, &left); + case TOKEN_BRACKET_LEFT: { + Literal l = readTypeToLiteral(parser); if (match(parser, TOKEN_COMMA)) { - //if there's 2 types, it's a dictionary - readVarType(parser, &right); - typeMask |= MASK_DICTIONARY; + Literal r = readTypeToLiteral(parser); + + //dictionary + Literal* dict = TYPE_PUSH_SUBTYPE(&literal, MASK_DICTIONARY); + + ((Literal*)(AS_TYPE(*dict).subtypes))[0] = l; + ((Literal*)(AS_TYPE(*dict).subtypes))[1] = r; } else { - //else it's just an array - typeMask |= MASK_ARRAY; - } - consume(parser, TOKEN_BRACKET_RIGHT, "Expected ']' at end of type definition"); - break; + //array + Literal* arr = TYPE_PUSH_SUBTYPE(&literal, MASK_ARRAY); - case TOKEN_ANY: - typeMask |= MASK_ANY; + //append the "l" literal + ((Literal*)(AS_TYPE(*arr).subtypes))[0] = l; + } + + consume(parser, TOKEN_BRACKET_RIGHT, "Expected ']' at end of type definition"); + } break; //TODO: function default: - error(parser, parser->previous, "Bad type"); - return; + error(parser, parser->previous, "Bad type signature"); + return TO_NULL_LITERAL; } //const follows the type if (match(parser, TOKEN_CONST)) { - typeMask |= MASK_CONST; + AS_TYPE(literal).mask |= MASK_CONST; } + return literal; +} + +static void readVarType(Parser* parser, Node** nodeHandle) { + //TODO: custom types with the "type" keyword + + //get the type literal + Literal type = readTypeToLiteral(parser); + //generate the node - emitNodeVarTypes(nodeHandle, typeMask); - - //check for sub-nodes - if (left) { - int oldCapacity = (*nodeHandle)->varTypes.capacity; - - (*nodeHandle)->varTypes.capacity = GROW_CAPACITY(oldCapacity); - (*nodeHandle)->varTypes.nodes = GROW_ARRAY(Node, (*nodeHandle)->varTypes.nodes, oldCapacity, (*nodeHandle)->varTypes.capacity); - - //push left to the array - *((*nodeHandle)->varTypes.nodes) = *left; - - //append the other one too - if (right) { - *((*nodeHandle)->varTypes.nodes + 1) = *right; - } - } + emitNodeVarTypes(nodeHandle, type); } static void varDecl(Parser* parser, Node** nodeHandle) { @@ -827,10 +820,10 @@ static void varDecl(Parser* parser, Node** nodeHandle) { expression(parser, &expressionNode); } - //TODO: compile-time static type check? + //TODO: static type checking? //finally - emitNodeVarDecl(nodeHandle, TO_IDENTIFIER_LITERAL(identifierToken.lexeme), typeNode, expressionNode); + // emitNodeVarDecl(nodeHandle, TO_IDENTIFIER_LITERAL(identifierToken.lexeme), typeNode, expressionNode); consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of var declaration"); } diff --git a/source/repl_main.c b/source/repl_main.c index f80cf93..1e0562a 100644 --- a/source/repl_main.c +++ b/source/repl_main.c @@ -247,27 +247,34 @@ int main(int argc, const char* argv[]) { return 0; } - // repl(); + repl(); - //testing the types, improving on them as I go - Literal root = TO_TYPE_LITERAL( MASK_ARRAY | MASK_DICTIONARY ); - Literal* arr = TYPE_PUSH_SUBTYPE(&root, MASK_ARRAY ); - Literal* dict = TYPE_PUSH_SUBTYPE(&root, MASK_DICTIONARY ); + // //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(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_BOOLEAN ); + // 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 ); - printLiteral(root); - printf("\n"); + // TYPE_PUSH_SUBTYPE(dict, MASK_STRING | MASK_CONST ); + // TYPE_PUSH_SUBTYPE(dict, MASK_INTEGER | MASK_FLOAT ); - //output: <[int] | [float] | [int | float] | [string const:bool] | [string const:int]> + // printLiteral(root); + // printf("\n"); + + // Literal any = TO_TYPE_LITERAL(MASK_ANY); + + // printLiteral(any); + + //output: return 0; }