Implement tostring and use it in print

This commit is contained in:
Laria 2022-10-30 22:44:34 +01:00
parent 4ecfeabded
commit 363334967a
5 changed files with 62 additions and 1 deletions

View file

@ -655,6 +655,8 @@ enum apfl_value_type apfl_get_type(apfl_ctx, apfl_stackidx);
// Drop a value from the stack
void apfl_drop(apfl_ctx, apfl_stackidx);
// Move a value to the top of the stack
void apfl_move_to_top_of_stack(apfl_ctx, apfl_stackidx);
// Push a nil onto the stack
void apfl_push_nil(apfl_ctx);
// Push a boolean onto the stack
@ -684,6 +686,8 @@ size_t apfl_len(apfl_ctx, apfl_stackidx);
// Get a string view into a APFL_VALUE_STRING value. The value stays on the stack.
// The returned string view is only guaranteed to be valid, as long as the value is on the stack.
struct apfl_string_view apfl_get_string(apfl_ctx, apfl_stackidx);
// Pops a value off the stack and turns it into a string.
void apfl_tostring(apfl_ctx, apfl_stackidx);
// Pops a value from the stack and returns whether is was truthy. All values except false and nil are truthy.
bool apfl_is_truthy(apfl_ctx, apfl_stackidx);
// Pops a number from the stack and returns it.

View file

@ -419,6 +419,14 @@ current_stack_move_to_top(apfl_ctx ctx, apfl_stackidx index)
return true;
}
void
apfl_move_to_top_of_stack(apfl_ctx ctx, apfl_stackidx index)
{
if (!current_stack_move_to_top(ctx, index)) {
apfl_raise_invalid_stackidx(ctx);
}
}
void
apfl_stack_clear(apfl_ctx ctx)
{
@ -1102,6 +1110,33 @@ apfl_get_type(apfl_ctx ctx, apfl_stackidx index)
return apfl_value_type_to_abstract_type(value.type);
}
void
apfl_tostring(apfl_ctx ctx, apfl_stackidx index)
{
apfl_move_to_top_of_stack(ctx, index);
struct apfl_value value = apfl_stack_must_get(ctx, -1);
if (apfl_value_type_to_abstract_type(value.type) == APFL_VALUE_STRING) {
return;
}
struct apfl_string_builder sb = apfl_string_builder_init(ctx->gc.allocator);
if (!apfl_value_format(value, apfl_format_string_writer(&sb))) {
apfl_string_builder_deinit(&sb);
apfl_stack_drop(ctx, -1);
apfl_raise_alloc_error(ctx);
}
struct apfl_string str = apfl_string_builder_move_string(&sb);
apfl_string_builder_deinit(&sb);
if (!apfl_move_string_onto_stack(ctx, str)) {
apfl_string_deinit(ctx->gc.allocator, &str);
apfl_stack_drop(ctx, -1);
apfl_raise_alloc_error(ctx);
}
apfl_stack_drop(ctx, -2); // Drop original value
}
bool
apfl_is_truthy(apfl_ctx ctx, apfl_stackidx index)
{

View file

@ -155,6 +155,7 @@ print(apfl_ctx ctx)
}
apfl_get_list_member_by_index(ctx, 0, i);
apfl_tostring(ctx, -1);
struct apfl_string_view sv = apfl_get_string(ctx, -1);
TRY_FORMAT(ctx, apfl_format_put_string(w, sv));
apfl_drop(ctx, -1);
@ -204,6 +205,19 @@ disasm(apfl_ctx ctx)
}
}
static void
tostring(apfl_ctx ctx)
{
size_t len = apfl_len(ctx, 0);
if (len != 1) {
apfl_raise_const_error(ctx, APFL_RESULT_ERR, "tostring needs exactly 1 argument");
}
apfl_get_list_member_by_index(ctx, 0, 0);
apfl_drop(ctx, 0);
apfl_tostring(ctx, -1);
}
static const struct global_def globals[] = {
{"if", impl_if},
{"==", impl_eq},
@ -214,6 +228,7 @@ static const struct global_def globals[] = {
{"print", print},
{"dump", dump},
{"disasm", disasm},
{"tostring", tostring},
{NULL, NULL},
};

View file

@ -274,10 +274,16 @@ apfl_value_move(struct apfl_value *src)
return out;
}
bool
apfl_value_format(struct apfl_value value, struct apfl_format_writer w)
{
return format(0, w, value, false);
}
bool
apfl_value_print(struct apfl_value value, struct apfl_format_writer w)
{
TRY(format(0, w, value, false));
TRY(apfl_value_format(value, w));
TRY(apfl_format_put_string(w, "\n"));
return true;
}

View file

@ -82,6 +82,7 @@ enum apfl_value_type apfl_value_type_to_abstract_type(enum value_type);
bool apfl_value_eq(const struct apfl_value, const struct apfl_value);
struct apfl_value apfl_value_move(struct apfl_value *src);
bool apfl_value_format(struct apfl_value, struct apfl_format_writer);
bool apfl_value_print(struct apfl_value, struct apfl_format_writer);
apfl_hash apfl_value_hash(const struct apfl_value);