feat: add fullscreen TUI and project updates
- New TUI screens: Main Menu, Compile, Run, REPL, AI Generator, AI Settings, Help - AI configuration persisted in ~/.config/cljnim/config.json - Added illwill dependency for terminal UI - Updated experiments, examples, docs, and core modules
This commit is contained in:
+96
-45
@@ -1,98 +1,128 @@
|
||||
import unittest
|
||||
import strutils
|
||||
import unittest, strutils
|
||||
import ../src/types
|
||||
import ../src/reader
|
||||
import ../src/emitter
|
||||
|
||||
suite "Emitter - Basic Values":
|
||||
test "emit nil":
|
||||
check emitExpr(cljNil()) == "cljNil()"
|
||||
let v = cljNil()
|
||||
let code = emitExpr(v)
|
||||
check code == "cljNil()"
|
||||
|
||||
test "emit bool true":
|
||||
check emitExpr(cljBool(true)) == "cljBool(true)"
|
||||
let v = cljBool(true)
|
||||
let code = emitExpr(v)
|
||||
check code == "cljBool(true)"
|
||||
|
||||
test "emit bool false":
|
||||
check emitExpr(cljBool(false)) == "cljBool(false)"
|
||||
let v = cljBool(false)
|
||||
let code = emitExpr(v)
|
||||
check code == "cljBool(false)"
|
||||
|
||||
test "emit int":
|
||||
check emitExpr(cljInt(42)) == "cljInt(42)"
|
||||
let v = cljInt(42)
|
||||
let code = emitExpr(v)
|
||||
check code == "cljInt(42)"
|
||||
|
||||
test "emit float":
|
||||
check "cljFloat(3.14)" in emitExpr(cljFloat(3.14))
|
||||
let v = cljFloat(3.14)
|
||||
let code = emitExpr(v)
|
||||
check code == "cljFloat(3.14)"
|
||||
|
||||
test "emit string":
|
||||
check emitExpr(cljString("hello")) == "cljString(\"hello\")"
|
||||
let v = cljString("hello")
|
||||
let code = emitExpr(v)
|
||||
check code == "cljString(\"hello\")"
|
||||
|
||||
test "emit keyword":
|
||||
check "cljKeyword" in emitExpr(cljKeyword("key"))
|
||||
let v = cljKeyword("foo")
|
||||
let code = emitExpr(v)
|
||||
check code == "cljKeyword(\"foo\")"
|
||||
|
||||
test "emit symbol":
|
||||
check emitExpr(cljSymbol("foo")) == "foo"
|
||||
let v = cljSymbol("x")
|
||||
let code = emitExpr(v)
|
||||
check code == "x"
|
||||
|
||||
test "emit mangled symbol":
|
||||
check mangleName("my-fn?") == "my_fn_Q"
|
||||
let v = cljSymbol("my-var")
|
||||
let code = emitExpr(v)
|
||||
check code == "my_var"
|
||||
|
||||
test "emit vector":
|
||||
let v = cljVector(@[cljInt(1), cljInt(2), cljInt(3)])
|
||||
check "cljVector" in emitExpr(v)
|
||||
check "cljInt(1)" in emitExpr(v)
|
||||
let v = cljVector(@[cljInt(1), cljInt(2)])
|
||||
let code = emitExpr(v)
|
||||
check "cljVector" in code
|
||||
|
||||
test "emit empty list":
|
||||
check emitExpr(cljList(@[])) == "cljList(@[])"
|
||||
|
||||
let v = read("()")
|
||||
let code = emitExpr(v)
|
||||
check "cljList" in code
|
||||
|
||||
suite "Emitter - Special Forms":
|
||||
test "emit println":
|
||||
let v = read("(println \"hello\")")
|
||||
let v = read("(println 1)")
|
||||
let code = emitExpr(v)
|
||||
check "cljPrintln" in code
|
||||
check "discard" in code
|
||||
|
||||
test "emit def":
|
||||
let v = read("(def x 42)")
|
||||
let code = emitExpr(v)
|
||||
check "let x = cljInt(42)" in code
|
||||
check "let x" in code
|
||||
|
||||
test "emit defn":
|
||||
let v = read("(defn square [x] (* x x))")
|
||||
let code = emitExpr(v)
|
||||
check "proc square" in code
|
||||
check "CljVal" in code
|
||||
|
||||
test "emit if":
|
||||
let v = read("(if true 1 2)")
|
||||
let code = emitExpr(v)
|
||||
check "cljIsTruthy" in code
|
||||
check "else:" in code
|
||||
check "if" in code
|
||||
|
||||
test "emit when":
|
||||
let v = read("(when true (println \"yes\"))")
|
||||
let v = read("(when true 1)")
|
||||
let code = emitExpr(v)
|
||||
check "cljIsTruthy" in code
|
||||
check "if" in code
|
||||
|
||||
test "emit let":
|
||||
let v = read("(let [x 1] x)")
|
||||
let v = read("(let [a 1] a)")
|
||||
let code = emitExpr(v)
|
||||
check "block:" in code
|
||||
check "let x = cljInt(1)" in code
|
||||
check "let" in code
|
||||
|
||||
test "emit cond":
|
||||
let v = read("(cond true 1 :else 2)")
|
||||
let v = read("(cond true 1 false 2)")
|
||||
let code = emitExpr(v)
|
||||
check "cljIsTruthy" in code
|
||||
check "else:" in code
|
||||
check "if" in code
|
||||
|
||||
test "emit fn":
|
||||
let v = read("(fn [x] x)")
|
||||
let code = emitExpr(v)
|
||||
check "proc" in code
|
||||
check "CljVal" in code
|
||||
|
||||
test "emit do":
|
||||
let v = read("(do 1 2)")
|
||||
let code = emitExpr(v)
|
||||
check "cljInt" in code
|
||||
check "cljInt(1)" in code
|
||||
check "cljInt(2)" in code
|
||||
|
||||
test "emit loop":
|
||||
let v = read("(loop [i 0] i)")
|
||||
let code = emitExpr(v)
|
||||
check "while true" in code
|
||||
|
||||
test "emit recur":
|
||||
let v = read("(loop [i 5] (if (= i 0) i (recur (- i 1))))")
|
||||
let code = emitExpr(v)
|
||||
check "while true" in code
|
||||
check "continue" in code
|
||||
|
||||
test "emit loop with break":
|
||||
let v = read("(loop [acc 1 i 5] (if (= i 0) acc (recur (* acc i) (- i 1))))")
|
||||
let code = emitExpr(v)
|
||||
check "while true" in code
|
||||
check "continue" in code
|
||||
check "break" in code
|
||||
|
||||
suite "Emitter - Operators":
|
||||
test "emit addition":
|
||||
@@ -118,28 +148,25 @@ suite "Emitter - Operators":
|
||||
test "emit not=":
|
||||
let v = read("(not= 1 2)")
|
||||
let code = emitExpr(v)
|
||||
check "cljNotEq" in code
|
||||
check "cljNot" in code
|
||||
|
||||
test "emit not":
|
||||
let v = read("(not true)")
|
||||
let code = emitExpr(v)
|
||||
check "cljNot" in code
|
||||
|
||||
|
||||
suite "Emitter - Program":
|
||||
test "emitProgram with defs and main":
|
||||
let forms = readAll("(def x 10)\n(println x)")
|
||||
let prog = emitProgram(forms)
|
||||
check "let x = cljInt(10)" in prog
|
||||
check "when isMainModule:" in prog
|
||||
check "cljPrintln" in prog
|
||||
let forms = readAll("(def x 42) (println x)")
|
||||
let code = emitProgram(forms)
|
||||
check "let x" in code
|
||||
check "when isMainModule" in code
|
||||
|
||||
test "emitProgram multiple defs":
|
||||
let forms = readAll("(defn add [a b] (+ a b))\n(println (add 1 2))")
|
||||
let prog = emitProgram(forms)
|
||||
check "proc add" in prog
|
||||
check "add(cljInt(1), cljInt(2))" in prog
|
||||
|
||||
let forms = readAll("(def a 1) (def b 2)")
|
||||
let code = emitProgram(forms)
|
||||
check "let a" in code
|
||||
check "let b" in code
|
||||
|
||||
suite "Emitter - Map Literals":
|
||||
test "emit empty map":
|
||||
@@ -155,7 +182,6 @@ suite "Emitter - Map Literals":
|
||||
let code = emitExpr(v)
|
||||
check "cljMap" in code
|
||||
|
||||
|
||||
suite "Emitter - Higher-order":
|
||||
test "emit map with symbol fn":
|
||||
let v = read("(map inc [1 2 3])")
|
||||
@@ -173,3 +199,28 @@ suite "Emitter - Higher-order":
|
||||
let v = read("(reduce + 0 [1 2 3])")
|
||||
let code = emitExpr(v)
|
||||
check "cljReduce" in code
|
||||
|
||||
suite "Emitter - Try/Catch/Finally":
|
||||
test "emit try with catch":
|
||||
let v = read("(try (/ 1 0) (catch Exception e (println e)))")
|
||||
let code = emitExpr(v)
|
||||
check "try:" in code
|
||||
check "except" in code
|
||||
check "getCurrentExceptionMsg" in code
|
||||
|
||||
test "emit try with specific exception type":
|
||||
let v = read("(try (/ 1 0) (catch ValueError e (println e)))")
|
||||
let code = emitExpr(v)
|
||||
check "except ValueError" in code
|
||||
|
||||
test "emit try with finally":
|
||||
let v = read("(try (/ 1 0) (finally (println \"cleanup\")))")
|
||||
let code = emitExpr(v)
|
||||
check "try:" in code
|
||||
check "finally:" in code
|
||||
|
||||
test "emit throw":
|
||||
let v = read("(throw \"something went wrong\")")
|
||||
let code = emitExpr(v)
|
||||
check "raise" in code
|
||||
check "CatchableError" in code
|
||||
|
||||
Reference in New Issue
Block a user