strings now support "+", "=" and "!=" operators

git-svn-id: https://svn.code.sf.net/p/acme-crossass/code-0/trunk@192 4df02467-bbd4-4a76-a152-e7ce94205b78
This commit is contained in:
marcobaye 2020-05-26 12:55:14 +00:00
parent bc0cd5b8ea
commit 78e7c32507

View File

@ -42,14 +42,6 @@ static const char exception_div_by_zero[] = "Division by zero.";
static const char exception_no_value[] = "No value given."; static const char exception_no_value[] = "No value given.";
static const char exception_paren_open[] = "Too many '('."; static const char exception_paren_open[] = "Too many '('.";
static const char exception_not_number[] = "Expression did not return a number."; static const char exception_not_number[] = "Expression did not return a number.";
#define s_or (s_eor + 1) // Yes, I know I'm sick
#define s_xor (s_scrxor + 3) // Yes, I know I'm sick
static const char s_arcsin[] = "arcsin";
#define s_sin (s_arcsin + 3) // Yes, I know I'm sick
static const char s_arccos[] = "arccos";
#define s_cos (s_arccos + 3) // Yes, I know I'm sick
static const char s_arctan[] = "arctan";
#define s_tan (s_arctan + 3) // Yes, I know I'm sick
enum op_group { enum op_group {
OPGROUP_SPECIAL, // start/end of expression, and parentheses OPGROUP_SPECIAL, // start/end of expression, and parentheses
@ -196,9 +188,9 @@ static struct ronode op_list[] = {
PREDEFNODE("div", &ops_intdiv), PREDEFNODE("div", &ops_intdiv),
PREDEFNODE("mod", &ops_modulo), PREDEFNODE("mod", &ops_modulo),
PREDEFNODE(s_and, &ops_and), PREDEFNODE(s_and, &ops_and),
PREDEFNODE(s_or, &ops_or), PREDEFNODE("or", &ops_or),
PREDEFNODE(s_eor, &ops_eor), // FIXME - remove PREDEFNODE(s_eor, &ops_eor), // FIXME - remove
PREDEFLAST(s_xor, &ops_xor), PREDEFLAST("xor", &ops_xor),
// ^^^^ this marks the last element // ^^^^ this marks the last element
}; };
static struct ronode *function_tree = NULL; // tree to hold functions static struct ronode *function_tree = NULL; // tree to hold functions
@ -208,12 +200,12 @@ static struct ronode function_list[] = {
PREDEFNODE("int", &ops_int), PREDEFNODE("int", &ops_int),
PREDEFNODE("float", &ops_float), PREDEFNODE("float", &ops_float),
PREDEFNODE("len", &ops_len), PREDEFNODE("len", &ops_len),
PREDEFNODE(s_arcsin, &ops_arcsin), PREDEFNODE("arcsin", &ops_arcsin),
PREDEFNODE(s_arccos, &ops_arccos), PREDEFNODE("arccos", &ops_arccos),
PREDEFNODE(s_arctan, &ops_arctan), PREDEFNODE("arctan", &ops_arctan),
PREDEFNODE(s_sin, &ops_sin), PREDEFNODE("sin", &ops_sin),
PREDEFNODE(s_cos, &ops_cos), PREDEFNODE("cos", &ops_cos),
PREDEFLAST(s_tan, &ops_tan), PREDEFLAST("tan", &ops_tan),
// ^^^^ this marks the last element // ^^^^ this marks the last element
}; };
@ -387,11 +379,10 @@ static void parse_program_counter(void) // Now GotByte = "*"
// make new string object // make new string object
static void string_init_string(struct object *self, const char *data, int len) static void string_prepare_string(struct object *self, int len)
{ {
self->type = &type_string; self->type = &type_string;
self->u.string = safe_malloc(sizeof(*(self->u.string)) + len); self->u.string = safe_malloc(sizeof(*(self->u.string)) + len);
memcpy(self->u.string->payload, data, len);
self->u.string->payload[len] = 0; // terminate, to facilitate string_print() self->u.string->payload[len] = 0; // terminate, to facilitate string_print()
self->u.string->length = len; // length does not include the added terminator self->u.string->length = len; // length does not include the added terminator
self->u.string->refs = 1; self->u.string->refs = 1;
@ -417,7 +408,9 @@ static void parse_quoted(char closing_quote)
// with backslash escaping, ' is for characters and " is for strings: // with backslash escaping, ' is for characters and " is for strings:
if ((closing_quote == '"') && (config.backslash_escaping)) { if ((closing_quote == '"') && (config.backslash_escaping)) {
// string ////////////////////////////////// // string //////////////////////////////////
string_init_string(&arg_stack[arg_sp++], GLOBALDYNABUF_CURRENT, GlobalDynaBuf->size); // create string object and put on arg stack string_prepare_string(&arg_stack[arg_sp], GlobalDynaBuf->size); // create string object and put on arg stack
memcpy(arg_stack[arg_sp].u.string->payload, GLOBALDYNABUF_CURRENT, GlobalDynaBuf->size); // copy payload
++arg_sp;
} else { } else {
// single character //////////////////////// // single character ////////////////////////
// too short? // too short?
@ -1050,6 +1043,15 @@ static void unsupported_operation(struct object *optional, struct op *op, struct
// int/float // int/float
// int:
// create byte-sized int object (for comparison results, converted characters, ...)
static void int_create_byte(struct object *self, intval_t byte)
{
self->type = &type_int;
self->u.number.flags = NUMBER_IS_DEFINED | NUMBER_FITS_BYTE;
self->u.number.val.intval = byte;
self->u.number.addr_refs = 0;
}
// int: // int:
// convert to float // convert to float
@ -1642,24 +1644,65 @@ static void string_handle_dyadic_operator(struct object *self, struct op *op, st
int length; int length;
int index; int index;
intval_t character; intval_t character;
struct string *arthur,
*ford;
length = self->u.string->length; length = self->u.string->length;
switch (op->id) { switch (op->id) {
case OPID_ATINDEX: case OPID_ATINDEX:
if (get_valid_index(&index, length, self, op, other)) if (get_valid_index(&index, length, self, op, other))
return; // error return; // error has already been reported
character = (intval_t) (unsigned char) encoding_encode_char(self->u.string->payload[index]); character = (intval_t) (unsigned char) encoding_encode_char(self->u.string->payload[index]);
self->u.string->refs--; // FIXME - call a function for this... self->u.string->refs--; // FIXME - call a function for this...
self->type = &type_int; int_create_byte(self, character);
self->u.number.flags = NUMBER_IS_DEFINED | NUMBER_FITS_BYTE; return; // ok
self->u.number.val.intval = character;
self->u.number.addr_refs = 0; case OPID_ADD:
break; if (other->type != &type_string)
//case OPID_ADD: TODO? break; // complain
arthur = self->u.string;
ford = other->u.string;
string_prepare_string(self, arthur->length + ford->length); // create string object and put on arg stack
memcpy(self->u.string->payload, arthur->payload, arthur->length);
memcpy(self->u.string->payload + arthur->length, ford->payload, ford->length);
arthur->refs--; // FIXME - call a function for this...
ford->refs--; // FIXME - call a function for this...
return;
case OPID_EQUALS:
if (other->type != &type_string)
break; // complain
arthur = self->u.string;
ford = other->u.string;
if (arthur->length != ford->length) {
int_create_byte(self, FALSE);
} else {
int_create_byte(self, !memcmp(arthur->payload, ford->payload, arthur->length));
}
arthur->refs--; // FIXME - call a function for this...
ford->refs--; // FIXME - call a function for this...
return;
case OPID_NOTEQUAL:
if (other->type != &type_string)
break; // complain
arthur = self->u.string;
ford = other->u.string;
if (arthur->length != ford->length) {
int_create_byte(self, TRUE);
} else {
int_create_byte(self, !!memcmp(arthur->payload, ford->payload, arthur->length));
}
arthur->refs--; // FIXME - call a function for this...
ford->refs--; // FIXME - call a function for this...
return;
//case ...: // maybe comparisons?
default: default:
unsupported_operation(self, op, other); break; // complain
} }
unsupported_operation(self, op, other);
} }
// int/float: // int/float: