mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Types now exist, but they're not being embedded into bytecode yet
This commit is contained in:
@@ -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"];
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
121
source/literal.c
121
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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user