- analyze-form: Clojure forms → annotated AST nodes (:op keys) - emit-ast: AST dispatch → Janet source via StringBuffer - compile-form: analyze → emit → Janet source string - Symbol classification: locals, core refs, qualified refs - Ops: const, do, if, def, fn, let, invoke, quote, vector, map - Local binding awareness in fn* and let* (shadowing works) - All 317 existing tests pass, 24 new compiler tests
95 lines
4.1 KiB
Text
95 lines
4.1 KiB
Text
# 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!")
|