Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions test/e2e/fixtures/python_face_runnable.pyaff
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# face: python
# SPDX-License-Identifier: MPL-2.0
#
# End-to-end proof (2026-07-07) that a *face-authored* program compiles
# through the Python face → canonical → typecheck → wasm and RUNS with the
# right answer. This is the README's headline claim ("faces are the product")
# exercised for real, not just parsed.
#
# Recursion, not a loop: the Python face currently drops the trailing `;` on
# the last statement of a while/for body (issue #683), so face-authored loops
# don't yet compile. Recursion's tail line is a value expression, which the
# face handles correctly — so this proves the face→wasm path without waiting
# on #683. (Variable names also avoid the `total` soft-keyword collision,
# issue #682.)

def fac(n: Int) -> Int:
if n == 0:
1
else:
n * fac(n - 1)

def sum_to(n: Int) -> Int:
if n == 0:
0
else:
n + sum_to(n - 1)

def main() -> Int:
# fac(5)=120, sum_to(100)=5050 -> 120 + 5050 = 5170
fac(5) + sum_to(100)
37 changes: 37 additions & 0 deletions test/e2e/python_face_e2e.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: MPL-2.0
#
# End-to-end proof that a Python-face-authored program runs: compile
# fixtures/python_face_runnable.pyaff *through the Python face* to core-WASM
# and assert main() === 5170 (fac(5)=120 + sum_to(100)=5050). Exercises the
# README's "faces are the product" claim as running code, not just a parse.
#
# Requires the compiler built (dune build → _build/default/bin/main.exe;
# override with AFFINESCRIPT_BIN) and node on PATH. Skips loudly (exit 0)
# if either is absent.
set -uo pipefail
cd "$(dirname "$0")"
REPO="$(cd ../.. && pwd)"
BIN="${AFFINESCRIPT_BIN:-$REPO/_build/default/bin/main.exe}"
SRC="fixtures/python_face_runnable.pyaff"
EXPECT=5170

[ -x "$BIN" ] || { echo "SKIP: compiler not built ($BIN) — run dune build"; exit 0; }

Check failure on line 19 in test/e2e/python_face_e2e.sh

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use '[[' instead of '[' for conditional tests. The '[[' construct is safer and more feature-rich.

See more on https://sonarcloud.io/project/issues?id=hyperpolymath_affinescript&issues=AZ891oh3_WxqgBnGqxd6&open=AZ891oh3_WxqgBnGqxd6&pullRequest=684
command -v node >/dev/null 2>&1 || { echo "SKIP: node not on PATH"; exit 0; }

TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
WASM="$TMP/pf.wasm"

# The `# face: python` pragma on line 1 selects the face; no --face needed.
"$BIN" compile "$SRC" -o "$WASM" || { echo "FAIL: compile through Python face"; exit 1; }

node - "$WASM" "$EXPECT" <<'JS'
import { readFile } from "node:fs/promises";
const [wasm, expect] = [process.argv[2], Number(process.argv[3])];
const { instance } = await WebAssembly.instantiate(
await readFile(wasm), { wasi_snapshot_preview1: { fd_write: () => 0 } });
const got = instance.exports.main();
console.log(`main() = ${got} (expected ${expect})`);
if (got !== expect) { console.error("FAIL: wrong result"); process.exit(1); }
console.log("PASS: Python-face program ran end-to-end (face → wasm → correct result)");
JS
Loading