# Clojure/Nim — AI-First Clojure Compiler import os, osproc, strutils import reader, emitter, types, repl proc getLibPath(): string = let appDir = getAppDir() let candidate1 = appDir / "lib" let candidate2 = appDir.parentDir / "lib" let candidate3 = getCurrentDir() / "lib" if dirExists(candidate1): return candidate1 if dirExists(candidate2): return candidate2 if dirExists(candidate3): return candidate3 return "lib" proc compileFile*(inputPath: string, outputPath: string) = let source = readFile(inputPath) let forms = reader.readAll(source) if forms.len == 0: stderr.writeLine("Error: No forms found in " & inputPath) quit(1) let nimCode = emitter.emitProgram(forms) writeFile(outputPath, nimCode) echo "Generated: ", outputPath proc nimCompile(nimPath: string, binPath: string, release: bool = false): int = let libPath = getLibPath() var cmd = "nim c" if release: cmd.add(" -d:release") cmd.add(" --path:" & quoteShell(libPath)) cmd.add(" -o:" & quoteShell(binPath) & " " & quoteShell(nimPath)) echo "Compiling: ", cmd execCmd(cmd) proc runFile*(inputPath: string) = let tmpDir = getTempDir() let baseName = inputPath.splitFile.name let nimPath = tmpDir / baseName & "_generated.nim" let binPath = tmpDir / baseName & "_generated" compileFile(inputPath, nimPath) let compileResult = nimCompile(nimPath, binPath) if compileResult != 0: stderr.writeLine("Compilation failed") quit(1) let runResult = execCmd(binPath) if runResult != 0: stderr.writeLine("Execution failed") quit(1) proc main() = let args = commandLineParams() if args.len == 0: echo "Clojure/Nim — AI-First Clojure Compiler" echo "" echo "Usage:" echo " cljnim compile [output.nim] Compile to Nim source" echo " cljnim run Compile and run binary" echo " cljnim read Parse and print AST" echo " cljnim repl [--json] Start REPL (human or AI mode)" echo " cljnim -e '' Evaluate expression" echo "" echo "REPL Commands:" echo " :quit, :q Exit REPL" echo " :defs List defined vars" echo " :clear Clear definitions" echo " :ns Show current namespace" echo "" echo "AI Mode (JSON):" echo " cljnim repl --json" echo " Input: {\"op\":\"eval\",\"form\":\"(+ 1 2)\"}" echo " Output: {\"status\":\"ok\",\"result\":{...},\"meta\":{...}}" quit(0) let cmd = args[0] # Handle -e flag if cmd == "-e": if args.len < 2: stderr.writeLine("Error: Missing expression after -e") quit(1) let code = args[1] let tmpDir = getTempDir() let nimPath = tmpDir / "cljnim_expr.nim" let binPath = tmpDir / "cljnim_expr" let forms = reader.readAll(code) let nimCode = emitter.emitProgram(forms) writeFile(nimPath, nimCode) let compileResult = nimCompile(nimPath, binPath) if compileResult != 0: stderr.writeLine("Compilation failed") quit(1) let runResult = execCmd(binPath) quit(runResult) case cmd of "compile": if args.len < 2: stderr.writeLine("Error: Missing input file") quit(1) let inputPath = args[1] let outputPath = if args.len >= 3: args[2] else: inputPath.changeFileExt("nim") compileFile(inputPath, outputPath) of "run": if args.len < 2: stderr.writeLine("Error: Missing input file") quit(1) runFile(args[1]) of "read": if args.len < 2: stderr.writeLine("Error: Missing input file") quit(1) let source = readFile(args[1]) let forms = reader.readAll(source) for form in forms: echo $form of "repl": var mode = rmHuman for i in 1..