Commit 59f9fa25 authored by Laszlo Domoszlai's avatar Laszlo Domoszlai
Browse files

"case" works with string constants

parent 0bd8c17d
......@@ -139,6 +139,7 @@ void set_create_thunk_fun(Code* code)
break;
case CT_SELECT_ADT:
case CT_SELECT_LIT:
case CT_SELECT_STR:
case CT_IF:
case CT_LET:
code->create_thunk = NULL;
......@@ -587,8 +588,9 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
if(caseEntry->lit != NULL)
{
assert(caseEntry->lit->thunk.desc == (Desc*) __INT__ ||
caseEntry->lit->thunk.desc == (Desc*) __BOOL__ );
caseEntry->lit->thunk.desc == (Desc*) __BOOL__ ||
caseEntry->lit->thunk.desc == (Desc*) __CHAR__);
if(caseEntry->lit->thunk._int != lit->_int) continue;
}
......@@ -610,6 +612,67 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
abort("no match");
}
case CT_SELECT_STR:
{
SelectEntry* select = (SelectEntry*) expr;
push_a(NULL);
exec(select->expr, frame_ptr, stack_top_a);
Thunk* str = pop_a();
int length;
char* chars;
if(str->desc == (Desc*) __STRING_PTR__)
{
chars = str->_string_ptr->chars;
length = str->_string_ptr->length;
}
else
{
chars = str->_array._chars;
length = str->_array.length;
}
bool handled = false;
for (int i = 0; i < expr->nr_cases; i++) {
SelectLitCaseEntry* caseEntry = &((SelectEntry*) expr)->cases[i];
// NULL means "default", we accept it anyway
if(caseEntry->lit != NULL)
{
assert(caseEntry->lit->thunk.desc == (Desc*) __STRING_PTR__);
int eq = length == caseEntry->lit->thunk._string_ptr->length;
int i = 0;
while(i<length && eq)
{
eq = chars[i] == caseEntry->lit->thunk._string_ptr->chars[i];
i++;
}
if(!eq) continue;
}
// must be SC_DEFAULT now
handled = true;
expr = caseEntry->body;
break;
}
if(handled) continue;
if(((SelectEntry*) expr)->fallback != NULL)
{
stack_top_a -= ((SelectEntry*) expr)->fallback_nrargs;
expr = ((SelectEntry*) expr)->fallback;
continue;
}
abort("no match");
}
case CT_SELECT_ADT:
{
SelectEntry* select = (SelectEntry*) expr;
......
......@@ -18,6 +18,7 @@ enum CodeType {
CT_APP_FUN_TR, // tail recursive
CT_SELECT_ADT,
CT_SELECT_LIT,
CT_SELECT_STR,
CT_IF,
CT_LET,
CT_THUNK // constant, always fits the B stack
......
......@@ -251,7 +251,7 @@ ThunkEntry* parseLit(char **ptr) {
case 'C': // Char
{
entry->thunk.desc = (Desc*) __CHAR__;
entry->thunk._char = *(*ptr)++;
entry->thunk._int = *(*ptr)++;
break;
}
......@@ -266,7 +266,7 @@ ThunkEntry* parseLit(char **ptr) {
case '1':
{
entry->thunk.desc = (Desc*) __BOOL__;
entry->thunk._bool = type == '1';
entry->thunk._int = type == '1';
break;
}
......@@ -583,6 +583,13 @@ SelectEntry* parseSelect(char **ptr, Code* fallback, int fallback_nrargs) {
for (int i = 0; i < nrCases; i++) {
(*ptr)++; // skip type
entry->cases[i].lit = parseLit(ptr);
// String literal is the third case for efficiency reasons
if(i == 0 && entry->cases[i].lit->thunk.desc == (Desc*) __STRING_PTR__)
{
entry->base.type = CT_SELECT_STR;
}
entry->cases[i].body = (Code*) parseSelectBody(ptr, child_fallback, child_fallback_base_nrargs);
}
}
......
......@@ -34,67 +34,67 @@ void __divI(int dst_idx) {
void __gtI(int dst_idx) {
Thunk* target = get_dst(dst_idx);
target->desc = (Desc*) __BOOL__;
target->_bool = readI(arg(2)) > readI(arg(1));
target->_int = readI(arg(2)) > readI(arg(1));
}
void __geI(int dst_idx) {
Thunk* target = get_dst(dst_idx);
target->desc = (Desc*) __BOOL__;
target->_bool = readI(arg(2)) >= readI(arg(1));
target->_int = readI(arg(2)) >= readI(arg(1));
}
void __ltI(int dst_idx) {
Thunk* target = get_dst(dst_idx);
target->desc = (Desc*) __BOOL__;
target->_bool = readI(arg(2)) < readI(arg(1));
target->_int = readI(arg(2)) < readI(arg(1));
}
void __geC(int dst_idx) {
Thunk* target = get_dst(dst_idx);
target->desc = (Desc*) __BOOL__;
target->_bool = readC(arg(2)) >= readC(arg(1));
target->_int = readC(arg(2)) >= readC(arg(1));
}
void __eqI(int dst_idx) {
Thunk* target = get_dst(dst_idx);
target->desc = (Desc*) __BOOL__;
target->_bool = readI(arg(2)) == readI(arg(1));
target->_int = readI(arg(2)) == readI(arg(1));
}
void __neqI(int dst_idx) {
Thunk* target = get_dst(dst_idx);
target->desc = (Desc*) __BOOL__;
target->_bool = readI(arg(2)) != readI(arg(1));
target->_int = readI(arg(2)) != readI(arg(1));
}
void __eqB(int dst_idx) {
Thunk* target = get_dst(dst_idx);
target->desc = (Desc*) __BOOL__;
target->_bool = readB(arg(2)) == readB(arg(1));
target->_int = readB(arg(2)) == readB(arg(1));
}
void __eqC(int dst_idx) {
Thunk* target = get_dst(dst_idx);
target->desc = (Desc*) __CHAR__;
target->_bool = readC(arg(2)) == readC(arg(1));
target->_int = readC(arg(2)) == readC(arg(1));
}
void __not(int dst_idx) {
Thunk* target = get_dst(dst_idx);
target->desc = (Desc*) __BOOL__;
target->_bool = !readB(arg(1));
target->_int = !readB(arg(1));
}
void __and(int dst_idx) {
Thunk* target = get_dst(dst_idx);
target->desc = (Desc*) __BOOL__;
target->_bool = readB(arg(2)) && readB(arg(1));
target->_int = readB(arg(2)) && readB(arg(1));
}
void __or(int dst_idx) {
Thunk* target = get_dst(dst_idx);
target->desc = (Desc*) __BOOL__;
target->_bool = readB(arg(2)) || readB(arg(1));
target->_int = readB(arg(2)) || readB(arg(1));
}
void __mod(int dst_idx) {
......@@ -147,7 +147,7 @@ void __string_select(int dst_idx)
}
target->desc = (Desc*) __CHAR__;
target->_char = chars[pos->_int];
target->_int = (char) chars[pos->_int];
}
Thunk* string_create(Thunk* target, int len)
......@@ -191,7 +191,7 @@ void __string_create2(int dst_idx)
target = string_create(target, len->_int);
for(int i=0; i<len->_int; i++)
{
target->_array._chars[i] = ch->_char;
target->_array._chars[i] = (char) ch->_int;
}
set_return(dst_idx, target);
......@@ -221,7 +221,7 @@ void __string_update(int dst_idx)
target = string_create(target, length);
memcpy(target->_array._chars, chars, length);
target->_array._chars[idx->_int] = ch->_char;
target->_array._chars[idx->_int] = (char) ch->_int;
set_return(dst_idx, target);
}
......@@ -330,18 +330,15 @@ void __eqS(int dst_idx)
int eq = length1 == length2;
if(eq)
int i = 0;
while(i<length1 && eq)
{
int i = 0;
while(i<length1 && eq)
{
eq = chars1[i] == chars2[i];
i++;
}
eq = chars1[i] == chars2[i];
i++;
}
target->desc = (Desc*) __BOOL__;
target->_bool = eq;
target->_int = eq;
}
void add_prim(int arity, int boxingMap, char* name, void (*exec)(int)) {
......
......@@ -30,7 +30,7 @@ int readB(Thunk* thunk) {
exit(-1);
}
return thunk->_bool;
return thunk->_int;
}
char readC(Thunk* thunk) {
......@@ -42,7 +42,7 @@ char readC(Thunk* thunk) {
exit(-1);
}
return thunk->_char;
return (char) thunk->_int;
}
#endif
......@@ -64,13 +64,13 @@ void print(bool force) {
if ((FunEntry*) thunk->desc == __INT__) {
printf("%d", thunk->_int);
} else if ((FunEntry*) thunk->desc == __BOOL__) {
if (thunk->_bool) {
if (thunk->_int) {
printf("True");
} else {
printf("False");
}
} else if ((FunEntry*) thunk->desc == __CHAR__) {
printf("%c", thunk->_char);
printf("%c", (char) thunk->_int);
} else if ((FunEntry*) thunk->desc == __STRING_PTR__) {
for(int i=0; i< thunk->_string_ptr->length; i++)
{
......
......@@ -37,10 +37,8 @@ typedef struct __attribute__((packed)) Thunk {
union {
Thunk* _forward_ptr;
int _int;
double _real; // TODO: move "real" out of here, too long (at least on 32 bits)
char _char;
int _bool;
int _int; // also char and bool
double _real; // TODO: move "real" out of here, too long (at least on 32 bits)
struct CleanString* _string_ptr; // For CT_THUNK
struct Array _array;
Thunk* _args[];
......@@ -60,8 +58,8 @@ char readC(Thunk* thunk);
#else
#define readI(thunk) thunk->_int
#define readB(thunk) thunk->_bool
#define readC(thunk) thunk->_char
#define readB(thunk) thunk->_int
#define readC(thunk) thunk->_int
#endif
......
[B]
\ No newline at end of file
main = string.Start
string.Start = <{string._c;16;9_2}> string.str
string.str = "Hello World!"
<{string._c;16;9_2}> !_x_0 = select _x_0 ("" -> "A") ("Hello World!" -> "B")
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment