diff --git a/lang/boolean.c b/lang/boolean.c index 9b22f88..e96cf39 100644 --- a/lang/boolean.c +++ b/lang/boolean.c @@ -13,20 +13,24 @@ bool value; }; -Object boolean_create(bool value) { - Object obj = object_create(&boolean_class, sizeof(struct boolean)); +Object boolean_create(VmState state, bool value) { + Object obj = + object_create(state, &boolean_class, sizeof(struct boolean)); abort_if(!obj, "unable to allocate boolean"); struct boolean *boolean = - (struct boolean *)object_priv(obj, &boolean_class); + (struct boolean *)object_priv(state, obj, &boolean_class); boolean->value = value; return obj; } -static void boolean_cleanup(Object obj) { (void)obj; } +static void boolean_cleanup(VmState state, Object obj) { + (void)state; + (void)obj; +} -bool boolean_value(Object obj) { +bool boolean_value(VmState state, Object obj) { struct boolean *boolean = - (struct boolean *)object_priv(obj, &boolean_class); + (struct boolean *)object_priv(state, obj, &boolean_class); return boolean->value; } @@ -34,9 +38,9 @@ (void)priv; int arg_count = vm_stack_depth(state); abort_if(arg_count != 1, "boolean_invert called with extra arguments"); - bool value = boolean_value(obj); + bool value = boolean_value(state, obj); bool invert = !value; - vm_stack_set(state, 0, boolean_create(invert)); + vm_stack_set(state, 0, boolean_create(state, invert)); } static struct object_call calls[] = { diff --git a/lang/boolean.h b/lang/boolean.h index b4b053f..5c86fb4 100644 --- a/lang/boolean.h +++ b/lang/boolean.h @@ -8,9 +8,9 @@ #include // Creates a boolean -Object boolean_create(bool value); +Object boolean_create(VmState state, bool value); // Gets a boolean's value -bool boolean_value(Object obj); +bool boolean_value(VmState state, Object obj); #endif diff --git a/lang/bytecode.c b/lang/bytecode.c index 197ddbb..f0ab824 100644 --- a/lang/bytecode.c +++ b/lang/bytecode.c @@ -41,7 +41,7 @@ num |= *pos_code++ << 8; num |= *pos_code++ << 16; num |= *pos_code++ << 24; - vm_stack_push(state, number_create(num)); + vm_stack_push(state, number_create(state, num)); break; } // OP_BOOLEAN pushes a boolean on to the stack @@ -49,7 +49,7 @@ case OP_BOOLEAN: { int value = *pos_code++; abort_if(value != 0 && value != 1, "invalid boolean"); - vm_stack_push(state, boolean_create(value)); + vm_stack_push(state, boolean_create(state, value)); break; } // OP_CALL dispatches a call to the top of stack object @@ -61,7 +61,7 @@ pos_code += strlen(dispatch) + 1; // Skip NULL too Object obj = vm_stack_pop(state); vm_call(state, obj, dispatch, arg_count); - object_drop(&obj); + object_drop(state, &obj); break; } // OP_TAIL_CALL queues a call and returns @@ -83,7 +83,7 @@ vm_stack_drop(state, remaining); } vm_tailcall(state, obj, dispatch); - object_drop(&obj); + object_drop(state, &obj); return; } // OP_NONE pushes object_none on to the stack @@ -123,7 +123,7 @@ } // OP_SELF pushes obj on to the stack case OP_SELF: { - object_hold(obj); + object_hold(state, obj); vm_stack_push(state, obj); break; } @@ -131,10 +131,10 @@ case OP_JUMP_FALSE: { int offset = *pos_code++; Object test = vm_stack_pop(state); - if (boolean_value(test) == false) { + if (boolean_value(state, test) == false) { pos_code += offset; } - object_drop(&test); + object_drop(state, &test); break; } // OP_JUMP_ALWAYS jumps diff --git a/lang/compile.py b/lang/compile.py index d51d8f3..eb46433 100755 --- a/lang/compile.py +++ b/lang/compile.py @@ -750,13 +750,14 @@ header += """ static struct object_class module_class; -Object module_create(void) { - Object obj = object_create(&module_class, 1); +Object module_create(VmState state) { + (void)state; + Object obj = object_create(state, &module_class, 1); abort_if(!obj, "unable to allocate module"); return obj; } -static void module_cleanup(Object obj) { (void)obj; } +static void module_cleanup(VmState state, Object obj) { (void)state; (void)obj; } static void module_call(VmState state, Object obj, void *priv) { bytecode_run(state, obj, (const unsigned char *)priv); diff --git a/lang/main.c b/lang/main.c index b4bf048..41e2ee2 100644 --- a/lang/main.c +++ b/lang/main.c @@ -9,48 +9,50 @@ #include static void test_number(VmState state) { - Object numA = number_create(5); - Object numB = number_create(3); + Object numA = number_create(state, 5); + Object numB = number_create(state, 3); vm_stack_push(state, object_none()); vm_stack_push(state, numB); numB = object_none(); vm_call(state, numA, "Add", 2); Object numC = vm_stack_pop(state); - printf("numC value is %i\n", number_value(numC)); - abort_if(number_value(numC) != 8, "add return value is not 8"); - object_drop(&numA); - object_drop(&numC); + printf("numC value is %i\n", number_value(state, numC)); + abort_if(number_value(state, numC) != 8, "add return value is not 8"); + object_drop(state, &numA); + object_drop(state, &numC); } static void test_module(VmState state) { - extern Object module_create(void); - Object module = module_create(); + extern Object module_create(VmState); + Object module = module_create(state); vm_stack_push(state, object_none()); vm_call(state, module, "MakeNumber", 1); Object numA = vm_stack_pop(state); - printf("code return value is %i\n", number_value(numA)); - abort_if(number_value(numA) != 1234, "code return value is not 1234"); + printf("code return value is %i\n", number_value(state, numA)); + abort_if(number_value(state, numA) != 1234, + "code return value is not 1234"); vm_stack_push(state, object_none()); vm_call(state, module, "BoolTest", 1); Object boolA = vm_stack_pop(state); - abort_if( - boolean_value(boolA) != false, "code return bool is not false"); - object_drop(&boolA); + abort_if(boolean_value(state, boolA) != false, + "code return bool is not false"); + object_drop(state, &boolA); vm_stack_push(state, object_none()); vm_call(state, module, "NoneTest", 1); Object noneA = vm_stack_pop(state); abort_if(noneA != object_none(), "code return none is not none"); - object_drop(&noneA); + object_drop(state, &noneA); vm_stack_push(state, object_none()); vm_call(state, module, "IfTest", 1); Object ifA = vm_stack_pop(state); - abort_if(boolean_value(ifA) == false, "if return bool is not true"); - object_drop(&ifA); + abort_if(boolean_value(state, ifA) == false, + "if return bool is not true"); + object_drop(state, &ifA); vm_stack_push(state, object_none()); vm_call(state, module, "LoopTest", 1); vm_stack_drop(state, 1); - object_drop(&numA); - object_drop(&module); + object_drop(state, &numA); + object_drop(state, &module); } int lang_main(void) { diff --git a/lang/number.c b/lang/number.c index 4107268..1e134e7 100644 --- a/lang/number.c +++ b/lang/number.c @@ -16,22 +16,25 @@ mpq_t value; }; -Object number_create(int value) { - Object obj = object_create(&num_class, sizeof(struct number)); +Object number_create(VmState state, int value) { + Object obj = object_create(state, &num_class, sizeof(struct number)); abort_if(!obj, "unable to allocate number"); - struct number *num = (struct number *)object_priv(obj, &num_class); + struct number *num = + (struct number *)object_priv(state, obj, &num_class); mpq_init(num->value); mpq_set_ui(num->value, value, 1); return obj; } -static void number_cleanup(Object obj) { - struct number *num = (struct number *)object_priv(obj, &num_class); +static void number_cleanup(VmState state, Object obj) { + struct number *num = + (struct number *)object_priv(state, obj, &num_class); mpq_clear(num->value); } -int number_value(Object obj) { - struct number *num = (struct number *)object_priv(obj, &num_class); +int number_value(VmState state, Object obj) { + struct number *num = + (struct number *)object_priv(state, obj, &num_class); mpz_t out; mpz_init(out); mpq_get_num(out, num->value); @@ -49,15 +52,15 @@ Object arg1 = vm_stack_get(state, 1); int result = 0; if (priv == OP_ADD) { - result = number_value(obj) + number_value(arg1); + result = number_value(state, obj) + number_value(state, arg1); } else if (priv == OP_SUBTRACT) { - result = number_value(obj) - number_value(arg1); + result = number_value(state, obj) - number_value(state, arg1); } else { abort_msg("number_math called with invalid priv"); } - vm_stack_set(state, 0, number_create(result)); + vm_stack_set(state, 0, number_create(state, result)); vm_stack_drop(state, 1); - object_drop(&arg1); + object_drop(state, &arg1); } static void number_equals(VmState state, Object obj, void *priv) { @@ -65,10 +68,10 @@ int arg_count = vm_stack_depth(state); abort_if(arg_count != 2, "number_equals called without 2 arguments"); Object arg1 = vm_stack_get(state, 1); - bool equals = number_value(obj) == number_value(arg1); - vm_stack_set(state, 0, boolean_create(equals)); + bool equals = number_value(state, obj) == number_value(state, arg1); + vm_stack_set(state, 0, boolean_create(state, equals)); vm_stack_drop(state, 1); - object_drop(&arg1); + object_drop(state, &arg1); } static struct object_call calls[] = { diff --git a/lang/number.h b/lang/number.h index 2795191..0bc4e7f 100644 --- a/lang/number.h +++ b/lang/number.h @@ -7,9 +7,9 @@ #include "types.h" // Creates a number -Object number_create(int value); +Object number_create(VmState state, int value); // Gets a number's value -int number_value(Object obj); +int number_value(VmState state, Object obj); #endif diff --git a/lang/object.c b/lang/object.c index 89d5acb..7d00c77 100644 --- a/lang/object.c +++ b/lang/object.c @@ -16,7 +16,8 @@ Object object_none(void) { return (Object)NULL; } -Object object_create(struct object_class *class, int priv_size) { +Object object_create(VmState state, struct object_class *class, int priv_size) { + (void)state; abort_if(priv_size < 1, "object_create: priv_size too small"); size_t size = sizeof(struct object) + priv_size; struct object *obj = calloc(size, 1); @@ -27,21 +28,23 @@ return (Object)obj; } -char *object_priv(Object object, struct object_class *class) { +char *object_priv(VmState state, Object object, struct object_class *class) { + (void)state; abort_if(object == object_none(), "object_priv: no priv on none"); struct object *obj = (struct object *)object; abort_if(obj->class_data != class, "object_priv: incompatible class"); return obj->priv_data; } -void object_hold(Object object) { +void object_hold(VmState state, Object object) { + (void)state; if (object == object_none()) return; struct object *obj = (struct object *)object; atomic_fetch_add_explicit(&obj->ref_count, 1, memory_order_relaxed); } -void object_drop(Object *objptr) { +void object_drop(VmState state, Object *objptr) { if (*objptr == object_none()) return; struct object *obj = (struct object *)*objptr; @@ -49,7 +52,7 @@ &obj->ref_count, 1, memory_order_relaxed); if (count == 1) { // We were the last user of the object, clean it up - obj->class_data->cleanup(obj); + obj->class_data->cleanup(state, obj); free(obj); } *objptr = object_none(); diff --git a/lang/object.h b/lang/object.h index 2510860..bf0a7b4 100644 --- a/lang/object.h +++ b/lang/object.h @@ -15,26 +15,26 @@ // Object class shared between objects struct object_class { - void (*cleanup)(Object obj); + void (*cleanup)(VmState state, Object obj); struct object_call *calls; // Points to array terminated by call with NULL name }; // Creates an object with a class and allocated private data -Object object_create(struct object_class *class, int priv_size); +Object object_create(VmState state, struct object_class *class, int priv_size); // Retrieves private data for an object with a specified class -char *object_priv(Object object, struct object_class *class); +char *object_priv(VmState state, Object object, struct object_class *class); // Creates a placeholder object for use when no object is present Object object_none(void); // Adds a reference to an object -void object_hold(Object obj); +void object_hold(VmState state, Object obj); // Drops a reference to an object, possibly cleaning up the object // Sets objptr to object_none -void object_drop(Object *objptr); +void object_drop(VmState state, Object *objptr); // Calls a method on an object void dispatch_call(VmState state, Object obj, const char *name); diff --git a/lang/vm.c b/lang/vm.c index 6776473..200fa23 100644 --- a/lang/vm.c +++ b/lang/vm.c @@ -41,7 +41,7 @@ abort_if(index < 0, "vm_stack_set: negative value"); abort_if(offset >= priv->stack_next, "vm_stack_set: stack overflow"); Object *stack_pos = &priv->stack[offset]; - object_drop(stack_pos); + object_drop(state, stack_pos); *stack_pos = obj; } @@ -51,7 +51,7 @@ abort_if(index < 0, "vm_stack_get: negative value"); abort_if(offset >= priv->stack_next, "vm_stack_get: stack overflow"); Object obj = priv->stack[offset]; - object_hold(obj); + object_hold(state, obj); return obj; } @@ -79,7 +79,7 @@ abort_if(count < 1, "vm_stack_drop: invalid drop count"); while (count--) { Object obj = vm_stack_pop(state); - object_drop(&obj); + object_drop(state, &obj); } } @@ -92,10 +92,10 @@ struct vm_state *priv = (struct vm_state *)state; int old_base = priv->stack_base; priv->stack_base = priv->stack_next - arg_count; - object_hold(obj); + object_hold(state, obj); do { dispatch_call(priv, obj, name); - object_drop(&obj); + object_drop(state, &obj); obj = priv->tail_obj; name = priv->tail_name; priv->tail_obj = object_none(); @@ -106,7 +106,7 @@ void vm_tailcall(VmState state, Object obj, const char *name) { struct vm_state *priv = (struct vm_state *)state; - object_hold(obj); + object_hold(state, obj); priv->tail_obj = obj; priv->tail_name = name; }