unquote splicing and implemented slime side list comprehensions

This commit is contained in:
Felix Brendel
2019-05-22 03:38:05 +02:00
parent eb3bc262b9
commit 3fb2326dd3
5 changed files with 108 additions and 94 deletions
+21 -2
View File
@@ -461,7 +461,8 @@ proc load_built_ins_into_environment(Environment* env) -> void {
// it is a pair!
Lisp_Object* originalPair = expr->value.pair.first;
if (Memory::get_type(originalPair) == Lisp_Object_Type::Symbol &&
string_equal(originalPair->value.symbol.identifier, "unquote"))
(string_equal(originalPair->value.symbol.identifier, "unquote") ||
string_equal(originalPair->value.symbol.identifier, "unquote-splicing")))
{
// eval replace the stuff
return eval_expr(expr->value.pair.rest->value.pair.first, env);
@@ -481,7 +482,25 @@ proc load_built_ins_into_environment(Environment* env) -> void {
Lisp_Object* newPairHead = newPair;
Lisp_Object* head = expr;
while (Memory::get_type(head) == Lisp_Object_Type::Pair) {
newPairHead->value.pair.first = unquoteSomeExpressions(head->value.pair.first);
// if it is ,@ we have to actually do more work
// and inline the result
if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Pair &&
Memory::get_type(head->value.pair.first->value.pair.first) == Lisp_Object_Type::Symbol &&
string_equal(head->value.pair.first->value.pair.first->value.symbol.identifier, "unquote-splicing"))
{
Lisp_Object* spliced = unquoteSomeExpressions(head->value.pair.first);
try assert_type(spliced, Lisp_Object_Type::Pair);
newPairHead->value.pair.first = spliced->value.pair.first;
newPairHead->value.pair.rest = spliced->value.pair.rest;
// now skip to the end
while (newPairHead->value.pair.rest != Memory::nil) {
newPairHead = newPairHead->value.pair.rest;
}
} else {
newPairHead->value.pair.first = unquoteSomeExpressions(head->value.pair.first);
}
if (Memory::get_type(head->value.pair.rest) != Lisp_Object_Type::Pair)
break;
+15 -13
View File
@@ -246,8 +246,10 @@ namespace Parser {
proc parse_expression(char* text, int* index_in_text) -> Lisp_Object* {
// if it is quoted
// TODO(Felix): This looks totally broken..
if (text[*index_in_text] == '\'' ||
text[*index_in_text] == '`' ||
text[*index_in_text] == '@' ||
text[*index_in_text] == ',')
{
char quoteType = text[*index_in_text];
@@ -257,15 +259,12 @@ namespace Parser {
if (text[*index_in_text] == '(' ||
text[*index_in_text] == '\'' ||
text[*index_in_text] == '`' ||
text[*index_in_text] == '@' ||
text[*index_in_text] == ',')
{
try {
result = parse_expression(text, index_in_text);
}
try result = parse_expression(text, index_in_text);
} else {
try {
result = parse_atom(text, index_in_text);
}
try result = parse_atom(text, index_in_text);
}
Lisp_Object* ret = nullptr;
@@ -278,10 +277,14 @@ namespace Parser {
try ret = Memory::create_lisp_object_pair(
Memory::get_or_create_lisp_object_symbol("quasiquote"),
Memory::create_lisp_object_pair(result, Memory::nil));
else if (quoteType == ',') {
else if (quoteType == ',')
try ret = Memory::create_lisp_object_pair(
Memory::get_or_create_lisp_object_symbol("unquote"),
Memory::create_lisp_object_pair(result, Memory::nil));
else if (quoteType == '@') {
try ret = Memory::create_lisp_object_pair(
Memory::get_or_create_lisp_object_symbol("unquote-splicing"),
Memory::create_lisp_object_pair(result, Memory::nil));
}
if (ret) {
inject_scl(ret);
@@ -316,15 +319,12 @@ namespace Parser {
if (text[*index_in_text] == '(' ||
text[*index_in_text] == '\''||
text[*index_in_text] == '`' ||
text[*index_in_text] == '@' ||
text[*index_in_text] == ',')
{
try {
head->value.pair.first = parse_expression(text, index_in_text);
}
try head->value.pair.first = parse_expression(text, index_in_text);
} else {
try {
head->value.pair.first = parse_atom(text, index_in_text);
}
try head->value.pair.first = parse_atom(text, index_in_text);
}
eat_until_code(text, index_in_text);
@@ -475,6 +475,7 @@ namespace Parser {
return Memory::nil;
if (text[index_in_text] == '(' ||
text[index_in_text] == '\'' ||
text[index_in_text] == '@' ||
text[index_in_text] == '`' ||
text[index_in_text] == ',')
{
@@ -507,6 +508,7 @@ namespace Parser {
return Memory::nil;
if (text[index_in_text] == '(' ||
text[index_in_text] == '\'' ||
text[index_in_text] == '@' ||
text[index_in_text] == '`' ||
text[index_in_text] == ',')
{