Types now exist, but they're not being embedded into bytecode yet

This commit is contained in:
2022-08-12 09:11:43 +01:00
parent 80b64cf21e
commit 2f18989f25
8 changed files with 193 additions and 18 deletions

View File

@@ -15,6 +15,19 @@ print -69;
print -4.20; print -4.20;
print 2 + (3 * 3); 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 //test scopes
{ {
print "This statement is within a scope."; print "This statement is within a scope.";
@@ -24,7 +37,7 @@ print 2 + (3 * 3);
} }
print "Back to the outer scope."; print "Back to the outer scope.";
//test compounds //test compounds, repeatedly
print [1, 2, 3]; print [1, 2, 3];
print [4, 5]; print [4, 5];
print ["key":"value"]; print ["key":"value"];

View File

@@ -221,13 +221,15 @@ void writeCompiler(Compiler* compiler, Node* node) {
fprintf(stderr, "[Internal] NODE_PAIR encountered in writeCompiler()"); fprintf(stderr, "[Internal] NODE_PAIR encountered in writeCompiler()");
break; break;
case NODE_VAR_TYPES: // case NODE_VAR_TYPES:
//TODO: OP_TYPE_DECL // //TODO: OP_TYPE_DECL
break;
case NODE_VAR_DECL: // //find the type declaration in the cache, or create it if it doesn't exist
//TODO: OP_VAR_DECL + OP_VAR_ASSIGN // break;
break;
// case NODE_VAR_DECL:
// //TODO: OP_VAR_DECL + OP_VAR_ASSIGN
// break;
//TODO: more //TODO: more
} }

View File

@@ -191,6 +191,86 @@ void printLiteralCustom(Literal literal, void (printFn)(const char*)) {
} }
break; 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: default:
//should never bee seen //should never bee seen
fprintf(stderr, "[Internal] Unrecognized literal type in print: %d\n", literal.type); 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) { void freeLiteral(Literal literal) {
if (IS_STRING(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; 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))}}); 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* copyString(char* original, int length) {
char* buffer = ALLOCATE(char, length + 1); char* buffer = ALLOCATE(char, length + 1);
strncpy(buffer, original, length); strncpy(buffer, original, length);
@@ -282,12 +387,26 @@ bool literalsAreEqual(Literal lhs, Literal rhs) {
} }
return true; return true;
//TODO: functions
case LITERAL_IDENTIFIER: case LITERAL_IDENTIFIER:
if (HASH_I(lhs) != HASH_I(rhs) && STRLEN_I(lhs) != STRLEN_I(rhs)) { if (HASH_I(lhs) != HASH_I(rhs) && STRLEN_I(lhs) != STRLEN_I(rhs)) {
return false; return false;
} }
return !strncmp(AS_IDENTIFIER(lhs), AS_IDENTIFIER(rhs), STRLEN_I(lhs)); 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: default:
//should never bee seen //should never bee seen
fprintf(stderr, "[Internal] Unrecognized literal type in equality: %d\n", lhs.type); fprintf(stderr, "[Internal] Unrecognized literal type in equality: %d\n", lhs.type);

View File

@@ -14,7 +14,7 @@ typedef enum {
LITERAL_DICTIONARY, LITERAL_DICTIONARY,
// LITERAL_FUNCTION, // LITERAL_FUNCTION,
LITERAL_IDENTIFIER, LITERAL_IDENTIFIER,
// LITERAL_TYPE, LITERAL_TYPE,
} LiteralType; } LiteralType;
typedef struct { typedef struct {
@@ -39,7 +39,12 @@ typedef struct {
int hash; int hash;
} identifier; } identifier;
//TODO: type struct {
unsigned char mask;
void* subtypes; //for nested types caused by compounds
int capacity;
int count;
} type;
} as; } as;
} Literal; } Literal;
@@ -52,6 +57,7 @@ typedef struct {
#define IS_DICTIONARY(value) ((value).type == LITERAL_DICTIONARY) #define IS_DICTIONARY(value) ((value).type == LITERAL_DICTIONARY)
#define IS_FUNCTION(value) ((value).type == LITERAL_FUNCTION) #define IS_FUNCTION(value) ((value).type == LITERAL_FUNCTION)
#define IS_IDENTIFIER(value) ((value).type == LITERAL_IDENTIFIER) #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_BOOLEAN(value) ((value).as.boolean)
#define AS_INTEGER(value) ((value).as.integer) #define AS_INTEGER(value) ((value).as.integer)
@@ -61,6 +67,7 @@ typedef struct {
#define AS_DICTIONARY(value) ((LiteralDictionary*)((value).as.dictionary)) #define AS_DICTIONARY(value) ((LiteralDictionary*)((value).as.dictionary))
// #define AS_FUNCTION(value) // #define AS_FUNCTION(value)
#define AS_IDENTIFIER(value) ((value).as.identifier.ptr) #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_NULL_LITERAL ((Literal){LITERAL_NULL, { .integer = 0 }})
#define TO_BOOLEAN_LITERAL(value) ((Literal){LITERAL_BOOLEAN, { .boolean = value }}) #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_DICTIONARY_LITERAL(value) ((Literal){LITERAL_DICTIONARY, { .dictionary = value }})
// #define TO_FUNCTION_LITERAL // #define TO_FUNCTION_LITERAL
#define TO_IDENTIFIER_LITERAL(value) _toIdentifierLiteral(value) #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_CONST 0
#define TYPE_BOOLEAN 1 #define TYPE_BOOLEAN 1
#define TYPE_INTEGER 2 #define TYPE_INTEGER 2
@@ -101,11 +109,13 @@ void freeLiteral(Literal literal);
#define STRLEN(lit) ((lit).as.string.length) #define STRLEN(lit) ((lit).as.string.length)
#define STRLEN_I(lit) ((lit).as.identifier.length) #define STRLEN_I(lit) ((lit).as.identifier.length)
#define HASH_I(lit) ((lit).as.identifier.hash) #define HASH_I(lit) ((lit).as.identifier.hash)
#define TYPE_PUSH_SUBTYPE(lit, submask) _typePushSubtype(&(lit), submask)
//BUGFIX: macros are not functions //BUGFIX: macros are not functions
bool _isTruthy(Literal x); bool _isTruthy(Literal x);
Literal _toStringLiteral(char* str); Literal _toStringLiteral(char* str);
Literal _toIdentifierLiteral(char* str); Literal _toIdentifierLiteral(char* str);
void _typePushSubtype(Literal* lit, unsigned char submask);
//utils //utils
char* copyString(char* original, int length); char* copyString(char* original, int length);

View File

@@ -66,7 +66,7 @@ typedef struct NodePair {
typedef struct NodeVarTypes { typedef struct NodeVarTypes {
NodeType type; NodeType type;
unsigned char mask; unsigned char mask; //the type mask
Node* nodes; Node* nodes;
int capacity; int capacity;
int count; int count;

View File

@@ -25,7 +25,7 @@ typedef enum Opcode {
OP_SCOPE_BEGIN, OP_SCOPE_BEGIN,
OP_SCOPE_END, 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_DECL, //stack: literal name, literal type (referenced by array index)
OP_VAR_ASSIGN, //stack: literal name, literal value OP_VAR_ASSIGN, //stack: literal name, literal value

View File

@@ -827,7 +827,7 @@ static void varDecl(Parser* parser, Node** nodeHandle) {
expression(parser, &expressionNode); expression(parser, &expressionNode);
} }
//TODO: compile-time static type check //TODO: compile-time static type check?
//finally //finally
emitNodeVarDecl(nodeHandle, TO_IDENTIFIER_LITERAL(identifierToken.lexeme), typeNode, expressionNode); emitNodeVarDecl(nodeHandle, TO_IDENTIFIER_LITERAL(identifierToken.lexeme), typeNode, expressionNode);

View File

@@ -247,7 +247,38 @@ int main(int argc, const char* argv[]) {
return 0; 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; return 0;
} }