Add (param :as type) annotations to all fn/lambda params across SX spec
Extend the type annotation system from defcomp-only to fn/lambda params: - Infrastructure: sf-lambda, py/js-collect-params-loop, and bootstrap_py.py now recognize (name :as type) in param lists, extracting just the name - bootstrap_py.py: add _extract_param_name() helper, fix _emit_for_each_stmt - 521 type annotations across 22 .sx spec files (eval, types, adapters, transpilers, engine, orchestration, deps, signals, router, prove, etc.) - Zero behavioral change: annotations are metadata for static analysis only - All bootstrappers (Python, JS, G1) pass, 81/81 spec tests pass Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
|
||||
;; Evaluate an SMT-LIB expression in a variable environment
|
||||
(define smt-eval
|
||||
(fn (expr env)
|
||||
(fn (expr (env :as dict))
|
||||
(cond
|
||||
;; Numbers
|
||||
(number? expr) expr
|
||||
@@ -136,11 +136,11 @@
|
||||
|
||||
;; Bind parameter names to values
|
||||
(define smt-bind-params
|
||||
(fn (params vals)
|
||||
(fn ((params :as list) (vals :as list))
|
||||
(smt-bind-loop params vals {})))
|
||||
|
||||
(define smt-bind-loop
|
||||
(fn (params vals acc)
|
||||
(fn ((params :as list) (vals :as list) (acc :as dict))
|
||||
(if (or (empty? params) (empty? vals))
|
||||
acc
|
||||
(smt-bind-loop (rest params) (rest vals)
|
||||
@@ -153,11 +153,11 @@
|
||||
|
||||
;; Extract declarations and assertions from parsed SMT-LIB
|
||||
(define smt-extract-statements
|
||||
(fn (exprs)
|
||||
(fn ((exprs :as list))
|
||||
(smt-extract-loop exprs {} (list))))
|
||||
|
||||
(define smt-extract-loop
|
||||
(fn (exprs decls assertions)
|
||||
(fn ((exprs :as list) (decls :as dict) (assertions :as list))
|
||||
(if (empty? exprs)
|
||||
{:decls decls :assertions assertions}
|
||||
(let ((expr (first exprs))
|
||||
@@ -286,7 +286,7 @@
|
||||
|
||||
;; Verify a single definitional assertion by construction + evaluation
|
||||
(define smt-verify-definition
|
||||
(fn (def-info decls)
|
||||
(fn ((def-info :as dict) (decls :as dict))
|
||||
(let ((name (get def-info "name"))
|
||||
(params (get def-info "params"))
|
||||
(body (get def-info "body"))
|
||||
@@ -295,10 +295,10 @@
|
||||
;; Build the model: define f = λparams.body
|
||||
(let ((model (assoc decls name {:params params :body body}))
|
||||
;; Select test values matching arity
|
||||
(tests (filter (fn (tv) (= (len tv) n-params)) smt-test-values))
|
||||
(tests (filter (fn ((tv :as list)) (= (len tv) n-params)) smt-test-values))
|
||||
;; Run tests
|
||||
(results (map
|
||||
(fn (test-vals)
|
||||
(fn ((test-vals :as list))
|
||||
(let ((env (merge model (smt-bind-params params test-vals)))
|
||||
;; Evaluate body directly
|
||||
(body-result (smt-eval body env))
|
||||
@@ -311,9 +311,9 @@
|
||||
:equal (= body-result call-result)}))
|
||||
tests)))
|
||||
{:name name
|
||||
:status (if (every? (fn (r) (get r "equal")) results) "sat" "FAIL")
|
||||
:status (if (every? (fn ((r :as dict)) (get r "equal")) results) "sat" "FAIL")
|
||||
:proof "by construction (definition is the model)"
|
||||
:tests-passed (len (filter (fn (r) (get r "equal")) results))
|
||||
:tests-passed (len (filter (fn ((r :as dict)) (get r "equal")) results))
|
||||
:tests-total (len results)
|
||||
:sample (if (empty? results) nil (first results))}))))
|
||||
|
||||
@@ -325,16 +325,16 @@
|
||||
;; Strip SMT-LIB comment lines (starting with ;) and return only actual forms.
|
||||
;; Handles comments that contain ( characters.
|
||||
(define smt-strip-comments
|
||||
(fn (s)
|
||||
(fn ((s :as string))
|
||||
(let ((lines (split s "\n"))
|
||||
(non-comment (filter
|
||||
(fn (line) (not (starts-with? (trim line) ";")))
|
||||
(fn ((line :as string)) (not (starts-with? (trim line) ";")))
|
||||
lines)))
|
||||
(join "\n" non-comment))))
|
||||
|
||||
;; Verify SMT-LIB output (string) — parse, classify, prove
|
||||
(define prove-check
|
||||
(fn (smtlib-str)
|
||||
(fn ((smtlib-str :as string))
|
||||
(let ((parsed (sx-parse (smt-strip-comments smtlib-str)))
|
||||
(stmts (smt-extract-statements parsed))
|
||||
(decls (get stmts "decls"))
|
||||
@@ -351,7 +351,7 @@
|
||||
{:status "unknown"
|
||||
:reason "non-definitional assertion (needs full SMT solver)"}))
|
||||
assertions)))
|
||||
{:status (if (every? (fn (r) (= (get r "status") "sat")) results)
|
||||
{:status (if (every? (fn ((r :as dict)) (= (get r "status") "sat")) results)
|
||||
"sat" "unknown")
|
||||
:assertions (len assertions)
|
||||
:results results})))))
|
||||
@@ -377,7 +377,7 @@
|
||||
|
||||
;; Batch verify: translate and prove all define-* forms
|
||||
(define prove-file
|
||||
(fn (exprs)
|
||||
(fn ((exprs :as list))
|
||||
(let ((translatable
|
||||
(filter
|
||||
(fn (expr)
|
||||
@@ -396,7 +396,7 @@
|
||||
(name (nth expr 1)))
|
||||
(assoc proof "name" name)))
|
||||
translatable))
|
||||
(sat-count (len (filter (fn (r) (= (get r "status") "sat")) results)))
|
||||
(sat-count (len (filter (fn ((r :as dict)) (= (get r "status") "sat")) results)))
|
||||
(total (len results)))
|
||||
{:total total
|
||||
:sat sat-count
|
||||
@@ -424,7 +424,7 @@
|
||||
|
||||
;; Default domain bounds by arity — balance coverage vs. combinatorics
|
||||
(define prove-domain-for
|
||||
(fn (arity)
|
||||
(fn ((arity :as number))
|
||||
(cond
|
||||
(<= arity 1) (range -50 51) ;; 101 values
|
||||
(= arity 2) (range -20 21) ;; 41^2 = 1,681 pairs
|
||||
@@ -433,7 +433,7 @@
|
||||
|
||||
;; Cartesian product: all n-tuples from a domain
|
||||
(define prove-tuples
|
||||
(fn (domain arity)
|
||||
(fn ((domain :as list) (arity :as number))
|
||||
(if (<= arity 0) (list (list))
|
||||
(if (= arity 1)
|
||||
(map (fn (x) (list x)) domain)
|
||||
@@ -441,12 +441,12 @@
|
||||
(prove-tuples-expand domain sub (list)))))))
|
||||
|
||||
(define prove-tuples-expand
|
||||
(fn (domain sub acc)
|
||||
(fn ((domain :as list) (sub :as list) (acc :as list))
|
||||
(if (empty? domain) acc
|
||||
(prove-tuples-expand
|
||||
(rest domain) sub
|
||||
(append acc
|
||||
(map (fn (t) (cons (first domain) t)) sub))))))
|
||||
(map (fn ((t :as list)) (cons (first domain) t)) sub))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -454,7 +454,7 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define prove-call
|
||||
(fn (f vals)
|
||||
(fn ((f :as lambda) (vals :as list))
|
||||
(let ((n (len vals)))
|
||||
(cond
|
||||
(= n 0) (f)
|
||||
@@ -472,13 +472,13 @@
|
||||
;; Search for a counterexample. Returns nil if property holds for all tested
|
||||
;; values, or the first counterexample found.
|
||||
(define prove-search
|
||||
(fn (test-fn given-fn domain vars)
|
||||
(fn ((test-fn :as lambda) given-fn (domain :as list) (vars :as list))
|
||||
(let ((arity (len vars))
|
||||
(tuples (prove-tuples domain arity)))
|
||||
(prove-search-loop test-fn given-fn tuples 0 0))))
|
||||
|
||||
(define prove-search-loop
|
||||
(fn (test-fn given-fn tuples tested skipped)
|
||||
(fn ((test-fn :as lambda) given-fn (tuples :as list) (tested :as number) (skipped :as number))
|
||||
(if (empty? tuples)
|
||||
{:status "verified" :tested tested :skipped skipped}
|
||||
(let ((vals (first tuples))
|
||||
@@ -505,7 +505,7 @@
|
||||
|
||||
;; Verify a single property via bounded model checking
|
||||
(define prove-property
|
||||
(fn (prop)
|
||||
(fn ((prop :as dict))
|
||||
(let ((name (get prop "name"))
|
||||
(vars (get prop "vars"))
|
||||
(test-fn (get prop "test"))
|
||||
@@ -519,10 +519,10 @@
|
||||
|
||||
;; Batch verify a list of properties
|
||||
(define prove-properties
|
||||
(fn (props)
|
||||
(fn ((props :as list))
|
||||
(let ((results (map prove-property props))
|
||||
(verified (filter (fn (r) (= (get r "status") "verified")) results))
|
||||
(falsified (filter (fn (r) (= (get r "status") "falsified")) results)))
|
||||
(verified (filter (fn ((r :as dict)) (= (get r "status") "verified")) results))
|
||||
(falsified (filter (fn ((r :as dict)) (= (get r "status") "falsified")) results)))
|
||||
{:total (len results)
|
||||
:verified (len verified)
|
||||
:falsified (len falsified)
|
||||
@@ -537,13 +537,13 @@
|
||||
;; Generate SMT-LIB for a property — asserts (not (forall ...)) so that
|
||||
;; Z3 returning "unsat" proves the property holds universally.
|
||||
(define prove-property-smtlib
|
||||
(fn (prop)
|
||||
(fn ((prop :as dict))
|
||||
(let ((name (get prop "name"))
|
||||
(vars (get prop "vars"))
|
||||
(holds (get prop "holds"))
|
||||
(given-e (get prop "given-expr" nil))
|
||||
(bindings (join " "
|
||||
(map (fn (v) (str "(" v " Int)")) vars)))
|
||||
(map (fn ((v :as string)) (str "(" v " Int)")) vars)))
|
||||
(holds-smt (z3-expr holds))
|
||||
(body (if (nil? given-e)
|
||||
holds-smt
|
||||
@@ -556,7 +556,7 @@
|
||||
|
||||
;; Generate SMT-LIB for all properties, including necessary definitions
|
||||
(define prove-properties-smtlib
|
||||
(fn (props primitives-exprs)
|
||||
(fn ((props :as list) (primitives-exprs :as list))
|
||||
(let ((defs (z3-translate-file primitives-exprs))
|
||||
(prop-smts (map prove-property-smtlib props)))
|
||||
(str ";; ================================================================\n"
|
||||
|
||||
Reference in New Issue
Block a user