diff --git a/lang/boolean.c b/lang/boolean.c index 9cb7037..eab6ca0 100644 --- a/lang/boolean.c +++ b/lang/boolean.c @@ -2,7 +2,6 @@ // Copyright (c) 2023 John Watts and the LuminaSensum contributors #include "boolean.h" -#include "error.h" #include "object.h" #include "vm.h" #include @@ -16,7 +15,7 @@ Object boolean_create(VmState state, bool value) { Object obj = object_create(state, &boolean_class, sizeof(struct boolean)); - abort_if(state, !obj, "unable to allocate boolean"); + vm_abort_if(state, !obj, "unable to allocate boolean"); struct boolean *boolean = (struct boolean *)object_priv(state, obj, &boolean_class); boolean->value = value; @@ -37,7 +36,7 @@ static void boolean_invert(VmState state, Object obj, void *priv) { (void)priv; int arg_count = vm_stack_depth(state); - abort_if(state, arg_count != 1, + vm_abort_if(state, arg_count != 1, "boolean_invert called with extra arguments"); bool value = boolean_value(state, obj); bool invert = !value; diff --git a/lang/bytecode.c b/lang/bytecode.c index 396347b..a51d59f 100644 --- a/lang/bytecode.c +++ b/lang/bytecode.c @@ -3,7 +3,6 @@ #include "bytecode.h" #include "boolean.h" -#include "error.h" #include "number.h" #include "object.h" #include "string.h" @@ -48,7 +47,7 @@ // First argument is a 1-byte boolean case OP_BOOLEAN: { int value = *pos_code++; - abort_if(state, value != 0 && value != 1, + vm_abort_if(state, value != 0 && value != 1, "invalid boolean"); vm_stack_push(state, boolean_create(state, value)); break; @@ -118,7 +117,7 @@ // First argument is the expected depth case OP_DEPTH_CHECK: { int depth = *pos_code++; - abort_if(state, vm_stack_depth(state) != depth, + vm_abort_if(state, vm_stack_depth(state) != depth, "stack depth mismatch"); break; } @@ -150,9 +149,9 @@ } // Unknown op, error out default: - abort_msg(state, "bytecode_run: Unknown op"); + vm_abort_msg(state, "bytecode_run: Unknown op"); } } // Uh-oh, no more bytecode? - abort_msg(state, "bytecode_run: Ran out of bytecode to run!"); + vm_abort_msg(state, "bytecode_run: Ran out of bytecode to run!"); } diff --git a/lang/compile.py b/lang/compile.py index ce057fb..6db97c9 100755 --- a/lang/compile.py +++ b/lang/compile.py @@ -740,7 +740,6 @@ header += "*/\n\n" includes = [ '"bytecode.h"', - '"error.h"', '"object.h"', '"vm.h"', '', @@ -753,7 +752,7 @@ Object module_create(VmState state) { (void)state; Object obj = object_create(state, &module_class, 1); - abort_if(state, !obj, "unable to allocate module"); + vm_abort_if(state, !obj, "unable to allocate module"); return obj; } diff --git a/lang/error.c b/lang/error.c index cdf2c57..3f9bc7b 100644 --- a/lang/error.c +++ b/lang/error.c @@ -5,14 +5,7 @@ #include #include -__attribute__((noreturn)) void abort_msg(VmState state, const char *msg) { - (void)state; +__attribute__((noreturn)) void abort_print(const char *msg) { fprintf(stderr, "ERROR: %s\n", msg); abort(); } - -void abort_if(VmState state, int value, const char *msg) { - if (value) { - abort_msg(state, msg); - } -} diff --git a/lang/error.h b/lang/error.h index 93fc2fc..917bc9f 100644 --- a/lang/error.h +++ b/lang/error.h @@ -6,10 +6,7 @@ #include "types.h" -// Aborts the program with a message to stderr -__attribute__((noreturn)) void abort_msg(VmState state, const char *msg); - -// Aborts the program if a value is true -void abort_if(VmState state, int value, const char *msg); +// Prints a message to stderr and stops running +__attribute__((noreturn)) void abort_print(const char *msg); #endif diff --git a/lang/main.c b/lang/main.c index c025a74..185c66a 100644 --- a/lang/main.c +++ b/lang/main.c @@ -2,7 +2,6 @@ // Copyright (c) 2023 John Watts and the LuminaSensum contributors #include "boolean.h" -#include "error.h" #include "number.h" #include "object.h" #include "vm.h" @@ -17,7 +16,7 @@ vm_call(state, numA, "Add", 2); Object numC = vm_stack_pop(state); printf("numC value is %i\n", number_value(state, numC)); - abort_if(state, number_value(state, numC) != 8, + vm_abort_if(state, number_value(state, numC) != 8, "add return value is not 8"); object_drop(state, &numA); object_drop(state, &numC); @@ -30,23 +29,24 @@ vm_call(state, module, "MakeNumber", 1); Object numA = vm_stack_pop(state); printf("code return value is %i\n", number_value(state, numA)); - abort_if(state, number_value(state, numA) != 1234, + vm_abort_if(state, 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(state, boolean_value(state, boolA) != false, + vm_abort_if(state, 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(state, noneA != object_none(), "code return none is not none"); + vm_abort_if( + state, noneA != object_none(), "code return none is not none"); object_drop(state, &noneA); vm_stack_push(state, object_none()); vm_call(state, module, "IfTest", 1); Object ifA = vm_stack_pop(state); - abort_if(state, boolean_value(state, ifA) == false, + vm_abort_if(state, boolean_value(state, ifA) == false, "if return bool is not true"); object_drop(state, &ifA); vm_stack_push(state, object_none()); diff --git a/lang/number.c b/lang/number.c index 6a27025..868aae4 100644 --- a/lang/number.c +++ b/lang/number.c @@ -3,7 +3,6 @@ #include "number.h" #include "boolean.h" -#include "error.h" #include "object.h" #include "vm.h" #include @@ -18,7 +17,7 @@ Object number_create(VmState state, int value) { Object obj = object_create(state, &num_class, sizeof(struct number)); - abort_if(state, !obj, "unable to allocate number"); + vm_abort_if(state, !obj, "unable to allocate number"); struct number *num = (struct number *)object_priv(state, obj, &num_class); mpq_init(num->value); @@ -48,7 +47,7 @@ static void number_math(VmState state, Object obj, void *priv) { int arg_count = vm_stack_depth(state); - abort_if(state, arg_count != 2, + vm_abort_if(state, arg_count != 2, "number_math called without 2 arguments"); Object arg1 = vm_stack_get(state, 1); int result = 0; @@ -57,7 +56,7 @@ } else if (priv == OP_SUBTRACT) { result = number_value(state, obj) - number_value(state, arg1); } else { - abort_msg(state, "number_math called with invalid priv"); + vm_abort_msg(state, "number_math called with invalid priv"); } vm_stack_set(state, 0, number_create(state, result)); vm_stack_drop(state, 1); @@ -67,7 +66,7 @@ static void number_equals(VmState state, Object obj, void *priv) { (void)priv; int arg_count = vm_stack_depth(state); - abort_if(state, arg_count != 2, + vm_abort_if(state, arg_count != 2, "number_equals called without 2 arguments"); Object arg1 = vm_stack_get(state, 1); bool equals = number_value(state, obj) == number_value(state, arg1); diff --git a/lang/object.c b/lang/object.c index dd0c129..23ab074 100644 --- a/lang/object.c +++ b/lang/object.c @@ -2,7 +2,7 @@ // Copyright (c) 2023 John Watts and the LuminaSensum contributors #include "object.h" -#include "error.h" +#include "vm.h" #include #include #include @@ -18,10 +18,10 @@ Object object_create(VmState state, struct object_class *class, int priv_size) { (void)state; - abort_if(state, priv_size < 1, "object_create: priv_size too small"); + vm_abort_if(state, priv_size < 1, "object_create: priv_size too small"); size_t size = sizeof(struct object) + priv_size; struct object *obj = calloc(size, 1); - abort_if(state, obj == NULL, + vm_abort_if(state, obj == NULL, "object_create: not enough memory for an objects"); obj->class_data = class; obj->ref_count = 1; @@ -30,10 +30,10 @@ char *object_priv(VmState state, Object object, struct object_class *class) { (void)state; - abort_if( + vm_abort_if( state, object == object_none(), "object_priv: no priv on none"); struct object *obj = (struct object *)object; - abort_if(state, obj->class_data != class, + vm_abort_if(state, obj->class_data != class, "object_priv: incompatible class"); return obj->priv_data; } @@ -62,7 +62,7 @@ void dispatch_call(VmState state, Object object, const char *name) { if (object == object_none()) { - abort_msg(state, "dispatch_call: cannot dispatch on none"); + vm_abort_msg(state, "dispatch_call: cannot dispatch on none"); } struct object *obj = (struct object *)object; struct object_call *call = obj->class_data->calls; @@ -73,5 +73,5 @@ } ++call; } - abort_msg(state, "dispatch_calll: no call found to dispatch"); + vm_abort_msg(state, "dispatch_calll: no call found to dispatch"); } diff --git a/lang/vm.c b/lang/vm.c index c54a232..552a7af 100644 --- a/lang/vm.c +++ b/lang/vm.c @@ -18,15 +18,16 @@ VmState vm_create(void) { struct vm_state *state = malloc(sizeof(struct vm_state)); - abort_if(state, state == NULL, "vm_create: unable to allocate state"); + if (state == NULL) + abort_print("vm_create: unable to allocate state"); state->stack_size = 16; state->stack_base = 0; state->stack_next = 0; state->tail_obj = object_none(); state->tail_name = NULL; state->stack = malloc(sizeof(Object) * state->stack_size); - abort_if(state, state->stack == NULL, - "vm_create: unable to allocate stack"); + if (state->stack == NULL) + abort_print("vm_create: unable to allocate stack"); return (VmState)state; } @@ -39,8 +40,8 @@ void vm_stack_set(VmState state, int index, Object obj) { struct vm_state *priv = (struct vm_state *)state; int offset = priv->stack_base + index; - abort_if(state, index < 0, "vm_stack_set: negative value"); - abort_if(state, offset >= priv->stack_next, + vm_abort_if(state, index < 0, "vm_stack_set: negative value"); + vm_abort_if(state, offset >= priv->stack_next, "vm_stack_set: stack overflow"); Object *stack_pos = &priv->stack[offset]; object_drop(state, stack_pos); @@ -50,8 +51,8 @@ Object vm_stack_get(VmState state, int index) { struct vm_state *priv = (struct vm_state *)state; int offset = priv->stack_base + index; - abort_if(state, index < 0, "vm_stack_get: negative value"); - abort_if(state, offset >= priv->stack_next, + vm_abort_if(state, index < 0, "vm_stack_get: negative value"); + vm_abort_if(state, offset >= priv->stack_next, "vm_stack_get: stack overflow"); Object obj = priv->stack[offset]; object_hold(state, obj); @@ -65,14 +66,14 @@ int max_stack = priv->stack_size - 1; // Check if stack_next is outside the stack before // writing to it - abort_if(state, priv->stack_next > max_stack, + vm_abort_if(state, priv->stack_next > max_stack, "vm_stack_push: stack overflow"); priv->stack[priv->stack_next++] = obj; } Object vm_stack_pop(VmState state) { struct vm_state *priv = (struct vm_state *)state; - abort_if(state, priv->stack_next <= priv->stack_base, + vm_abort_if(state, priv->stack_next <= priv->stack_base, "vm_stack_pop: stack base underflow"); Object obj = priv->stack[--priv->stack_next]; priv->stack[priv->stack_next] = object_none(); @@ -80,7 +81,7 @@ } void vm_stack_drop(VmState state, int count) { - abort_if(state, count < 1, "vm_stack_drop: invalid drop count"); + vm_abort_if(state, count < 1, "vm_stack_drop: invalid drop count"); while (count--) { Object obj = vm_stack_pop(state); object_drop(state, &obj); @@ -114,3 +115,14 @@ priv->tail_obj = obj; priv->tail_name = name; } + +__attribute__((noreturn)) void vm_abort_msg(VmState state, const char *msg) { + (void)state; + abort_print(msg); +} + +void vm_abort_if(VmState state, int value, const char *msg) { + if (value) { + vm_abort_msg(state, msg); + } +} diff --git a/lang/vm.h b/lang/vm.h index 9dd38fe..b0a747d 100644 --- a/lang/vm.h +++ b/lang/vm.h @@ -42,4 +42,10 @@ // Queues a call to be scheduled on next return to vm_call void vm_tailcall(VmState state, Object obj, const char *name); +// Aborts the program with a message to stderr +__attribute__((noreturn)) void vm_abort_msg(VmState state, const char *msg); + +// Aborts the program if a value is true +void vm_abort_if(VmState state, int value, const char *msg); + #endif