Files
bara-lang/tests/test_emitter.nim
T
dimgigov 456636700c feat: 80/80 unit tests, real-world examples (FizzBuzz, WordFreq)
- Emitter: def registry (definedGlobals) for symbol emit distinction
- Emitter: cond emits return statements
- Emitter: reduce wraps named functions in closure adapter
- Emitter: clojure.string/* function mappings (split, lower-case, etc.)
- Emitter: statement detection for echo cljRepr wrapping
- Runtime: cljGet supports default value (3 args)
- Runtime: cljStrSplit supports regex patterns via re module
- Examples: fizzbuzz.clj and wordfreq.clj both compile and run correctly
- Tests: emit symbol / emit mangled symbol now pass (80/80)
- Compliance: 233/233 (100%) maintained
2026-05-11 10:08:46 +03:00

229 lines
5.5 KiB
Nim

import unittest, strutils
import ../src/types
import ../src/reader
import ../src/emitter
suite "Emitter - Basic Values":
test "emit nil":
let v = cljNil()
let code = emitExpr(v)
check code == "cljNil()"
test "emit bool true":
let v = cljBool(true)
let code = emitExpr(v)
check code == "cljBool(true)"
test "emit bool false":
let v = cljBool(false)
let code = emitExpr(v)
check code == "cljBool(false)"
test "emit int":
let v = cljInt(42)
let code = emitExpr(v)
check code == "cljInt(42)"
test "emit float":
let v = cljFloat(3.14)
let code = emitExpr(v)
check code == "cljFloat(3.14)"
test "emit string":
let v = cljString("hello")
let code = emitExpr(v)
check code == "cljString(\"hello\")"
test "emit keyword":
let v = cljKeyword("foo")
let code = emitExpr(v)
check code == "cljKeyword(\"foo\")"
test "emit symbol":
registerGlobal("x")
let v = cljSymbol("x")
let code = emitExpr(v)
check code == "x"
test "emit mangled symbol":
registerGlobal("my-var")
let v = cljSymbol("my-var")
let code = emitExpr(v)
check code == "my_var"
test "emit vector":
let v = cljVector(@[cljInt(1), cljInt(2)])
let code = emitExpr(v)
check "cljVector" in code
test "emit empty list":
let v = read("()")
let code = emitExpr(v)
check "cljList" in code
suite "Emitter - Special Forms":
test "emit println":
let v = read("(println 1)")
let code = emitExpr(v)
check "cljPrintln" in code
test "emit def":
let v = read("(def x 42)")
let code = emitExpr(v)
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
test "emit if":
let v = read("(if true 1 2)")
let code = emitExpr(v)
check "if" in code
test "emit when":
let v = read("(when true 1)")
let code = emitExpr(v)
check "if" in code
test "emit let":
let v = read("(let [a 1] a)")
let code = emitExpr(v)
check "let" in code
test "emit cond":
let v = read("(cond true 1 false 2)")
let code = emitExpr(v)
check "if" in code
test "emit fn":
let v = read("(fn [x] x)")
let code = emitExpr(v)
check "proc" in code
test "emit do":
let v = read("(do 1 2)")
let code = emitExpr(v)
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":
let v = read("(+ 1 2)")
let code = emitExpr(v)
check "cljAdd" in code
test "emit subtraction":
let v = read("(- 5 3)")
let code = emitExpr(v)
check "cljSub" in code
test "emit multiplication":
let v = read("(* 2 3)")
let code = emitExpr(v)
check "cljMul" in code
test "emit equality":
let v = read("(= 1 1)")
let code = emitExpr(v)
check "cljMultiEqual" in code
test "emit not=":
let v = read("(not= 1 2)")
let code = emitExpr(v)
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 42) (println x)")
let code = emitProgram(forms)
check "let x" in code
check "when isMainModule" in code
test "emitProgram multiple defs":
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":
let v = cljMap(@[], @[])
let code = emitExpr(v)
check "cljMap" in code
test "emit map with entries":
let v = cljMapFromPairs(@[
(cljKeyword("a"), cljInt(1)),
(cljKeyword("b"), cljInt(2))
])
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])")
let code = emitExpr(v)
check "cljMap" in code
check "cljFn" in code
test "emit filter with inline fn":
let v = read("(filter (fn [x] (> x 2)) [1 2 3])")
let code = emitExpr(v)
check "cljFilter" in code
check "cljFn" in code
test "emit reduce":
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