Content-addressed computation: freeze → hash → CID → thaw
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
Hash frozen SX to a content identifier (djb2 → hex). Same state always produces the same CID. Store by CID, retrieve by CID. - content-hash: djb2 hash of SX text → hex string - content-put/get: in-memory content store - freeze-to-cid: freeze scope → store → return CID - thaw-from-cid: look up CID → thaw signals - char-code-at / to-hex primitives for both platforms - Live demo: counter + name widget, content-address button, CID display, restore from CID input, CID history Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1129,3 +1129,50 @@
|
||||
(cek-thaw-scope (get frozen "name") frozen))))))
|
||||
|
||||
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; 14. Content-addressed computation
|
||||
;; --------------------------------------------------------------------------
|
||||
;;
|
||||
;; Hash frozen SX to a content identifier. Store and retrieve by CID.
|
||||
;; The content IS the address — same SX always produces the same CID.
|
||||
;;
|
||||
;; Uses an in-memory content store. Applications can persist to
|
||||
;; localStorage or IPFS by providing their own store backend.
|
||||
|
||||
(define content-store (dict))
|
||||
|
||||
(define content-hash :effects []
|
||||
(fn (sx-text)
|
||||
;; djb2 hash → hex string. Simple, deterministic, fast.
|
||||
;; Real deployment would use SHA-256 / multihash.
|
||||
(let ((hash 5381))
|
||||
(for-each (fn (i)
|
||||
(set! hash (mod (+ (* hash 33) (char-code-at sx-text i)) 4294967296)))
|
||||
(range 0 (len sx-text)))
|
||||
(to-hex hash))))
|
||||
|
||||
(define content-put :effects [mutation]
|
||||
(fn (sx-text)
|
||||
(let ((cid (content-hash sx-text)))
|
||||
(dict-set! content-store cid sx-text)
|
||||
cid)))
|
||||
|
||||
(define content-get :effects []
|
||||
(fn (cid)
|
||||
(get content-store cid)))
|
||||
|
||||
;; Freeze a scope → store → return CID
|
||||
(define freeze-to-cid :effects [mutation]
|
||||
(fn (scope-name)
|
||||
(let ((sx-text (freeze-to-sx scope-name)))
|
||||
(content-put sx-text))))
|
||||
|
||||
;; Thaw from CID → look up → restore
|
||||
(define thaw-from-cid :effects [mutation]
|
||||
(fn (cid)
|
||||
(let ((sx-text (content-get cid)))
|
||||
(when sx-text
|
||||
(thaw-from-sx sx-text)
|
||||
true))))
|
||||
|
||||
@@ -1532,6 +1532,10 @@ CEK_FIXUPS_JS = '''
|
||||
PRIMITIVES["is-html-tag?"] = function(n) { return HTML_TAGS.indexOf(n) >= 0; };
|
||||
PRIMITIVES["make-env"] = function() { return merge(componentEnv, PRIMITIVES); };
|
||||
|
||||
// String/number utilities for content addressing
|
||||
PRIMITIVES["char-code-at"] = function(s, i) { return s.charCodeAt(i); };
|
||||
PRIMITIVES["to-hex"] = function(n) { return (n >>> 0).toString(16); };
|
||||
|
||||
// localStorage — defined here (before boot) so islands can use at hydration
|
||||
PRIMITIVES["local-storage-get"] = function(key) {
|
||||
try { var v = localStorage.getItem(key); return v === null ? NIL : v; }
|
||||
|
||||
@@ -1020,6 +1020,10 @@ number_p = PRIMITIVES["number?"]
|
||||
string_p = PRIMITIVES["string?"]
|
||||
list_p = PRIMITIVES["list?"]
|
||||
dissoc = PRIMITIVES["dissoc"]
|
||||
PRIMITIVES["char-code-at"] = lambda s, i: ord(s[int(i)]) if 0 <= int(i) < len(s) else 0
|
||||
PRIMITIVES["to-hex"] = lambda n: hex(int(n) & 0xFFFFFFFF)[2:]
|
||||
char_code_at = PRIMITIVES["char-code-at"]
|
||||
to_hex = PRIMITIVES["to-hex"]
|
||||
index_of = PRIMITIVES["index-of"]
|
||||
lower = PRIMITIVES["lower"]
|
||||
char_from_code = PRIMITIVES["char-from-code"]
|
||||
|
||||
@@ -940,6 +940,10 @@ number_p = PRIMITIVES["number?"]
|
||||
string_p = PRIMITIVES["string?"]
|
||||
list_p = PRIMITIVES["list?"]
|
||||
dissoc = PRIMITIVES["dissoc"]
|
||||
PRIMITIVES["char-code-at"] = lambda s, i: ord(s[int(i)]) if 0 <= int(i) < len(s) else 0
|
||||
PRIMITIVES["to-hex"] = lambda n: hex(int(n) & 0xFFFFFFFF)[2:]
|
||||
char_code_at = PRIMITIVES["char-code-at"]
|
||||
to_hex = PRIMITIVES["to-hex"]
|
||||
index_of = PRIMITIVES["index-of"]
|
||||
lower = PRIMITIVES["lower"]
|
||||
char_from_code = PRIMITIVES["char-from-code"]
|
||||
@@ -4659,6 +4663,40 @@ def thaw_from_sx(sx_text):
|
||||
return cek_thaw_scope(get(frozen, 'name'), frozen)
|
||||
return NIL
|
||||
|
||||
# content-store
|
||||
content_store = {}
|
||||
|
||||
# content-hash
|
||||
def content_hash(sx_text):
|
||||
_cells = {}
|
||||
_cells['hash'] = 5381
|
||||
for i in range(0, len(sx_text)):
|
||||
_cells['hash'] = (((_cells['hash'] * 33) + char_code_at(sx_text, i)) % 4294967296)
|
||||
return to_hex(_cells['hash'])
|
||||
|
||||
# content-put
|
||||
def content_put(sx_text):
|
||||
cid = content_hash(sx_text)
|
||||
content_store[cid] = sx_text
|
||||
return cid
|
||||
|
||||
# content-get
|
||||
def content_get(cid):
|
||||
return get(content_store, cid)
|
||||
|
||||
# freeze-to-cid
|
||||
def freeze_to_cid(scope_name):
|
||||
sx_text = freeze_to_sx(scope_name)
|
||||
return content_put(sx_text)
|
||||
|
||||
# thaw-from-cid
|
||||
def thaw_from_cid(cid):
|
||||
sx_text = content_get(cid)
|
||||
if sx_truthy(sx_text):
|
||||
thaw_from_sx(sx_text)
|
||||
return True
|
||||
return NIL
|
||||
|
||||
|
||||
# === Transpiled from signals (reactive signal runtime) ===
|
||||
|
||||
|
||||
Reference in New Issue
Block a user