X-Git-Url: http://git.hcoop.net/jackhill/mal.git/blobdiff_plain/ece70f970306f819b148979c3d17f266c7e08146..fbfe6784d2db983018340e4e1492d8d017029867:/impls/fantom/src/step8_macros/fan/main.fan diff --git a/impls/fantom/src/step8_macros/fan/main.fan b/impls/fantom/src/step8_macros/fan/main.fan index ab2d2bff..418ddd66 100644 --- a/impls/fantom/src/step8_macros/fan/main.fan +++ b/impls/fantom/src/step8_macros/fan/main.fan @@ -2,20 +2,43 @@ using mallib class Main { + + static MalList qq_loop(MalVal elt, MalList acc) + { + lst := elt as MalList + if (lst?.count == 2 && (lst[0] as MalSymbol)?.value == "splice-unquote") + return MalList(MalVal[MalSymbol("concat"), lst[1], acc]) + else + return MalList(MalVal[MalSymbol("cons"), quasiquote(elt), acc]) + } + + static MalList qq_foldr(MalSeq xs) + { + acc := MalList([,]) + for (i:=xs.count-1; 0<=i; i-=1) + acc = qq_loop(xs[i], acc) + return acc + } + static MalVal quasiquote(MalVal ast) { - if (!MalTypes.isPair(ast)) - return MalList(MalVal[MalSymbol("quote"), ast]) - astSeq := ast as MalSeq - if ((astSeq[0] as MalSymbol)?.value == "unquote") - return astSeq[1] - if (MalTypes.isPair(astSeq[0])) + switch (ast.typeof) { - ast0Seq := astSeq[0] as MalSeq - if ((ast0Seq[0] as MalSymbol)?.value == "splice-unquote") - return MalList(MalVal[MalSymbol("concat"), ast0Seq[1], quasiquote(astSeq.drop(1))]) + case MalList#: + lst := ast as MalList + if (lst.count == 2 && (lst[0] as MalSymbol)?.value == "unquote") + return lst[1] + else + return qq_foldr((MalSeq)ast) + case MalVector#: + return MalList(MalVal[MalSymbol("vec"), qq_foldr((MalSeq)ast)]) + case MalSymbol#: + return MalList(MalVal[MalSymbol("quote"), ast]) + case MalHashMap#: + return MalList(MalVal[MalSymbol("quote"), ast]) + default: + return ast } - return MalList(MalVal[MalSymbol("cons"), quasiquote(astSeq[0]), quasiquote(astSeq.drop(1))]) } static Bool isMacroCall(MalVal ast, MalEnv env) @@ -87,6 +110,8 @@ class Main // TCO case "quote": return astList[1] + case "quasiquoteexpand": + return quasiquote(astList[1]) case "quasiquote": ast = quasiquote(astList[1]) // TCO