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:
@@ -73,7 +73,7 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define eval-expr
|
||||
(fn (expr env)
|
||||
(fn (expr (env :as dict))
|
||||
(case (type-of expr)
|
||||
|
||||
;; --- literals pass through ---
|
||||
@@ -116,7 +116,7 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define eval-list
|
||||
(fn (expr env)
|
||||
(fn (expr (env :as dict))
|
||||
(let ((head (first expr))
|
||||
(args (rest expr)))
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define eval-call
|
||||
(fn (head args env)
|
||||
(fn (head (args :as list) (env :as dict))
|
||||
(let ((f (trampoline (eval-expr head env)))
|
||||
(evaluated-args (map (fn (a) (trampoline (eval-expr a env))) args)))
|
||||
(cond
|
||||
@@ -215,7 +215,7 @@
|
||||
|
||||
|
||||
(define call-lambda
|
||||
(fn (f args caller-env)
|
||||
(fn ((f :as lambda) (args :as list) (caller-env :as dict))
|
||||
(let ((params (lambda-params f))
|
||||
(local (env-merge (lambda-closure f) caller-env)))
|
||||
;; Too many args is an error; too few pads with nil
|
||||
@@ -235,7 +235,7 @@
|
||||
|
||||
|
||||
(define call-component
|
||||
(fn (comp raw-args env)
|
||||
(fn (comp (raw-args :as list) (env :as dict))
|
||||
;; Parse keyword args and children from unevaluated arg list
|
||||
(let ((parsed (parse-keyword-args raw-args env))
|
||||
(kwargs (first parsed))
|
||||
@@ -253,7 +253,7 @@
|
||||
|
||||
|
||||
(define parse-keyword-args
|
||||
(fn (raw-args env)
|
||||
(fn ((raw-args :as list) (env :as dict))
|
||||
;; Walk args: keyword + next-val → kwargs dict, else → children list
|
||||
(let ((kwargs (dict))
|
||||
(children (list))
|
||||
@@ -287,7 +287,7 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define sf-if
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((condition (trampoline (eval-expr (first args) env))))
|
||||
(if (and condition (not (nil? condition)))
|
||||
(make-thunk (nth args 1) env)
|
||||
@@ -297,7 +297,7 @@
|
||||
|
||||
|
||||
(define sf-when
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((condition (trampoline (eval-expr (first args) env))))
|
||||
(if (and condition (not (nil? condition)))
|
||||
(do
|
||||
@@ -314,18 +314,18 @@
|
||||
;; Checking only the first arg is ambiguous — (nil? x) is a 2-element
|
||||
;; function call, not a scheme clause ((test body)).
|
||||
(define cond-scheme?
|
||||
(fn (clauses)
|
||||
(fn ((clauses :as list))
|
||||
(every? (fn (c) (and (= (type-of c) "list") (= (len c) 2)))
|
||||
clauses)))
|
||||
|
||||
(define sf-cond
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(if (cond-scheme? args)
|
||||
(sf-cond-scheme args env)
|
||||
(sf-cond-clojure args env))))
|
||||
|
||||
(define sf-cond-scheme
|
||||
(fn (clauses env)
|
||||
(fn ((clauses :as list) (env :as dict))
|
||||
(if (empty? clauses)
|
||||
nil
|
||||
(let ((clause (first clauses))
|
||||
@@ -342,7 +342,7 @@
|
||||
(sf-cond-scheme (rest clauses) env)))))))
|
||||
|
||||
(define sf-cond-clojure
|
||||
(fn (clauses env)
|
||||
(fn ((clauses :as list) (env :as dict))
|
||||
(if (< (len clauses) 2)
|
||||
nil
|
||||
(let ((test (first clauses))
|
||||
@@ -358,13 +358,13 @@
|
||||
|
||||
|
||||
(define sf-case
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((match-val (trampoline (eval-expr (first args) env)))
|
||||
(clauses (rest args)))
|
||||
(sf-case-loop match-val clauses env))))
|
||||
|
||||
(define sf-case-loop
|
||||
(fn (match-val clauses env)
|
||||
(fn (match-val (clauses :as list) (env :as dict))
|
||||
(if (< (len clauses) 2)
|
||||
nil
|
||||
(let ((test (first clauses))
|
||||
@@ -380,7 +380,7 @@
|
||||
|
||||
|
||||
(define sf-and
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(if (empty? args)
|
||||
true
|
||||
(let ((val (trampoline (eval-expr (first args) env))))
|
||||
@@ -392,7 +392,7 @@
|
||||
|
||||
|
||||
(define sf-or
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(if (empty? args)
|
||||
false
|
||||
(let ((val (trampoline (eval-expr (first args) env))))
|
||||
@@ -402,7 +402,7 @@
|
||||
|
||||
|
||||
(define sf-let
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
;; Detect named let: (let name ((x 0) ...) body)
|
||||
;; If first arg is a symbol, delegate to sf-named-let.
|
||||
(if (= (type-of (first args)) "symbol")
|
||||
@@ -443,7 +443,7 @@
|
||||
;; Desugars to a self-recursive lambda called with initial values.
|
||||
;; The loop name is bound in the body so recursive calls produce TCO thunks.
|
||||
(define sf-named-let
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((loop-name (symbol-name (first args)))
|
||||
(bindings (nth args 1))
|
||||
(body (slice args 2))
|
||||
@@ -483,22 +483,29 @@
|
||||
|
||||
|
||||
(define sf-lambda
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((params-expr (first args))
|
||||
(body-exprs (rest args))
|
||||
(body (if (= (len body-exprs) 1)
|
||||
(first body-exprs)
|
||||
(cons (make-symbol "begin") body-exprs)))
|
||||
(param-names (map (fn (p)
|
||||
(if (= (type-of p) "symbol")
|
||||
(symbol-name p)
|
||||
p))
|
||||
(cond
|
||||
(= (type-of p) "symbol")
|
||||
(symbol-name p)
|
||||
;; Annotated param: (name :as type) → extract name
|
||||
(and (= (type-of p) "list")
|
||||
(= (len p) 3)
|
||||
(= (type-of (nth p 1)) "keyword")
|
||||
(= (keyword-name (nth p 1)) "as"))
|
||||
(symbol-name (first p))
|
||||
:else p))
|
||||
params-expr)))
|
||||
(make-lambda param-names body env))))
|
||||
|
||||
|
||||
(define sf-define
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((name-sym (first args))
|
||||
(value (trampoline (eval-expr (nth args 1) env))))
|
||||
(when (and (lambda? value) (nil? (lambda-name value)))
|
||||
@@ -508,7 +515,7 @@
|
||||
|
||||
|
||||
(define sf-defcomp
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
;; (defcomp ~name (params) [:affinity :client|:server] body)
|
||||
;; Body is always the last element. Optional keyword annotations
|
||||
;; may appear between the params list and the body.
|
||||
@@ -530,7 +537,7 @@
|
||||
comp))))
|
||||
|
||||
(define defcomp-kwarg
|
||||
(fn (args key default)
|
||||
(fn ((args :as list) (key :as string) default)
|
||||
;; Search for :key value between params (index 2) and body (last).
|
||||
(let ((end (- (len args) 1))
|
||||
(result default))
|
||||
@@ -546,7 +553,7 @@
|
||||
result)))
|
||||
|
||||
(define parse-comp-params
|
||||
(fn (params-expr)
|
||||
(fn ((params-expr :as list))
|
||||
;; Parse (&key param1 param2 &children) → (params has-children param-types)
|
||||
;; Also accepts &rest as synonym for &children.
|
||||
;; Supports typed params: (name :as type) — a 3-element list where
|
||||
@@ -588,7 +595,7 @@
|
||||
|
||||
|
||||
(define sf-defisland
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
;; (defisland ~name (params) body)
|
||||
;; Like defcomp but creates an island (reactive component).
|
||||
;; Islands have the same calling convention as components but
|
||||
@@ -606,7 +613,7 @@
|
||||
|
||||
|
||||
(define sf-defmacro
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((name-sym (first args))
|
||||
(params-raw (nth args 1))
|
||||
(body (nth args 2))
|
||||
@@ -618,7 +625,7 @@
|
||||
mac))))
|
||||
|
||||
(define parse-macro-params
|
||||
(fn (params-expr)
|
||||
(fn ((params-expr :as list))
|
||||
;; Parse (a b &rest rest) → ((a b) rest)
|
||||
(let ((params (list))
|
||||
(rest-param nil))
|
||||
@@ -639,7 +646,7 @@
|
||||
|
||||
|
||||
(define sf-defstyle
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
;; (defstyle name expr) — bind name to evaluated expr (string, function, etc.)
|
||||
(let ((name-sym (first args))
|
||||
(value (trampoline (eval-expr (nth args 1) env))))
|
||||
@@ -648,7 +655,7 @@
|
||||
|
||||
|
||||
(define sf-begin
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(if (empty? args)
|
||||
nil
|
||||
(do
|
||||
@@ -659,16 +666,16 @@
|
||||
|
||||
|
||||
(define sf-quote
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(if (empty? args) nil (first args))))
|
||||
|
||||
|
||||
(define sf-quasiquote
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(qq-expand (first args) env)))
|
||||
|
||||
(define qq-expand
|
||||
(fn (template env)
|
||||
(fn (template (env :as dict))
|
||||
(if (not (= (type-of template) "list"))
|
||||
template
|
||||
(if (empty? template)
|
||||
@@ -693,7 +700,7 @@
|
||||
|
||||
|
||||
(define sf-thread-first
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((val (trampoline (eval-expr (first args) env))))
|
||||
(reduce
|
||||
(fn (result form)
|
||||
@@ -720,7 +727,7 @@
|
||||
|
||||
|
||||
(define sf-set!
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((name (symbol-name (first args)))
|
||||
(value (trampoline (eval-expr (nth args 1) env))))
|
||||
(env-set! env name value)
|
||||
@@ -741,7 +748,7 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define sf-letrec
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((bindings (first args))
|
||||
(body (rest args))
|
||||
(local (env-extend env))
|
||||
@@ -816,7 +823,7 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define sf-dynamic-wind
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((before (trampoline (eval-expr (first args) env)))
|
||||
(body (trampoline (eval-expr (nth args 1) env)))
|
||||
(after (trampoline (eval-expr (nth args 2) env))))
|
||||
@@ -835,7 +842,7 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define expand-macro
|
||||
(fn (mac raw-args env)
|
||||
(fn ((mac :as macro) (raw-args :as list) (env :as dict))
|
||||
(let ((local (env-merge (macro-closure mac) env)))
|
||||
;; Bind positional params (unevaluated)
|
||||
(for-each
|
||||
@@ -859,20 +866,20 @@
|
||||
|
||||
;; call-fn: unified caller for HO forms — handles both Lambda and native callable
|
||||
(define call-fn
|
||||
(fn (f args env)
|
||||
(fn (f (args :as list) (env :as dict))
|
||||
(cond
|
||||
(lambda? f) (trampoline (call-lambda f args env))
|
||||
(callable? f) (apply f args)
|
||||
:else (error (str "Not callable in HO form: " (inspect f))))))
|
||||
|
||||
(define ho-map
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(map (fn (item) (call-fn f (list item) env)) coll))))
|
||||
|
||||
(define ho-map-indexed
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(map-indexed
|
||||
@@ -880,7 +887,7 @@
|
||||
coll))))
|
||||
|
||||
(define ho-filter
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(filter
|
||||
@@ -888,7 +895,7 @@
|
||||
coll))))
|
||||
|
||||
(define ho-reduce
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(init (trampoline (eval-expr (nth args 1) env)))
|
||||
(coll (trampoline (eval-expr (nth args 2) env))))
|
||||
@@ -898,7 +905,7 @@
|
||||
coll))))
|
||||
|
||||
(define ho-some
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(some
|
||||
@@ -906,7 +913,7 @@
|
||||
coll))))
|
||||
|
||||
(define ho-every
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(every?
|
||||
@@ -915,7 +922,7 @@
|
||||
|
||||
|
||||
(define ho-for-each
|
||||
(fn (args env)
|
||||
(fn ((args :as list) (env :as dict))
|
||||
(let ((f (trampoline (eval-expr (first args) env)))
|
||||
(coll (trampoline (eval-expr (nth args 1) env))))
|
||||
(for-each
|
||||
|
||||
Reference in New Issue
Block a user