fix: macro test failures — and, or, when, cond, as->, some->
- and: fix base case for 2 args (was double-wrapping in if) - or: simplify to direct if without let/gensym - when: remove nil else branch, validate args.len >= 2 - cond: recursive expansion with cond in else branch - as->: swap arg order to match Clojure (init, name, body) - some->: use nil? check instead of truthy check
This commit is contained in:
+21
-26
@@ -149,9 +149,7 @@ proc initMacros*() =
|
||||
defineMacro("and", proc(args: seq[CljVal]): CljVal =
|
||||
if args.len == 0: return cljBool(true)
|
||||
if args.len == 1: return args[0]
|
||||
var result = cljList(@[cljSymbol("if"), args[^1],
|
||||
args[^1],
|
||||
cljBool(false)])
|
||||
var result = args[^1]
|
||||
for i in countdown(args.len - 2, 0):
|
||||
result = cljList(@[cljSymbol("if"), args[i], result, cljBool(false)])
|
||||
return result
|
||||
@@ -163,9 +161,7 @@ proc initMacros*() =
|
||||
if args.len == 1: return args[0]
|
||||
var result = args[^1]
|
||||
for i in countdown(args.len - 2, 0):
|
||||
let gs = cljSymbol(gensymName("or_"))
|
||||
result = cljList(@[cljSymbol("let"), cljVector(@[gs, args[i]]),
|
||||
cljList(@[cljSymbol("if"), gs, gs, result])])
|
||||
result = cljList(@[cljSymbol("if"), args[i], args[i], result])
|
||||
return result
|
||||
)
|
||||
|
||||
@@ -205,13 +201,12 @@ proc initMacros*() =
|
||||
|
||||
# when
|
||||
defineMacro("when", proc(args: seq[CljVal]): CljVal =
|
||||
if args.len < 1:
|
||||
if args.len < 2:
|
||||
raise newException(CatchableError, "when requires condition and body")
|
||||
let cond = args[0]
|
||||
let body = args[1..^1]
|
||||
cljList(@[cljSymbol("if"), cond,
|
||||
cljList(@[cljSymbol("do")] & body),
|
||||
cljNil()])
|
||||
cljList(@[cljSymbol("do")] & body)])
|
||||
)
|
||||
|
||||
# when-not
|
||||
@@ -229,15 +224,14 @@ proc initMacros*() =
|
||||
if args.len == 0: return cljNil()
|
||||
if args.len mod 2 != 0:
|
||||
raise newException(CatchableError, "cond requires pairs of test/expr")
|
||||
var result = cljNil()
|
||||
for i in countdown((args.len div 2) - 1, 0):
|
||||
let test = args[i * 2]
|
||||
let expr = args[i * 2 + 1]
|
||||
let test = args[0]
|
||||
let expr = args[1]
|
||||
if test.kind == ckKeyword and test.kwName == "else":
|
||||
result = expr
|
||||
else:
|
||||
result = cljList(@[cljSymbol("if"), test, expr, result])
|
||||
return result
|
||||
return expr
|
||||
if args.len == 2:
|
||||
return cljList(@[cljSymbol("if"), test, expr])
|
||||
return cljList(@[cljSymbol("if"), test, expr,
|
||||
cljList(@[cljSymbol("cond")] & args[2..^1])])
|
||||
)
|
||||
|
||||
# cond->
|
||||
@@ -314,9 +308,9 @@ proc initMacros*() =
|
||||
# as->
|
||||
defineMacro("as->", proc(args: seq[CljVal]): CljVal =
|
||||
if args.len < 3:
|
||||
raise newException(CatchableError, "as-> requires name, init, and body")
|
||||
let name = args[0]
|
||||
let init = args[1]
|
||||
raise newException(CatchableError, "as-> requires init, name, and body")
|
||||
let init = args[0]
|
||||
let name = args[1]
|
||||
let body = args[2..^1]
|
||||
var result = init
|
||||
for form in body:
|
||||
@@ -333,16 +327,17 @@ proc initMacros*() =
|
||||
var result = init
|
||||
for form in body:
|
||||
let gs = cljSymbol(gensymName("st_"))
|
||||
let nilCheck = cljList(@[cljSymbol("nil?"), gs])
|
||||
if form.kind == ckList and form.items.len > 0:
|
||||
result = cljList(@[cljSymbol("let"), cljVector(@[gs, result]),
|
||||
cljList(@[cljSymbol("if"), gs,
|
||||
cljList(@[form.items[0], gs] & form.items[1..^1]),
|
||||
cljNil()])])
|
||||
cljList(@[cljSymbol("if"), nilCheck,
|
||||
cljNil(),
|
||||
cljList(@[form.items[0], gs] & form.items[1..^1])])])
|
||||
else:
|
||||
result = cljList(@[cljSymbol("let"), cljVector(@[gs, result]),
|
||||
cljList(@[cljSymbol("if"), gs,
|
||||
cljList(@[form, gs]),
|
||||
cljNil()])])
|
||||
cljList(@[cljSymbol("if"), nilCheck,
|
||||
cljNil(),
|
||||
cljList(@[form, gs])])])
|
||||
return result
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user