uns_lisp: quasiquote parser
This commit is contained in:
parent
23ad070039
commit
2e3d3a23cd
|
@ -74,7 +74,7 @@
|
||||||
(__define-macro cond body
|
(__define-macro cond body
|
||||||
(let ((cases (car body)))
|
(let ((cases (car body)))
|
||||||
(if (null? body)
|
(if (null? body)
|
||||||
<undefined>
|
(null)
|
||||||
(let* ((branch (car cases))
|
(let* ((branch (car cases))
|
||||||
(rest (cdr cases))
|
(rest (cdr cases))
|
||||||
(test (car branch))
|
(test (car branch))
|
||||||
|
|
|
@ -69,7 +69,7 @@ static const char *token2string_repr[TOKEN_NUM] = {
|
||||||
"quote",
|
"quote",
|
||||||
"quasiquote",
|
"quasiquote",
|
||||||
"unquote",
|
"unquote",
|
||||||
"unquote-list",
|
"unquote-splice",
|
||||||
"'ident",
|
"'ident",
|
||||||
"'number",
|
"'number",
|
||||||
"'float",
|
"'float",
|
||||||
|
@ -392,6 +392,8 @@ static const char *get_string(struct uns_ctr *ctr)
|
||||||
case STRING: case SYMBOL:
|
case STRING: case SYMBOL:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
abort();
|
||||||
|
uns_root_remove(gc, &s);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1011,8 +1013,8 @@ enum cps_return {
|
||||||
CPS_CANNOT_CALL_TYPE,
|
CPS_CANNOT_CALL_TYPE,
|
||||||
CPS_QUOTE_UNDERFLOW,
|
CPS_QUOTE_UNDERFLOW,
|
||||||
CPS_QUOTE_OVERFLOW,
|
CPS_QUOTE_OVERFLOW,
|
||||||
CPS_QUASIQUOTE_UNDERFLOW,
|
CPS_EXEC_QUASIQUOTE_UNDERFLOW,
|
||||||
CPS_QUASIQUOTE_OVERFLOW,
|
CPS_EXEC_QUASIQUOTE_OVERFLOW,
|
||||||
CPS_EXEC_LAMBDA_UNDERFLOW,
|
CPS_EXEC_LAMBDA_UNDERFLOW,
|
||||||
CPS_EXEC_LAMBDA_OVERFLOW,
|
CPS_EXEC_LAMBDA_OVERFLOW,
|
||||||
CPS_INVALID_LAMBDA_FORMAL,
|
CPS_INVALID_LAMBDA_FORMAL,
|
||||||
|
@ -1038,6 +1040,13 @@ enum cps_return {
|
||||||
CPS_SWAP_UNDERFLOW,
|
CPS_SWAP_UNDERFLOW,
|
||||||
CPS_IF_UNDERFLOW,
|
CPS_IF_UNDERFLOW,
|
||||||
CPS_LAMBDA_UNDERFLOW,
|
CPS_LAMBDA_UNDERFLOW,
|
||||||
|
CPS_QUASIQUOTE_UNQUOTE_UNDERFLOW,
|
||||||
|
CPS_QUASIQUOTE_UNQUOTE_OVERFLOW,
|
||||||
|
CPS_QUASIQUOTE_SPLICE_UNDERFLOW,
|
||||||
|
CPS_QUASIQUOTE_SPLICE_OVERFLOW,
|
||||||
|
CPS_QUASIQUOTE_UNDERFLOW,
|
||||||
|
CPS_WRAP_SPLICE_UNDERFLOW,
|
||||||
|
CPS_WRAP_UNDERFLOW,
|
||||||
|
|
||||||
CPS_RETURN_LEN
|
CPS_RETURN_LEN
|
||||||
};
|
};
|
||||||
|
@ -1050,8 +1059,8 @@ static const char *cps_return_to_string[CPS_RETURN_LEN] = {
|
||||||
"CPS_CANNOT_CALL_TYPE",
|
"CPS_CANNOT_CALL_TYPE",
|
||||||
"CPS_QUOTE_UNDERFLOW",
|
"CPS_QUOTE_UNDERFLOW",
|
||||||
"CPS_QUOTE_OVERFLOW",
|
"CPS_QUOTE_OVERFLOW",
|
||||||
"CPS_QUASIQUOTE_UNDERFLOW",
|
"CPS_EXEC_QUASIQUOTE_UNDERFLOW",
|
||||||
"CPS_QUASIQUOTE_OVERFLOW",
|
"CPS_EXEC_QUASIQUOTE_OVERFLOW",
|
||||||
"CPS_EXEC_LAMBDA_UNDERFLOW",
|
"CPS_EXEC_LAMBDA_UNDERFLOW",
|
||||||
"CPS_EXEC_LAMBDA_OVERFLOW",
|
"CPS_EXEC_LAMBDA_OVERFLOW",
|
||||||
"CPS_INVALID_LAMBDA_FORMAL",
|
"CPS_INVALID_LAMBDA_FORMAL",
|
||||||
|
@ -1076,13 +1085,20 @@ static const char *cps_return_to_string[CPS_RETURN_LEN] = {
|
||||||
"CPS_FCALL_IMPROPER_LIST",
|
"CPS_FCALL_IMPROPER_LIST",
|
||||||
"CPS_SWAP_UNDERFLOW",
|
"CPS_SWAP_UNDERFLOW",
|
||||||
"CPS_IF_UNDERFLOW",
|
"CPS_IF_UNDERFLOW",
|
||||||
"CPS_LAMBDA_UNDERFLOW"
|
"CPS_LAMBDA_UNDERFLOW",
|
||||||
|
"CPS_QUASIQUOTE_UNQUOTE_UNDERFLOW",
|
||||||
|
"CPS_QUASIQUOTE_UNQUOTE_OVERFLOW",
|
||||||
|
"CPS_QUASIQUOTE_SPLICE_UNDERFLOW",
|
||||||
|
"CPS_QUASIQUOTE_SPLICE_OVERFLOW",
|
||||||
|
"CPS_QUASIQUOTE_UNDERFLOW",
|
||||||
|
"CPS_WRAP_SPLICE_UNDERFLOW",
|
||||||
|
"CPS_WRAP_UNDERFLOW"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* {K (quote QUOTED)} {cps} = {(-> (quote QUOTED) K)} */
|
/* {K (quote QUOTED)} {cps} = {(quote-> QUOTED K)} */
|
||||||
static enum cps_return cps_exec_quote(struct uns_ctr *prevstack,
|
static enum cps_return cps_exec_quote(struct uns_ctr *prevstack,
|
||||||
struct uns_ctr *K,
|
struct uns_ctr *K,
|
||||||
struct uns_ctr *quote,
|
struct uns_ctr *quoted,
|
||||||
struct uns_ctr *readstack
|
struct uns_ctr *readstack
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -1090,9 +1106,10 @@ static enum cps_return cps_exec_quote(struct uns_ctr *prevstack,
|
||||||
|
|
||||||
uns_root_add(gc, &wrapped);
|
uns_root_add(gc, &wrapped);
|
||||||
wrapped.p = empty_list.p;
|
wrapped.p = empty_list.p;
|
||||||
|
|
||||||
stack_push(&wrapped, K);
|
stack_push(&wrapped, K);
|
||||||
stack_push(&wrapped, quote);
|
stack_push(&wrapped, quoted);
|
||||||
stack_push_const(&wrapped, "->");
|
stack_push_const(&wrapped, "quote->");
|
||||||
|
|
||||||
stack_push(prevstack, &wrapped);
|
stack_push(prevstack, &wrapped);
|
||||||
|
|
||||||
|
@ -1100,7 +1117,7 @@ static enum cps_return cps_exec_quote(struct uns_ctr *prevstack,
|
||||||
return CPS_CONTINUE;
|
return CPS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* {K (quasiquote E)} {cps} = {K 1 E} {quasiquote}
|
/* {K (quasiquote E)} {cps} = {K E n} {quasiquote}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static enum cps_return cps_exec_quasiquote(struct uns_ctr *prevstack,
|
static enum cps_return cps_exec_quasiquote(struct uns_ctr *prevstack,
|
||||||
|
@ -1110,32 +1127,22 @@ static enum cps_return cps_exec_quasiquote(struct uns_ctr *prevstack,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
struct uns_ctr tmp = {0};
|
struct uns_ctr tmp = {0};
|
||||||
struct uns_ctr tmpint = {0};
|
|
||||||
const long i = 1;
|
|
||||||
|
|
||||||
if (get_type(quoted->p) != CELL)
|
if (get_type(quoted->p) != CELL)
|
||||||
return CPS_QUASIQUOTE_UNDERFLOW;
|
return CPS_EXEC_QUASIQUOTE_UNDERFLOW;
|
||||||
if (get_type(CDR(quoted->p)) != EMPTY_LIST)
|
if (get_type(CDR(quoted->p)) != EMPTY_LIST)
|
||||||
return CPS_QUASIQUOTE_OVERFLOW;
|
return CPS_EXEC_QUASIQUOTE_OVERFLOW;
|
||||||
quoted->p = CAR(quoted->p);
|
quoted->p = CAR(quoted->p);
|
||||||
|
|
||||||
stack_push(prevstack, quoted);
|
|
||||||
|
|
||||||
uns_root_add(gc, &tmp);
|
uns_root_add(gc, &tmp);
|
||||||
alloc_of_type(&tmp, INTEGER);
|
|
||||||
|
|
||||||
uns_root_add(gc, &tmpint);
|
|
||||||
tmpint.p = uns_alloc(gc, sizeof(i), 0);
|
|
||||||
memcpy(tmpint.p, &i, sizeof(i));
|
|
||||||
|
|
||||||
uns_set(gc, tmp.p, 1, UNS_POINTER, tmpint.p);
|
|
||||||
|
|
||||||
|
alloc_int(&tmp, 1);
|
||||||
stack_push(prevstack, &tmp);
|
stack_push(prevstack, &tmp);
|
||||||
|
stack_push(prevstack, quoted);
|
||||||
stack_push(prevstack, K);
|
stack_push(prevstack, K);
|
||||||
|
|
||||||
stack_push_const(readstack, "quasiquote");
|
stack_push_const(readstack, "qq");
|
||||||
|
|
||||||
uns_root_remove(gc, &tmpint);
|
|
||||||
uns_root_remove(gc, &tmp);
|
uns_root_remove(gc, &tmp);
|
||||||
|
|
||||||
return CPS_CONTINUE;
|
return CPS_CONTINUE;
|
||||||
|
@ -1372,6 +1379,7 @@ static enum cps_return cps_exec_if(struct uns_ctr *prevstack,
|
||||||
struct uns_ctr b1 = {0};
|
struct uns_ctr b1 = {0};
|
||||||
struct uns_ctr b2 = {0};
|
struct uns_ctr b2 = {0};
|
||||||
struct uns_ctr e = {0};
|
struct uns_ctr e = {0};
|
||||||
|
enum cps_return r = CPS_CONTINUE;
|
||||||
|
|
||||||
uns_root_add(gc, &newk);
|
uns_root_add(gc, &newk);
|
||||||
uns_root_add(gc, &e);
|
uns_root_add(gc, &e);
|
||||||
|
@ -1380,21 +1388,31 @@ static enum cps_return cps_exec_if(struct uns_ctr *prevstack,
|
||||||
|
|
||||||
gensym(&newk);
|
gensym(&newk);
|
||||||
|
|
||||||
if (get_type(lst->p) != CELL)
|
if (get_type(lst->p) != CELL) {
|
||||||
return CPS_EXEC_IF_UNDERFLOW;
|
r = CPS_EXEC_IF_UNDERFLOW;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
e.p = CAR(lst->p);
|
e.p = CAR(lst->p);
|
||||||
lst->p = CDR(lst->p);
|
lst->p = CDR(lst->p);
|
||||||
|
|
||||||
if (get_type(lst->p) != CELL)
|
if (get_type(lst->p) != CELL) {
|
||||||
return CPS_EXEC_IF_UNDERFLOW;
|
r = CPS_EXEC_IF_UNDERFLOW;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
b1.p = CAR(lst->p);
|
b1.p = CAR(lst->p);
|
||||||
lst->p = CDR(lst->p);
|
lst->p = CDR(lst->p);
|
||||||
|
|
||||||
if (get_type(lst->p) != CELL)
|
if (get_type(lst->p) != CELL) {
|
||||||
return CPS_EXEC_IF_UNDERFLOW;
|
r = CPS_EXEC_IF_UNDERFLOW;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
b2.p = CAR(lst->p);
|
b2.p = CAR(lst->p);
|
||||||
if (get_type(CDR(lst->p)) != EMPTY_LIST)
|
if (get_type(CDR(lst->p)) != EMPTY_LIST) {
|
||||||
return CPS_EXEC_IF_OVERFLOW;
|
r = CPS_EXEC_IF_OVERFLOW;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
stack_push(prevstack, &e);
|
stack_push(prevstack, &e);
|
||||||
stack_push(prevstack, K);
|
stack_push(prevstack, K);
|
||||||
|
@ -1414,7 +1432,8 @@ static enum cps_return cps_exec_if(struct uns_ctr *prevstack,
|
||||||
uns_root_remove(gc, &b1);
|
uns_root_remove(gc, &b1);
|
||||||
uns_root_remove(gc, &b2);
|
uns_root_remove(gc, &b2);
|
||||||
|
|
||||||
return CPS_CONTINUE;
|
end:
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int reverse(struct uns_ctr *into, struct uns_ctr *from)
|
static int reverse(struct uns_ctr *into, struct uns_ctr *from)
|
||||||
|
@ -1566,7 +1585,8 @@ static enum cps_return cps_exec_cell(struct uns_ctr *prevstack,
|
||||||
case SYMBOL:
|
case SYMBOL:
|
||||||
symb = get_string(tmp);
|
symb = get_string(tmp);
|
||||||
if (strcmp(symb, "quote") == 0) {
|
if (strcmp(symb, "quote") == 0) {
|
||||||
r = cps_exec_quote(prevstack, K, E, readstack);
|
tmp-> p = CDR(E->p);
|
||||||
|
r = cps_exec_quote(prevstack, K, tmp, readstack);
|
||||||
break;
|
break;
|
||||||
} else if (strcmp(symb, "quasiquote") == 0) {
|
} else if (strcmp(symb, "quasiquote") == 0) {
|
||||||
tmp->p = CDR(E->p);
|
tmp->p = CDR(E->p);
|
||||||
|
@ -1587,7 +1607,7 @@ static enum cps_return cps_exec_cell(struct uns_ctr *prevstack,
|
||||||
} else if (strcmp(symb, "unquote") == 0) {
|
} else if (strcmp(symb, "unquote") == 0) {
|
||||||
r = CPS_UNQUOTE_INVALID;
|
r = CPS_UNQUOTE_INVALID;
|
||||||
break;
|
break;
|
||||||
} else if (strcmp(symb, "unquote-list") == 0) {
|
} else if (strcmp(symb, "unquote-splice") == 0) {
|
||||||
r = CPS_UNQUOTE_LIST_INVALID;
|
r = CPS_UNQUOTE_LIST_INVALID;
|
||||||
break;
|
break;
|
||||||
} else if (strcmp(symb, "if") == 0) {
|
} else if (strcmp(symb, "if") == 0) {
|
||||||
|
@ -1912,6 +1932,435 @@ end:
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum cps_quasiquote_unquote {
|
||||||
|
CPS_QUASIQUOTE_NONE = 0,
|
||||||
|
CPS_QUASIQUOTE_UNQUOTE = 1,
|
||||||
|
CPS_QUASIQUOTE_UNQUOTE_SPLICE = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
static enum cps_quasiquote_unquote is_unquote(struct uns_ctr *E)
|
||||||
|
{
|
||||||
|
struct uns_ctr carptr = {0};
|
||||||
|
const char *s;
|
||||||
|
enum cps_quasiquote_unquote r = CPS_QUASIQUOTE_NONE;
|
||||||
|
|
||||||
|
uns_root_add(gc, &carptr);
|
||||||
|
carptr.p = CAR(E->p);
|
||||||
|
|
||||||
|
if (get_type(carptr.p) == SYMBOL) {
|
||||||
|
s = get_string(&carptr);
|
||||||
|
if (!s)
|
||||||
|
r = CPS_QUASIQUOTE_NONE;
|
||||||
|
else if (strcmp(s, "unquote") == 0)
|
||||||
|
r = CPS_QUASIQUOTE_UNQUOTE;
|
||||||
|
} else if (get_type(carptr.p) == CELL) {
|
||||||
|
carptr.p = CAR(carptr.p);
|
||||||
|
|
||||||
|
if (get_type(carptr.p) != SYMBOL)
|
||||||
|
goto end;
|
||||||
|
s = get_string(&carptr);
|
||||||
|
if (!s)
|
||||||
|
r = CPS_QUASIQUOTE_NONE;
|
||||||
|
else if (strcmp(s, "unquote-splice") == 0)
|
||||||
|
r = CPS_QUASIQUOTE_UNQUOTE_SPLICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
uns_root_remove(gc, &carptr);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{K (,@A . B) 1} {qq}
|
||||||
|
= {(kappa b (append-> a b K))
|
||||||
|
B 1 a A} {qq wrap cps}
|
||||||
|
|
||||||
|
{K (,@A . B) n} {qq}
|
||||||
|
= { (kappa b (cons-> aquote b K))
|
||||||
|
|
||||||
|
B n aquote a A [- n 1]} {qq wrap-splice qq}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static enum cps_return cps_quasiquote_splice(struct uns_ctr *prevstack,
|
||||||
|
struct uns_ctr *K,
|
||||||
|
struct uns_ctr *E,
|
||||||
|
struct uns_ctr *nptr,
|
||||||
|
struct uns_ctr *readstack
|
||||||
|
)
|
||||||
|
{
|
||||||
|
struct uns_ctr A = {0};
|
||||||
|
struct uns_ctr asymb = {0};
|
||||||
|
struct uns_ctr aquote = {0};
|
||||||
|
struct uns_ctr bsymb = {0};
|
||||||
|
struct uns_ctr expr = {0};
|
||||||
|
struct uns_ctr tmp = {0};
|
||||||
|
long n;
|
||||||
|
enum cps_return r = CPS_CONTINUE;
|
||||||
|
|
||||||
|
uns_root_add(gc, &A);
|
||||||
|
uns_root_add(gc, &asymb);
|
||||||
|
uns_root_add(gc, &aquote);
|
||||||
|
uns_root_add(gc, &bsymb);
|
||||||
|
uns_root_add(gc, &expr);
|
||||||
|
uns_root_add(gc, &tmp);
|
||||||
|
|
||||||
|
A.p = CAR(E->p);
|
||||||
|
if (get_type(CDR(A.p)) != CELL) {
|
||||||
|
r = CPS_QUASIQUOTE_SPLICE_UNDERFLOW;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (get_type(CDR(CDR(A.p))) != EMPTY_LIST) {
|
||||||
|
r = CPS_QUASIQUOTE_SPLICE_OVERFLOW;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
A.p = CAR(CDR(A.p));
|
||||||
|
|
||||||
|
n = get_int(nptr);
|
||||||
|
if (n == 1) {
|
||||||
|
gensym(&asymb);
|
||||||
|
gensym(&bsymb);
|
||||||
|
stack_push(prevstack, &A);
|
||||||
|
stack_push(prevstack, &asymb);
|
||||||
|
stack_push(prevstack, nptr);
|
||||||
|
A.p = CDR(E->p);
|
||||||
|
stack_push(prevstack, &A);
|
||||||
|
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, K);
|
||||||
|
stack_push(&expr, &bsymb);
|
||||||
|
stack_push(&expr, &asymb);
|
||||||
|
stack_push_const(&expr, "append->");
|
||||||
|
|
||||||
|
tmp.p = expr.p;
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, &tmp);
|
||||||
|
stack_push(&expr, &bsymb);
|
||||||
|
stack_push_const(&expr, "K");
|
||||||
|
|
||||||
|
stack_push(prevstack, &expr);
|
||||||
|
stack_push_const(readstack, "cps");
|
||||||
|
stack_push_const(readstack, "wrap");
|
||||||
|
stack_push_const(readstack, "qq");
|
||||||
|
} else {
|
||||||
|
alloc_int(&tmp, n - 1);
|
||||||
|
stack_push(prevstack, &tmp);
|
||||||
|
stack_push(prevstack, &A);
|
||||||
|
|
||||||
|
gensym(&asymb);
|
||||||
|
gensym(&bsymb);
|
||||||
|
gensym(&aquote);
|
||||||
|
|
||||||
|
A.p = CDR(E->p);
|
||||||
|
stack_push(prevstack, nptr);
|
||||||
|
stack_push(prevstack, &aquote);
|
||||||
|
stack_push(prevstack, &asymb);
|
||||||
|
stack_push(prevstack, &A);
|
||||||
|
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, K);
|
||||||
|
stack_push(&expr, &bsymb);
|
||||||
|
stack_push(&expr, &aquote);
|
||||||
|
stack_push_const(&expr, "cons->");
|
||||||
|
|
||||||
|
tmp.p = expr.p;
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, &tmp);
|
||||||
|
stack_push(&expr, &bsymb);
|
||||||
|
stack_push_const(&expr, "K");
|
||||||
|
|
||||||
|
stack_push(prevstack, &expr);
|
||||||
|
stack_push_const(readstack, "qq");
|
||||||
|
stack_push_const(readstack, "wrap-splice");
|
||||||
|
stack_push_const(readstack, "qq");
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
uns_root_remove(gc, &A);
|
||||||
|
uns_root_remove(gc, &asymb);
|
||||||
|
uns_root_remove(gc, &aquote);
|
||||||
|
uns_root_remove(gc, &bsymb);
|
||||||
|
uns_root_remove(gc, &expr);
|
||||||
|
uns_root_remove(gc, &tmp);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
{K ,A 1} {qq} = {K A} {cps}
|
||||||
|
{K ,A n} {qq} = {(kappa a (unquote-> a K)) A [- n 1]} {qq}
|
||||||
|
*/
|
||||||
|
static enum cps_return cps_quasiquote_unquote(struct uns_ctr *prevstack,
|
||||||
|
struct uns_ctr *K,
|
||||||
|
struct uns_ctr *E,
|
||||||
|
struct uns_ctr *nptr,
|
||||||
|
struct uns_ctr *readstack
|
||||||
|
)
|
||||||
|
{
|
||||||
|
long n;
|
||||||
|
struct uns_ctr expr = {0};
|
||||||
|
struct uns_ctr tmp = {0};
|
||||||
|
struct uns_ctr asym = {0};
|
||||||
|
enum cps_return r = CPS_CONTINUE;
|
||||||
|
|
||||||
|
uns_root_add(gc, &expr);
|
||||||
|
uns_root_add(gc, &tmp);
|
||||||
|
uns_root_add(gc, &asym);
|
||||||
|
|
||||||
|
if (get_type(CDR(E->p)) != CELL) {
|
||||||
|
r = CPS_QUASIQUOTE_UNQUOTE_UNDERFLOW;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (get_type(CDR(CDR(E->p))) != EMPTY_LIST) {
|
||||||
|
r = CPS_QUASIQUOTE_UNQUOTE_OVERFLOW;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr.p = CAR(CDR(E->p));
|
||||||
|
|
||||||
|
n = get_int(nptr);
|
||||||
|
if (n == 1) {
|
||||||
|
stack_push(prevstack, &expr);
|
||||||
|
stack_push(prevstack, K);
|
||||||
|
stack_push_const(readstack, "cps");
|
||||||
|
} else {
|
||||||
|
gensym(&asym);
|
||||||
|
alloc_int(nptr, n - 1);
|
||||||
|
stack_push(prevstack, nptr);
|
||||||
|
stack_push(prevstack, &expr);
|
||||||
|
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, K);
|
||||||
|
stack_push(&expr, &asym);
|
||||||
|
stack_push_const(&expr, "unquote->");
|
||||||
|
|
||||||
|
tmp.p = expr.p;
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, &tmp);
|
||||||
|
stack_push(&expr, &asym);
|
||||||
|
stack_push_const(&expr, "K");
|
||||||
|
stack_push_const(readstack, "qq");
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
uns_root_remove(gc, &expr);
|
||||||
|
uns_root_remove(gc, &tmp);
|
||||||
|
uns_root_remove(gc, &asym);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* {K (A . B) n} {qq}
|
||||||
|
= {(kappa b (cons-> a b K))
|
||||||
|
B n a A n} {qq wrap qq}
|
||||||
|
*/
|
||||||
|
static enum cps_return cps_quasiquote_cons(struct uns_ctr *prevstack,
|
||||||
|
struct uns_ctr *K,
|
||||||
|
struct uns_ctr *E,
|
||||||
|
struct uns_ctr *n,
|
||||||
|
struct uns_ctr *readstack
|
||||||
|
)
|
||||||
|
{
|
||||||
|
struct uns_ctr tmp = {0};
|
||||||
|
struct uns_ctr expr = {0};
|
||||||
|
struct uns_ctr asym = {0};
|
||||||
|
struct uns_ctr bsym = {0};
|
||||||
|
|
||||||
|
uns_root_add(gc, &expr);
|
||||||
|
uns_root_add(gc, &tmp);
|
||||||
|
uns_root_add(gc, &asym);
|
||||||
|
uns_root_add(gc, &bsym);
|
||||||
|
gensym(&asym);
|
||||||
|
gensym(&bsym);
|
||||||
|
|
||||||
|
tmp.p = CAR(E->p);
|
||||||
|
stack_push(prevstack, n);
|
||||||
|
stack_push(prevstack, &tmp);
|
||||||
|
stack_push(prevstack, &asym);
|
||||||
|
|
||||||
|
tmp.p = CDR(E->p);
|
||||||
|
stack_push(prevstack, n);
|
||||||
|
stack_push(prevstack, &tmp);
|
||||||
|
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, K);
|
||||||
|
stack_push(&expr, &bsym);
|
||||||
|
stack_push(&expr, &asym);
|
||||||
|
stack_push_const(&expr, "cons->");
|
||||||
|
|
||||||
|
tmp.p = expr.p;
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, &tmp);
|
||||||
|
stack_push(&expr, &bsym);
|
||||||
|
stack_push_const(&expr, "K");
|
||||||
|
|
||||||
|
stack_push(prevstack, &expr);
|
||||||
|
stack_push_const(readstack, "qq");
|
||||||
|
stack_push_const(readstack, "wrap");
|
||||||
|
stack_push_const(readstack, "qq");
|
||||||
|
|
||||||
|
uns_root_remove(gc, &expr);
|
||||||
|
uns_root_remove(gc, &tmp);
|
||||||
|
uns_root_remove(gc, &asym);
|
||||||
|
uns_root_remove(gc, &bsym);
|
||||||
|
|
||||||
|
return CPS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum cps_return cps_quasiquote_cell(struct uns_ctr *prevstack,
|
||||||
|
struct uns_ctr *K,
|
||||||
|
struct uns_ctr *E,
|
||||||
|
struct uns_ctr *n,
|
||||||
|
struct uns_ctr *readstack
|
||||||
|
)
|
||||||
|
{
|
||||||
|
switch (is_unquote(E)) {
|
||||||
|
case CPS_QUASIQUOTE_NONE:
|
||||||
|
return cps_quasiquote_cons(prevstack, K, E, n, readstack);
|
||||||
|
case CPS_QUASIQUOTE_UNQUOTE:
|
||||||
|
return cps_quasiquote_unquote(prevstack, K, E, n, readstack);
|
||||||
|
case CPS_QUASIQUOTE_UNQUOTE_SPLICE:
|
||||||
|
return cps_quasiquote_splice(prevstack, K, E, n, readstack);
|
||||||
|
}
|
||||||
|
return CPS_QUASIQUOTE_UNDERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* {K E _} {qq} = {(quote-> E K} */
|
||||||
|
static enum cps_return cps_quasiquote_simple(struct uns_ctr *prevstack,
|
||||||
|
struct uns_ctr *K,
|
||||||
|
struct uns_ctr *quoted
|
||||||
|
)
|
||||||
|
{
|
||||||
|
struct uns_ctr expr = {0};
|
||||||
|
|
||||||
|
uns_root_add(gc, &expr);
|
||||||
|
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, K);
|
||||||
|
stack_push(&expr, quoted);
|
||||||
|
stack_push_const(&expr, "quote->");
|
||||||
|
|
||||||
|
stack_push(prevstack, &expr);
|
||||||
|
|
||||||
|
uns_root_remove(gc, &expr);
|
||||||
|
return CPS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum cps_return cps_quasiquote(struct uns_ctr *prevstack,
|
||||||
|
struct uns_ctr *readstack
|
||||||
|
)
|
||||||
|
{
|
||||||
|
struct uns_ctr K = {0};
|
||||||
|
struct uns_ctr expr = {0};
|
||||||
|
struct uns_ctr number = {0};
|
||||||
|
enum cps_return r = CPS_CONTINUE;
|
||||||
|
|
||||||
|
uns_root_add(gc, &K);
|
||||||
|
uns_root_add(gc, &expr);
|
||||||
|
uns_root_add(gc, &number);
|
||||||
|
|
||||||
|
if (!stack_pop(prevstack, &K)
|
||||||
|
|| !stack_pop(prevstack, &expr)
|
||||||
|
|| !stack_pop(prevstack, &number)) {
|
||||||
|
r = CPS_QUASIQUOTE_UNDERFLOW;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (get_type(expr.p)) {
|
||||||
|
case CELL:
|
||||||
|
r = cps_quasiquote_cell(prevstack, &K, &expr, &number, readstack);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r = cps_quasiquote_simple(prevstack, &K, &expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
uns_root_remove(gc, &K);
|
||||||
|
uns_root_remove(gc, &expr);
|
||||||
|
uns_root_remove(gc, &number);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* {K a} {wrap} = {(kappa a K)} {} */
|
||||||
|
static enum cps_return cps_wrap(struct uns_ctr *prevstack)
|
||||||
|
{
|
||||||
|
struct uns_ctr K = {0};
|
||||||
|
struct uns_ctr a = {0};
|
||||||
|
struct uns_ctr expr = {0};
|
||||||
|
enum cps_return r = CPS_CONTINUE;
|
||||||
|
|
||||||
|
uns_root_add(gc, &K);
|
||||||
|
uns_root_add(gc, &a);
|
||||||
|
uns_root_add(gc, &expr);
|
||||||
|
|
||||||
|
if (!stack_pop(prevstack, &K)
|
||||||
|
|| !stack_pop(prevstack, &a)) {
|
||||||
|
r = CPS_WRAP_UNDERFLOW;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, &K);
|
||||||
|
stack_push(&expr, &a);
|
||||||
|
stack_push_const(&expr, "K");
|
||||||
|
|
||||||
|
stack_push(prevstack, &expr);
|
||||||
|
|
||||||
|
end:
|
||||||
|
|
||||||
|
uns_root_remove(gc, &K);
|
||||||
|
uns_root_remove(gc, &a);
|
||||||
|
uns_root_remove(gc, &expr);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* {K aquote a} {wrap-splice}
|
||||||
|
= {(kappa a (unquote-splice-> a (kappa aquote K)))}
|
||||||
|
*/
|
||||||
|
static enum cps_return cps_wrap_splice(struct uns_ctr *prevstack)
|
||||||
|
{
|
||||||
|
struct uns_ctr expr = {0};
|
||||||
|
struct uns_ctr tmp = {0};
|
||||||
|
struct uns_ctr K = {0};
|
||||||
|
struct uns_ctr aquote = {0};
|
||||||
|
struct uns_ctr a = {0};
|
||||||
|
enum cps_return r = CPS_CONTINUE;
|
||||||
|
|
||||||
|
uns_root_add(gc, &expr);
|
||||||
|
uns_root_add(gc, &tmp);
|
||||||
|
uns_root_add(gc, &K);
|
||||||
|
uns_root_add(gc, &aquote);
|
||||||
|
uns_root_add(gc, &a);
|
||||||
|
|
||||||
|
if (!stack_pop(prevstack, &K)
|
||||||
|
|| !stack_pop(prevstack, &aquote)
|
||||||
|
|| !stack_pop(prevstack, &a)) {
|
||||||
|
r = CPS_WRAP_SPLICE_UNDERFLOW;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, &K);
|
||||||
|
stack_push(&expr, &aquote);
|
||||||
|
stack_push_const(&expr, "K");
|
||||||
|
|
||||||
|
tmp.p = expr.p;
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, &tmp);
|
||||||
|
stack_push(&expr, &a);
|
||||||
|
stack_push_const(&expr, "unquote-splice->");
|
||||||
|
|
||||||
|
tmp.p = expr.p;
|
||||||
|
expr.p = empty_list.p;
|
||||||
|
stack_push(&expr, &tmp);
|
||||||
|
stack_push(&expr, &a);
|
||||||
|
stack_push_const(&expr, "K");
|
||||||
|
end:
|
||||||
|
uns_root_remove(gc, &expr);
|
||||||
|
uns_root_remove(gc, &tmp);
|
||||||
|
uns_root_remove(gc, &K);
|
||||||
|
uns_root_remove(gc, &aquote);
|
||||||
|
uns_root_remove(gc, &a);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static enum cps_return cps(struct uns_ctr *prevstack,
|
static enum cps_return cps(struct uns_ctr *prevstack,
|
||||||
struct uns_ctr *readstack)
|
struct uns_ctr *readstack)
|
||||||
{
|
{
|
||||||
|
@ -1942,6 +2391,12 @@ static enum cps_return cps(struct uns_ctr *prevstack,
|
||||||
r = cps_if(prevstack, readstack);
|
r = cps_if(prevstack, readstack);
|
||||||
} else if (strcmp(cmd, "cps-lambda") == 0) {
|
} else if (strcmp(cmd, "cps-lambda") == 0) {
|
||||||
r = cps_lambda(prevstack);
|
r = cps_lambda(prevstack);
|
||||||
|
} else if (strcmp(cmd, "qq") == 0) {
|
||||||
|
r = cps_quasiquote(prevstack, readstack);
|
||||||
|
} else if (strcmp(cmd, "wrap") == 0) {
|
||||||
|
r = cps_wrap(prevstack);
|
||||||
|
} else if (strcmp(cmd, "wrap-splice") == 0) {
|
||||||
|
r = cps_wrap_splice(prevstack);
|
||||||
} else {
|
} else {
|
||||||
r = CPS_INVALID_CMD;
|
r = CPS_INVALID_CMD;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue