Skip to content

Commit 9a4c3dc

Browse files
authored
Support nested quasiquote unquote. (#15)
Co-authored-by: Bowen Fu <missing>
1 parent 9d6cee6 commit 9a4c3dc

File tree

4 files changed

+26
-31
lines changed

4 files changed

+26
-31
lines changed

include/lisp/evaluator.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -219,20 +219,6 @@ class Cons final: public Expr
219219
}
220220
};
221221

222-
class Unquote final: public Expr
223-
{
224-
MExprPtr mInternal;
225-
public:
226-
explicit Unquote(MExprPtr const& mexpr)
227-
: mInternal{mexpr}
228-
{}
229-
ExprPtr eval(std::shared_ptr<Env> const& /* env */) override;
230-
std::string toString() const override
231-
{
232-
return mInternal->toString();
233-
}
234-
};
235-
236222
template <typename Iter>
237223
ExprPtr vecToCons(Iter begin, Iter end)
238224
{

include/lisp/parser.h

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ inline ExprPtr or_(MExprPtr const& mexpr)
9797
return std::make_shared<Or>(parseActions(mexpr));
9898
}
9999

100-
inline auto parseAsQuoted(MExprPtr const& mexpr, bool quasi) -> ExprPtr;
100+
inline auto parseAsQuoted(MExprPtr const& mexpr, std::optional<int32_t> quasiquoteLevel) -> ExprPtr;
101101

102102
inline MExprPtr assertIsLastAndGet(MExprPtr const& mexpr)
103103
{
@@ -113,12 +113,12 @@ inline MExprPtr assertIsLastAndGet(MExprPtr const& mexpr)
113113

114114
inline ExprPtr quote(MExprPtr const& mexpr)
115115
{
116-
return parseAsQuoted(assertIsLastAndGet(mexpr), /* quasi = */ false);
116+
return parseAsQuoted(assertIsLastAndGet(mexpr), /* quasiquoteLevel = */ {});
117117
}
118118

119119
inline ExprPtr quasiquote(MExprPtr const& mexpr)
120120
{
121-
return parseAsQuoted(assertIsLastAndGet(mexpr), /* quasi = */ true);
121+
return parseAsQuoted(assertIsLastAndGet(mexpr), /* quasiquoteLevel = */ 1);
122122
}
123123

124124
inline ExprPtr definition(MExprPtr const& mexpr)
@@ -321,10 +321,10 @@ inline auto atomicToQuoted(ExprPtr const& expr)
321321

322322
inline ExprPtr unquote(MExprPtr const& mexpr)
323323
{
324-
return ExprPtr{new Unquote{assertIsLastAndGet(mexpr)}};
324+
return parse(assertIsLastAndGet(mexpr));
325325
}
326326

327-
inline auto consToQuoted(MExprPtr const& mexpr, bool quasi) -> ExprPtr
327+
inline auto consToQuoted(MExprPtr const& mexpr, std::optional<int32_t> quasiquoteLevel) -> ExprPtr
328328
{
329329
if (mexpr == MNil::instance())
330330
{
@@ -334,21 +334,34 @@ inline auto consToQuoted(MExprPtr const& mexpr, bool quasi) -> ExprPtr
334334
ASSERT(cons);
335335
auto car = cons->car();
336336
auto cdr = cons->cdr();
337-
if (quasi && car->toString() == "unquote")
337+
auto carStr = car->toString();
338+
if (quasiquoteLevel)
338339
{
339-
return unquote(cdr);
340+
if (carStr == "unquote")
341+
{
342+
if ( quasiquoteLevel.value() == 1)
343+
{
344+
return unquote(cdr);
345+
}
346+
--(*quasiquoteLevel);
347+
}
348+
else if (carStr == "quasiquote")
349+
{
350+
++(*quasiquoteLevel);
351+
}
340352
}
341-
return ExprPtr{new Cons{parseAsQuoted(car, quasi), consToQuoted(cdr, quasi)}};
353+
return ExprPtr{new Cons{parseAsQuoted(car, quasiquoteLevel), consToQuoted(cdr, quasiquoteLevel)}};
342354
}
343355

344-
inline auto parseAsQuoted(MExprPtr const& mexpr, bool quasi) -> ExprPtr
356+
// TODO: change quasi to quote level.
357+
inline auto parseAsQuoted(MExprPtr const& mexpr, std::optional<int32_t> quasiquoteLevel) -> ExprPtr
345358
{
346359
if (auto atomic = tryMAtomic(mexpr))
347360
{
348361
return atomicToQuoted(atomic);
349362
}
350363

351364
// else mexpr is cons, map quote on it
352-
return consToQuoted(mexpr, quasi);
365+
return consToQuoted(mexpr, quasiquoteLevel);
353366
}
354367
#endif // LISP_PARSER_H

sample/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,6 @@ do_test(test_short_quote_quoted_list "''(x)" "\\\\('quote \\\\('x\\\\)\\\\)")
123123
do_test(test_quote_unquote_sym "(quote (unquote 'x))" "'x")
124124
do_test(test_quasiquote_unquote_lst "`,(+ 1 2)" "3")
125125
do_test(test_quasiquote_lst_unquote_lst "`(,(+ 1 2))" "(3)")
126-
do_test(test_quasiquote_pair_unquote_lst "`(1 . ,(+ 1 2))" "(1 . 3)")
126+
do_test(test_quasiquote_pair_unquote_lst "`(1 . ,(+ 1 2))" "(1 . 3)")
127+
128+
do_test(test_quasiquote_nested_unquote "\`(1 \`,(+ 1 ,(+ 2 3)) 4)" "\\\\(1 \\\\(\'quasiquote \\\\(\'unquote \\\\(\'\\\\+ 1 5\\\\)\\\\)\\\\) 4\\\\)")

src/evaluator.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include "lisp/evaluator.h"
2-
#include "lisp/parser.h"
32

43
ExprPtr true_()
54
{
@@ -29,8 +28,3 @@ ExprPtr Definition::eval(std::shared_ptr<Env> const& env)
2928
{
3029
return env->defineVariable(mVariableName, mValue->eval(env));
3130
}
32-
33-
ExprPtr Unquote::eval(std::shared_ptr<Env> const& env)
34-
{
35-
return parse(mInternal)->eval(env);
36-
}

0 commit comments

Comments
 (0)