diff --git a/uncommonlisp.py b/uncommonlisp.py index 1a9baa2..ae30783 100644 --- a/uncommonlisp.py +++ b/uncommonlisp.py @@ -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})'