Added 'range' to standard library, adjusted native functions
This commit is contained in:
+49
-7
@@ -15,18 +15,21 @@ typedef struct CallbackPairs {
|
|||||||
} CallbackPairs;
|
} CallbackPairs;
|
||||||
|
|
||||||
//example callbacks
|
//example callbacks
|
||||||
void debug(Toy_VM* vm) {
|
static void answer(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
(void)vm;
|
(void)vm;
|
||||||
Toy_print("This function returns the integer '42' to the calling scope.");
|
(void)self;
|
||||||
|
Toy_print(TOY_CC_DEBUG "This function returns the integer '42' to the calling scope." TOY_CC_RESET);
|
||||||
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_INTEGER(42));
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_INTEGER(42));
|
||||||
}
|
}
|
||||||
|
|
||||||
void identity(Toy_VM* vm) {
|
static void identity(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
//does nothing, but any arguements are left on the stack as results
|
//does nothing, but any arguements are left on the stack as results
|
||||||
(void)vm;
|
(void)vm;
|
||||||
|
(void)self;
|
||||||
}
|
}
|
||||||
|
|
||||||
void echo(Toy_VM* vm) {
|
static void echo(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
|
(void)self;
|
||||||
//pops one argument, and prints it
|
//pops one argument, and prints it
|
||||||
Toy_Value value = Toy_popStack(&vm->stack);
|
Toy_Value value = Toy_popStack(&vm->stack);
|
||||||
Toy_String* string = Toy_stringifyValue(&vm->memoryBucket, value);
|
Toy_String* string = Toy_stringifyValue(&vm->memoryBucket, value);
|
||||||
@@ -39,10 +42,49 @@ void echo(Toy_VM* vm) {
|
|||||||
Toy_freeValue(value);
|
Toy_freeValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void next(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
|
//used by 'range'
|
||||||
|
if (self->meta2 < self->meta1) {
|
||||||
|
Toy_Value result = TOY_VALUE_FROM_INTEGER(self->meta2);
|
||||||
|
Toy_pushStack(&vm->stack, result);
|
||||||
|
self->meta2++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Toy_pushStack(&vm->stack, TOY_VALUE_FROM_NULL());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void range(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
|
(void)self;
|
||||||
|
|
||||||
|
//one arg to represent the number of iterations
|
||||||
|
Toy_Value value = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
|
//check types
|
||||||
|
if (!TOY_VALUE_IS_INTEGER(value)) {
|
||||||
|
char buffer[256];
|
||||||
|
snprintf(buffer, 256, "Expected Integer argument in 'range', found '%s'", Toy_getValueTypeAsCString(value.type));
|
||||||
|
Toy_error(buffer);
|
||||||
|
Toy_freeValue(value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//make the callback
|
||||||
|
Toy_Function* fn = Toy_createFunctionFromCallback(&vm->memoryBucket, next);
|
||||||
|
fn->native.meta1 = TOY_VALUE_AS_INTEGER(value); //fake a closure
|
||||||
|
fn->native.meta2 = 0; //counter
|
||||||
|
|
||||||
|
Toy_Value result = TOY_VALUE_FROM_FUNCTION(fn);
|
||||||
|
|
||||||
|
Toy_pushStack(&vm->stack, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CallbackPairs callbackPairs[] = {
|
CallbackPairs callbackPairs[] = {
|
||||||
{"debug", debug},
|
{"dbg_answer", answer},
|
||||||
{"identity", identity},
|
{"dbg_identity", identity},
|
||||||
{"echo", echo},
|
{"dbg_echo", echo},
|
||||||
|
{"range", range},
|
||||||
|
|
||||||
{NULL, NULL},
|
{NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
//WARN: This is just a scratch pad, don't use it
|
//WARN: This is just a scratch pad, don't use it
|
||||||
|
//TODO: table.hasValue or table.getKeyFromValue?
|
||||||
|
|
||||||
|
|
||||||
//for (var i in array) print i;
|
//for (var i in array) print i;
|
||||||
|
//for (var i in table) print i;
|
||||||
//for (var i in range(10)) print i;
|
//for (var i in range(10)) print i;
|
||||||
|
//for (range(10)) print "ha";
|
||||||
|
|
||||||
|
|
||||||
//example of a `range` function
|
//example of a `range`-like function
|
||||||
fn range(limit: Int) {
|
fn range(limit: Int) {
|
||||||
var counter: Int = 0;
|
var counter: Int = 0;
|
||||||
|
|
||||||
|
|||||||
+25
-9
@@ -45,7 +45,9 @@ Toy_Value Toy_private_handleStringAttributes(Toy_VM* vm, Toy_Value compound, Toy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void attr_arrayPushBack(Toy_VM* vm) {
|
static void attr_arrayPushBack(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
|
(void)self;
|
||||||
|
|
||||||
Toy_Value compound = Toy_popStack(&vm->stack);
|
Toy_Value compound = Toy_popStack(&vm->stack);
|
||||||
Toy_Value element = Toy_popStack(&vm->stack);
|
Toy_Value element = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
@@ -69,7 +71,9 @@ static void attr_arrayPushBack(Toy_VM* vm) {
|
|||||||
array->count++;
|
array->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void attr_arrayPopBack(Toy_VM* vm) {
|
static void attr_arrayPopBack(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
|
(void)self;
|
||||||
|
|
||||||
Toy_Value compound = Toy_popStack(&vm->stack);
|
Toy_Value compound = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
Toy_Array* array = TOY_VALUE_AS_ARRAY(compound);
|
Toy_Array* array = TOY_VALUE_AS_ARRAY(compound);
|
||||||
@@ -86,7 +90,9 @@ static void attr_arrayPopBack(Toy_VM* vm) {
|
|||||||
Toy_pushStack(&vm->stack, element);
|
Toy_pushStack(&vm->stack, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void attr_arrayForEach(Toy_VM* vm) {
|
static void attr_arrayForEach(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
|
(void)self;
|
||||||
|
|
||||||
Toy_Value compound = Toy_popStack(&vm->stack);
|
Toy_Value compound = Toy_popStack(&vm->stack);
|
||||||
Toy_Value callback = Toy_popStack(&vm->stack);
|
Toy_Value callback = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
@@ -133,7 +139,7 @@ static void attr_arrayForEach(Toy_VM* vm) {
|
|||||||
for (unsigned int iterator = 0; iterator < array->count; iterator++) {
|
for (unsigned int iterator = 0; iterator < array->count; iterator++) {
|
||||||
Toy_pushStack(&subVM.stack, Toy_copyValue(&subVM.memoryBucket, array->data[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
|
fn->native.callback(&subVM, &fn->native); //NOTE: try not to leave anything on the stack afterwards
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -147,8 +153,10 @@ static void attr_arrayForEach(Toy_VM* vm) {
|
|||||||
Toy_freeVM(&subVM);
|
Toy_freeVM(&subVM);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void attr_arraySort(Toy_VM* vm) {
|
static void attr_arraySort(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
(void)vm;
|
(void)vm;
|
||||||
|
(void)self;
|
||||||
|
|
||||||
//URGENT: attr_arraySort
|
//URGENT: attr_arraySort
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +188,9 @@ Toy_Value Toy_private_handleArrayAttributes(Toy_VM* vm, Toy_Value compound, Toy_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void attr_tableInsert(Toy_VM* vm) {
|
static void attr_tableInsert(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
|
(void)self;
|
||||||
|
|
||||||
Toy_Value compound = Toy_popStack(&vm->stack);
|
Toy_Value compound = Toy_popStack(&vm->stack);
|
||||||
Toy_Value value = Toy_popStack(&vm->stack); //NOTE: the args are still backwards, except compound
|
Toy_Value value = Toy_popStack(&vm->stack); //NOTE: the args are still backwards, except compound
|
||||||
Toy_Value key = Toy_popStack(&vm->stack);
|
Toy_Value key = Toy_popStack(&vm->stack);
|
||||||
@@ -202,7 +212,9 @@ static void attr_tableInsert(Toy_VM* vm) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void attr_tableHasKey(Toy_VM* vm) {
|
static void attr_tableHasKey(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
|
(void)self;
|
||||||
|
|
||||||
Toy_Value compound = Toy_popStack(&vm->stack);
|
Toy_Value compound = Toy_popStack(&vm->stack);
|
||||||
Toy_Value key = Toy_popStack(&vm->stack);
|
Toy_Value key = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
@@ -214,7 +226,9 @@ static void attr_tableHasKey(Toy_VM* vm) {
|
|||||||
Toy_pushStack(&vm->stack, result);
|
Toy_pushStack(&vm->stack, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void attr_tableRemove(Toy_VM* vm) {
|
static void attr_tableRemove(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
|
(void)self;
|
||||||
|
|
||||||
Toy_Value compound = Toy_popStack(&vm->stack);
|
Toy_Value compound = Toy_popStack(&vm->stack);
|
||||||
Toy_Value key = Toy_popStack(&vm->stack);
|
Toy_Value key = Toy_popStack(&vm->stack);
|
||||||
|
|
||||||
@@ -223,8 +237,10 @@ static void attr_tableRemove(Toy_VM* vm) {
|
|||||||
Toy_removeTable(&table, key);
|
Toy_removeTable(&table, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void attr_tableForEach(Toy_VM* vm) {
|
static void attr_tableForEach(Toy_VM* vm, Toy_FunctionNative* self) {
|
||||||
(void)vm;
|
(void)vm;
|
||||||
|
(void)self;
|
||||||
|
|
||||||
//URGENT: attr_tableForEach
|
//URGENT: attr_tableForEach
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-2
@@ -16,6 +16,8 @@ Toy_Function* Toy_createFunctionFromCallback(Toy_Bucket** bucketHandle, Toy_nati
|
|||||||
|
|
||||||
fn->type = TOY_FUNCTION_NATIVE;
|
fn->type = TOY_FUNCTION_NATIVE;
|
||||||
fn->native.callback = callback;
|
fn->native.callback = callback;
|
||||||
|
fn->native.meta1 = 0; //BUGFIX: Workaround for native functions lacking access to a closure-like scope
|
||||||
|
fn->native.meta2 = 0;
|
||||||
|
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
@@ -23,15 +25,22 @@ Toy_Function* Toy_createFunctionFromCallback(Toy_Bucket** bucketHandle, Toy_nati
|
|||||||
Toy_Function* Toy_copyFunction(Toy_Bucket** bucketHandle, Toy_Function* original) {
|
Toy_Function* Toy_copyFunction(Toy_Bucket** bucketHandle, Toy_Function* original) {
|
||||||
Toy_Function* fn = (Toy_Function*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Function));
|
Toy_Function* fn = (Toy_Function*)Toy_partitionBucket(bucketHandle, sizeof(Toy_Function));
|
||||||
|
|
||||||
if (original->type == TOY_FUNCTION_CUSTOM) {
|
switch(original->type) {
|
||||||
|
case TOY_FUNCTION_CUSTOM: {
|
||||||
fn->type = original->type;
|
fn->type = original->type;
|
||||||
fn->bytecode.code = original->bytecode.code;
|
fn->bytecode.code = original->bytecode.code;
|
||||||
fn->bytecode.parentScope = original->bytecode.parentScope;
|
fn->bytecode.parentScope = original->bytecode.parentScope;
|
||||||
Toy_private_incrementScopeRefCount(fn->bytecode.parentScope);
|
Toy_private_incrementScopeRefCount(fn->bytecode.parentScope);
|
||||||
}
|
}
|
||||||
else if (fn->type == TOY_FUNCTION_NATIVE) {
|
break;
|
||||||
|
|
||||||
|
case TOY_FUNCTION_NATIVE: {
|
||||||
fn->type = original->type;
|
fn->type = original->type;
|
||||||
fn->native.callback = original->native.callback;
|
fn->native.callback = original->native.callback;
|
||||||
|
fn->native.meta1 = original->native.meta1;
|
||||||
|
fn->native.meta2 = original->native.meta2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fn;
|
return fn;
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
|
|
||||||
//forward declare
|
//forward declare
|
||||||
struct Toy_VM;
|
struct Toy_VM;
|
||||||
typedef void (*Toy_nativeCallback)(struct Toy_VM*);
|
struct Toy_FunctionNative;
|
||||||
|
|
||||||
|
typedef void (*Toy_nativeCallback)(struct Toy_VM*, struct Toy_FunctionNative* self);
|
||||||
|
|
||||||
typedef enum Toy_FunctionType {
|
typedef enum Toy_FunctionType {
|
||||||
TOY_FUNCTION_CUSTOM,
|
TOY_FUNCTION_CUSTOM,
|
||||||
@@ -23,6 +25,8 @@ typedef struct Toy_FunctionBytecode {
|
|||||||
typedef struct Toy_FunctionNative {
|
typedef struct Toy_FunctionNative {
|
||||||
Toy_FunctionType type;
|
Toy_FunctionType type;
|
||||||
Toy_nativeCallback callback;
|
Toy_nativeCallback callback;
|
||||||
|
int meta1;
|
||||||
|
int meta2;
|
||||||
} Toy_FunctionNative;
|
} Toy_FunctionNative;
|
||||||
|
|
||||||
typedef union Toy_Function_t {
|
typedef union Toy_Function_t {
|
||||||
|
|||||||
+1
-1
@@ -405,7 +405,7 @@ static void processInvoke(Toy_VM* vm) {
|
|||||||
|
|
||||||
case TOY_FUNCTION_NATIVE: {
|
case TOY_FUNCTION_NATIVE: {
|
||||||
//NOTE: arguments are on the stack, leave results on the stack
|
//NOTE: arguments are on the stack, leave results on the stack
|
||||||
fn->native.callback(vm);
|
fn->native.callback(vm, &fn->native);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user