mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
The value is displaying correctly, but not the type
This commit is contained in:
@@ -1 +1 @@
|
|||||||
var a : [string const, int] = 42;
|
var name : [string const, int] = ["foo" : 42];
|
||||||
@@ -88,7 +88,7 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//push the store to the cache, with instructions about how pack it
|
//push the store to the cache, with instructions about how pack it
|
||||||
index = pushLiteralArray(&compiler->literalCache, TO_DICTIONARY_LITERAL(store));
|
index = pushLiteralArray(&compiler->literalCache, TO_DICTIONARY_LITERAL(store)); //pushed as an array, so below can recognize it
|
||||||
}
|
}
|
||||||
else if (node->compound.literalType == LITERAL_ARRAY) {
|
else if (node->compound.literalType == LITERAL_ARRAY) {
|
||||||
//ensure each literal value is in the cache, individually
|
//ensure each literal value is in the cache, individually
|
||||||
@@ -128,7 +128,7 @@ static int writeNodeCompoundToCache(Compiler* compiler, Node* node) {
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int writeLiteralTypeToCache(Compiler* compiler, Literal literal) {
|
static int writeLiteralTypeToCache(LiteralArray* parent, Literal literal) {
|
||||||
int index = -1;
|
int index = -1;
|
||||||
|
|
||||||
//for now, stored as an array
|
//for now, stored as an array
|
||||||
@@ -136,9 +136,9 @@ static int writeLiteralTypeToCache(Compiler* compiler, Literal literal) {
|
|||||||
initLiteralArray(store);
|
initLiteralArray(store);
|
||||||
|
|
||||||
//save the mask to the store
|
//save the mask to the store
|
||||||
int maskIndex = findLiteralIndex(store, TO_INTEGER_LITERAL(AS_TYPE(literal).mask));
|
int maskIndex = findLiteralIndex(parent, TO_INTEGER_LITERAL(AS_TYPE(literal).mask));
|
||||||
if (maskIndex < 0) {
|
if (maskIndex < 0) {
|
||||||
maskIndex = pushLiteralArray(store, TO_INTEGER_LITERAL(AS_TYPE(literal).mask));
|
maskIndex = pushLiteralArray(parent, TO_INTEGER_LITERAL(AS_TYPE(literal).mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
pushLiteralArray(store, TO_INTEGER_LITERAL(maskIndex));
|
pushLiteralArray(store, TO_INTEGER_LITERAL(maskIndex));
|
||||||
@@ -146,13 +146,13 @@ static int writeLiteralTypeToCache(Compiler* compiler, Literal literal) {
|
|||||||
//if it's a compound type, recurse
|
//if it's a compound type, recurse
|
||||||
if (AS_TYPE(literal).mask & (MASK_ARRAY|MASK_DICTIONARY)) {
|
if (AS_TYPE(literal).mask & (MASK_ARRAY|MASK_DICTIONARY)) {
|
||||||
for (int i = 0; i < AS_TYPE(literal).count; i++) {
|
for (int i = 0; i < AS_TYPE(literal).count; i++) {
|
||||||
int subIndex = writeLiteralTypeToCache(compiler, ((Literal*)(AS_TYPE(literal).subtypes))[i]);
|
int subIndex = writeLiteralTypeToCache(parent, ((Literal*)(AS_TYPE(literal).subtypes))[i]);
|
||||||
pushLiteralArray(store, TO_INTEGER_LITERAL(subIndex));
|
pushLiteralArray(store, TO_INTEGER_LITERAL(subIndex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//push the store to the compiler
|
//push the store to the parent
|
||||||
index = pushLiteralArray(&compiler->literalCache, TO_ARRAY_LITERAL(store));
|
index = pushLiteralArray(parent, TO_ARRAY_LITERAL(store));
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
@@ -250,8 +250,8 @@ 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: the "type" keyword
|
||||||
int index = writeLiteralTypeToCache(compiler, node->varTypes.typeLiteral);
|
int index = writeLiteralTypeToCache(&compiler->literalCache, node->varTypes.typeLiteral);
|
||||||
|
|
||||||
//embed the info into the bytecode
|
//embed the info into the bytecode
|
||||||
if (index >= 256) {
|
if (index >= 256) {
|
||||||
@@ -269,9 +269,39 @@ void writeCompiler(Compiler* compiler, Node* node) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// case NODE_VAR_DECL:
|
case NODE_VAR_DECL: {
|
||||||
// //TODO: OP_VAR_DECL + OP_VAR_ASSIGN
|
//first, embed the expression (leaves it on the stack)
|
||||||
// break;
|
writeCompiler(compiler, node->varDecl.expression);
|
||||||
|
|
||||||
|
//write each piece of the declaration to the bytecode
|
||||||
|
int identifierIndex = findLiteralIndex(&compiler->literalCache, node->varDecl.identifier);
|
||||||
|
if (identifierIndex < 0) {
|
||||||
|
identifierIndex = pushLiteralArray(&compiler->literalCache, node->varDecl.identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
int typeIndex = writeLiteralTypeToCache(&compiler->literalCache, node->varDecl.typeLiteral);
|
||||||
|
|
||||||
|
//embed the info into the bytecode
|
||||||
|
if (identifierIndex >= 256 || typeIndex >= 256) {
|
||||||
|
//push a "long" declaration
|
||||||
|
compiler->bytecode[compiler->count++] = OP_VAR_DECL_LONG; //1 byte
|
||||||
|
|
||||||
|
*((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)identifierIndex; //2 bytes
|
||||||
|
compiler->count += sizeof(unsigned short);
|
||||||
|
|
||||||
|
*((unsigned short*)(compiler->bytecode + compiler->count)) = (unsigned short)typeIndex; //2 bytes
|
||||||
|
compiler->count += sizeof(unsigned short);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//push a declaration
|
||||||
|
compiler->bytecode[compiler->count++] = OP_VAR_DECL; //1 byte
|
||||||
|
compiler->bytecode[compiler->count++] = (unsigned char)identifierIndex; //1 byte
|
||||||
|
compiler->bytecode[compiler->count++] = (unsigned char)typeIndex; //1 byte
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
//TODO: OP_VAR_ASSIGN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,6 +458,19 @@ unsigned char* collateCompiler(Compiler* compiler, int* size) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LITERAL_IDENTIFIER: {
|
||||||
|
emitByte(&collation, &capacity, &count, LITERAL_IDENTIFIER);
|
||||||
|
|
||||||
|
Literal identifier = compiler->literalCache.literals[i];
|
||||||
|
|
||||||
|
for (int c = 0; c < STRLEN_I(identifier); c++) {
|
||||||
|
emitByte(&collation, &capacity, &count, AS_IDENTIFIER(identifier)[c]);
|
||||||
|
}
|
||||||
|
|
||||||
|
emitByte(&collation, &capacity, &count, '\0'); //terminate the string
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case LITERAL_TYPE: {
|
case LITERAL_TYPE: {
|
||||||
emitByte(&collation, &capacity, &count, LITERAL_TYPE);
|
emitByte(&collation, &capacity, &count, LITERAL_TYPE);
|
||||||
|
|
||||||
|
|||||||
@@ -250,6 +250,34 @@ static bool execArithmetic(Interpreter* interpreter, Opcode opcode) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool execVarDecl(Interpreter* interpreter, bool lng) {
|
||||||
|
//read the index in the cache
|
||||||
|
int identifierIndex = 0;
|
||||||
|
int typeIndex = 0;
|
||||||
|
|
||||||
|
if (lng) {
|
||||||
|
identifierIndex = (int)readShort(interpreter->bytecode, &interpreter->count);
|
||||||
|
typeIndex = (int)readShort(interpreter->bytecode, &interpreter->count);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
identifierIndex = (int)readByte(interpreter->bytecode, &interpreter->count);
|
||||||
|
typeIndex = (int)readByte(interpreter->bytecode, &interpreter->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Literal identifier = interpreter->literalCache.literals[identifierIndex];
|
||||||
|
Literal type = interpreter->literalCache.literals[typeIndex];
|
||||||
|
|
||||||
|
if (!declareScopeVariable(interpreter->scope, identifier, type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!setScopeVariable(interpreter->scope, identifier, popLiteralArray(&interpreter->stack) )) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//the heart of toy
|
//the heart of toy
|
||||||
static void execInterpreter(Interpreter* interpreter) {
|
static void execInterpreter(Interpreter* interpreter) {
|
||||||
unsigned char opcode = readByte(interpreter->bytecode, &interpreter->count);
|
unsigned char opcode = readByte(interpreter->bytecode, &interpreter->count);
|
||||||
@@ -307,6 +335,15 @@ static void execInterpreter(Interpreter* interpreter) {
|
|||||||
interpreter->scope = popScope(interpreter->scope);
|
interpreter->scope = popScope(interpreter->scope);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
//TODO: type declarations
|
||||||
|
|
||||||
|
case OP_VAR_DECL:
|
||||||
|
case OP_VAR_DECL_LONG:
|
||||||
|
if (!execVarDecl(interpreter, opcode == OP_LITERAL_LONG)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printf("Unknown opcode found %d, terminating\n", opcode);
|
printf("Unknown opcode found %d, terminating\n", opcode);
|
||||||
printLiteralArray(&interpreter->stack, "\n");
|
printLiteralArray(&interpreter->stack, "\n");
|
||||||
@@ -449,6 +486,43 @@ void runInterpreter(Interpreter* interpreter) {
|
|||||||
pushLiteralArray(&interpreter->literalCache, TO_DICTIONARY_LITERAL(dictionary));
|
pushLiteralArray(&interpreter->literalCache, TO_DICTIONARY_LITERAL(dictionary));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
//TODO: functions
|
||||||
|
|
||||||
|
case LITERAL_IDENTIFIER: {
|
||||||
|
char* str = readString(interpreter->bytecode, &interpreter->count);
|
||||||
|
|
||||||
|
Literal identifier = TO_IDENTIFIER_LITERAL(str);
|
||||||
|
|
||||||
|
pushLiteralArray(&interpreter->literalCache, identifier);
|
||||||
|
|
||||||
|
if (command.verbose) {
|
||||||
|
printf("(identifier %s)\n", AS_IDENTIFIER(identifier));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LITERAL_TYPE: {
|
||||||
|
Literal typeLiteral;
|
||||||
|
|
||||||
|
// read the mask
|
||||||
|
unsigned char mask = readByte(interpreter->bytecode, &interpreter->count);
|
||||||
|
|
||||||
|
typeLiteral = TO_TYPE_LITERAL(mask);
|
||||||
|
|
||||||
|
AS_TYPE(typeLiteral).count = readShort(interpreter->bytecode, &interpreter->count);
|
||||||
|
|
||||||
|
//if it's got subtypes, grab them from the existing cache
|
||||||
|
if (AS_TYPE(typeLiteral).count > 0) {
|
||||||
|
AS_TYPE(typeLiteral).subtypes = ALLOCATE(Literal, AS_TYPE(typeLiteral).count);
|
||||||
|
for (int i = 0; i < AS_TYPE(typeLiteral).count; i++) {
|
||||||
|
//read each index
|
||||||
|
int index = readShort(interpreter->bytecode, &interpreter->count);
|
||||||
|
((Literal*)(AS_TYPE(typeLiteral).subtypes))[i] = interpreter->literalCache.literals[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ typedef enum Opcode {
|
|||||||
OP_TYPE_DECL, //declare a type to be used (as a literal)
|
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_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_DECL,
|
||||||
|
OP_VAR_DECL_LONG,
|
||||||
// OP_VAR_ASSIGN, //stack: literal name, literal value
|
// OP_VAR_ASSIGN, //stack: literal name, literal value
|
||||||
|
|
||||||
//meta
|
//meta
|
||||||
|
|||||||
@@ -801,25 +801,18 @@ static Literal readTypeToLiteral(Parser* parser) {
|
|||||||
return literal;
|
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, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void varDecl(Parser* parser, Node** nodeHandle) {
|
static void varDecl(Parser* parser, Node** nodeHandle) {
|
||||||
//read the identifier
|
//read the identifier
|
||||||
consume(parser, TOKEN_IDENTIFIER, "Expected identifier after var keyword");
|
consume(parser, TOKEN_IDENTIFIER, "Expected identifier after var keyword");
|
||||||
Token identifierToken = parser->previous;
|
Token identifierToken = parser->previous;
|
||||||
|
|
||||||
|
Literal identifier = TO_IDENTIFIER_LITERAL(identifierToken.lexeme);
|
||||||
|
identifier.as.identifier.length = identifierToken.length; //BUGFIX
|
||||||
|
|
||||||
//read the type, if present
|
//read the type, if present
|
||||||
Node* typeNode = NULL;
|
Literal typeLiteral;
|
||||||
if (match(parser, TOKEN_COLON)) {
|
if (match(parser, TOKEN_COLON)) {
|
||||||
readVarType(parser, &typeNode);
|
typeLiteral = readTypeToLiteral(parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
//variable definition is an expression
|
//variable definition is an expression
|
||||||
@@ -830,8 +823,8 @@ static void varDecl(Parser* parser, Node** nodeHandle) {
|
|||||||
|
|
||||||
//TODO: static type checking?
|
//TODO: static type checking?
|
||||||
|
|
||||||
//finally
|
//declare it
|
||||||
// emitNodeVarDecl(nodeHandle, TO_IDENTIFIER_LITERAL(identifierToken.lexeme), typeNode, expressionNode);
|
emitNodeVarDecl(nodeHandle, identifier, typeLiteral, expressionNode);
|
||||||
|
|
||||||
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of var declaration");
|
consume(parser, TOKEN_SEMICOLON, "Expected ';' at end of var declaration");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,6 +105,19 @@ void runBinary(unsigned char* tb, size_t size) {
|
|||||||
Interpreter interpreter;
|
Interpreter interpreter;
|
||||||
initInterpreter(&interpreter, tb, size);
|
initInterpreter(&interpreter, tb, size);
|
||||||
runInterpreter(&interpreter);
|
runInterpreter(&interpreter);
|
||||||
|
|
||||||
|
//DEBUG
|
||||||
|
Literal lit;
|
||||||
|
|
||||||
|
printf("DEBUG> ");
|
||||||
|
if (getScopeVariable(interpreter.scope, TO_IDENTIFIER_LITERAL("name"), &lit)) {
|
||||||
|
printLiteral(lit);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Failed");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
freeInterpreter(&interpreter);
|
freeInterpreter(&interpreter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,10 @@ Scope* popScope(Scope* scope) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//returns false if error
|
//returns false if error
|
||||||
bool declareScopeVariable(Scope* scope, Literal key) {
|
bool declareScopeVariable(Scope* scope, Literal key, Literal type) {
|
||||||
|
//store the type, for later checking on assignment
|
||||||
|
//TODO
|
||||||
|
|
||||||
//don't redefine a variable within this scope
|
//don't redefine a variable within this scope
|
||||||
if (existsLiteralDictionary(&scope->variables, key)) {
|
if (existsLiteralDictionary(&scope->variables, key)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ Scope* pushScope(Scope* scope);
|
|||||||
Scope* popScope(Scope* scope);
|
Scope* popScope(Scope* scope);
|
||||||
|
|
||||||
//returns false if error
|
//returns false if error
|
||||||
bool declareScopeVariable(Scope* scope, Literal key);
|
bool declareScopeVariable(Scope* scope, Literal key, Literal type);
|
||||||
|
|
||||||
//return false if undefined
|
//return false if undefined
|
||||||
bool setScopeVariable(Scope* scope, Literal key, Literal value);
|
bool setScopeVariable(Scope* scope, Literal key, Literal value);
|
||||||
|
|||||||
Reference in New Issue
Block a user