Files
bara-lang/test_single.py
T
dimgigov e6859568b3 fix: clojure test suite compatibility — 145/225 passing (64%)
Reader: #? reader conditionals with :default, #?@ splicing, char literals,
N/M suffix and ratio parsing, comma as whitespace, number parsing fix
for negative BigInt/Decimal/Ratio literals

Emitter: mangleName trailing/double underscore fixes, scope stack for
local var tracking, symbol-as-value emits cljSymbol() not bare identifier,
macro-expanded do-unwrap in processForm, emitBlock multiline wrap,
indentCode helper, when-var-exists emitter form, variadic apply fix,
fn proc spacing fix, def indent fix

Macros: deftest, is, testing, thrown?, are, when-var-exists builtins;
rewritten and/or using gensym; improved for/doseq/dotimes; cond->
and cond->> threading fixes; threading macro insert fixes

Runtime: sorted-map, sorted-set, sorted?, array-map, object-array,
hash-map, hash-set, inf, nan; assoc extended to vectors

Test runner: #?@ splice unwrapping, removed conflicting defmacro stubs
2026-05-09 16:14:44 +03:00

135 lines
4.1 KiB
Python

import subprocess, tempfile, os, re, sys
def extract_default(content, start):
"""Extract the :default branch value from reader conditional content.
Returns (value_string, consumed_length)."""
content = content.strip()
# Find :default keyword
default_idx = content.find(':default')
if default_idx < 0:
return '', len(content)
rest = content[default_idx + len(':default'):].strip()
if not rest:
return '', len(content)
# Read one s-expression
if rest[0] in '([':
open_c = rest[0]
close_c = ']' if open_c == '[' else ')'
depth = 0
k = 0
while k < len(rest):
if rest[k] == open_c:
depth += 1
elif rest[k] == close_c:
depth -= 1
if depth == 0:
return rest[:k+1], k+1
k += 1
return rest, len(rest)
elif rest[0] == '"':
# String
k = 1
while k < len(rest):
if rest[k] == '\\':
k += 1
elif rest[k] == '"':
return rest[:k+1], k+1
k += 1
return rest, len(rest)
else:
# Atom: read until whitespace or )
k = 0
while k < len(rest) and rest[k] not in ' \t\n\r,)':
k += 1
return rest[:k], k
def strip_reader_conditionals(text):
"""Strip #? and #?@ reader conditionals, keeping :default branch content.
For #?@, if the default is a vector/list, unwrap it (splice semantics)."""
result = []
i = 0
while i < len(text):
# Check for #?@ or #?
is_splice = False
if i + 3 <= len(text) and text[i:i+3] == '#?@':
j = i + 3
is_splice = True
elif i + 2 <= len(text) and text[i:i+2] == '#?':
j = i + 2
else:
result.append(text[i])
i += 1
continue
# Skip whitespace between #? and (
while j < len(text) and text[j] in ' \t\n\r':
j += 1
if j >= len(text) or text[j] != '(':
result.append(text[i])
i += 1
continue
# Find matching closing paren
depth = 0
k = j
while k < len(text):
if text[k] == '(':
depth += 1
elif text[k] == ')':
depth -= 1
if depth == 0:
break
k += 1
if depth != 0:
result.append(text[i])
i += 1
continue
# Extract content between parens
inner = text[j+1:k]
default_val, _ = extract_default(inner, 0)
if is_splice and len(default_val) >= 2 and default_val[0] in '([':
default_val = default_val[1:-1]
result.append(default_val)
i = k + 1
return ''.join(result)
def run_test(cljc_path, timeout=30):
with open(cljc_path, 'r') as f:
content = f.read()
content = strip_reader_conditionals(content)
content = content.replace('##Inf', 'inf').replace('##-Inf', '-inf').replace('##NaN', 'nan')
content = re.sub(r'#\{[^}]*\}', r'@[]', content) # #{} → @[]
content = re.sub(r'#:([\w-]+)', r'\1', content) # #:foo → foo
stubs = '''(do
'''
content = stubs + content + ')'
content = re.sub(r'clojure\.test', 'test', content)
fd, path = tempfile.mkstemp(suffix='.clj')
try:
os.write(fd, content.encode())
finally:
os.close(fd)
try:
result = subprocess.run(['./cljnim', 'run', path], capture_output=True, text=True, timeout=timeout)
return result.returncode, result.stdout, result.stderr
finally:
os.unlink(path)
if len(sys.argv) > 1:
cljc = sys.argv[1]
rc, out, err = run_test(cljc)
print(f'rc={rc}')
if rc != 0:
print('stderr:', err[:500])
if out.strip():
print('stdout:', out[:500])
else:
for test in ['zipmap', 'zero_qmark', 'with_out_str']:
cljc = f'/tmp/clojure-test-suite/test/clojure/core_test/{test}.cljc'
rc, out, err = run_test(cljc)
print(f'{test}: rc={rc}')
if rc != 0:
print(' stderr:', err[:300])