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:
2026-05-11 11:02:33 +03:00
parent 55f0cd842c
commit a5bed368b0
+22 -27
View File
@@ -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]
if test.kind == ckKeyword and test.kwName == "else":
result = expr
else:
result = cljList(@[cljSymbol("if"), test, expr, result])
return result
let test = args[0]
let expr = args[1]
if test.kind == ckKeyword and test.kwName == "else":
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
)