Implement more string instructions

Implement all of the string instructions that I could get the compiler
to generate code for. Still ASCII-only.
This commit is contained in:
Nunuhara Cabbage
2019-10-14 14:18:09 -07:00
parent cc2a2c594a
commit 55f3991546
3 changed files with 179 additions and 18 deletions
+60 -2
View File
@@ -36,7 +36,7 @@ void free_string(struct string *str)
free(str);
}
struct string *string_dup(struct string *in)
struct string *string_dup(const struct string *in)
{
struct string *out = xmalloc(sizeof(struct string) + in->size + 1);
out->size = in->size;
@@ -45,7 +45,24 @@ struct string *string_dup(struct string *in)
return out;
}
struct string *string_append(struct string *a, struct string *b)
void string_append(struct string **_a, const struct string *b)
{
struct string *a = *_a;
size_t a_size = a->size;
if (a->literal) {
a = xmalloc(sizeof(struct string) + a->size + b->size + 1);
a->literal = false;
memcpy(a->text, (*_a)->text, a_size+1);
} else {
a = xrealloc(a, sizeof(struct string) + a->size + b->size + 1);
}
a->size = a_size + b->size;
memcpy(a->text + a_size, b->text, b->size + 1);
*_a = a;
}
struct string *string_concatenate(const struct string *a, const struct string *b)
{
struct string *s = xmalloc(sizeof(struct string) + a->size + b->size + 1);
s->size = a->size + b->size;
@@ -55,6 +72,47 @@ struct string *string_append(struct string *a, struct string *b)
return s;
}
struct string *string_copy(const struct string *s, int index, int len)
{
if (index < 0)
index = 0;
if (index >= s->size || len <= 0)
return make_string("", 0);
if (index + len > s->size)
len = s->size - index;
return make_string(s->text + index, len);
}
int string_find(const struct string *haystack, const struct string *needle)
{
char *r = strstr(haystack->text, needle->text);
if (!r)
return -1;
return r - haystack->text;
}
void string_push_back(struct string **s, int c)
{
*s = xrealloc(*s, sizeof(struct string) + (*s)->size + 2);
(*s)->text[(*s)->size++] = c & 0xFF;
(*s)->text[(*s)->size] = '\0';
}
void string_pop_back(struct string *s)
{
s->text[--s->size] = '\0';
}
void string_erase(struct string *s, int index)
{
if (index < 0)
index = 0;
if (index >= s->size)
return;
memcpy(s->text + index, s->text + index + 1, s->size - index - 1);
s->text[--s->size] = '\0';
}
struct string *integer_to_string(int n)
{
char buf[512];
+110 -13
View File
@@ -223,9 +223,9 @@ static void stack_push_string(struct string *s)
stack[stack_ptr++].i = heap_slot;
}
static struct string *stack_peek_string(void)
static struct string *stack_peek_string(int n)
{
return heap[stack_peek(0).i].s;
return heap[stack_peek(n).i].s;
}
/*
@@ -253,9 +253,21 @@ static void function_call(int32_t no)
// create local page
heap[page_slot].page = page_stack + new_pp;
for (int i = f->nr_args - 1; i >= 0; i--) {
page_stack[new_pp + i] = stack_pop();
int32_t slot;
switch (f->vars[i].data_type) {
case AIN_STRING:
slot = heap_alloc_slot(VM_STRING);
heap[slot].s = string_dup(heap[stack_pop().i].s);
page_stack[new_pp + i].i = slot;
break;
default:
page_stack[new_pp + i] = stack_pop();
break;
}
// TODO: when argument is heap-backed, and not a reference
// need to either copy or set some kind of COW flag
}
// heap-backed variables need a allocate a slot
// heap-backed variables need to allocate a slot
for (int i = f->nr_args; i < f->nr_vars; i++) {
int32_t slot;
switch (f->vars[i].data_type) {
@@ -280,7 +292,7 @@ static void function_return(void)
// unref slots for heap-backed variables
struct ain_function *f = &ain->functions[call_stack[call_stack_ptr].fno];
for (int i = f->nr_args; i < f->nr_vars; i++) {
for (int i = 0; i < f->nr_vars; i++) {
switch (f->vars[i].data_type) {
case AIN_STRING:
heap_unref(local_get(i));
@@ -304,7 +316,7 @@ static void system_call(int32_t code)
sys_exit(stack_pop().i);
break;
case 0x6: // system.Output(string szText)
sys_message("%s", stack_peek_string()->text);
sys_message("%s", stack_peek_string(0)->text);
// XXX: caller S_POPs
break;
case 0x14: // system.Peek()
@@ -321,6 +333,7 @@ static void execute_instruction(int16_t opcode)
{
int32_t index, a, b, c, v;
float f;
struct string *s;
union vm_value val;
union vm_value *ref;
const char *opcode_name = "UNKNOWN";
@@ -348,18 +361,19 @@ static void execute_instruction(int16_t opcode)
// Dereference a reference to a value.
stack_push(stack_pop_ref()[0]);
break;
case REFREF:
//case S_REFREF: // ???
// Dereference a reference to a reference.
ref = stack_pop_ref();
stack_push(ref[0].i);
stack_push(ref[1].i);
break;
case S_REF:
// Dereference a reference to a string
index = stack_pop_ref()->i;
heap_ref(index);
stack_push(index);
break;
case REFREF:
// Dereference a reference to a reference.
ref = stack_pop_ref();
stack_push(ref[0].i);
stack_push(ref[1].i);
break;
case DUP:
// A -> AA
stack_push(stack_peek(0).i);
@@ -662,13 +676,96 @@ static void execute_instruction(int16_t opcode)
heap[a].s = string_dup(heap[b].s);
heap_unref(b);
break;
case S_PLUSA2:
b = stack_pop().i;
a = stack_peek(0).i;
string_append(&heap[a].s, heap[b].s);
heap_unref(b);
break;
case S_ADD:
b = stack_pop().i;
a = stack_pop().i;
stack_push_string(string_append(heap[a].s, heap[b].s));
stack_push_string(string_concatenate(heap[a].s, heap[b].s));
heap_unref(a);
heap_unref(b);
break;
case S_LT:
v = strcmp(stack_peek_string(1)->text, stack_peek_string(0)->text) < 0;
heap_unref(stack_pop().i);
heap_unref(stack_pop().i);
stack_push(v);
break;
case S_GT:
v = strcmp(stack_peek_string(1)->text, stack_peek_string(0)->text) > 0;
heap_unref(stack_pop().i);
heap_unref(stack_pop().i);
stack_push(v);
break;
case S_LTE:
v = strcmp(stack_peek_string(1)->text, stack_peek_string(0)->text) <= 0;
heap_unref(stack_pop().i);
heap_unref(stack_pop().i);
stack_push(v);
break;
case S_GTE:
v = strcmp(stack_peek_string(1)->text, stack_peek_string(0)->text) >= 0;
heap_unref(stack_pop().i);
heap_unref(stack_pop().i);
stack_push(v);
break;
case S_NOTE:
v = !!strcmp(stack_peek_string(1)->text, stack_peek_string(0)->text);
heap_unref(stack_pop().i);
heap_unref(stack_pop().i);
stack_push(v);
break;
case S_EQUALE:
v = !strcmp(stack_peek_string(1)->text, stack_peek_string(0)->text);
heap_unref(stack_pop().i);
heap_unref(stack_pop().i);
stack_push(v);
break;
case S_LENGTH:
// TODO: handle sjis
case S_LENGTHBYTE:
a = stack_pop_ref()->i;
stack_push((int32_t)heap[a].s->size);
break;
case S_EMPTY:
v = !stack_peek_string(0)->size;
heap_unref(stack_pop().i);
stack_push(v);
break;
case S_FIND:
v = string_find(stack_peek_string(1), stack_peek_string(0));
heap_unref(stack_pop().i);
stack_push(v);
break;
case S_GETPART:
b = stack_pop().i; // length
a = stack_pop().i; // index
s = string_copy(stack_peek_string(0), a, b);
heap_unref(stack_pop().i);
stack_push_string(s);
break;
//case S_PUSHBACK: // ???
case S_PUSHBACK2:
v = stack_pop().i;
string_push_back(&heap[stack_peek(0).i].s, v);
heap_unref(stack_pop().i);
break;
//case S_POPBACK: // ???
case S_POPBACK2:
string_pop_back(stack_peek_string(0));
heap_unref(stack_pop().i);
break;
//case S_ERASE: // ???
case S_ERASE2:
b = stack_pop().i; // ???
a = stack_pop().i; // index
string_erase(stack_peek_string(0), a);
heap_unref(stack_pop().i);
break;
case I_STRING:
stack_push_string(integer_to_string(stack_pop().i));
break;
+9 -3
View File
@@ -21,15 +21,21 @@
#include <stddef.h>
struct string {
unsigned int size;
int size;
bool literal;
char text[];
};
struct string *make_string(const char *str, unsigned int len);
void free_string(struct string *str);
struct string *string_dup(struct string *in);
struct string *string_append(struct string *a, struct string *b);
struct string *string_dup(const struct string *in);
void string_append(struct string **a, const struct string *b);
struct string *string_concatenate(const struct string *a, const struct string *b);
struct string *string_copy(const struct string *s, int index, int len);
int string_find(const struct string *haystack, const struct string *needle);
void string_push_back(struct string **s, int c);
void string_pop_back(struct string *s);
void string_erase(struct string *s, int index);
struct string *integer_to_string(int n);
struct string *float_to_string(float f, int precision);