Commit 2b85525f authored by Laszlo Domoszlai's avatar Laszlo Domoszlai
Browse files

implement proper pattern matching

parent 90f5876d
......@@ -504,50 +504,85 @@ void exec(Code* expr, int frame_ptr, int root_frame_ptr)
return;
}
case CT_SELECT:
{
{
bool handled = false;
Thunk* pattern = alloc_b();
pattern->desc = (Desc*) __STACK_PLACEHOLDER__;
push_a(pattern);
exec(((SelectEntry*) expr)->expr, frame_ptr, stack_top_a);
pattern = pop_a();
pattern = pop_a();
int i = 0;
do
{
assert(is_hnf(pattern));
for (;i < expr->nr_cases; i++) {
SelectCaseEntry* caseEntry = &((SelectEntry*) expr)->cases[i];
if (caseEntry->type == SC_CONS) {
// Pattern match
if ((Desc*) caseEntry->cons != pattern->desc) continue;
// Put the constructor arguments to the stack if matches
for (int i = 0; i < pattern->desc->arity; i++) {
push_a(pattern->_args[i]);
}
}
else if(caseEntry->type == SC_DEFAULT)
{
// accept it
}
else if (caseEntry->type == SC_LIT) {
assert(caseEntry->lit->thunk.desc != (Desc*) __INT__);
if(caseEntry->lit->thunk._int != pattern->_int) continue;
}
assert(is_hnf(pattern));
assert(pattern->desc->type == FT_ADT);
// must be SC_DEFAULT now
expr = caseEntry->body;
if(expr->type == CT_SELECT)
{
i=-1;
((SelectEntry*) expr)->saved_pattern = pattern;
pattern = alloc_b();
pattern->desc = (Desc*) __STACK_PLACEHOLDER__;
push_a(pattern);
exec(((SelectEntry*) expr)->expr, frame_ptr, stack_top_a);
pattern = pop_a();
continue;
}
handled = true;
break;
}
bool handled = false;
for (int i = 0; i < expr->nr_cases; i++) {
SelectCaseEntry* caseEntry = &((SelectEntry*) expr)->cases[i];
if (caseEntry->type == SC_CONS) {
// Pattern match
if ((Desc*) caseEntry->cons != pattern->desc) continue;
// Put the constructor arguments to the stack if matches
for (int i = 0; i < pattern->desc->arity; i++) {
push_a(pattern->_args[i]);
}
}
else if(caseEntry->type == SC_DEFAULT)
if(!handled)
{
// accept it
}
else if (caseEntry->type == SC_LIT) {
printf("Exec: Unhandled entry type in CT_SELECT (SC_LIT)");
exit(-1);
if(((SelectEntry*) expr)->fallback != NULL)
{
expr = (Code*) ((SelectEntry*) expr)->fallback;
i = ((SelectEntry*) expr)->fallbackidx;
pattern = ((SelectEntry*) expr)->saved_pattern;
}
else
{
printf("Exec: no select cases matches");
print(pattern, false);
exit(-1);
}
}
// must be SC_DEFAULT now
handled = true;
expr = caseEntry->body;
break;
}
if(handled) continue;
}
while(!handled);
printf("Exec: no select cases matches");
print(pattern, false);
exit(-1);
continue;
}
case CT_IF:
{
......
......@@ -47,7 +47,9 @@ struct AppEntry {
struct SelectCaseEntry {
int type;
struct Code* body;
Code* parent; // SelectEntry
union {
struct ADTEntry* cons;
struct ThunkEntry* lit;
......@@ -57,6 +59,13 @@ struct SelectCaseEntry {
struct SelectEntry {
struct Code base;
struct Code* expr;
SelectEntry* fallback;
int fallbackidx;
// save pattern temporarily before SelectEntry child is tried
Thunk* saved_pattern;
struct SelectCaseEntry cases[];
};
......
......@@ -29,7 +29,7 @@ int main ( int argc, char *argv[] )
init_desc();
init_prim();
char* input = "..\\tests\\Sprimes.bsapl";
char* input = "..\\tests\\Eval.bsapl";
if ( argc == 2 )
{
......@@ -77,7 +77,7 @@ int main ( int argc, char *argv[] )
// TODO: put it into a special "expression" space, instead of "code"
char *exprstream = "A0 F4 main";
Code* expr = parseTerm(&exprstream);
Code* expr = parseTerm(&exprstream, NULL);
#ifdef BENCHMARK
struct timeval t1, t2;
......
......@@ -302,7 +302,7 @@ VarEntry* parseVar(char **ptr, VarEntry* target) {
return entry;
}
Code* parseTerm(char **ptr);
Code* parseTerm(char **ptr, SelectCaseEntry* fallback);
/*
* It is very messy, because it handles 3 cases:
......@@ -344,7 +344,7 @@ Code* parseApp(char **ptr, bool dynamic) {
entry = (AppEntry*) alloc_code(sizeof (AppEntry) + sizeof (void*) * nrArgs);
for (int i = 0; i < nrArgs; i++) {
entry->args[i] = parseTerm(ptr);
entry->args[i] = parseTerm(ptr, NULL);
if (entry->args[i] == 0) return 0;
}
......@@ -434,8 +434,8 @@ Code* parseApp(char **ptr, bool dynamic) {
return (Code*) entry;
}
SelectEntry* parseSelect(char **ptr) {
Code* expr = parseTerm(ptr);
SelectEntry* parseSelect(char **ptr, SelectCaseEntry* fallback) {
Code* expr = parseTerm(ptr, NULL);
int nrCases;
if (!parseInt(ptr, &nrCases)) return 0;
......@@ -464,9 +464,21 @@ SelectEntry* parseSelect(char **ptr) {
return 0; // unknown case
}
entry->cases[i].body = (Code*) parseTerm(ptr);
entry->cases[i].parent = (Code*) entry;
entry->cases[i].body = (Code*) parseTerm(ptr, &entry->cases[i]);
}
if(fallback != NULL)
{
SelectEntry* parent = (SelectEntry*) fallback->parent;
entry->fallback = parent;
entry->fallbackidx = (fallback - parent->cases) + 1;
}
else
{
entry->fallback = NULL;
}
set_create_thunk_fun((Code*) entry);
return entry;
}
......@@ -474,15 +486,15 @@ SelectEntry* parseSelect(char **ptr) {
IfEntry* parseIf(char **ptr) {
struct IfEntry* entry = (IfEntry*) alloc_code(sizeof (IfEntry));
entry->base.type = CT_IF;
entry->cond = parseTerm(ptr);
entry->texpr = parseTerm(ptr);
entry->fexpr = parseTerm(ptr);
entry->cond = parseTerm(ptr, NULL);
entry->texpr = parseTerm(ptr, NULL);
entry->fexpr = parseTerm(ptr, NULL);
set_create_thunk_fun((Code*) entry);
return entry;
}
Code* parseTerm(char **ptr) {
Code* parseTerm(char **ptr, SelectCaseEntry* parent) {
// 1. Type char
char type = *(*ptr)++;
......@@ -498,7 +510,7 @@ Code* parseTerm(char **ptr) {
case 'D': // Dynamic application
return (Code*) parseApp(ptr, true);
case 'S': // Select
return (Code*) parseSelect(ptr);
return (Code*) parseSelect(ptr, parent);
case 'I': // If
return (Code*) parseIf(ptr);
default:
......@@ -525,7 +537,7 @@ int parseDef2(char** ptr) {
*ptr = entry->parseCont;
// parse body
entry->body = parseTerm(ptr);
entry->body = parseTerm(ptr, NULL);
break;
}
......@@ -538,7 +550,7 @@ int parseDef2(char** ptr) {
*ptr = entry->parseCont;
// parse body
entry->body = parseTerm(ptr);
entry->body = parseTerm(ptr, NULL);
break;
}
......
......@@ -7,6 +7,6 @@
int parse(char** ptr, int length);
Code* parseTerm(char **ptr);
Code* parseTerm(char **ptr, SelectCaseEntry* fallback);
#endif // __PARSE_H
\ No newline at end of file
[547]
\ No newline at end of file
......@@ -12,7 +12,7 @@ Eval.funcs = Eval.Cons Eval.fneq (Eval.Cons Eval.ftypeof (Eval.Cons Eval.fnrargs
:: Eval.MList = Eval.Cons a1 a2 | Eval.Empty
Eval.fsieve0 = Eval.tup 2 (Eval.App (Eval.App (Eval.Func 9) (Eval.Var 0)) (Eval.App (Eval.Func 19) (Eval.App (Eval.App (Eval.Func 13) (Eval.App (Eval.Func 17) (Eval.Var 0))) (Eval.Var 1))))
:: Eval.Expr = Eval.App a1 a2 | Eval.Func a1 | Eval.Var a1 | Eval.Num a1 | Eval.Oper a1 | Eval.Relop a1 | Eval.Boolean a1 | Eval.Error
Eval.tup a_0 b_1 = _Tuple2 a_0 b_1
Eval.tup a_0 b_1 = T2 a_0 b_1
Eval.fmember0 = Eval.tup 3 (Eval.App (Eval.App (Eval.App (Eval.App (Eval.Relop Eval.eq_54) (Eval.Var 1)) (Eval.Var 0)) (Eval.Boolean True)) (Eval.App (Eval.App (Eval.Func 16) (Eval.Var 2)) (Eval.Var 0)))
Eval.eq_54 !a_0 !b_1 = eqI a_0 b_1
Eval.fcount0 = Eval.tup 2 (Eval.App (Eval.Func 6) (Eval.App (Eval.Func 15) (Eval.Var 1)))
......
[2680]
\ No newline at end of file
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