Add (name :as type) annotation syntax for defcomp params
parse-comp-params now recognizes (name :as type) — a 3-element list with :as keyword separator. Type annotations are stored on the Component via component-param-types and used by types.sx for call-site checking. Unannotated params default to any. 428/428 tests pass (50 types tests including 6 annotation tests). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -518,8 +518,13 @@
|
||||
(parsed (parse-comp-params params-raw))
|
||||
(params (first parsed))
|
||||
(has-children (nth parsed 1))
|
||||
(param-types (nth parsed 2))
|
||||
(affinity (defcomp-kwarg args "affinity" "auto")))
|
||||
(let ((comp (make-component comp-name params has-children body env affinity)))
|
||||
;; Store type annotations if any were declared
|
||||
(when (and (not (nil? param-types))
|
||||
(not (empty? (keys param-types))))
|
||||
(component-set-param-types! comp param-types))
|
||||
(env-set! env (symbol-name name-sym) comp)
|
||||
comp))))
|
||||
|
||||
@@ -541,24 +546,44 @@
|
||||
|
||||
(define parse-comp-params
|
||||
(fn (params-expr)
|
||||
;; Parse (&key param1 param2 &children) → (params has-children)
|
||||
;; 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
|
||||
;; the second element is the keyword :as. Unannotated params get no
|
||||
;; type entry. param-types is a dict {name → type-expr} or empty dict.
|
||||
(let ((params (list))
|
||||
(param-types (dict))
|
||||
(has-children false)
|
||||
(in-key false))
|
||||
(for-each
|
||||
(fn (p)
|
||||
(when (= (type-of p) "symbol")
|
||||
(let ((name (symbol-name p)))
|
||||
(cond
|
||||
(= name "&key") (set! in-key true)
|
||||
(= name "&rest") (set! has-children true)
|
||||
(= name "&children") (set! has-children true)
|
||||
has-children nil ;; skip params after &children/&rest
|
||||
in-key (append! params name)
|
||||
:else (append! params name)))))
|
||||
(if (and (= (type-of p) "list")
|
||||
(= (len p) 3)
|
||||
(= (type-of (first p)) "symbol")
|
||||
(= (type-of (nth p 1)) "keyword")
|
||||
(= (keyword-name (nth p 1)) "as"))
|
||||
;; Typed param: (name :as type)
|
||||
(let ((name (symbol-name (first p)))
|
||||
(ptype (nth p 2)))
|
||||
;; Convert type to string if it's a symbol
|
||||
(let ((type-val (if (= (type-of ptype) "symbol")
|
||||
(symbol-name ptype)
|
||||
ptype)))
|
||||
(when (not has-children)
|
||||
(append! params name)
|
||||
(dict-set! param-types name type-val))))
|
||||
;; Untyped param or marker
|
||||
(when (= (type-of p) "symbol")
|
||||
(let ((name (symbol-name p)))
|
||||
(cond
|
||||
(= name "&key") (set! in-key true)
|
||||
(= name "&rest") (set! has-children true)
|
||||
(= name "&children") (set! has-children true)
|
||||
has-children nil ;; skip params after &children/&rest
|
||||
in-key (append! params name)
|
||||
:else (append! params name))))))
|
||||
params-expr)
|
||||
(list params has-children))))
|
||||
(list params has-children param-types))))
|
||||
|
||||
|
||||
(define sf-defisland
|
||||
|
||||
Reference in New Issue
Block a user