Fixed nagging issues, read more
* A segfault from the inspector * multiple returns no longer a goal * Cleaned up the 'URGENT' comment tags * Narrowed down what is needed for alpha
This commit is contained in:
@@ -385,5 +385,3 @@ int inspect_read(unsigned char* bytecode, unsigned int pc, unsigned int jumps_ad
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Check if strings are reused in the bytecode
|
|
||||||
+20
-5
@@ -321,8 +321,6 @@ int repl(const char* filepath, bool verbose) {
|
|||||||
char inputBuffer[INPUT_BUFFER_SIZE];
|
char inputBuffer[INPUT_BUFFER_SIZE];
|
||||||
memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
|
memset(inputBuffer, 0, INPUT_BUFFER_SIZE);
|
||||||
|
|
||||||
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL); //TODO: gc this
|
|
||||||
|
|
||||||
Toy_VM vm;
|
Toy_VM vm;
|
||||||
Toy_initVM(&vm);
|
Toy_initVM(&vm);
|
||||||
|
|
||||||
@@ -347,14 +345,16 @@ int repl(const char* filepath, bool verbose) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//parse the input, prep the VM for execution
|
//parse the input, prep the VM for execution
|
||||||
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||||
Toy_Lexer lexer;
|
Toy_Lexer lexer;
|
||||||
Toy_bindLexer(&lexer, inputBuffer);
|
Toy_bindLexer(&lexer, inputBuffer);
|
||||||
Toy_Parser parser;
|
Toy_Parser parser;
|
||||||
Toy_bindParser(&parser, &lexer);
|
Toy_bindParser(&parser, &lexer);
|
||||||
Toy_Ast* ast = Toy_scanParser(&bucket, &parser); //Ast is in the bucket, so it doesn't need to be freed
|
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
|
||||||
|
|
||||||
//parsing error, retry
|
//parsing error, retry
|
||||||
if (parser.error) {
|
if (parser.error || ast == NULL) {
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
printf("%s> ", prompt); //shows the terminal prompt
|
printf("%s> ", prompt); //shows the terminal prompt
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -364,6 +364,12 @@ int repl(const char* filepath, bool verbose) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* bytecode = Toy_compileToBytecode(ast);
|
unsigned char* bytecode = Toy_compileToBytecode(ast);
|
||||||
|
Toy_freeBucket(&bucket); //no need to for the GC here
|
||||||
|
|
||||||
|
if (bytecode == NULL) {
|
||||||
|
printf("%s> ", prompt);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
inspect_bytecode(bytecode);
|
inspect_bytecode(bytecode);
|
||||||
@@ -408,7 +414,6 @@ int repl(const char* filepath, bool verbose) {
|
|||||||
|
|
||||||
//cleanup all memory
|
//cleanup all memory
|
||||||
Toy_freeVM(&vm);
|
Toy_freeVM(&vm);
|
||||||
Toy_freeBucket(&bucket);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -479,6 +484,12 @@ int main(int argc, const char* argv[]) {
|
|||||||
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
Toy_Bucket* bucket = Toy_allocateBucket(TOY_BUCKET_IDEAL);
|
||||||
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
|
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
|
||||||
|
|
||||||
|
if (ast == NULL) {
|
||||||
|
Toy_freeBucket(&bucket);
|
||||||
|
free(source);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd.verbose) {
|
if (cmd.verbose) {
|
||||||
inspect_ast(ast);
|
inspect_ast(ast);
|
||||||
}
|
}
|
||||||
@@ -487,6 +498,10 @@ int main(int argc, const char* argv[]) {
|
|||||||
Toy_freeBucket(&bucket);
|
Toy_freeBucket(&bucket);
|
||||||
free(source);
|
free(source);
|
||||||
|
|
||||||
|
if (bytecode == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd.verbose) {
|
if (cmd.verbose) {
|
||||||
inspect_bytecode(bytecode);
|
inspect_bytecode(bytecode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
fn swap(a, b) {
|
fn swap(a, b) {
|
||||||
return b, a;
|
return b, a;
|
||||||
}
|
}
|
||||||
@@ -9,11 +8,4 @@ var b = 69;
|
|||||||
var c;
|
var c;
|
||||||
var d;
|
var d;
|
||||||
|
|
||||||
//BUG: still causes a segfault
|
|
||||||
c, d = swap(a, b);
|
c, d = swap(a, b);
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
{ var str = "Hello"; var i = 0; while (i < 100) { str = str .. " World"; i++; } }
|
|
||||||
|
|
||||||
|
|||||||
+19
-15
@@ -9,13 +9,17 @@
|
|||||||
//if set, used for delegating to user-defined code
|
//if set, used for delegating to user-defined code
|
||||||
static Toy_OpaqueAttributeHandler opaqueAttributeCallback = NULL;
|
static Toy_OpaqueAttributeHandler opaqueAttributeCallback = NULL;
|
||||||
|
|
||||||
//NOTE: there is no need to call 'Toy_freeValue' on the arguments, as the VM assumes you don't
|
//utils
|
||||||
|
#define MATCH_VALUE_AND_CSTRING(value, cstring) \
|
||||||
|
((TOY_VALUE_AS_STRING(value)->info.length == strlen(cstring)) && \
|
||||||
|
(strncmp(cstring, TOY_VALUE_AS_STRING(value)->leaf.data, TOY_VALUE_AS_STRING(value)->info.length) == 0))
|
||||||
|
|
||||||
|
//NOTE: there is no need to call 'Toy_freeValue' on the arguments, as the VM assumes you don't
|
||||||
Toy_Value Toy_private_handleStringAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
|
Toy_Value Toy_private_handleStringAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
|
||||||
if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "length", 6) == 0) {
|
if (MATCH_VALUE_AND_CSTRING(attribute, "length")) {
|
||||||
return TOY_VALUE_FROM_INTEGER(TOY_VALUE_AS_STRING(compound)->info.length);
|
return TOY_VALUE_FROM_INTEGER(TOY_VALUE_AS_STRING(compound)->info.length);
|
||||||
}
|
}
|
||||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "asUpper", 7) == 0) {
|
else if (MATCH_VALUE_AND_CSTRING(attribute, "asUpper")) {
|
||||||
char* buffer = Toy_getStringRaw(TOY_VALUE_AS_STRING(compound));
|
char* buffer = Toy_getStringRaw(TOY_VALUE_AS_STRING(compound));
|
||||||
for (int i = 0; buffer[i] != '\0'; i++) {
|
for (int i = 0; buffer[i] != '\0'; i++) {
|
||||||
buffer[i] = toupper(buffer[i]);
|
buffer[i] = toupper(buffer[i]);
|
||||||
@@ -24,7 +28,7 @@ Toy_Value Toy_private_handleStringAttributes(Toy_VM* vm, Toy_Value compound, Toy
|
|||||||
free(buffer);
|
free(buffer);
|
||||||
return TOY_VALUE_FROM_STRING(str);
|
return TOY_VALUE_FROM_STRING(str);
|
||||||
}
|
}
|
||||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "asLower", 7) == 0) {
|
else if (MATCH_VALUE_AND_CSTRING(attribute, "asLower")) {
|
||||||
char* buffer = Toy_getStringRaw(TOY_VALUE_AS_STRING(compound));
|
char* buffer = Toy_getStringRaw(TOY_VALUE_AS_STRING(compound));
|
||||||
for (int i = 0; buffer[i] != '\0'; i++) {
|
for (int i = 0; buffer[i] != '\0'; i++) {
|
||||||
buffer[i] = tolower(buffer[i]);
|
buffer[i] = tolower(buffer[i]);
|
||||||
@@ -116,7 +120,7 @@ static void attr_arrayForEach(Toy_VM* vm) {
|
|||||||
Toy_declareScope(subVM.scope, Toy_copyString(name), paramType, Toy_copyValue(&subVM.memoryBucket, array->data[iterator]), true);
|
Toy_declareScope(subVM.scope, Toy_copyString(name), paramType, Toy_copyValue(&subVM.memoryBucket, array->data[iterator]), true);
|
||||||
Toy_freeString(name);
|
Toy_freeString(name);
|
||||||
|
|
||||||
Toy_runVM(&subVM); //TODO: could use a 'map'-style method by storing the results
|
Toy_runVM(&subVM);
|
||||||
|
|
||||||
Toy_resetVM(&subVM, false, true);
|
Toy_resetVM(&subVM, false, true);
|
||||||
}
|
}
|
||||||
@@ -148,22 +152,22 @@ static void attr_arraySort(Toy_VM* vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Toy_Value Toy_private_handleArrayAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
|
Toy_Value Toy_private_handleArrayAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
|
||||||
if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "length", 6) == 0) {
|
if (MATCH_VALUE_AND_CSTRING(attribute, "length")) {
|
||||||
return TOY_VALUE_FROM_INTEGER(TOY_VALUE_AS_ARRAY(compound)->count);
|
return TOY_VALUE_FROM_INTEGER(TOY_VALUE_AS_ARRAY(compound)->count);
|
||||||
}
|
}
|
||||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "pushBack", 8) == 0) {
|
else if (MATCH_VALUE_AND_CSTRING(attribute, "pushBack")) {
|
||||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arrayPushBack);
|
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arrayPushBack);
|
||||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||||
}
|
}
|
||||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "popBack", 7) == 0) {
|
else if (MATCH_VALUE_AND_CSTRING(attribute, "popBack")) {
|
||||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arrayPopBack);
|
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arrayPopBack);
|
||||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||||
}
|
}
|
||||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "forEach", 7) == 0) {
|
else if (MATCH_VALUE_AND_CSTRING(attribute, "forEach")) {
|
||||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arrayForEach);
|
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arrayForEach);
|
||||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||||
}
|
}
|
||||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "sort", 4) == 0) {
|
else if (MATCH_VALUE_AND_CSTRING(attribute, "sort")) {
|
||||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arraySort);
|
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_arraySort);
|
||||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||||
}
|
}
|
||||||
@@ -224,22 +228,22 @@ static void attr_tableForEach(Toy_VM* vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Toy_Value Toy_private_handleTableAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
|
Toy_Value Toy_private_handleTableAttributes(Toy_VM* vm, Toy_Value compound, Toy_Value attribute) {
|
||||||
if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "length", 6) == 0) {
|
if (MATCH_VALUE_AND_CSTRING(attribute, "length")) {
|
||||||
return TOY_VALUE_FROM_INTEGER(TOY_VALUE_AS_ARRAY(compound)->count);
|
return TOY_VALUE_FROM_INTEGER(TOY_VALUE_AS_ARRAY(compound)->count);
|
||||||
}
|
}
|
||||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "insert", 6) == 0) {
|
else if (MATCH_VALUE_AND_CSTRING(attribute, "insert")) {
|
||||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_tableInsert);
|
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_tableInsert);
|
||||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||||
}
|
}
|
||||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "hasKey", 6) == 0) {
|
else if (MATCH_VALUE_AND_CSTRING(attribute, "hasKey")) {
|
||||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_tableHasKey);
|
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_tableHasKey);
|
||||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||||
}
|
}
|
||||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "remove", 6) == 0) {
|
else if (MATCH_VALUE_AND_CSTRING(attribute, "remove")) {
|
||||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_tableRemove);
|
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_tableRemove);
|
||||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||||
}
|
}
|
||||||
else if (strncmp(TOY_VALUE_AS_STRING(attribute)->leaf.data, "forEach", 7) == 0) { //URGENT: compare the contents AND length of these strings
|
else if (MATCH_VALUE_AND_CSTRING(attribute, "forEach")) {
|
||||||
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_tableForEach);
|
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, attr_tableForEach);
|
||||||
return TOY_VALUE_FROM_FUNCTION(fn);
|
return TOY_VALUE_FROM_FUNCTION(fn);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -820,9 +820,6 @@ static unsigned int writeInstructionVarDeclare(Toy_Bytecode** mb, Toy_AstVarDecl
|
|||||||
static unsigned int writeInstructionAssign(Toy_Bytecode** mb, Toy_AstVarAssign ast, bool chainedAssignment) {
|
static unsigned int writeInstructionAssign(Toy_Bytecode** mb, Toy_AstVarAssign ast, bool chainedAssignment) {
|
||||||
unsigned int result = 0;
|
unsigned int result = 0;
|
||||||
|
|
||||||
//BUG: flip the order of target & value, to allow chained assignment AND multiple return values
|
|
||||||
//do I need multiple return values?
|
|
||||||
|
|
||||||
//target is a variable name
|
//target is a variable name
|
||||||
if (ast.target->type == TOY_AST_VALUE && TOY_VALUE_IS_STRING(ast.target->value.value)) {
|
if (ast.target->type == TOY_AST_VALUE && TOY_VALUE_IS_STRING(ast.target->value.value)) {
|
||||||
//name string
|
//name string
|
||||||
|
|||||||
+1
-1
@@ -1066,7 +1066,7 @@ static void makeStmt(Toy_Bucket** bucketHandle, Toy_Parser* parser, Toy_Ast** ro
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: for-pre-clause-post-then
|
//URGENT: for-pre-clause-post-then
|
||||||
|
|
||||||
//break
|
//break
|
||||||
else if (match(parser, TOY_TOKEN_KEYWORD_BREAK)) {
|
else if (match(parser, TOY_TOKEN_KEYWORD_BREAK)) {
|
||||||
|
|||||||
@@ -494,7 +494,6 @@ Toy_String* Toy_stringifyValue(Toy_Bucket** bucketHandle, Toy_Value value) {
|
|||||||
return Toy_copyString(value.as.string);
|
return Toy_copyString(value.as.string);
|
||||||
|
|
||||||
case TOY_VALUE_ARRAY: {
|
case TOY_VALUE_ARRAY: {
|
||||||
//TODO: concat + free is definitely a performance nightmare, could make an append function?
|
|
||||||
Toy_Array* ptr = value.as.array;
|
Toy_Array* ptr = value.as.array;
|
||||||
|
|
||||||
//if array is empty, skip below
|
//if array is empty, skip below
|
||||||
|
|||||||
+8
-23
@@ -394,15 +394,8 @@ static void processInvoke(Toy_VM* vm) {
|
|||||||
|
|
||||||
//extract and store any results
|
//extract and store any results
|
||||||
if (resultCount > 0) {
|
if (resultCount > 0) {
|
||||||
Toy_Array* results = Toy_extractResultsFromVM(vm, &subVM, resultCount);
|
Toy_Value result = Toy_getReturnValueFromVM(vm, &subVM);
|
||||||
|
Toy_pushStack(&vm->stack, result);
|
||||||
for (unsigned int i = 0; i < results->count; i++) {
|
|
||||||
//NOTE: since the results array is being immediately freed, just push each element without a call to copy
|
|
||||||
Toy_pushStack(&vm->stack, results->data[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
//a bit naughty
|
|
||||||
free(results);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup
|
//cleanup
|
||||||
@@ -1104,7 +1097,7 @@ void Toy_resetVM(Toy_VM* vm, bool preserveScope, bool preserveStack) {
|
|||||||
|
|
||||||
//not sure how often to call teh GC
|
//not sure how often to call teh GC
|
||||||
if (vm->memoryBucket) {
|
if (vm->memoryBucket) {
|
||||||
Toy_collectBucketGarbage(&vm->memoryBucket); //URGENT: call GC after a certain number of bucket links allocated
|
Toy_collectBucketGarbage(&vm->memoryBucket); //WONTFIX: call GC after a certain number of bucket links allocated
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1189,19 +1182,11 @@ void Toy_freeVM(Toy_VM* vm) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_Array* Toy_extractResultsFromVM(Toy_VM* parentVM, Toy_VM* subVM, unsigned int resultCount) {
|
Toy_Value Toy_getReturnValueFromVM(Toy_VM* parentVM, Toy_VM* subVM) {
|
||||||
if (subVM->stack->count != resultCount) {
|
if (subVM->stack->count > 0) {
|
||||||
fprintf(stderr, TOY_CC_ERROR "ERROR: Too %s results requested from VM, exiting\n" TOY_CC_RESET, subVM->stack->count < resultCount ? "many":"few");
|
return Toy_copyValue(&parentVM->memoryBucket, subVM->stack->data[subVM->stack->count-1]);
|
||||||
exit(-1);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
Toy_Array* results = Toy_resizeArray(NULL, resultCount);
|
return TOY_VALUE_FROM_NULL();
|
||||||
|
|
||||||
const unsigned int offset = subVM->stack->count - resultCount; //first element to extract
|
|
||||||
|
|
||||||
for (/* EMPTY */; results->count < resultCount; results->count++) {
|
|
||||||
results->data[results->count] = Toy_copyValue(&parentVM->memoryBucket, subVM->stack->data[offset + results->count]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -51,5 +51,5 @@ void Toy_bindVM(Toy_VM* vm, unsigned char* bytecode, Toy_Scope* parentScope);
|
|||||||
TOY_API unsigned int Toy_runVM(Toy_VM* vm);
|
TOY_API unsigned int Toy_runVM(Toy_VM* vm);
|
||||||
TOY_API void Toy_freeVM(Toy_VM* vm);
|
TOY_API void Toy_freeVM(Toy_VM* vm);
|
||||||
|
|
||||||
TOY_API Toy_Array* Toy_extractResultsFromVM(Toy_VM* parentVM, Toy_VM* subVM, unsigned int resultCount);
|
TOY_API Toy_Value Toy_getReturnValueFromVM(Toy_VM* parentVM, Toy_VM* subVM);
|
||||||
|
|
||||||
|
|||||||
@@ -24,5 +24,3 @@ print a;
|
|||||||
var b = [];
|
var b = [];
|
||||||
|
|
||||||
print b;
|
print b;
|
||||||
|
|
||||||
//TODO: utility functions are needed, see toy_array.h
|
|
||||||
@@ -609,6 +609,7 @@ int main(void) {
|
|||||||
|
|
||||||
//TODO: references
|
//TODO: references
|
||||||
//TODO: type coersions
|
//TODO: type coersions
|
||||||
|
//TODO: opaques?
|
||||||
|
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user