diff --git a/instructions.c b/instructions.c index df37a35..60e0529 100644 --- a/instructions.c +++ b/instructions.c @@ -123,8 +123,8 @@ const struct instruction instructions[NR_OPCODES] = { OP(SF_CREATEPIXEL, 0), // TODO OP(SF_CREATEALPHA, 0), // TODO - OP(SR_POP, 0), // TODO - OP(SR_ASSIGN, 0), // TODO + OP(SR_POP, 0), + OP(SR_ASSIGN, 0), OP(SR_REF, 1, INSTR_INT), OP(SR_REFREF, 0), // TODO OP(A_ALLOC, 0), @@ -133,8 +133,8 @@ const struct instruction instructions[NR_OPCODES] = { OP(A_NUMOF, 0), OP(A_COPY, 0), OP(A_FILL, 0), - OP(C_REF, 0), // TODO - OP(C_ASSIGN, 0), // TODO + OP(C_REF, 0), + OP(C_ASSIGN, 0), OP(MSG, 0), // TODO OP(CALLHLL, 0), // TODO OP(PUSHSTRUCTPAGE, 0), diff --git a/string.c b/string.c index f4af5a4..ca5b949 100644 --- a/string.c +++ b/string.c @@ -197,3 +197,49 @@ int string_find(const struct string *haystack, const struct string *needle) } return -1; } + +int string_get_char(const struct string *str, int i) +{ + if ((i = sjis_index(str->text, i)) < 0) + ERROR("String index out of bounds"); + + if (SJIS_2BYTE(str->text[i])) + return (uint8_t)str->text[i] | ((uint8_t)str->text[i+1] << 8); + return str->text[i]; +} + +void string_set_char(struct string **_str, int i, unsigned int c) +{ + struct string *str = *_str = cow_check(*_str); + int bytes_src, bytes_dst; + + if ((i = sjis_index(str->text, i)) < 0) + ERROR("String index out of bounds"); + + bytes_src = SJIS_2BYTE(c) ? 2 : 1; + bytes_dst = SJIS_2BYTE(str->text[i]) ? 2 : 1; + + if (bytes_src == 1 && bytes_dst == 1) { + str->text[i] = c; + } else if (bytes_src == 2 && bytes_dst == 2) { + str->text[i] = c & 0xFF; + str->text[i+1] = (c >> 8) & 0xFF; + } else if (bytes_src == 1 && bytes_dst == 2) { + // shrink 1 byte + str->text[i] = c; + for (int j = i+1; j < str->size; j++) { + str->text[j] = str->text[j+1]; + } + str->size--; + } else if (bytes_src == 2 && bytes_dst == 1) { + // grow 1 byte + str = xrealloc(str, sizeof(struct string) + str->size + 1); + str->size++; + *_str = str; + for (int j = str->size; j > i; j--) { + str->text[j] = str->text[j-1]; + } + str->text[i] = c & 0xFF; + str->text[i+1] = (c >> 8) & 0xFF; + } +} diff --git a/test/Source/strings.jaf b/test/Source/strings.jaf index 5906875..e7b2419 100755 --- a/test/Source/strings.jaf +++ b/test/Source/strings.jaf @@ -67,4 +67,11 @@ void test_strings(void) // FTOS test_bool("(4.2).String()", (f = 4.2, f.String() == "4.200000"), true); test_bool("(4.222).String(2)", (f = 4.222, f.String(2) == "4.22"), true); + // C_REF + test_equal("abあいう[3]", (s = "abあいう", s[3]), 'い'); + // C_ASSIGN + test_string("abあいう[1] = 'c'", (s = "abあいう", s[1] = 'c', s), "acあいう"); + test_string("abあいう[3] = 'あ'", (s = "abあいう", s[3] = 'あ', s), "abああう"); + test_string("abあいう[1] = 'あ'", (s = "abあいう", s[1] = 'あ', s), "aああいう"); + test_string("abあいう[3] = 'c'", (s = "abあいう", s[3] = 'c', s), "abあcう"); } diff --git a/test/Source/structs.jaf b/test/Source/structs.jaf index 841f485..f11475f 100755 --- a/test/Source/structs.jaf +++ b/test/Source/structs.jaf @@ -50,4 +50,10 @@ void test_structs(void) test_equal("nested constructor", c.inner.a, 99); test_equal("nested constructor precedence", c.b, 100); test_equal("c.set_a(22)", (c.set_a(22), c.a), 22); + + my_struct a; + my_struct b; + a.a = 42; + b = a; + test_equal("struct assign", b.a, 42); } diff --git a/utfsjis.c b/utfsjis.c index 50f02e3..93e73d0 100644 --- a/utfsjis.c +++ b/utfsjis.c @@ -29,7 +29,7 @@ #include "utfsjis.h" #include "s2utbl.h" -// Convert a byte-index to a character-index for a given SJIS string. +// Convert a character-index to a byte-index for a given SJIS string. int sjis_index(const char *_src, int index) { const uint8_t *src = (uint8_t*)_src; diff --git a/vm.c b/vm.c index f072d8e..915a643 100644 --- a/vm.c +++ b/vm.c @@ -801,12 +801,39 @@ static void execute_instruction(int16_t opcode) v = stack_pop().i; // precision stack_push_string(float_to_string(stack_pop().f, v)); break; + // --- Characters --- + case C_REF: + v = stack_pop().i; + slot = stack_pop().i; + stack_push(string_get_char(heap[slot].s, v)); + break; + case C_ASSIGN: + v = stack_pop().i; + i = stack_pop().i; + slot = stack_pop().i; + string_set_char(&heap[slot].s, i, v); + stack_push(v); + break; // // --- Structs/Classes --- // case SR_REF: stack_push(vm_copy_page(heap[stack_pop_var()->i].page)); break; + case SR_POP: + heap_unref(stack_pop().i); + break; + case SR_ASSIGN: + stack_pop(); // struct type + b = stack_pop().i; + a = stack_pop().i; + if (a == -1) + EXECUTION_ERROR("Assignment to null-pointer"); + if (heap[a].page) + delete_page(heap[a].page); + heap[a].page = copy_page(heap[b].page); + stack_push(b); + break; // // -- Arrays -- // diff --git a/vm_string.h b/vm_string.h index f3b39fb..6a40d82 100644 --- a/vm_string.h +++ b/vm_string.h @@ -49,4 +49,8 @@ void string_erase(struct string **s, int index); // queries int string_find(const struct string *haystack, const struct string *needle); +// characters +int string_get_char(const struct string *str, int i); +void string_set_char(struct string **_s, int i, unsigned int c); + #endif