fix: clj_ prefix for identifiers + try/catch/finally fixes
- #9: Add clj_ prefix to all mangled identifiers to avoid Nim case-insensitive name conflicts (parseQueryString ≡ parse_query_string) - #11: Fix finally block - discard expression results - #11: Fix catch handler - use original name for scope tracking - Fix loop handler - use original name for addToScope - Update emitter tests for clj_ prefix
This commit is contained in:
+19
-9
@@ -79,6 +79,8 @@ proc mangleName*(name: string): string =
|
||||
"interface", "lambda", "open", "quit", "result", "nil", "end"]
|
||||
if result in nimKeywords:
|
||||
result = result & "1"
|
||||
# Prefix to avoid conflicts with Nim identifiers (case-insensitive + underscore ignoring)
|
||||
result = "clj_" & result
|
||||
|
||||
proc pushScope() =
|
||||
scopeStack.add(initHashSet[string]())
|
||||
@@ -1165,7 +1167,7 @@ proc emitSpecialForm(items: seq[CljVal], indent: int): string =
|
||||
raise newException(EmitterError, "loop bindings must be a vector")
|
||||
if bindings.items.len mod 2 != 0:
|
||||
raise newException(EmitterError, "loop bindings must have even number of elements")
|
||||
var loopParams: seq[(string, string)] = @[]
|
||||
var loopParams: seq[(string, string, string)] = @[] # (mangled, original, value)
|
||||
var li = 0
|
||||
while li < bindings.items.len:
|
||||
var lname = bindings.items[li]
|
||||
@@ -1175,13 +1177,13 @@ proc emitSpecialForm(items: seq[CljVal], indent: int): string =
|
||||
lname = lname.items[1]
|
||||
if lname.kind != ckSymbol:
|
||||
raise newException(EmitterError, "loop binding name must be a symbol")
|
||||
loopParams.add((mangleName(lname.symName), emitExpr(lval, 0)))
|
||||
loopParams.add((mangleName(lname.symName), lname.symName, emitExpr(lval, 0)))
|
||||
li += 2
|
||||
var loopVars: seq[string] = @[]
|
||||
var lines: seq[string] = @[]
|
||||
pushScope()
|
||||
for (lpName, lpVal) in loopParams:
|
||||
addToScope(lpName)
|
||||
for (lpName, lpOrig, lpVal) in loopParams:
|
||||
addToScope(lpOrig)
|
||||
lines.add(sp & "var " & lpName & ": CljVal = " & lpVal)
|
||||
loopVars.add(lpName)
|
||||
loopStack.add(loopVars)
|
||||
@@ -1271,7 +1273,7 @@ proc emitSpecialForm(items: seq[CljVal], indent: int): string =
|
||||
if items.len < 2:
|
||||
raise newException(EmitterError, "try requires body")
|
||||
var bodyForms: seq[CljVal] = @[]
|
||||
var catchClauses: seq[(string, string, seq[CljVal])] = @[]
|
||||
var catchClauses: seq[(string, string, string, seq[CljVal])] = @[] # (exType, mangledName, origName, body)
|
||||
var finallyBody: seq[CljVal] = @[]
|
||||
var ti = 1
|
||||
while ti < items.len:
|
||||
@@ -1304,7 +1306,7 @@ proc emitSpecialForm(items: seq[CljVal], indent: int): string =
|
||||
let exName = form.items[nameIdx]
|
||||
if exName.kind != ckSymbol:
|
||||
raise newException(EmitterError, "catch name must be a symbol")
|
||||
catchClauses.add((exTypeStr, mangleName(exName.symName), form.items[bodyIdx..^1]))
|
||||
catchClauses.add((exTypeStr, mangleName(exName.symName), exName.symName, form.items[bodyIdx..^1]))
|
||||
elif form.items[0].symName == "finally":
|
||||
finallyBody = form.items[1..^1]
|
||||
else:
|
||||
@@ -1330,7 +1332,7 @@ proc emitSpecialForm(items: seq[CljVal], indent: int): string =
|
||||
lines.add(code)
|
||||
else:
|
||||
lines.add(indentStr(indent + 1) & "discard " & stripped)
|
||||
for (exType, exVar, exBody) in catchClauses:
|
||||
for (exType, exVar, exOrig, exBody) in catchClauses:
|
||||
lines.add(sp & "except " & exType & ":")
|
||||
lines.add(indentStr(indent + 1) & "let " & exVar & " = cljMap(@[cljKeyword(\"message\")], @[cljString(getCurrentExceptionMsg())])")
|
||||
lines.add(indentStr(indent + 1) & "discard cljAssoc(" & exVar & ", cljKeyword(\"type\"), cljString(\"" & exType & "\"))")
|
||||
@@ -1338,7 +1340,7 @@ proc emitSpecialForm(items: seq[CljVal], indent: int): string =
|
||||
lines.add(indentStr(indent + 1) & "if exPtr" & exVar & " of ExInfo:")
|
||||
lines.add(indentStr(indent + 2) & "discard cljAssoc(" & exVar & ", cljKeyword(\"data\"), (ref ExInfo)(exPtr" & exVar & ").exData)")
|
||||
pushScope()
|
||||
addToScope(exVar)
|
||||
addToScope(exOrig)
|
||||
for i, eb in exBody:
|
||||
let isLast = (i == exBody.len - 1)
|
||||
let code = emitExpr(eb, indent + 1)
|
||||
@@ -1359,7 +1361,15 @@ proc emitSpecialForm(items: seq[CljVal], indent: int): string =
|
||||
if finallyBody.len > 0:
|
||||
lines.add(sp & "finally:")
|
||||
for fb in finallyBody:
|
||||
lines.add(emitExpr(fb, indent + 1))
|
||||
let fbCode = emitExpr(fb, indent + 1)
|
||||
let fbStripped = fbCode.strip()
|
||||
if fbStripped.startsWith("echo ") or fbStripped.startsWith("discard ") or
|
||||
fbStripped.startsWith("var ") or fbStripped.startsWith("let ") or
|
||||
fbStripped.startsWith("proc ") or fbStripped.startsWith("if ") or
|
||||
fbStripped.startsWith("try:") or fbStripped.startsWith("while "):
|
||||
lines.add(fbCode)
|
||||
else:
|
||||
lines.add(indentStr(indent + 1) & "discard " & fbStripped)
|
||||
return lines.join("\n")
|
||||
|
||||
of "throw":
|
||||
|
||||
Reference in New Issue
Block a user