Files
bara-lang/src/cljnim.nim
T

147 lines
4.2 KiB
Nim

# 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 <file.clj> [output.nim] Compile to Nim source"
echo " cljnim run <file.clj> Compile and run binary"
echo " cljnim read <file.clj> Parse and print AST"
echo " cljnim repl [--json] Start REPL (human or AI mode)"
echo " cljnim -e '<code>' 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..<args.len:
if args[i] == "--json":
mode = rmJson
elif args[i] == "--edn":
mode = rmEdn
var state = initReplState(mode)
try:
case mode
of rmHuman: runHumanRepl(state)
of rmJson: runJsonRepl(state)
of rmEdn: runJsonRepl(state)
finally:
state.cleanup()
else:
stderr.writeLine("Unknown command: " & cmd)
quit(1)
when isMainModule:
main()