Transpiler: native mutable globals support, eliminate 5 bootstrap patches
transpiler.sx: ml-mutable-globals list + ml-is-mutable-global? predicate. Symbol reads emit !_ref, set! emits _ref :=, define emits !_ref deref. bootstrap.py: remove all mutable globals regex fixups (strict, prim-param-types). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -211,60 +211,10 @@ def compile_spec_to_ml(spec_dir: str | None = None) -> str:
|
|||||||
parts.append(FIXUPS)
|
parts.append(FIXUPS)
|
||||||
output = "\n".join(parts)
|
output = "\n".join(parts)
|
||||||
|
|
||||||
# Post-process: fix mutable globals that the transpiler can't handle.
|
# Mutable globals (*strict*, *prim-param-types*) are now handled by
|
||||||
# The transpiler emits local refs for set! targets within functions,
|
# the transpiler directly — it emits !_ref for reads, _ref := for writes.
|
||||||
# but top-level globals (*strict*, *prim-param-types*) need to use
|
|
||||||
# the pre-declared refs from the preamble.
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
# Fix *strict*: use _strict_ref instead of immutable let rec binding
|
|
||||||
output = re.sub(
|
|
||||||
r'and _strict_ =\n \(Bool false\)',
|
|
||||||
'and _strict_ = !_strict_ref',
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
# Fix set-strict!: use _strict_ref instead of local ref
|
|
||||||
output = re.sub(
|
|
||||||
r'and set_strict_b val\' =\n let _strict_ = ref Nil in \(_strict_ := val\'; Nil\)',
|
|
||||||
"and set_strict_b val' =\n _strict_ref := val'; Nil",
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
# Fix *prim-param-types*: use _prim_param_types_ref
|
|
||||||
output = re.sub(
|
|
||||||
r'and _prim_param_types_ =\n Nil',
|
|
||||||
'and _prim_param_types_ = !_prim_param_types_ref',
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
# Fix set-prim-param-types!: use _prim_param_types_ref
|
|
||||||
output = re.sub(
|
|
||||||
r'and set_prim_param_types_b types =\n let _prim_param_types_ = ref Nil in \(_prim_param_types_ := types; Nil\)',
|
|
||||||
"and set_prim_param_types_b types =\n _prim_param_types_ref := types; Nil",
|
|
||||||
output,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Fix all runtime reads of _strict_ and _prim_param_types_ to deref
|
|
||||||
# the mutable refs instead of using the stale let-rec bindings.
|
|
||||||
# This is needed because let-rec value bindings capture initial values.
|
|
||||||
# Use regex with word boundary to avoid replacing _strict_ref with
|
|
||||||
# !_strict_refref.
|
|
||||||
def fix_mutable_reads(text):
|
|
||||||
lines = text.split('\n')
|
|
||||||
fixed = []
|
|
||||||
for line in lines:
|
|
||||||
# Skip the definition lines
|
|
||||||
stripped = line.strip()
|
|
||||||
if stripped.startswith('and _strict_ =') or stripped.startswith('and _prim_param_types_ ='):
|
|
||||||
fixed.append(line)
|
|
||||||
continue
|
|
||||||
# Replace _strict_ as a standalone identifier only (not inside
|
|
||||||
# other names like set_strict_b). Match when preceded by space,
|
|
||||||
# paren, or start-of-line, and followed by space, paren, or ;.
|
|
||||||
line = re.sub(r'(?<=[ (])_strict_(?=[ );])', '!_strict_ref', line)
|
|
||||||
line = re.sub(r'(?<=[ (])_prim_param_types_(?=[ );])', '!_prim_param_types_ref', line)
|
|
||||||
fixed.append(line)
|
|
||||||
return '\n'.join(fixed)
|
|
||||||
output = fix_mutable_reads(output)
|
|
||||||
|
|
||||||
# Fix cek_call: the spec passes (make-env) as the env arg to
|
# Fix cek_call: the spec passes (make-env) as the env arg to
|
||||||
# continue_with_call, but the transpiler evaluates make-env at
|
# continue_with_call, but the transpiler evaluates make-env at
|
||||||
# transpile time (it's a primitive), producing Dict instead of Env.
|
# transpile time (it's a primitive), producing Dict instead of Env.
|
||||||
|
|||||||
@@ -268,6 +268,12 @@
|
|||||||
|
|
||||||
(define ml-dynamic-globals (list "*render-check*" "*render-fn*"))
|
(define ml-dynamic-globals (list "*render-check*" "*render-fn*"))
|
||||||
|
|
||||||
|
(define ml-mutable-globals (list "*strict*" "*prim-param-types*"))
|
||||||
|
|
||||||
|
(define
|
||||||
|
ml-is-mutable-global?
|
||||||
|
(fn (name) (some (fn (g) (= g name)) ml-mutable-globals)))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
ml-is-dyn-global?
|
ml-is-dyn-global?
|
||||||
(fn ((name :as string)) (some (fn (g) (= g name)) ml-dynamic-globals)))
|
(fn ((name :as string)) (some (fn (g) (= g name)) ml-dynamic-globals)))
|
||||||
@@ -431,9 +437,12 @@
|
|||||||
(let
|
(let
|
||||||
((mangled (ml-mangle (symbol-name expr))))
|
((mangled (ml-mangle (symbol-name expr))))
|
||||||
(if
|
(if
|
||||||
(some (fn (c) (= c mangled)) set-vars)
|
(ml-is-mutable-global? (symbol-name expr))
|
||||||
(str "!" mangled)
|
(str "!" mangled "ref")
|
||||||
mangled))
|
(if
|
||||||
|
(some (fn (c) (= c mangled)) set-vars)
|
||||||
|
(str "!" mangled)
|
||||||
|
mangled)))
|
||||||
(= (type-of expr) "keyword")
|
(= (type-of expr) "keyword")
|
||||||
(str "(String " (ml-quote-string (keyword-name expr)) ")")
|
(str "(String " (ml-quote-string (keyword-name expr)) ")")
|
||||||
(= (type-of expr) "dict")
|
(= (type-of expr) "dict")
|
||||||
@@ -636,15 +645,23 @@
|
|||||||
(ml-emit-quote (first args))
|
(ml-emit-quote (first args))
|
||||||
(= op "set!")
|
(= op "set!")
|
||||||
(let
|
(let
|
||||||
((var-name (if (= (type-of (first args)) "symbol") (symbol-name (first args)) (str (first args)))))
|
((var-name (symbol-name (first args))))
|
||||||
(let
|
(if
|
||||||
((mangled (ml-mangle var-name)))
|
(ml-is-mutable-global? var-name)
|
||||||
(str
|
(str
|
||||||
"("
|
"("
|
||||||
mangled
|
(ml-mangle var-name)
|
||||||
" := "
|
"ref := "
|
||||||
(ml-expr-inner (nth args 1) set-vars)
|
(ml-expr-inner (nth args 1) set-vars)
|
||||||
"; Nil)")))
|
"; Nil)")
|
||||||
|
(let
|
||||||
|
((mangled (ml-mangle var-name)))
|
||||||
|
(str
|
||||||
|
"("
|
||||||
|
mangled
|
||||||
|
" := "
|
||||||
|
(ml-expr-inner (nth args 1) set-vars)
|
||||||
|
"; Nil)"))))
|
||||||
(= op "str")
|
(= op "str")
|
||||||
(str
|
(str
|
||||||
"(String (sx_str ["
|
"(String (sx_str ["
|
||||||
@@ -1751,7 +1768,10 @@
|
|||||||
ref-decls
|
ref-decls
|
||||||
body-str
|
body-str
|
||||||
"\n")))))
|
"\n")))))
|
||||||
(str "let " ml-name " =\n " (ml-expr val-expr) "\n")))))))
|
(if
|
||||||
|
(ml-is-mutable-global? name)
|
||||||
|
(str "let " ml-name " =\n !" ml-name "ref\n")
|
||||||
|
(str "let " ml-name " =\n " (ml-expr val-expr) "\n"))))))))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
ml-translate-file
|
ml-translate-file
|
||||||
@@ -1854,4 +1874,7 @@
|
|||||||
ref-decls
|
ref-decls
|
||||||
body-str
|
body-str
|
||||||
"\n")))))
|
"\n")))))
|
||||||
(str "let rec " ml-name " =\n " (ml-expr val-expr) "\n"))))))
|
(if
|
||||||
|
(ml-is-mutable-global? name)
|
||||||
|
(str "let rec " ml-name " =\n !" ml-name "ref\n")
|
||||||
|
(str "let rec " ml-name " =\n " (ml-expr val-expr) "\n")))))))
|
||||||
|
|||||||
Reference in New Issue
Block a user