diff --git a/src/apfl.h b/src/apfl.h index e0df0a3..165f2b8 100644 --- a/src/apfl.h +++ b/src/apfl.h @@ -601,6 +601,14 @@ void apfl_iterative_runner_destroy(apfl_iterative_runner); // Get the type of a value on the stack enum apfl_value_type apfl_get_type(apfl_ctx, apfl_stackidx); +// Push a nil onto the stack +enum apfl_result apfl_push_nil(apfl_ctx); +// Push a boolean onto the stack +enum apfl_result apfl_push_bool(apfl_ctx, bool); +// Push a number onto the stack +enum apfl_result apfl_push_number(apfl_ctx, apfl_number); +// Push a string onto the stack +enum apfl_result apfl_push_string_view_copy(apfl_ctx, struct apfl_string_view); // Create a new empty list on the stack enum apfl_result apfl_list_create(apfl_ctx, size_t initial_capacity); // Append a value to a list. The value will be dropped. diff --git a/src/context.c b/src/context.c index eb7040b..c703678 100644 --- a/src/context.c +++ b/src/context.c @@ -7,6 +7,7 @@ #include "context.h" #include "gc.h" #include "hashmap.h" +#include "internal.h" #include "resizable.h" #include "value.h" @@ -240,6 +241,60 @@ apfl_ctx_destroy(apfl_ctx ctx) \ return APFL_RESULT_OK; +enum apfl_result +apfl_push_nil(apfl_ctx ctx) +{ + return apfl_stack_push(ctx, (struct apfl_value) { + .type = VALUE_NIL, + }) ? APFL_RESULT_OK : APFL_RESULT_ERR; +} + +enum apfl_result +apfl_push_bool(apfl_ctx ctx, bool b) +{ + return apfl_stack_push(ctx, (struct apfl_value) { + .type = VALUE_BOOLEAN, + .boolean = b, + }) ? APFL_RESULT_OK : APFL_RESULT_ERR; +} + +enum apfl_result +apfl_push_number(apfl_ctx ctx, apfl_number num) +{ + return apfl_stack_push(ctx, (struct apfl_value) { + .type = VALUE_NUMBER, + .number = num, + }) ? APFL_RESULT_OK : APFL_RESULT_ERR; +} + +static struct apfl_string * +new_copied_string(struct gc *gc, struct apfl_string_view sv) +{ + struct apfl_string s = apfl_string_blank(); + if (!apfl_string_copy(gc->allocator, &s, sv)) { + return NULL; + } + + struct apfl_string *out = apfl_string_move_into_new_gc_string(gc, &s); + if (out == NULL) { + apfl_string_deinit(gc->allocator, &s); + return NULL; + } + + return out; +} + +enum apfl_result +apfl_push_string_view_copy(apfl_ctx ctx, struct apfl_string_view sv) +{ + CREATE_GC_OBJECT_VALUE_ON_STACK( + ctx, + VALUE_STRING, + string, + new_copied_string(&ctx->gc, sv) + ) +} + enum apfl_result apfl_list_create(apfl_ctx ctx, size_t initial_cap) { diff --git a/src/eval.c b/src/eval.c index 8cab423..84013a5 100644 --- a/src/eval.c +++ b/src/eval.c @@ -90,23 +90,14 @@ evaluate(apfl_ctx ctx, size_t *i, struct instruction_list *ilist) assert(*i < ilist->len); switch (ilist->instructions[(*i)++].instruction) { case INSN_NIL: - return stack_push_or_fatal(ctx, (struct apfl_value) {.type = VALUE_NIL}); + return apfl_push_nil(ctx); case INSN_TRUE: - return stack_push_or_fatal(ctx, (struct apfl_value) { - .type = VALUE_BOOLEAN, - .boolean = true, - }); + return apfl_push_bool(ctx, true); case INSN_FALSE: - return stack_push_or_fatal(ctx, (struct apfl_value) { - .type = VALUE_BOOLEAN, - .boolean = true, - }); + return apfl_push_bool(ctx, false); case INSN_NUMBER: TRY(get_argument(i, ilist, &arg)); - return stack_push_or_fatal(ctx, (struct apfl_value) { - .type = VALUE_NUMBER, - .number = arg.number, - }); + return apfl_push_number(ctx, arg.number); case INSN_STRING: TRY(get_argument(i, ilist, &arg)); return stack_push_or_fatal(ctx, (struct apfl_value) {