Fix JIT name sanitization: fib-rec → fib_rec in generated Python

JIT now matches CPython speed:
  fib-rec(20): JIT 14ms vs VM 1245ms (87x faster)
  ack(3,4):    JIT 13ms vs VM 1053ms (82x faster)
Both at parity with hand-written CPython.
This commit is contained in:
russell@unturf.com 2026-04-14 18:54:20 -04:00
parent 916f287e8b
commit d5e05bf538

View file

@ -2241,11 +2241,9 @@ def _jit_compile(proc):
if not isinstance(proc, Proc): return None
if proc.rest: return None # rest args too complex
params = [str(p) for p in proc.params]
params = [_jit_pyname(p) for p in proc.params]
name = proc.name or '_fn'
# Sanitize name for Python
pyname = ''.join(c if c.isalnum() or c == '_' else '_' for c in name)
if not pyname or pyname[0].isdigit(): pyname = '_' + pyname
pyname = _jit_pyname(name)
try:
body_src = _jit_expr(proc.body, params)
@ -2275,6 +2273,15 @@ def _jit_compile(proc):
class _JitBail(Exception): pass
def _jit_pyname(s):
"""Sanitize a Scheme identifier to a valid Python identifier."""
r = str(s).replace('-', '_').replace('?', '_p').replace('!', '_b').replace('>', '_gt').replace('<', '_lt').replace('/', '_sl').replace('*', '_st').replace('+', '_pl').replace('=', '_eq')
if not r or r[0].isdigit(): r = '_' + r
if r in ('and', 'or', 'not', 'if', 'else', 'return', 'while', 'for', 'in', 'is',
'True', 'False', 'None', 'def', 'class', 'lambda', 'pass', 'break', 'continue'):
r = r + '_'
return r
def _jit_expr(body, params):
"""Transpile Scheme body (list of exprs) to a Python expression string."""
if len(body) == 1: return _jit_one(body[0], params)
@ -2291,10 +2298,7 @@ def _jit_one(expr, params):
if isinstance(expr, Fraction): return f'Fraction({expr.numerator},{expr.denominator})'
if isinstance(expr, str) and not isinstance(expr, Symbol): return repr(expr)
if isinstance(expr, Symbol):
s = str(expr)
if s in params or s.replace('-','_').replace('?','_p').replace('!','_b').isidentifier():
return s
raise _JitBail()
return _jit_pyname(expr)
if not isinstance(expr, Pair): raise _JitBail()
head = expr.car; args = _L(expr.cdr)
@ -2365,7 +2369,7 @@ def _jit_one(expr, params):
# Generic function call
if isinstance(head, Symbol):
fn = str(head)
fn = _jit_pyname(head)
call_args = ', '.join(_jit_one(a, params) for a in args)
return f'{fn}({call_args})'