X-Git-Url: http://git.hcoop.net/jackhill/mal.git/blobdiff_plain/ece70f970306f819b148979c3d17f266c7e08146..fbfe6784d2db983018340e4e1492d8d017029867:/impls/nim/step8_macros.nim diff --git a/impls/nim/step8_macros.nim b/impls/nim/step8_macros.nim index 5b3fa2d0..1db46b4a 100644 --- a/impls/nim/step8_macros.nim +++ b/impls/nim/step8_macros.nim @@ -2,19 +2,32 @@ import rdstdin, tables, sequtils, os, types, reader, printer, env, core proc read(str: string): MalType = str.read_str -proc is_pair(x: MalType): bool = - x.kind in {List, Vector} and x.list.len > 0 +proc quasiquote(ast: MalType): MalType + +proc quasiquote_loop(xs: seq[MalType]): MalType = + result = list() + for i in countdown(xs.high, 0): + var elt = xs[i] + if elt.kind == List and 0 < elt.list.len and elt.list[0] == symbol "splice-unquote": + result = list(symbol "concat", elt.list[1], result) + else: + result = list(symbol "cons", quasiquote(elt), result) proc quasiquote(ast: MalType): MalType = - if not ast.is_pair: - return list(symbol "quote", ast) - elif ast.list[0] == symbol "unquote": - return ast.list[1] - elif ast.list[0].is_pair and ast.list[0].list[0] == symbol "splice-unquote": - return list(symbol "concat", ast.list[0].list[1], - quasiquote(list ast.list[1 .. ^1])) + case ast.kind + of List: + if ast.list.len == 2 and ast.list[0] == symbol "unquote": + result = ast.list[1] + else: + result = quasiquote_loop(ast.list) + of Vector: + result = list(symbol "vec", quasiquote_loop(ast.list)) + of Symbol: + result = list(symbol "quote", ast) + of HashMap: + result = list(symbol "quote", ast) else: - return list(symbol "cons", quasiquote(ast.list[0]), quasiquote(list(ast.list[1 .. ^1]))) + result = ast proc is_macro_call(ast: MalType, env: Env): bool = ast.kind == List and ast.list.len > 0 and ast.list[0].kind == Symbol and @@ -91,6 +104,9 @@ proc eval(ast: MalType, env: Env): MalType = of "quote": return ast.list[1] + of "quasiquoteexpand": + return ast.list[1].quasiquote + of "quasiquote": ast = ast.list[1].quasiquote # Continue loop (TCO)