diff --git a/.github/workflows/avm-ci.yml b/.github/workflows/avm-ci.yml index 56055ba8..6655d043 100644 --- a/.github/workflows/avm-ci.yml +++ b/.github/workflows/avm-ci.yml @@ -3,12 +3,17 @@ name: AVM ISA Cross-Port CI on: push: paths: - - 'python/avm.py' - - 'go/avm.go' - - 'rust/src/avm/**' - - 'c/avm.c' - - 'cpp/avm.hpp' + - 'python/**' + - 'go/**' + - 'rust/src/**' + - 'c/**' + - 'cpp/**' + - 'julia/**' + - 'r/**' - 'fortran/**' + - 'octave/**' + - 'scala/**' + - 'coq/**' - 'tests/**' - 'scripts/wolfram_verify.py' workflow_dispatch: @@ -18,16 +23,18 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 with: { python-version: '3.12' } - - name: Run Python AVM tests - run: PYTHONPATH=python python3 -m pytest tests/test_avm_python.py -v + - uses: actions/setup-python@v5 + with: { python-version: '3.12' } + - name: Python AVM tests + run: PYTHONPATH=python python3 tests/test_avm_python.py go: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-go@v5 with: { go-version: '1.26' } - - name: Run Go AVM tests + - uses: actions/setup-go@v5 + with: { go-version: '1.26' } + - name: Go AVM tests run: go test -v ./go/ rust: @@ -35,32 +42,45 @@ jobs: steps: - uses: actions/checkout@v4 - uses: actions-rust-lang/setup-rust-toolchain@v1 - - name: Run Rust AVM tests + - name: Rust AVM tests run: cd rust && cargo test c: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Build and run C AVM tests - run: | - gcc -o c/test_avm c/test_avm.c -lm - ./c/test_avm + - name: C AVM tests + run: gcc -o /tmp/c_avm c/test_avm.c -lm && /tmp/c_avm cpp: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Build and run C++ AVM tests - run: | - g++ -std=c++20 -o cpp/test_avm cpp/test_avm.cpp - ./cpp/test_avm + - name: C++ AVM tests + run: g++ -std=c++17 -o /tmp/cpp_avm cpp/test_avm.cpp && /tmp/cpp_avm + + julia: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 + - name: Julia AVM tests + run: julia julia/AVMIsa/test_avm.jl + + r: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: r-lib/actions/setup-r@v2 + - name: R AVM tests + run: Rscript r/AVMIsa/test_avm.r wolfram-verify: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 with: { python-version: '3.12' } + - uses: actions/setup-python@v5 + with: { python-version: '3.12' } - name: Wolfram Alpha verification run: python3 scripts/wolfram_verify.py env: @@ -68,8 +88,8 @@ jobs: cross-verify: runs-on: ubuntu-latest - needs: [python, go, rust, c, cpp] + needs: [python, go, rust, c, cpp, julia, r] steps: - uses: actions/checkout@v4 - name: All AVM ports passed - run: echo "✅ All AVM ISA port tests passed" + run: echo "✅ All AVM ISA port tests passed (Python, Go, Rust, C, C++, Julia, R)" diff --git a/scripts/wolfram_verify.py b/scripts/wolfram_verify.py index 45c5b80c..6cadb800 100644 --- a/scripts/wolfram_verify.py +++ b/scripts/wolfram_verify.py @@ -36,18 +36,34 @@ def verify_arithmetic(): return results def run_port_tests(): - """Run all AVM port test harnesses and collect results.""" + """Run ALL AVM port test harnesses.""" + import shutil results = {} + + # Each port: (name, [cmd, args...], working_dir_relative, env_add) ports = [ - ("Python", [sys.executable, "tests/test_avm_python.py"], {"cwd": SILVER, "env": {**os.environ, "PYTHONPATH": str(SILVER / "python")}}), - ("Rust", ["cargo", "test"], {"cwd": SILVER / "rust"}), + ("Python", [sys.executable, "tests/test_avm_python.py"], ".", {"PYTHONPATH": str(SILVER / "python")}), + ("Rust", ["cargo", "test"], "rust", {}), + ("Go", ["go", "test", "-v", "./go/"], ".", {}), + ("C", ["sh", "-c", "gcc -o /tmp/c_avm_test c/test_avm.c -lm && /tmp/c_avm_test"], ".", {}), + ("C++", ["sh", "-c", "g++ -std=c++20 -o /tmp/cpp_avm_test cpp/test_avm.cpp && /tmp/cpp_avm_test"], ".", {}), + ("Julia", ["julia", "julia/AVMIsa/test_avm.jl"], ".", {}), + ("R", ["Rscript", "r/AVMIsa/test_avm.r"], ".", {}), + ("Octave", ["octave", "--no-gui", "octave/test_avm.m"], ".", {}), ] - for name, cmd, kw in ports: + + for name, cmd, wd, env_add in ports: + exe = cmd[0] + if not shutil.which(exe.split()[0] if '/' in exe else exe): + results[name] = {"passed": False, "skipped": True, "reason": f"{exe} not found"} + continue try: - r = subprocess.run(cmd, capture_output=True, text=True, timeout=60, **kw) - results[name] = {"passed": r.returncode == 0, "output": r.stdout[-200:]} + env = {**os.environ, **env_add} + r = subprocess.run(cmd, capture_output=True, text=True, timeout=120, cwd=SILVER / wd, env=env) + ok = r.returncode == 0 and ("fail" not in r.stdout.lower() and "error" not in r.stdout.lower()[:500]) + results[name] = {"passed": ok, "output": r.stdout[-300:]} except Exception as e: - results[name] = {"passed": False, "error": str(e)} + results[name] = {"passed": False, "error": str(e)[:200]} return results def main():