WASM: implement string-from-static, intern-symbol, and static data replacement
ober
a453273505b0d2c8ea028a7fd86dd7da4be9772b
--- a/lib/jerboa/wasm/scheme-runtime.sls +++ b/lib/jerboa/wasm/scheme-runtime.sls @@ -266,6 +266,19 @@ (string-byte-set! s i (i32.load8_u (+ offset i))) (set! i (+ i 1))) s)) + + ;; Load a string from the static data segment. + ;; The data segment stores strings as: [4-byte LE length][UTF-8 bytes]. + ;; offset is the raw i32 address of the length prefix. + (define (string-from-static offset) + (let ([len (i32.load offset)]) + (string-from-memory (+ offset 4) len))) + + ;; Intern a symbol by wrapping a string pointer. + ;; Simple MVP: symbol identity is by string equality (not pointer equality). + ;; Full symbol table interning can be added later. + (define (intern-symbol str-ptr) + (alloc-symbol str-ptr)) )) ;; ================================================================ --- a/lib/std/secure/wasm-target.sls +++ b/lib/std/secure/wasm-target.sls @@ -948,7 +948,9 @@ [lifted (lambda-lift lowered)] ;; Collect static string data for data segments [static-strings (collect-static-strings lifted)] - [string-data-forms (generate-string-data static-strings)]) + [string-data-forms (generate-string-data static-strings)] + ;; Replace (string-from-static #vu8(...)) with (string-from-static offset) + [lifted (replace-static-strings lifted static-strings)]) ;; Assemble the complete program (append @@ -1013,6 +1015,26 @@ `(define-data ,offset ,data))) string-table)) + ;; Replace (string-from-static #vu8(...)) with (string-from-static offset) + ;; using the offset table produced by collect-static-strings. + ;; This converts bytevector literals to raw memory addresses so the + ;; generated WASM calls the runtime string-from-static with an i32. + (define (replace-static-strings forms string-table) + (define (replace expr) + (cond + [(pair? expr) + (if (and (eq? (car expr) 'string-from-static) + (bytevector? (cadr expr))) + ;; Replace with the assigned integer offset + (let ([entry (assoc (cadr expr) string-table)]) + (if entry + `(string-from-static ,(cdr entry)) + expr)) ;; shouldn't happen if collect was complete + ;; Otherwise recurse into subforms + (map replace expr))] + [else expr])) + (map replace forms)) + ;; Check if any form references closures (define (has-closures? forms) (let ([found #f])