# Jolt Compiler Tests — Phase 2 # Tests for source-to-source Clojure→Janet compilation. # Core ops: const, do, if, def, fn, let, invoke # Phase 2 adds: symbol classification with binding awareness (use ../src/jolt/compiler) (use ../src/jolt/reader) (defn compile-str [s] (let [form (parse-string s)] (compile-form form))) # ============================================================ # 1. Literals (const) # ============================================================ (print "1: literal constants...") (assert (= "42" (compile-str "42")) "integer") (assert (= "nil" (compile-str "nil")) "nil") (assert (= "true" (compile-str "true")) "true") (assert (= "false" (compile-str "false")) "false") (assert (= "\"hello\"" (compile-str "\"hello\"")) "string") (assert (= ":foo" (compile-str ":foo")) "keyword") (print " passed") # ============================================================ # 2. do # ============================================================ (print "2: do...") (assert (= "(do 1 2)" (compile-str "(do 1 2)")) "do two exprs") (assert (= "(do 42)" (compile-str "(do 42)")) "do single expr") (assert (= "(do (core-inc 1) (core-inc 2))" (compile-str "(do (inc 1) (inc 2))")) "do with fn calls") (print " passed") # ============================================================ # 3. if # ============================================================ (print "3: if...") (assert (= "(if true 1 2)" (compile-str "(if true 1 2)")) "if three-arg") (assert (= "(if false 1 nil)" (compile-str "(if false 1)")) "if two-arg") (print " passed") # ============================================================ # 4. def # ============================================================ (print "4: def...") (assert (= "(def x 42)" (compile-str "(def x 42)")) "def constant") (assert (= "(def f (fn [x] (core-inc x)))" (compile-str "(def f (fn* [x] (inc x)))")) "def with fn") (print " passed") # ============================================================ # 5. fn # ============================================================ (print "5: fn...") (assert (= "(fn [x] (core-inc x))" (compile-str "(fn* [x] (inc x))")) "fn single arity") (assert (= "(fn [] 42)" (compile-str "(fn* [] 42)")) "fn no args") (assert (= "(fn [x] (do (core-print x) (core-inc x)))" (compile-str "(fn* [x] (print x) (inc x))")) "fn multi-expr body") (print " passed") # ============================================================ # 6. let # ============================================================ (print "6: let...") (assert (= "(let [x 1] (core-inc x))" (compile-str "(let* [x 1] (inc x))")) "let single binding") (assert (= "(let [x 1 y 2] (core-+ x y))" (compile-str "(let* [x 1 y 2] (+ x y))")) "let two bindings") (assert (= "(let [x (core-inc 1)] (core-inc x))" (compile-str "(let* [x (inc 1)] (inc x))")) "let with fn in binding") (print " passed") # ============================================================ # 7. invoke (function calls) # ============================================================ (print "7: invoke...") (assert (= "(core-inc 1)" (compile-str "(inc 1)")) "inc call") (assert (= "(core-+ 1 2)" (compile-str "(+ 1 2)")) "+ call") (assert (= "(core-+ (core-inc 1) 2)" (compile-str "(+ (inc 1) 2)")) "nested calls") (assert (= "(core-map core-inc (core-vec 1 2 3))" (compile-str "(map inc (vec 1 2 3))")) "multi-arg call") (print " passed") # ============================================================ # 8. Local symbol classification (Phase 2) # ============================================================ (print "8: local classification...") # Shadowing: local inc should NOT be rewritten to core-inc (assert (= "(let [inc 5] (inc inc))" (compile-str "(let* [inc 5] (inc inc))")) "local shadows core fn") # fn params are locals, not core symbols (assert (= "(fn [map] (core-vec map))" (compile-str "(fn* [map] (vec map))")) "fn param shadows core map") # nested let with shadowing (assert (= "(let [x 1] (let [inc x] (inc x)))" (compile-str "(let* [x 1] (let* [inc x] (inc x)))")) "nested let local") (print " passed") (print "\nAll compiler Phase 2 tests passed!")