Step 5 piece 6: migrate 23 .sx files to define-library/import
Wraps all core .sx files in R7RS define-library with explicit export lists, plus (import ...) at end for backward-compatible global re-export. Libraries registered: (sx bytecode) — 83 opcode constants (sx render) — 15 tag registries + render helpers (sx signals) — 23 reactive signal primitives (sx r7rs) — 21 R7RS aliases (sx compiler) — 42 compiler functions (sx vm) — 32 VM functions (sx freeze) — 9 freeze/thaw functions (sx content) — 6 content store functions (sx callcc) — 1 call/cc wrapper (sx highlight) — 13 syntax highlighting functions (sx stdlib) — 47 stdlib functions (sx swap) — 13 swap algebra functions (sx render-trace) — 8 render trace functions (sx harness) — 21 test harness functions (sx canonical) — 12 canonical serialization functions (web adapter-html) — 13 HTML renderer functions (web adapter-sx) — 13 SX wire format functions (web engine) — 33 hypermedia engine functions (web request-handler) — 4 request handling functions (web page-helpers) — 12 page helper functions (web router) — 36 routing functions (web deps) — 19 dependency analysis functions (web orchestration) — 59 page orchestration functions Key changes: - define-library now inherits parent env (env-extend env instead of env-extend make-env) so library bodies can access platform primitives - sx_server.ml: added resolve_library_path + load_library_file for import resolution (maps library specs to file paths) - cek_run_with_io: handles "import" locally instead of sending to Python bridge 2608/2608 tests passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -280,10 +280,44 @@ let flush_batched_io result_str =
|
||||
!final
|
||||
end
|
||||
|
||||
(** Resolve a library spec to a file path.
|
||||
(sx render) → spec/render.sx, (sx bytecode) → lib/bytecode.sx, etc.
|
||||
Returns Some path or None if unknown. *)
|
||||
let _lib_base = ref "lib"
|
||||
let _spec_base = ref "spec"
|
||||
let _web_base = ref "web"
|
||||
|
||||
let resolve_library_path lib_spec =
|
||||
let parts = match lib_spec with List l | ListRef { contents = l } -> l | _ -> [] in
|
||||
match List.map (fun v -> match v with Symbol s -> s | String s -> s | _ -> "") parts with
|
||||
| ["sx"; name] ->
|
||||
(* Check spec/ first, then lib/ *)
|
||||
let spec_path = Filename.concat !_spec_base (name ^ ".sx") in
|
||||
let lib_path = Filename.concat !_lib_base (name ^ ".sx") in
|
||||
if Sys.file_exists spec_path then Some spec_path
|
||||
else if Sys.file_exists lib_path then Some lib_path
|
||||
else None
|
||||
| ["web"; name] ->
|
||||
let path = Filename.concat !_web_base (name ^ ".sx") in
|
||||
if Sys.file_exists path then Some path else None
|
||||
| [prefix; name] ->
|
||||
(* Generic: try prefix/name.sx *)
|
||||
let path = Filename.concat prefix (name ^ ".sx") in
|
||||
if Sys.file_exists path then Some path else None
|
||||
| _ -> None
|
||||
|
||||
(** Load a library file — parse and evaluate all expressions in the global env.
|
||||
The file should contain a define-library form that registers itself. *)
|
||||
let _import_env : env option ref = ref None
|
||||
|
||||
let load_library_file path =
|
||||
let env = match !_import_env with Some e -> e | None -> Sx_types.make_env () in
|
||||
let exprs = Sx_parser.parse_file path in
|
||||
List.iter (fun expr -> ignore (Sx_ref.eval_expr expr (Env env))) exprs
|
||||
|
||||
(** IO-aware CEK run — handles suspension by dispatching IO requests.
|
||||
When the CEK machine suspends with a perform, this function sends
|
||||
the IO request to the Python bridge, resumes with the response,
|
||||
and repeats until evaluation completes. *)
|
||||
Import requests are handled locally (load .sx file).
|
||||
Other IO requests are sent to the Python bridge. *)
|
||||
let cek_run_with_io state =
|
||||
let s = ref state in
|
||||
let is_terminal s = match Sx_ref.cek_terminal_p s with Bool true -> true | _ -> false in
|
||||
@@ -295,16 +329,27 @@ let cek_run_with_io state =
|
||||
if is_suspended !s then begin
|
||||
let request = Sx_runtime.get_val !s (String "request") in
|
||||
let op = match Sx_runtime.get_val request (String "op") with String s -> s | _ -> "" in
|
||||
(* Extract args based on operation type *)
|
||||
let args = match op with
|
||||
let response = match op with
|
||||
| "import" ->
|
||||
let lib = Sx_runtime.get_val request (String "library") in
|
||||
[String "import"; lib]
|
||||
(* Resolve library locally — load the .sx file *)
|
||||
let lib_spec = Sx_runtime.get_val request (String "library") in
|
||||
let key = Sx_ref.library_name_key lib_spec in
|
||||
if Sx_types.sx_truthy (Sx_ref.library_loaded_p key) then
|
||||
(* Already loaded — just resume *)
|
||||
Nil
|
||||
else begin
|
||||
(match resolve_library_path lib_spec with
|
||||
| Some path -> load_library_file path
|
||||
| None ->
|
||||
Printf.eprintf "[import] WARNING: no file for library %s\n%!"
|
||||
(Sx_runtime.value_to_str lib_spec));
|
||||
Nil
|
||||
end
|
||||
| _ ->
|
||||
let a = Sx_runtime.get_val request (String "args") in
|
||||
(match a with List l -> l | _ -> [a])
|
||||
let args = let a = Sx_runtime.get_val request (String "args") in
|
||||
(match a with List l -> l | _ -> [a]) in
|
||||
io_request op args
|
||||
in
|
||||
let response = io_request op args in
|
||||
s := Sx_ref.cek_resume !s response;
|
||||
loop ()
|
||||
end else
|
||||
|
||||
@@ -503,7 +503,7 @@ and step_eval_list expr env kont =
|
||||
|
||||
(* step-sf-define-library *)
|
||||
and step_sf_define_library args env kont =
|
||||
(let lib_spec = (first (args)) in let decls = (rest (args)) in (let lib_env = (env_extend ((make_env ()))) in let exports = ref ((List [])) in let body_forms = ref ((List [])) in (let () = ignore ((List.iter (fun decl -> ignore ((if sx_truthy ((let _and = (list_p (decl)) in if not (sx_truthy _and) then _and else (let _and = (Bool (not (sx_truthy ((empty_p (decl)))))) in if not (sx_truthy _and) then _and else (symbol_p ((first (decl))))))) then (let kind = (symbol_name ((first (decl)))) in (if sx_truthy ((prim_call "=" [kind; (String "export")])) then (exports := (prim_call "append" [!exports; (List (List.map (fun s -> (if sx_truthy ((symbol_p (s))) then (symbol_name (s)) else (String (sx_str [s])))) (sx_to_list (rest (decl)))))]); Nil) else (if sx_truthy ((prim_call "=" [kind; (String "begin")])) then (body_forms := (prim_call "append" [!body_forms; (rest (decl))]); Nil) else Nil))) else Nil))) (sx_to_list decls); Nil)) in (let () = ignore ((List.iter (fun form -> ignore ((eval_expr (form) (lib_env)))) (sx_to_list !body_forms); Nil)) in (let export_dict = (Dict (Hashtbl.create 0)) in (let () = ignore ((List.iter (fun name -> ignore ((if sx_truthy ((env_has (lib_env) (name))) then (sx_dict_set_b export_dict name (env_get (lib_env) (name))) else Nil))) (sx_to_list !exports); Nil)) in (let () = ignore ((register_library (lib_spec) (export_dict))) in (make_cek_value (Nil) (env) (kont)))))))))
|
||||
(let lib_spec = (first (args)) in let decls = (rest (args)) in (let lib_env = (env_extend (env)) in let exports = ref ((List [])) in let body_forms = ref ((List [])) in (let () = ignore ((List.iter (fun decl -> ignore ((if sx_truthy ((let _and = (list_p (decl)) in if not (sx_truthy _and) then _and else (let _and = (Bool (not (sx_truthy ((empty_p (decl)))))) in if not (sx_truthy _and) then _and else (symbol_p ((first (decl))))))) then (let kind = (symbol_name ((first (decl)))) in (if sx_truthy ((prim_call "=" [kind; (String "export")])) then (exports := (prim_call "append" [!exports; (List (List.map (fun s -> (if sx_truthy ((symbol_p (s))) then (symbol_name (s)) else (String (sx_str [s])))) (sx_to_list (rest (decl)))))]); Nil) else (if sx_truthy ((prim_call "=" [kind; (String "begin")])) then (body_forms := (prim_call "append" [!body_forms; (rest (decl))]); Nil) else Nil))) else Nil))) (sx_to_list decls); Nil)) in (let () = ignore ((List.iter (fun form -> ignore ((eval_expr (form) (lib_env)))) (sx_to_list !body_forms); Nil)) in (let export_dict = (Dict (Hashtbl.create 0)) in (let () = ignore ((List.iter (fun name -> ignore ((if sx_truthy ((env_has (lib_env) (name))) then (sx_dict_set_b export_dict name (env_get (lib_env) (name))) else Nil))) (sx_to_list !exports); Nil)) in (let () = ignore ((register_library (lib_spec) (export_dict))) in (make_cek_value (Nil) (env) (kont)))))))))
|
||||
|
||||
(* bind-import-set *)
|
||||
and bind_import_set import_set env =
|
||||
|
||||
@@ -19,6 +19,94 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
;; Stack / Constants
|
||||
|
||||
(define-library (sx bytecode)
|
||||
(export
|
||||
OP_CONST
|
||||
OP_NIL
|
||||
OP_TRUE
|
||||
OP_FALSE
|
||||
OP_POP
|
||||
OP_DUP
|
||||
OP_LOCAL_GET
|
||||
OP_LOCAL_SET
|
||||
OP_UPVALUE_GET
|
||||
OP_UPVALUE_SET
|
||||
OP_GLOBAL_GET
|
||||
OP_GLOBAL_SET
|
||||
OP_JUMP
|
||||
OP_JUMP_IF_FALSE
|
||||
OP_JUMP_IF_TRUE
|
||||
OP_CALL
|
||||
OP_TAIL_CALL
|
||||
OP_RETURN
|
||||
OP_CLOSURE
|
||||
OP_CALL_PRIM
|
||||
OP_APPLY
|
||||
OP_LIST
|
||||
OP_DICT
|
||||
OP_APPEND_BANG
|
||||
OP_ITER_INIT
|
||||
OP_ITER_NEXT
|
||||
OP_MAP_OPEN
|
||||
OP_MAP_APPEND
|
||||
OP_MAP_CLOSE
|
||||
OP_FILTER_TEST
|
||||
OP_HO_MAP
|
||||
OP_HO_FILTER
|
||||
OP_HO_REDUCE
|
||||
OP_HO_FOR_EACH
|
||||
OP_HO_SOME
|
||||
OP_HO_EVERY
|
||||
OP_SCOPE_PUSH
|
||||
OP_SCOPE_POP
|
||||
OP_PROVIDE_PUSH
|
||||
OP_PROVIDE_POP
|
||||
OP_CONTEXT
|
||||
OP_EMIT
|
||||
OP_EMITTED
|
||||
OP_RESET
|
||||
OP_SHIFT
|
||||
OP_DEFINE
|
||||
OP_DEFCOMP
|
||||
OP_DEFISLAND
|
||||
OP_DEFMACRO
|
||||
OP_EXPAND_MACRO
|
||||
OP_STR_CONCAT
|
||||
OP_STR_JOIN
|
||||
OP_SERIALIZE
|
||||
OP_ADD
|
||||
OP_SUB
|
||||
OP_MUL
|
||||
OP_DIV
|
||||
OP_EQ
|
||||
OP_LT
|
||||
OP_GT
|
||||
OP_NOT
|
||||
OP_LEN
|
||||
OP_FIRST
|
||||
OP_REST
|
||||
OP_NTH
|
||||
OP_CONS
|
||||
OP_NEG
|
||||
OP_INC
|
||||
OP_DEC
|
||||
OP_ASER_TAG
|
||||
OP_ASER_FRAG
|
||||
BYTECODE_MAGIC
|
||||
BYTECODE_VERSION
|
||||
CONST_NUMBER
|
||||
CONST_STRING
|
||||
CONST_BOOL
|
||||
CONST_NIL
|
||||
CONST_SYMBOL
|
||||
CONST_KEYWORD
|
||||
CONST_LIST
|
||||
CONST_DICT
|
||||
CONST_CODE
|
||||
opcode-name)
|
||||
(begin
|
||||
|
||||
(define OP_CONST 1) ;; u16 pool_idx — push constant
|
||||
(define OP_NIL 2) ;; push nil
|
||||
(define OP_TRUE 3) ;; push true
|
||||
@@ -161,3 +249,9 @@
|
||||
(= op 50) "RETURN" (= op 52) "CALL_PRIM"
|
||||
(= op 128) "DEFINE" (= op 144) "STR_CONCAT"
|
||||
:else (str "OP_" op))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx bytecode))
|
||||
|
||||
@@ -77,6 +77,12 @@
|
||||
;; 2. call/cc — call with current continuation
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
|
||||
(define-library (sx callcc)
|
||||
(export
|
||||
sf-callcc)
|
||||
(begin
|
||||
|
||||
(define sf-callcc
|
||||
(fn (args env)
|
||||
;; Single argument: a function to call with the current continuation.
|
||||
@@ -243,3 +249,9 @@
|
||||
;; dispatch in eval-list (same path as lambda calls).
|
||||
;;
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx callcc))
|
||||
|
||||
@@ -14,6 +14,53 @@
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Constant pool builder
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(define-library (sx compiler)
|
||||
(export
|
||||
make-pool
|
||||
pool-add
|
||||
make-scope
|
||||
scope-define-local
|
||||
scope-resolve
|
||||
make-emitter
|
||||
emit-byte
|
||||
emit-u16
|
||||
emit-i16
|
||||
emit-op
|
||||
emit-const
|
||||
current-offset
|
||||
patch-i16
|
||||
compile-expr
|
||||
compile-symbol
|
||||
compile-dict
|
||||
compile-list
|
||||
compile-if
|
||||
compile-when
|
||||
compile-and
|
||||
compile-or
|
||||
compile-begin
|
||||
compile-let
|
||||
compile-letrec
|
||||
compile-lambda
|
||||
compile-define
|
||||
compile-set
|
||||
compile-quote
|
||||
compile-cond
|
||||
compile-case
|
||||
compile-case-clauses
|
||||
compile-match
|
||||
compile-thread
|
||||
compile-thread-step
|
||||
compile-defcomp
|
||||
compile-defmacro
|
||||
compile-quasiquote
|
||||
compile-qq-expr
|
||||
compile-qq-list
|
||||
compile-call
|
||||
compile
|
||||
compile-module)
|
||||
(begin
|
||||
|
||||
(define make-pool (fn () {:entries (if (primitive? "mutable-list") (mutable-list) (list)) :index {:_count 0}}))
|
||||
|
||||
(define
|
||||
@@ -871,3 +918,9 @@
|
||||
(compile-expr em (last exprs) scope false)
|
||||
(emit-op em 50)
|
||||
{:constants (get (get em "pool") "entries") :bytecode (get em "bytecode")})))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx compiler))
|
||||
|
||||
@@ -11,6 +11,17 @@
|
||||
;; localStorage or IPFS by providing their own store backend.
|
||||
;; ==========================================================================
|
||||
|
||||
|
||||
(define-library (sx content)
|
||||
(export
|
||||
content-store
|
||||
content-hash
|
||||
content-put
|
||||
content-get
|
||||
freeze-to-cid
|
||||
thaw-from-cid)
|
||||
(begin
|
||||
|
||||
(define content-store (dict))
|
||||
|
||||
(define content-hash :effects []
|
||||
@@ -46,3 +57,9 @@
|
||||
(when sx-text
|
||||
(thaw-from-sx sx-text)
|
||||
true))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx content))
|
||||
|
||||
@@ -20,6 +20,20 @@
|
||||
;; ==========================================================================
|
||||
|
||||
;; Registry of freeze scopes: name → list of {name signal} entries
|
||||
|
||||
(define-library (sx freeze)
|
||||
(export
|
||||
freeze-registry
|
||||
freeze-signal
|
||||
freeze-scope
|
||||
cek-freeze-scope
|
||||
cek-freeze-all
|
||||
cek-thaw-scope
|
||||
cek-thaw-all
|
||||
freeze-to-sx
|
||||
thaw-from-sx)
|
||||
(begin
|
||||
|
||||
(define freeze-registry (dict))
|
||||
|
||||
;; Register a signal in the current freeze scope
|
||||
@@ -92,3 +106,9 @@
|
||||
(when (not (empty? parsed))
|
||||
(let ((frozen (first parsed)))
|
||||
(cek-thaw-scope (get frozen "name") frozen))))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx freeze))
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
|
||||
|
||||
(define-library (sx highlight)
|
||||
(export
|
||||
sx-specials
|
||||
sx-special?
|
||||
hl-digit?
|
||||
hl-alpha?
|
||||
hl-sym-char?
|
||||
hl-ws?
|
||||
hl-escape
|
||||
hl-span
|
||||
tokenize-sx
|
||||
sx-token-classes
|
||||
render-sx-tokens
|
||||
highlight-sx
|
||||
highlight)
|
||||
(begin
|
||||
|
||||
(define
|
||||
sx-specials
|
||||
(list
|
||||
@@ -298,3 +317,9 @@
|
||||
(or (= lang "lisp") (= lang "sx") (= lang "sexp") (= lang "scheme"))
|
||||
(highlight-sx code)
|
||||
(list (quote code) code))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx highlight))
|
||||
|
||||
33
lib/r7rs.sx
33
lib/r7rs.sx
@@ -1,3 +1,30 @@
|
||||
|
||||
|
||||
(define-library (sx r7rs)
|
||||
(export
|
||||
make-error-object
|
||||
error-object?
|
||||
error-message
|
||||
error-object-irritants
|
||||
with-exception-handler
|
||||
car
|
||||
cdr
|
||||
cadr
|
||||
cddr
|
||||
caar
|
||||
cdar
|
||||
caddr
|
||||
cadddr
|
||||
null?
|
||||
pair?
|
||||
procedure?
|
||||
boolean=?
|
||||
symbol->string
|
||||
string->symbol
|
||||
number->string
|
||||
string->number)
|
||||
(begin
|
||||
|
||||
(define make-error-object (fn (message irritants) {:irritants irritants :type "error-object" :message message}))
|
||||
|
||||
(define
|
||||
@@ -51,3 +78,9 @@
|
||||
(define
|
||||
string->number
|
||||
(fn (s) (if (string-contains? s ".") (parse-float s) (parse-int s))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx r7rs))
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
|
||||
|
||||
(define-library (sx render-trace)
|
||||
(export
|
||||
*render-trace*
|
||||
*render-trace-log*
|
||||
*render-trace-depth*
|
||||
render-trace-reset!
|
||||
render-trace-push!
|
||||
render-trace-enter!
|
||||
render-trace-exit!
|
||||
format-render-trace)
|
||||
(begin
|
||||
|
||||
(define *render-trace* false)
|
||||
|
||||
(define *render-trace-log* (list))
|
||||
@@ -49,3 +63,9 @@
|
||||
(result (get entry :result)))
|
||||
(str indent kind " " detail " → " result)))
|
||||
*render-trace-log*))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx render-trace))
|
||||
|
||||
@@ -13,6 +13,58 @@
|
||||
;; Replacing them with SX lambdas changes behavior inside shift/reset
|
||||
;; because the transpiled evaluator code uses them directly.
|
||||
|
||||
|
||||
(define-library (sx stdlib)
|
||||
(export
|
||||
eq?
|
||||
eqv?
|
||||
equal?
|
||||
boolean?
|
||||
number?
|
||||
string?
|
||||
list?
|
||||
dict?
|
||||
continuation?
|
||||
zero?
|
||||
odd?
|
||||
even?
|
||||
empty?
|
||||
abs
|
||||
ceil
|
||||
round
|
||||
min
|
||||
max
|
||||
clamp
|
||||
first
|
||||
last
|
||||
rest
|
||||
nth
|
||||
cons
|
||||
append
|
||||
reverse
|
||||
flatten
|
||||
range
|
||||
chunk-every
|
||||
zip-pairs
|
||||
vals
|
||||
has-key?
|
||||
assoc
|
||||
dissoc
|
||||
into
|
||||
upcase
|
||||
downcase
|
||||
string-length
|
||||
substring
|
||||
string-contains?
|
||||
starts-with?
|
||||
ends-with?
|
||||
contains?
|
||||
pluralize
|
||||
escape
|
||||
parse-datetime
|
||||
assert)
|
||||
(begin
|
||||
|
||||
(define eq? (fn (a b) (= a b)))
|
||||
(define eqv? (fn (a b) (= a b)))
|
||||
(define equal? (fn (a b) (= a b)))
|
||||
@@ -273,3 +325,9 @@
|
||||
(when (not condition)
|
||||
(error (or message "Assertion failed")))
|
||||
true))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx stdlib))
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
|
||||
|
||||
(define-library (sx swap)
|
||||
(export
|
||||
_skip-string
|
||||
_find-close
|
||||
_skip-ws
|
||||
_skip-token
|
||||
_skip-value
|
||||
_find-children-start
|
||||
_scan-back
|
||||
find-element-by-id
|
||||
sx-swap
|
||||
_extract-attr-value
|
||||
find-oob-elements
|
||||
strip-oob
|
||||
apply-response)
|
||||
(begin
|
||||
|
||||
(define
|
||||
_skip-string
|
||||
(fn
|
||||
@@ -298,3 +317,9 @@
|
||||
(get oob "content"))
|
||||
(rest items))))))
|
||||
(_apply-oobs result oobs)))))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx swap))
|
||||
|
||||
44
lib/vm.sx
44
lib/vm.sx
@@ -1,3 +1,41 @@
|
||||
|
||||
|
||||
(define-library (sx vm)
|
||||
(export
|
||||
make-upvalue-cell
|
||||
uv-get
|
||||
uv-set!
|
||||
make-vm-code
|
||||
make-vm-closure
|
||||
make-vm-frame
|
||||
make-vm
|
||||
vm-push
|
||||
vm-pop
|
||||
vm-peek
|
||||
frame-read-u8
|
||||
frame-read-u16
|
||||
frame-read-i16
|
||||
vm-push-frame
|
||||
code-from-value
|
||||
vm-closure?
|
||||
vm-call
|
||||
frame-local-get
|
||||
frame-local-set
|
||||
frame-upvalue-get
|
||||
frame-upvalue-set
|
||||
vm-global-get
|
||||
vm-resolve-ho-form
|
||||
vm-call-external
|
||||
vm-global-set
|
||||
env-walk
|
||||
env-walk-set!
|
||||
vm-create-closure
|
||||
vm-run
|
||||
vm-step
|
||||
vm-call-closure
|
||||
vm-execute-module)
|
||||
(begin
|
||||
|
||||
(define make-upvalue-cell (fn (value) {:uv-value value}))
|
||||
|
||||
(define uv-get (fn (cell) (get cell "uv-value")))
|
||||
@@ -556,3 +594,9 @@
|
||||
(dict-set! vm "frames" (list frame))
|
||||
(vm-run vm)
|
||||
(vm-pop vm)))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx vm))
|
||||
|
||||
@@ -1,4 +1,21 @@
|
||||
;; Deterministic serialization for content addressing
|
||||
|
||||
(define-library (sx canonical)
|
||||
(export
|
||||
canonical-serialize
|
||||
canonical-number
|
||||
canonical-dict
|
||||
content-id
|
||||
content-id-short
|
||||
make-bytecode-module
|
||||
bytecode-module?
|
||||
bytecode-module-version
|
||||
bytecode-module-source-hash
|
||||
bytecode-module-code
|
||||
make-code-object
|
||||
make-provenance)
|
||||
(begin
|
||||
|
||||
(define
|
||||
canonical-serialize
|
||||
:effects ()
|
||||
@@ -127,3 +144,9 @@
|
||||
:bytecode-cid bytecode-cid
|
||||
:compiler-cid compiler-cid
|
||||
:timestamp timestamp)))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx canonical))
|
||||
|
||||
@@ -1469,9 +1469,7 @@
|
||||
(let
|
||||
((lib-spec (first args)) (decls (rest args)))
|
||||
(let
|
||||
((lib-env (env-extend (make-env)))
|
||||
(exports (list))
|
||||
(body-forms (list)))
|
||||
((lib-env (env-extend env)) (exports (list)) (body-forms (list)))
|
||||
(for-each
|
||||
(fn
|
||||
(decl)
|
||||
|
||||
@@ -1,4 +1,30 @@
|
||||
;; Assert condition is truthy, error with message
|
||||
|
||||
(define-library (sx harness)
|
||||
(export
|
||||
assert
|
||||
assert=
|
||||
default-platform
|
||||
make-harness
|
||||
harness-reset!
|
||||
harness-log
|
||||
harness-get
|
||||
harness-set!
|
||||
make-interceptor
|
||||
install-interceptors
|
||||
io-calls
|
||||
io-call-count
|
||||
io-call-nth
|
||||
io-call-args
|
||||
io-call-result
|
||||
assert-io-called
|
||||
assert-no-io
|
||||
assert-io-count
|
||||
assert-io-args
|
||||
assert-io-result
|
||||
assert-state)
|
||||
(begin
|
||||
|
||||
(define assert (fn (condition msg) (when (not condition) (error (or msg "Assertion failed")))))
|
||||
|
||||
;; Assert two values are equal
|
||||
@@ -60,3 +86,9 @@
|
||||
|
||||
;; Assert a state key has the expected value
|
||||
(define assert-state :effects () (fn (session key expected) (let ((actual (harness-get session key))) (assert (equal? actual expected) (str "Expected state " key " to be " (str expected) " but got " (str actual))))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx harness))
|
||||
|
||||
@@ -1,4 +1,24 @@
|
||||
;; Registry of all valid HTML tag names
|
||||
|
||||
(define-library (sx render)
|
||||
(export
|
||||
HTML_TAGS
|
||||
VOID_ELEMENTS
|
||||
BOOLEAN_ATTRS
|
||||
*definition-form-extensions*
|
||||
definition-form?
|
||||
parse-element-args
|
||||
render-attrs
|
||||
eval-cond
|
||||
eval-cond-scheme
|
||||
eval-cond-clojure
|
||||
process-bindings
|
||||
is-render-expr?
|
||||
merge-spread-attrs
|
||||
escape-html
|
||||
escape-attr)
|
||||
(begin
|
||||
|
||||
(define
|
||||
HTML_TAGS
|
||||
(list
|
||||
@@ -413,3 +433,9 @@
|
||||
|
||||
;; Escape special chars for HTML attribute values
|
||||
(define escape-attr (fn (s) (escape-html s)))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx render))
|
||||
|
||||
@@ -1,3 +1,32 @@
|
||||
|
||||
|
||||
(define-library (sx signals)
|
||||
(export
|
||||
make-signal
|
||||
signal?
|
||||
signal-value
|
||||
signal-set-value!
|
||||
signal-subscribers
|
||||
signal-add-sub!
|
||||
signal-remove-sub!
|
||||
signal-deps
|
||||
signal-set-deps!
|
||||
signal
|
||||
deref
|
||||
reset!
|
||||
swap!
|
||||
computed
|
||||
effect
|
||||
*batch-depth*
|
||||
*batch-queue*
|
||||
batch
|
||||
notify-subscribers
|
||||
flush-subscribers
|
||||
dispose-computed
|
||||
with-island-scope
|
||||
register-in-scope)
|
||||
(begin
|
||||
|
||||
(define
|
||||
make-signal
|
||||
(fn
|
||||
@@ -193,3 +222,9 @@
|
||||
(let
|
||||
((collector (scope-peek "sx-island-scope")))
|
||||
(when collector (cek-call collector (list disposable))))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (sx signals))
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
|
||||
|
||||
(define-library (web adapter-html)
|
||||
(export
|
||||
render-to-html
|
||||
render-value-to-html
|
||||
RENDER_HTML_FORMS
|
||||
render-html-form?
|
||||
render-list-to-html
|
||||
dispatch-html-form
|
||||
render-lambda-html
|
||||
render-html-component
|
||||
render-html-element
|
||||
render-html-lake
|
||||
render-html-marsh
|
||||
render-html-island
|
||||
serialize-island-state)
|
||||
(begin
|
||||
|
||||
(define
|
||||
render-to-html
|
||||
:effects (render)
|
||||
@@ -589,3 +608,9 @@
|
||||
(fn
|
||||
((kwargs :as dict))
|
||||
(if (empty-dict? kwargs) nil (sx-serialize kwargs))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (web adapter-html))
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
|
||||
|
||||
(define-library (web adapter-sx)
|
||||
(export
|
||||
render-to-sx
|
||||
aser
|
||||
aser-list
|
||||
aser-reserialize
|
||||
aser-fragment
|
||||
aser-call
|
||||
aser-expand-component
|
||||
SPECIAL_FORM_NAMES
|
||||
HO_FORM_NAMES
|
||||
special-form?
|
||||
ho-form?
|
||||
aser-special
|
||||
eval-case-aser)
|
||||
(begin
|
||||
|
||||
(define
|
||||
render-to-sx
|
||||
:effects (render)
|
||||
@@ -570,3 +589,9 @@
|
||||
(= match-val (trampoline (eval-expr test env)))
|
||||
(aser body env)
|
||||
(eval-case-aser match-val (slice clauses 2) env)))))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (web adapter-sx))
|
||||
|
||||
31
web/deps.sx
31
web/deps.sx
@@ -1,3 +1,28 @@
|
||||
|
||||
|
||||
(define-library (web deps)
|
||||
(export
|
||||
scan-refs
|
||||
scan-refs-walk
|
||||
transitive-deps-walk
|
||||
transitive-deps
|
||||
compute-all-deps
|
||||
scan-components-from-source
|
||||
components-needed
|
||||
page-component-bundle
|
||||
page-css-classes
|
||||
scan-io-refs-walk
|
||||
scan-io-refs
|
||||
transitive-io-refs-walk
|
||||
transitive-io-refs
|
||||
compute-all-io-refs
|
||||
component-io-refs-cached
|
||||
component-pure?
|
||||
render-target
|
||||
page-render-plan
|
||||
env-components)
|
||||
(begin
|
||||
|
||||
(define
|
||||
scan-refs
|
||||
:effects ()
|
||||
@@ -335,3 +360,9 @@
|
||||
((k :as string))
|
||||
(let ((v (env-get env k))) (or (component? v) (macro? v))))
|
||||
(keys env))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (web deps))
|
||||
|
||||
@@ -1,3 +1,42 @@
|
||||
|
||||
|
||||
(define-library (web engine)
|
||||
(export
|
||||
ENGINE_VERBS
|
||||
DEFAULT_SWAP
|
||||
parse-time
|
||||
parse-trigger-spec
|
||||
default-trigger
|
||||
get-verb-info
|
||||
build-request-headers
|
||||
process-response-headers
|
||||
parse-swap-spec
|
||||
parse-retry-spec
|
||||
next-retry-ms
|
||||
filter-params
|
||||
resolve-target
|
||||
apply-optimistic
|
||||
revert-optimistic
|
||||
find-oob-swaps
|
||||
morph-node
|
||||
sync-attrs
|
||||
morph-children
|
||||
morph-island-children
|
||||
morph-marsh
|
||||
process-signal-updates
|
||||
swap-dom-nodes
|
||||
insert-remaining-siblings
|
||||
swap-html-string
|
||||
handle-history
|
||||
PRELOAD_TTL
|
||||
preload-cache-get
|
||||
preload-cache-set
|
||||
classify-trigger
|
||||
should-boost-link?
|
||||
should-boost-form?
|
||||
parse-sse-swap)
|
||||
(begin
|
||||
|
||||
(define ENGINE_VERBS (list "get" "post" "put" "delete" "patch"))
|
||||
|
||||
(define DEFAULT_SWAP "outerHTML")
|
||||
@@ -806,3 +845,9 @@
|
||||
parse-sse-swap
|
||||
:effects (io)
|
||||
(fn (el) (or (dom-get-attr el "sx-sse-swap") "message")))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (web engine))
|
||||
|
||||
@@ -1,3 +1,68 @@
|
||||
|
||||
|
||||
(define-library (web orchestration)
|
||||
(export
|
||||
_preload-cache
|
||||
dispatch-trigger-events
|
||||
execute-request
|
||||
do-fetch
|
||||
handle-fetch-success
|
||||
flush-collected-styles
|
||||
handle-sx-response
|
||||
handle-html-response
|
||||
handle-retry
|
||||
bind-triggers
|
||||
bind-event
|
||||
post-swap
|
||||
process-settle-hooks
|
||||
activate-scripts
|
||||
process-oob-swaps
|
||||
hoist-head-elements
|
||||
process-boosted
|
||||
boost-descendants
|
||||
_page-data-cache
|
||||
_page-data-cache-ttl
|
||||
page-data-cache-key
|
||||
page-data-cache-get
|
||||
page-data-cache-set
|
||||
invalidate-page-cache
|
||||
invalidate-all-page-cache
|
||||
update-page-cache
|
||||
process-cache-directives
|
||||
_optimistic-snapshots
|
||||
optimistic-cache-update
|
||||
optimistic-cache-revert
|
||||
optimistic-cache-confirm
|
||||
submit-mutation
|
||||
_is-online
|
||||
_offline-queue
|
||||
offline-is-online?
|
||||
offline-set-online!
|
||||
offline-queue-mutation
|
||||
offline-sync
|
||||
offline-pending-count
|
||||
offline-aware-mutation
|
||||
current-page-layout
|
||||
swap-rendered-content
|
||||
resolve-route-target
|
||||
deps-satisfied?
|
||||
try-client-route
|
||||
bind-client-route-link
|
||||
process-sse
|
||||
bind-sse
|
||||
bind-sse-swap
|
||||
bind-inline-handlers
|
||||
bind-preload-for
|
||||
do-preload
|
||||
VERB_SELECTOR
|
||||
process-elements
|
||||
process-one
|
||||
process-emit-elements
|
||||
save-scroll-position
|
||||
handle-popstate
|
||||
engine-init)
|
||||
(begin
|
||||
|
||||
(define _preload-cache (dict))
|
||||
|
||||
(define
|
||||
@@ -1566,3 +1631,9 @@
|
||||
(fn
|
||||
()
|
||||
(do (sx-process-scripts nil) (sx-hydrate nil) (process-elements nil))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (web orchestration))
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
|
||||
|
||||
(define-library (web page-helpers)
|
||||
(export
|
||||
special-form-category-map
|
||||
extract-define-kwargs
|
||||
categorize-special-forms
|
||||
build-ref-items-with-href
|
||||
build-reference-data
|
||||
build-attr-detail
|
||||
build-header-detail
|
||||
build-event-detail
|
||||
build-component-source
|
||||
build-bundle-analysis
|
||||
build-routing-analysis
|
||||
build-affinity-analysis)
|
||||
(begin
|
||||
|
||||
(define special-form-category-map {:defmacro "Functions & Components" :for-each "Higher-Order Forms" :defpage "Domain Definitions" :let "Binding" :filter "Higher-Order Forms" :shift "Continuations" :and "Control Flow" :set! "Binding" :map-indexed "Higher-Order Forms" :dynamic-wind "Guards" :reduce "Higher-Order Forms" :cond "Control Flow" :defquery "Domain Definitions" :-> "Sequencing & Threading" :let* "Binding" :define "Binding" :reset "Continuations" :case "Control Flow" :do "Sequencing & Threading" :map "Higher-Order Forms" :some "Higher-Order Forms" :letrec "Binding" :if "Control Flow" :quote "Quoting" :every? "Higher-Order Forms" :defhandler "Domain Definitions" :fn "Functions & Components" :defstyle "Domain Definitions" :lambda "Functions & Components" :defaction "Domain Definitions" :or "Control Flow" :defcomp "Functions & Components" :quasiquote "Quoting" :when "Control Flow" :begin "Sequencing & Threading"})
|
||||
|
||||
(define
|
||||
@@ -230,3 +248,9 @@
|
||||
(define
|
||||
build-affinity-analysis
|
||||
(fn ((demo-components :as list) (page-plans :as list)) {:components demo-components :page-plans page-plans}))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (web page-helpers))
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
|
||||
|
||||
(define-library (web request-handler)
|
||||
(export
|
||||
sx-url-to-expr
|
||||
sx-auto-quote
|
||||
sx-eval-page
|
||||
sx-handle-request)
|
||||
(begin
|
||||
|
||||
(define
|
||||
sx-url-to-expr
|
||||
(fn
|
||||
@@ -66,3 +76,9 @@
|
||||
path
|
||||
(str (slice prefix 0 (- prefix-len 1)) path))))
|
||||
{:page-ast page-ast :nav-path nav-path :is-ajax is-ajax})))))
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (web request-handler))
|
||||
|
||||
@@ -17,6 +17,47 @@
|
||||
;; "/" → ()
|
||||
;; "/docs/" → ("docs")
|
||||
|
||||
|
||||
(define-library (web router)
|
||||
(export
|
||||
split-path-segments
|
||||
make-route-segment
|
||||
parse-route-pattern
|
||||
match-route-segments
|
||||
match-route
|
||||
find-matching-route
|
||||
_fn-to-segment
|
||||
sx-url-to-path
|
||||
_count-leading-dots
|
||||
_strip-trailing-close
|
||||
_index-of-safe
|
||||
_last-index-of
|
||||
_pop-sx-url-level
|
||||
_pop-sx-url-levels
|
||||
_split-pos-kw
|
||||
_parse-relative-body
|
||||
_extract-innermost
|
||||
_find-kw-in-tokens
|
||||
_find-keyword-value
|
||||
_replace-kw-in-tokens
|
||||
_set-keyword-in-content
|
||||
_is-delta-value?
|
||||
_apply-delta
|
||||
_apply-kw-pairs
|
||||
_apply-keywords-to-url
|
||||
_normalize-relative
|
||||
resolve-relative-url
|
||||
relative-sx-url?
|
||||
_url-special-forms
|
||||
url-special-form?
|
||||
parse-sx-url
|
||||
url-special-form-name
|
||||
url-special-form-inner
|
||||
url-to-expr
|
||||
auto-quote-unknowns
|
||||
prepare-url-expr)
|
||||
(begin
|
||||
|
||||
(define split-path-segments :effects []
|
||||
(fn ((path :as string))
|
||||
(let ((trimmed (if (starts-with? path "/") (slice path 1) path)))
|
||||
@@ -678,3 +719,9 @@
|
||||
;;
|
||||
;; From parser.sx: sx-parse, sx-serialize
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
|
||||
)) ;; end define-library
|
||||
|
||||
;; Re-export to global namespace for backward compatibility
|
||||
(import (web router))
|
||||
|
||||
Reference in New Issue
Block a user