mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-05-06 00:40:11 +10:00
Implemented array.forEach(fn)
This commit is contained in:
+12
-1
@@ -8,6 +8,9 @@
|
|||||||
#include "toy_compiler.h"
|
#include "toy_compiler.h"
|
||||||
#include "toy_vm.h"
|
#include "toy_vm.h"
|
||||||
|
|
||||||
|
//NOTE: for testing
|
||||||
|
#include "standard_library.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -367,7 +370,14 @@ int repl(const char* filepath, bool verbose) {
|
|||||||
inspect_bytecode(bytecode);
|
inspect_bytecode(bytecode);
|
||||||
}
|
}
|
||||||
|
|
||||||
Toy_bindVM(&vm, bytecode, NULL);
|
//WARN: Hacky debugging
|
||||||
|
if (vm.scope == NULL) {
|
||||||
|
Toy_bindVM(&vm, bytecode, NULL);
|
||||||
|
initStandardLibrary(&vm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Toy_bindVM(&vm, bytecode, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
//run
|
//run
|
||||||
Toy_runVM(&vm);
|
Toy_runVM(&vm);
|
||||||
@@ -474,6 +484,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
Toy_VM vm;
|
Toy_VM vm;
|
||||||
Toy_initVM(&vm);
|
Toy_initVM(&vm);
|
||||||
Toy_bindVM(&vm, bytecode, NULL);
|
Toy_bindVM(&vm, bytecode, NULL);
|
||||||
|
initStandardLibrary(&vm); //WARN: Hacky debugging
|
||||||
|
|
||||||
Toy_runVM(&vm);
|
Toy_runVM(&vm);
|
||||||
|
|
||||||
|
|||||||
+21
-6
@@ -15,20 +15,35 @@ typedef struct CallbackPairs {
|
|||||||
} CallbackPairs;
|
} CallbackPairs;
|
||||||
|
|
||||||
//example callbacks
|
//example callbacks
|
||||||
void hello(Toy_VM* vm) {
|
|
||||||
(void)vm;
|
|
||||||
Toy_print("Hello world!");
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug(Toy_VM* vm) {
|
void debug(Toy_VM* vm) {
|
||||||
(void)vm;
|
(void)vm;
|
||||||
Toy_print("This function returns the integer '42' to the calling scope.");
|
Toy_print("This function returns the integer '42' to the calling scope.");
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_INTEGER(42));
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_INTEGER(42));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void identity(Toy_VM* vm) {
|
||||||
|
//does nothing, but any arguements are left on the stack as results
|
||||||
|
(void)vm;
|
||||||
|
}
|
||||||
|
|
||||||
|
void echo(Toy_VM* vm) {
|
||||||
|
//pops one argument, and prints it
|
||||||
|
Toy_Value value = Toy_popStack(&vm->stack);
|
||||||
|
Toy_String* string = Toy_stringifyValue(&vm->memoryBucket, value);
|
||||||
|
char* cstr = Toy_getStringRaw(string);
|
||||||
|
|
||||||
|
Toy_print(cstr);
|
||||||
|
|
||||||
|
free(cstr);
|
||||||
|
Toy_freeString(string);
|
||||||
|
Toy_freeValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
CallbackPairs callbackPairs[] = {
|
CallbackPairs callbackPairs[] = {
|
||||||
{"hello", hello},
|
|
||||||
{"debug", debug},
|
{"debug", debug},
|
||||||
|
{"identity", identity},
|
||||||
|
{"echo", echo},
|
||||||
|
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+8
-15
@@ -1,18 +1,11 @@
|
|||||||
|
|
||||||
|
fn output(arg) {
|
||||||
|
print arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
var array = ["alpha", "bravo", "charlie"];
|
||||||
|
|
||||||
|
|
||||||
var table: Table = ["answer":42];
|
|
||||||
|
|
||||||
print table.hasKey("answer");
|
|
||||||
print table.hasKey("question");
|
|
||||||
|
|
||||||
table.insert("question", "roads");
|
|
||||||
|
|
||||||
print table.hasKey("answer");
|
|
||||||
print table.hasKey("question");
|
|
||||||
|
|
||||||
table.remove("answer");
|
|
||||||
|
|
||||||
print table.hasKey("answer");
|
|
||||||
print table.hasKey("question");
|
|
||||||
|
|
||||||
|
|
||||||
|
array.forEach(echo);
|
||||||
|
array.forEach(output);
|
||||||
+57
-2
@@ -80,8 +80,63 @@ static void attr_arrayPopBack(Toy_VM* vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void attr_arrayForEach(Toy_VM* vm) {
|
static void attr_arrayForEach(Toy_VM* vm) {
|
||||||
(void)vm;
|
Toy_Value compound = Toy_popStack(&vm->stack);
|
||||||
//URGENT: attr_arrayForEach
|
Toy_Value callback = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
|
if (TOY_VALUE_IS_FUNCTION(callback) != true) {
|
||||||
|
char buffer[256];
|
||||||
|
snprintf(buffer, 256, "Expected function, found '%s'", Toy_private_getValueTypeAsCString(callback.type));
|
||||||
|
Toy_error(buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toy_Array* array = TOY_VALUE_AS_ARRAY(compound);
|
||||||
|
Toy_Function* fn = TOY_VALUE_AS_FUNCTION(callback);
|
||||||
|
|
||||||
|
//this emulates 'processInvoke' a bit, but not entirely
|
||||||
|
Toy_VM subVM;
|
||||||
|
Toy_inheritVM(vm, &subVM);
|
||||||
|
|
||||||
|
switch(fn->type) {
|
||||||
|
case TOY_FUNCTION_CUSTOM: {
|
||||||
|
//push and run for each element
|
||||||
|
for (unsigned int iterator = 0; iterator < array->count; iterator++) {
|
||||||
|
//bind to the subVM (more expensive than I'd like)
|
||||||
|
Toy_bindVM(&subVM, fn->bytecode.code, fn->bytecode.parentScope);
|
||||||
|
|
||||||
|
//get parameter name as a string
|
||||||
|
unsigned int paramAddr = ((unsigned int*)(subVM.code + subVM.paramAddr))[0];
|
||||||
|
Toy_ValueType paramType = (Toy_ValueType)(((unsigned int*)(subVM.code + subVM.paramAddr))[1]);
|
||||||
|
const char* cstr = ((char*)(subVM.code + subVM.dataAddr)) + paramAddr;
|
||||||
|
Toy_String* name = Toy_toStringLength(&subVM.memoryBucket, cstr, strlen(cstr));
|
||||||
|
|
||||||
|
Toy_declareScope(subVM.scope, Toy_copyString(name), paramType, Toy_copyValue(&subVM.memoryBucket, array->data[iterator]), true);
|
||||||
|
Toy_freeString(name);
|
||||||
|
|
||||||
|
Toy_runVM(&subVM); //TODO: could use a 'map'-style method by storing the results
|
||||||
|
|
||||||
|
Toy_resetVM(&subVM, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TOY_FUNCTION_NATIVE: {
|
||||||
|
//this uses a subVM for the native function, which is a slight difference than 'processInoke'
|
||||||
|
for (unsigned int iterator = 0; iterator < array->count; iterator++) {
|
||||||
|
Toy_pushStack(&subVM.stack, Toy_copyValue(&subVM.memoryBucket, array->data[iterator]));
|
||||||
|
|
||||||
|
fn->native.callback(&subVM); //NOTE: try not to leave anything on the stack afterwards
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Toy_error("Can't call an unknown function type in 'forEach'");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
Toy_freeVM(&subVM);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void attr_arraySort(Toy_VM* vm) {
|
static void attr_arraySort(Toy_VM* vm) {
|
||||||
|
|||||||
+7
-7
@@ -444,8 +444,8 @@ static void processAttribute(Toy_VM* vm) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BUGFIX: check for callable native functions, so they can access the compound too
|
//BUGFIX: check for callable functions, so they can access the compound too
|
||||||
if (TOY_VALUE_IS_FUNCTION(result) && TOY_VALUE_AS_FUNCTION(result)->type == TOY_FUNCTION_NATIVE) {
|
if (TOY_VALUE_IS_FUNCTION(result)) {
|
||||||
//WONTFIX: `print array.pushBack;' will leave the compound's reference on the stack
|
//WONTFIX: `print array.pushBack;' will leave the compound's reference on the stack
|
||||||
Toy_pushStack(&vm->stack, compound);
|
Toy_pushStack(&vm->stack, compound);
|
||||||
}
|
}
|
||||||
@@ -1086,14 +1086,14 @@ void Toy_resetVM(Toy_VM* vm, bool preserveScope, bool preserveStack) {
|
|||||||
|
|
||||||
vm->programCounter = 0;
|
vm->programCounter = 0;
|
||||||
|
|
||||||
if (!preserveStack) {
|
|
||||||
Toy_resetStack(&vm->stack); //NOTE: has a realloc()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!preserveScope) {
|
if (!preserveScope) {
|
||||||
vm->scope = Toy_popScope(vm->scope);
|
vm->scope = Toy_popScope(vm->scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!preserveStack) {
|
||||||
|
Toy_resetStack(&vm->stack); //NOTE: has a realloc()
|
||||||
|
}
|
||||||
|
|
||||||
//NOTE: buckets are not altered during resets
|
//NOTE: buckets are not altered during resets
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1171,7 +1171,7 @@ void Toy_freeVM(Toy_VM* vm) {
|
|||||||
Toy_freeStack(vm->stack);
|
Toy_freeStack(vm->stack);
|
||||||
|
|
||||||
if (vm->parentBucketHandle != NULL) {
|
if (vm->parentBucketHandle != NULL) {
|
||||||
*(vm->parentBucketHandle) = vm->memoryBucket; //update the outter VM, if there is one
|
*(vm->parentBucketHandle) = vm->memoryBucket; //update the outer VM, if there is one
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Toy_freeBucket(&vm->memoryBucket);
|
Toy_freeBucket(&vm->memoryBucket);
|
||||||
|
|||||||
Reference in New Issue
Block a user