Merge pull request #135 from kichikuou/s_mod

Fix S_MOD for bool and long int
This commit is contained in:
Nunuhara Cabbage
2023-09-01 20:38:21 -07:00
committed by GitHub
6 changed files with 39 additions and 20 deletions
+10 -1
View File
@@ -114,7 +114,16 @@ bool library_function_exists(int libno, int fno);
void init_libraries(void);
void exit_libraries(void);
struct string *string_format(struct string *fmt, union vm_value arg, enum ain_data_type type);
// NOTE: This can probably be merged with ain_data_type, since the values are
// disjoint.
enum string_format_type {
STRFMT_INT = 2,
STRFMT_FLOAT = 3,
STRFMT_STRING = 4,
STRFMT_BOOL = 48,
STRFMT_LONG_INT = 56,
};
struct string *string_format(struct string *fmt, union vm_value arg, enum string_format_type type);
void vm_stack_trace(void);
_Noreturn void _vm_error(const char *fmt, ...);
+20 -13
View File
@@ -37,10 +37,17 @@ struct fmt_spec {
enum fmt_type type;
int precision;
int padding;
bool zero_pad;
bool zero_pad;
bool zenkaku;
};
static inline bool is_integer_type(enum string_format_type t)
{
return t == STRFMT_INT
|| t == STRFMT_BOOL
|| t == STRFMT_LONG_INT;
}
static int read_number(const char **_fmt)
{
int n = 0;
@@ -54,7 +61,7 @@ static int read_number(const char **_fmt)
return n;
}
static bool parse_fmt_spec(const char **_fmt, struct fmt_spec *spec, enum ain_data_type target)
static bool parse_fmt_spec(const char **_fmt, struct fmt_spec *spec, enum string_format_type target)
{
bool r = false;
const char *fmt = (*_fmt) + 1;
@@ -64,33 +71,33 @@ static bool parse_fmt_spec(const char **_fmt, struct fmt_spec *spec, enum ain_da
switch (*fmt) {
case 'd':
spec->type = FMT_INT;
r = target == AIN_INT;
r = is_integer_type(target);
goto end;
case 'D':
spec->type = FMT_INT;
spec->zenkaku = true;
r = target == AIN_INT;
r = is_integer_type(target);
goto end;
case 'f':
spec->type = FMT_FLOAT;
r = target == AIN_FLOAT;
r = target == STRFMT_FLOAT;
goto end;
case 'F':
spec->type = FMT_FLOAT;
spec->zenkaku = true;
r = target == AIN_FLOAT;
r = target == STRFMT_FLOAT;
goto end;
case 's':
spec->type = FMT_STRING;
r = target == AIN_STRING;
r = target == STRFMT_STRING;
goto end;
case 'c':
spec->type = FMT_CHAR;
r = target == AIN_INT;
r = is_integer_type(target);
goto end;
case 'b':
spec->type = FMT_BOOL;
r = target == AIN_INT;
r = is_integer_type(target);
goto end;
case '0':
spec->zero_pad = true;
@@ -154,9 +161,8 @@ static void append_fmt(struct string **s, struct fmt_spec *spec, union vm_value
}
}
struct string *string_format(struct string *fmt, union vm_value arg, enum ain_data_type type)
struct string *string_format(struct string *fmt, union vm_value arg, enum string_format_type type)
{
struct string *out = string_ref(&EMPTY_STRING);
for (const char *s = fmt->text; *s; s++) {
if (*s != '%')
continue;
@@ -164,11 +170,12 @@ struct string *string_format(struct string *fmt, union vm_value arg, enum ain_da
size_t size = s - fmt->text;
struct fmt_spec spec;
if (parse_fmt_spec(&s, &spec, type)) {
struct string *out = string_ref(&EMPTY_STRING);
string_append_cstr(&out, fmt->text, size);
append_fmt(&out, &spec, arg);
string_append_cstr(&out, s, strlen(s));
break;
return out;
}
}
return out;
return string_ref(fmt);
}
+2 -2
View File
@@ -413,7 +413,7 @@ static void DrawDungeon14_SetRasterScroll(int surface, int type)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->renderer)
return true;
return;
return dungeon_renderer_set_raster_scroll(ctx->renderer, type);
}
@@ -421,7 +421,7 @@ static void DrawDungeon14_SetRasterAmp(int surface, float amp)
{
struct dungeon_context *ctx = dungeon_get_context(surface);
if (!ctx || !ctx->renderer)
return true;
return;
return dungeon_renderer_set_raster_amp(ctx->renderer, amp);
}
+1 -1
View File
@@ -1008,7 +1008,7 @@ bool PE_SetLoopCG_by_index(int parts_no, int cg_no, int nr_frames, int frame_tim
static struct cg *load_loop_cg_by_name(int no, void *data)
{
int unused_no;
struct string *cg_name = string_format((struct string*)data, (union vm_value){.i=no}, AIN_INT);
struct string *cg_name = string_format((struct string*)data, (union vm_value){.i=no}, STRFMT_INT);
struct cg *cg = asset_cg_load_by_name(cg_name->text, &unused_no);
free_string(cg_name);
return cg;
+1 -1
View File
@@ -1532,7 +1532,7 @@ static enum opcode execute_instruction(enum opcode opcode)
union vm_value val = stack_pop();
int fmt = stack_pop().i;
int dst = heap_alloc_slot(VM_STRING);
heap[dst].s = string_format(heap[fmt].s, val, type + 8);
heap[dst].s = string_format(heap[fmt].s, val, type);
heap_unref(fmt);
stack_push(dst);
break;
+5 -2
View File
@@ -5,6 +5,7 @@ void test_strings(void)
int i;
float f;
string s;
bool b;
test_bool("\"a\" == \"a\"", "a" == "a", true);
test_bool("\"a\" != \"b\"", "a" == "b", false);
test_bool("\"a\" < \"b\"", "a" < "b", true);
@@ -86,8 +87,10 @@ void test_strings(void)
// char
test_string("abc%cdef % 'あ'", "abc%cdef" % 'あ', "abcあdef");
// bool
test_string("abc%bdef % 1", "abc%bdef" % 1, "abctruedef");
test_string("abc%bdef % 0", "abc%bdef" % 0, "abcfalsedef");
test_string("abc%bdef % 1", "abc%bdef" % (b = 1), "abctruedef");
test_string("abc%bdef % 0", "abc%bdef" % (b = 0), "abcfalsedef");
// type mismatch
test_string("%s % 42", "%s" % 42, "%s");
// I_STRING
test_bool("(42).String()", (i = 42, i.String() == "42"), true);