From 2f18989f25706247590c2caf4c1224c26a6ec03b Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Fri, 12 Aug 2022 09:11:43 +0100 Subject: [PATCH] Types now exist, but they're not being embedded into bytecode yet --- scripts/example.toy | 15 +++++- source/compiler.c | 14 ++--- source/literal.c | 121 +++++++++++++++++++++++++++++++++++++++++++- source/literal.h | 22 +++++--- source/node.h | 2 +- source/opcodes.h | 2 +- source/parser.c | 2 +- source/repl_main.c | 33 +++++++++++- 8 files changed, 193 insertions(+), 18 deletions(-) diff --git a/scripts/example.toy b/scripts/example.toy index 29c8ea9..7240219 100644 --- a/scripts/example.toy +++ b/scripts/example.toy @@ -15,6 +15,19 @@ print -69; print -4.20; print 2 + (3 * 3); +//test operators (integers) +print 1 + 1; +print 1 - 1; +print 2 * 2; +print 1 / 2; +print 4 % 2; + +//test operators (floats) +print 1.0 + 1.0; +print 1.0 - 1.0; +print 2.0 * 2.0; +print 1.0 / 2.0; + //test scopes { print "This statement is within a scope."; @@ -24,7 +37,7 @@ print 2 + (3 * 3); } print "Back to the outer scope."; -//test compounds +//test compounds, repeatedly print [1, 2, 3]; print [4, 5]; print ["key":"value"]; diff --git a/source/compiler.c b/source/compiler.c index 9b7f793..92e172d 100644 --- a/source/compiler.c +++ b/source/compiler.c @@ -221,13 +221,15 @@ void writeCompiler(Compiler* compiler, Node* node) { fprintf(stderr, "[Internal] NODE_PAIR encountered in writeCompiler()"); break; - case NODE_VAR_TYPES: - //TODO: OP_TYPE_DECL - break; + // case NODE_VAR_TYPES: + // //TODO: OP_TYPE_DECL - case NODE_VAR_DECL: - //TODO: OP_VAR_DECL + OP_VAR_ASSIGN - break; + // //find the type declaration in the cache, or create it if it doesn't exist + // break; + + // case NODE_VAR_DECL: + // //TODO: OP_VAR_DECL + OP_VAR_ASSIGN + // break; //TODO: more } diff --git a/source/literal.c b/source/literal.c index ce57785..57e0508 100644 --- a/source/literal.c +++ b/source/literal.c @@ -191,6 +191,86 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) { } break; + case LITERAL_TYPE: { + //hold potential parent-call buffers + char* cacheBuffer = globalPrintBuffer; + globalPrintBuffer = NULL; + int cacheCapacity = globalPrintCapacity; + globalPrintCapacity = 0; + int cacheCount = globalPrintCount; + globalPrintCount = 0; + + //print the type + int iterations = 0; + printToBuffer("<"); + for (int i = 1; i < 8; i ++) { //0th bit is const + if (AS_TYPE(literal).mask & MASK(i)) { + //pretty print + if (iterations++ > 0) { + printToBuffer(","); + } + + 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: + printToBuffer("["); + printLiteralCustom(((Literal*)(AS_TYPE(literal).subtypes))[0], printToBuffer); + printToBuffer("]"); + break; + + case TYPE_DICTIONARY: + printToBuffer("["); + printLiteralCustom(((Literal*)(AS_TYPE(literal).subtypes))[0], printToBuffer); + printToBuffer(":"); + printLiteralCustom(((Literal*)(AS_TYPE(literal).subtypes))[1], printToBuffer); + printToBuffer("]"); + break; + + //TODO: function + } + } + } + + //const (printed last) + if (AS_TYPE(literal).mask & MASK_CONST) { + if (iterations++ > 0) { + printToBuffer(","); + } + printToBuffer("const"); + } + printToBuffer(">"); + + //swap the parent-call buffer back into place + char* printBuffer = globalPrintBuffer; + int printCapacity = globalPrintCapacity; + int printCount = globalPrintCount; + + globalPrintBuffer = cacheBuffer; + globalPrintCapacity = cacheCapacity; + globalPrintCount = cacheCount; + + //finally, output and cleanup + printFn(printBuffer); + FREE_ARRAY(char, printBuffer, printCapacity); + quotes = 0; + } + break; + default: //should never bee seen fprintf(stderr, "[Internal] Unrecognized literal type in print: %d\n", literal.type); @@ -199,7 +279,20 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) { void freeLiteral(Literal literal) { if (IS_STRING(literal)) { - FREE(char, AS_STRING(literal)); + FREE_ARRAY(char, AS_STRING(literal), STRLEN(literal)); + return; + } + + if (IS_IDENTIFIER(literal)) { + FREE_ARRAY(char, AS_IDENTIFIER(literal), STRLEN_I(literal)); + return; + } + + if (IS_TYPE(literal)) { + for (int i = 0; i < AS_TYPE(literal).count; i++) { + freeLiteral(((Literal*)(AS_TYPE(literal).subtypes))[i]); + } + FREE_ARRAY(Literal, AS_TYPE(literal).subtypes, AS_TYPE(literal).capacity); return; } } @@ -216,6 +309,18 @@ Literal _toIdentifierLiteral(char* str) { return ((Literal){LITERAL_IDENTIFIER,{.identifier.ptr = (char*)str,.identifier.length = strlen((char*)str), .identifier.hash=hashString(str, strlen((char*)str))}}); } +void _typePushSubtype(Literal* lit, unsigned char submask) { + if (AS_TYPE(*lit).count + 1 > AS_TYPE(*lit).capacity) { + int oldCapacity = AS_TYPE(*lit).capacity; + + AS_TYPE(*lit).capacity = GROW_CAPACITY(oldCapacity); + AS_TYPE(*lit).subtypes = GROW_ARRAY(Literal, AS_TYPE(*lit).subtypes, oldCapacity, AS_TYPE(*lit).capacity); + } + + //actually push + ((Literal*)(AS_TYPE(*lit).subtypes))[ AS_TYPE(*lit).count++ ] = TO_TYPE_LITERAL( submask ); +} + char* copyString(char* original, int length) { char* buffer = ALLOCATE(char, length + 1); strncpy(buffer, original, length); @@ -282,12 +387,26 @@ bool literalsAreEqual(Literal lhs, Literal rhs) { } return true; + //TODO: functions + case LITERAL_IDENTIFIER: 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) { + return false; + } + if (AS_TYPE(lhs).mask & MASK_ARRAY && !literalsAreEqual( ((Literal*)(AS_TYPE(lhs).subtypes))[0], ((Literal*)(AS_TYPE(rhs).subtypes))[0] )) { + return false; + } + if (AS_TYPE(lhs).mask & MASK_DICTIONARY && !literalsAreEqual( ((Literal*)(AS_TYPE(lhs).subtypes))[1], ((Literal*)(AS_TYPE(rhs).subtypes))[1] )) { + return false; + } + return true; + default: //should never bee seen fprintf(stderr, "[Internal] Unrecognized literal type in equality: %d\n", lhs.type); diff --git a/source/literal.h b/source/literal.h index 2aba053..0377033 100644 --- a/source/literal.h +++ b/source/literal.h @@ -14,7 +14,7 @@ typedef enum { LITERAL_DICTIONARY, // LITERAL_FUNCTION, LITERAL_IDENTIFIER, - // LITERAL_TYPE, + LITERAL_TYPE, } LiteralType; typedef struct { @@ -39,7 +39,12 @@ typedef struct { int hash; } identifier; - //TODO: type + struct { + unsigned char mask; + void* subtypes; //for nested types caused by compounds + int capacity; + int count; + } type; } as; } Literal; @@ -52,6 +57,7 @@ typedef struct { #define IS_DICTIONARY(value) ((value).type == LITERAL_DICTIONARY) #define IS_FUNCTION(value) ((value).type == LITERAL_FUNCTION) #define IS_IDENTIFIER(value) ((value).type == LITERAL_IDENTIFIER) +#define IS_TYPE(value) ((value).type == LITERAL_TYPE) #define AS_BOOLEAN(value) ((value).as.boolean) #define AS_INTEGER(value) ((value).as.integer) @@ -61,6 +67,7 @@ typedef struct { #define AS_DICTIONARY(value) ((LiteralDictionary*)((value).as.dictionary)) // #define AS_FUNCTION(value) #define AS_IDENTIFIER(value) ((value).as.identifier.ptr) +#define AS_TYPE(value) ((value).as.type) #define TO_NULL_LITERAL ((Literal){LITERAL_NULL, { .integer = 0 }}) #define TO_BOOLEAN_LITERAL(value) ((Literal){LITERAL_BOOLEAN, { .boolean = value }}) @@ -71,8 +78,9 @@ typedef struct { #define TO_DICTIONARY_LITERAL(value) ((Literal){LITERAL_DICTIONARY, { .dictionary = value }}) // #define TO_FUNCTION_LITERAL #define TO_IDENTIFIER_LITERAL(value) _toIdentifierLiteral(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 MASK(x) (1 << (x)) #define TYPE_CONST 0 #define TYPE_BOOLEAN 1 #define TYPE_INTEGER 2 @@ -98,14 +106,16 @@ void freeLiteral(Literal literal); #define IS_TRUTHY(x) _isTruthy(x) -#define STRLEN(lit) ((lit).as.string.length) -#define STRLEN_I(lit) ((lit).as.identifier.length) -#define HASH_I(lit) ((lit).as.identifier.hash) +#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) //BUGFIX: macros are not functions bool _isTruthy(Literal x); Literal _toStringLiteral(char* str); Literal _toIdentifierLiteral(char* str); +void _typePushSubtype(Literal* lit, unsigned char submask); //utils char* copyString(char* original, int length); diff --git a/source/node.h b/source/node.h index 06bc80d..5b51549 100644 --- a/source/node.h +++ b/source/node.h @@ -66,7 +66,7 @@ typedef struct NodePair { typedef struct NodeVarTypes { NodeType type; - unsigned char mask; + unsigned char mask; //the type mask Node* nodes; int capacity; int count; diff --git a/source/opcodes.h b/source/opcodes.h index 82d375a..f13a91b 100644 --- a/source/opcodes.h +++ b/source/opcodes.h @@ -25,7 +25,7 @@ typedef enum Opcode { OP_SCOPE_BEGIN, OP_SCOPE_END, - OP_TYPE_DECL, //declare a compound type to be used + 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 diff --git a/source/parser.c b/source/parser.c index 2a859fd..3075995 100644 --- a/source/parser.c +++ b/source/parser.c @@ -827,7 +827,7 @@ static void varDecl(Parser* parser, Node** nodeHandle) { expression(parser, &expressionNode); } - //TODO: compile-time static type check + //TODO: compile-time static type check? //finally emitNodeVarDecl(nodeHandle, TO_IDENTIFIER_LITERAL(identifierToken.lexeme), typeNode, expressionNode); diff --git a/source/repl_main.c b/source/repl_main.c index 7c8568c..880f18e 100644 --- a/source/repl_main.c +++ b/source/repl_main.c @@ -247,7 +247,38 @@ int main(int argc, const char* argv[]) { return 0; } - repl(); + // repl(); + + // Literal t = TO_TYPE_LITERAL(MASK_INTEGER | MASK_FLOAT | MASK_CONST); + // printLiteral(t); + // printf("\n"); + + // Literal c = TO_TYPE_LITERAL( MASK_ARRAY ); + // c.as.type.subtypes = ALLOCATE(Literal, 8); + // ((Literal*)(c.as.type.subtypes))[0] = TO_TYPE_LITERAL( MASK_INTEGER ); + // c.as.type.capacity = 8; + // c.as.type.count = 1; + // printLiteral(c); + // printf("\n"); + + // freeLiteral(c); + + // Literal d = TO_TYPE_LITERAL( MASK_DICTIONARY ); + // d.as.type.subtypes = ALLOCATE(Literal, 8); + // ((Literal*)(d.as.type.subtypes))[0] = TO_TYPE_LITERAL( MASK_STRING ); + // ((Literal*)(d.as.type.subtypes))[1] = TO_TYPE_LITERAL( MASK_INTEGER ); + // d.as.type.capacity = 8; + // d.as.type.count = 2; + // printLiteral(d); + // printf("\n"); + + // freeLiteral(d); + + Literal e = TO_TYPE_LITERAL( MASK_DICTIONARY | MASK_CONST ); + TYPE_PUSH_SUBTYPE(e, MASK_STRING | MASK_CONST ); + TYPE_PUSH_SUBTYPE(e, MASK_INTEGER); + + printLiteral(e); return 0; } \ No newline at end of file