fix: 230/233 (98.7%) — reader :default preference, cond/new/definterface, runtime stubs, seq overloads

- Reader: prefer :default over :clj in reader conditionals
- Emitter: add cond, definterface, new special forms
- Emitter: ns handler registers namespace aliases from :require
- Emitter: when body always discarded (fixes type mismatch with else)
- Emitter: try/catch maps clojure.lang.ExceptionInfo → ExInfo, scope catch vars
- Emitter: def inside proc uses var (not {.global.}), removed debug output
- Runtime: cljRandomUuid, cljSystemGetProperty, cljVresetB, cljRestartAgent
- Runtime: cljRequire, cljEvalStub, cljResolve no-op stubs
- Runtime: Boolean/Object/Integer/Long/Float/Double constructors
- Runtime: seq overloads for cljAssoc, cljDissoc, cljGet, cljExInfo, cljTransduce
- Unit tests: 78/80 (was 77/80)
- 3 remaining: not_eq (cross-namespace), add_watch/remove_watch (def hoisting)
This commit is contained in:
2026-05-11 03:36:53 +03:00
parent e5897125fd
commit d7e5697f3a
4 changed files with 262 additions and 84 deletions
+110
View File
@@ -1338,6 +1338,10 @@ proc cljGet*(m: CljVal, key: CljVal): CljVal =
else: cljNil()
else: cljNil()
proc cljGet*(args: seq[CljVal]): CljVal =
if args.len < 2: return cljNil()
cljGet(args[0], args[1])
proc cljGetDefault*(m: CljVal, key: CljVal, default: CljVal): CljVal =
if m.isNil: return default
case m.kind
@@ -1352,6 +1356,13 @@ proc cljExInfo*(msg: CljVal, data: CljVal): CljVal =
ex.exData = data
raise ex
proc cljExInfo*(args: seq[CljVal]): CljVal =
var msg = if args.len > 0: args[0] else: cljString("")
var data = if args.len > 1: args[1] else: cljNil()
var ex = newException(ExInfo, cljStr(msg))
ex.exData = data
raise ex
proc cljExData*(ex: CljVal): CljVal =
if ex.isNil: return cljNil()
case ex.kind
@@ -1403,10 +1414,18 @@ proc cljAssoc*(m: CljVal, key: CljVal, val: CljVal): CljVal =
else:
raise newException(CatchableError, "assoc expects a map or vector")
proc cljAssoc*(args: seq[CljVal]): CljVal =
if args.len < 3: raise newException(CatchableError, "assoc requires 3 arguments")
cljAssoc(args[0], args[1], args[2])
proc cljDissoc*(m: CljVal, key: CljVal): CljVal =
if m.isNil or m.kind != ckMap: return cljMap(@[], @[])
CljVal(kind: ckMap, mapData: pmapDissoc(m.mapData, key, hash(key), cljEq))
proc cljDissoc*(args: seq[CljVal]): CljVal =
if args.len < 2: return cljMap(@[], @[])
cljDissoc(args[0], args[1])
proc cljContains*(m: CljVal, key: CljVal): CljVal =
if m.isNil: return cljBool(false)
case m.kind
@@ -1523,6 +1542,10 @@ proc cljTransduce*(xform: CljVal, f: CljVal, init: CljVal, coll: CljVal): CljVal
# Fallback: just return init
return init
proc cljTransduce*(args: seq[CljVal]): CljVal =
if args.len < 4: return cljNil()
cljTransduce(args[0], args[1], args[2], args[3])
proc cljMapv*(f: proc(args: seq[CljVal]): CljVal, coll: CljVal): CljVal =
if coll.isNil: return cljVector(@[])
case coll.kind
@@ -2246,3 +2269,90 @@ proc cljZipmap*(args: seq[CljVal]): CljVal =
mk.add(kitems[i])
mv.add(vitems[i])
return cljMap(mk, mv)
# ---- Missing stubs ----
proc cljRandomUuid*(args: seq[CljVal]): CljVal =
randomize()
var uuid = ""
for i in 0..<32:
uuid.add("0123456789abcdef"[rand(15)])
if i in {7, 11, 15, 19}: uuid.add('-')
cljString(uuid)
proc cljSystemGetProperty*(args: seq[CljVal]): CljVal =
if args.len == 0: return cljNil()
let key = if args[0].kind == ckString: args[0].strVal else: ""
case key
of "line.separator": cljString("\n")
of "file.separator": cljString("/")
of "path.separator": cljString(":")
of "os.name": cljString("linux")
of "os.arch": cljString("x86_64")
of "java.version": cljString("0")
else: cljString("")
proc cljVresetB*(args: seq[CljVal]): CljVal =
if args.len < 2: return cljNil()
if args[0].kind == ckAtom:
args[0].atomVal = args[1]
args[1]
else:
raise newException(CatchableError, "vreset! requires a volatile")
proc cljRestartAgent*(args: seq[CljVal]): CljVal =
if args.len < 2: return cljNil()
if args[0].kind == ckAgent:
args[0].agentVal = args[1]
args[0].agentBusy = false
args[0]
else:
raise newException(CatchableError, "restart-agent requires an agent")
proc cljRequire*(args: seq[CljVal]): CljVal =
cljNil()
proc cljEvalStub*(args: seq[CljVal]): CljVal =
cljNil()
proc cljResolve*(args: seq[CljVal]): CljVal =
if args.len == 0: return cljNil()
cljNil()
proc Boolean*(args: seq[CljVal]): CljVal =
if args.len == 0: return cljBool(false)
let v = args[0]
if v.kind == ckBool: v
elif v.kind == ckString: cljBool(v.strVal.toLowerAscii() == "true")
elif v.kind == ckInt: cljBool(v.intVal != 0)
elif v.kind == ckFloat: cljBool(v.floatVal != 0.0)
else: cljBool(cljIsTruthy(v))
proc Boolean*(v: CljVal): CljVal =
Boolean(@[v])
proc Object*(args: seq[CljVal]): CljVal =
if args.len == 0: cljKeyword("Object")
else: args[0]
proc Object*(): CljVal =
cljKeyword("Object")
proc Integer*(args: seq[CljVal]): CljVal =
if args.len == 0: return cljInt(0)
cljToInt(args)
proc Integer*(v: CljVal): CljVal =
cljToInt(@[v])
proc Long*(args: seq[CljVal]): CljVal =
if args.len == 0: return cljInt(0)
cljToInt(args)
proc Float*(args: seq[CljVal]): CljVal =
if args.len == 0: return cljFloat(0.0)
cljToFloat(args)
proc Double*(args: seq[CljVal]): CljVal =
if args.len == 0: return cljFloat(0.0)
cljToFloat(args)