Skip to content

Commit a27c2f5

Browse files
committed
Merge remote-tracking branch 'origin/develop' into work/desktop-stdlib
2 parents b8cb969 + d143417 commit a27c2f5

69 files changed

Lines changed: 16744 additions & 17 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/typedpython.yml‎

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: TypedPython CI
2+
3+
# The TypedPython gate and compiler are Python (python-multiplatform-ksp/src/{main,test}/python).
4+
# Gradle does not run them; this workflow does.
5+
on:
6+
push:
7+
branches: [ "develop", "main" ]
8+
paths: [ "python-multiplatform-ksp/**", ".github/workflows/typedpython.yml" ]
9+
pull_request:
10+
branches: [ "develop", "main" ]
11+
paths: [ "python-multiplatform-ksp/**", ".github/workflows/typedpython.yml" ]
12+
13+
jobs:
14+
test:
15+
name: TypedPython tests (${{ matrix.os }})
16+
runs-on: ${{ matrix.os }}
17+
strategy:
18+
fail-fast: false
19+
matrix:
20+
os: [ubuntu-latest, macos-latest]
21+
defaults:
22+
run:
23+
working-directory: python-multiplatform-ksp
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- uses: astral-sh/setup-uv@v5
28+
29+
- name: Create the environment
30+
# pyrefly is pinned exactly: the gate reads its versioned type-report format.
31+
run: |
32+
uv venv .venv --python 3.13
33+
uv pip install --python .venv/bin/python "pyrefly==1.3.2" pytest
34+
35+
- name: Behaviour tests
36+
run: .venv/bin/python -m pytest -q -m "not measurement"
37+
38+
- name: Measurements (recorded, sanity bounds only)
39+
# A shared runner is not an idle machine (AGENTS.md §8): read ratios, not absolute times.
40+
run: .venv/bin/python -m pytest -q -s -m measurement
41+
42+
sanitizers:
43+
# SPEC N-8: ASan/UBSan runs are the safety net outside the proof. Every extension TypedPython
44+
# builds in these tests is compiled with -fsanitize=address,undefined (TP_SANITIZE=1, see
45+
# conftest.py) and the interpreter runs with the ASan runtime preloaded; any report fails the run.
46+
# Linux only: macOS refuses to load the ASan runtime into the framework Python (the cgen
47+
# sanitizer test has a launcher-based macOS path of its own).
48+
name: TypedPython tests under ASan + UBSan (ubuntu-latest)
49+
runs-on: ubuntu-latest
50+
defaults:
51+
run:
52+
working-directory: python-multiplatform-ksp
53+
steps:
54+
- uses: actions/checkout@v4
55+
56+
- uses: astral-sh/setup-uv@v5
57+
58+
- name: Create the environment
59+
run: |
60+
uv venv .venv --python 3.13
61+
uv pip install --python .venv/bin/python "pyrefly==1.3.2" pytest
62+
63+
- name: Relax ASLR entropy (ASan shadow mapping on newer kernels)
64+
run: sudo sysctl -w vm.mmap_rnd_bits=28 || true
65+
66+
- name: Self-check, the sanitizers must catch planted faults
67+
# Builds a deliberately faulty extension (heap out-of-bounds read, signed overflow) and
68+
# REQUIRES both reports. If this step passes, the setup below can detect faults.
69+
run: .venv/bin/python tools/sanitizers.py selfcheck
70+
71+
- name: cgen, runtime and pipeline tests, sanitized
72+
# detect_leaks=0: CPython itself leaks at exit. LD_PRELOAD is applied to this one command
73+
# only (tools/sanitizers.py env prints it); the gate's pyrefly runs without it.
74+
run: |
75+
env $(.venv/bin/python tools/sanitizers.py env) \
76+
.venv/bin/python -m pytest -q -m "not measurement" \
77+
src/test/python/test_cgen.py src/test/python/test_runtime.py src/test/python/test_pipeline.py

‎benchmarks/typedpython/.gitignore‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
target/
2+
java-out/
3+
__pycache__/
4+
*.class
5+
tp-build/
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
public class BinaryTrees {
2+
static final class Node {
3+
final Node left, right;
4+
Node(Node left, Node right) { this.left = left; this.right = right; }
5+
}
6+
7+
static Node make(int depth) {
8+
if (depth > 0) return new Node(make(depth - 1), make(depth - 1));
9+
return new Node(null, null);
10+
}
11+
12+
static int check(Node node) {
13+
Node left = node.left, right = node.right;
14+
if (left == null || right == null) return 1;
15+
return 1 + check(left) + check(right);
16+
}
17+
18+
public static void main(String[] args) {
19+
int n = Integer.parseInt(args[0]);
20+
int minDepth = 4;
21+
int maxDepth = Math.max(minDepth + 2, n);
22+
int stretch = check(make(maxDepth + 1));
23+
Node longLived = make(maxDepth);
24+
long total = 0;
25+
for (int depth = minDepth; depth <= maxDepth; depth += 2) {
26+
int iterations = 1 << (maxDepth - depth + minDepth);
27+
long chk = 0;
28+
for (int i = 0; i < iterations; i++) chk += check(make(depth));
29+
total += chk;
30+
}
31+
System.out.println(stretch + " " + total + " " + check(longLived));
32+
}
33+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
public class Fannkuch {
2+
public static void main(String[] args) {
3+
int n = Integer.parseInt(args[0]);
4+
int[] perm1 = new int[n];
5+
for (int i = 0; i < n; i++) perm1[i] = i;
6+
int[] count = new int[n];
7+
int maxFlips = 0, checksum = 0, permCount = 0, r = n;
8+
while (true) {
9+
while (r != 1) { count[r - 1] = r; r--; }
10+
int[] perm = perm1.clone();
11+
int flips = 0;
12+
int k = perm[0];
13+
while (k != 0) {
14+
int lo = 0, hi = k;
15+
while (lo < hi) {
16+
int t = perm[lo]; perm[lo] = perm[hi]; perm[hi] = t;
17+
lo++; hi--;
18+
}
19+
flips++;
20+
k = perm[0];
21+
}
22+
if (flips > maxFlips) maxFlips = flips;
23+
if (permCount % 2 == 0) checksum += flips; else checksum -= flips;
24+
boolean done = false;
25+
while (true) {
26+
if (r == n) { done = true; break; }
27+
int p0 = perm1[0];
28+
for (int i = 0; i < r; i++) perm1[i] = perm1[i + 1];
29+
perm1[r] = p0;
30+
count[r]--;
31+
if (count[r] > 0) break;
32+
r++;
33+
}
34+
if (done) break;
35+
permCount++;
36+
}
37+
System.out.println(checksum + " " + maxFlips);
38+
}
39+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import java.util.Locale;
2+
3+
public class Nbody {
4+
static final double PI = 3.141592653589793;
5+
static final double SOLAR_MASS = 4 * PI * PI;
6+
static final double DAYS = 365.24;
7+
static final double[] x = {0.0, 4.84143144246472090e+00, 8.34336671824457987e+00, 1.28943695621391310e+01, 1.53796971148509165e+01};
8+
static final double[] y = {0.0, -1.16032004402742839e+00, 4.12479856412430479e+00, -1.51111514016986312e+01, -2.59193146099879641e+01};
9+
static final double[] z = {0.0, -1.03622044471123109e-01, -4.03523417114321381e-01, -2.23307578892655734e-01, 1.79258772950371181e-01};
10+
static final double[] vx = {0.0, 1.66007664274403694e-03 * DAYS, -2.76742510726862411e-03 * DAYS, 2.96460137564761618e-03 * DAYS, 2.68067772490389322e-03 * DAYS};
11+
static final double[] vy = {0.0, 7.69901118419740425e-03 * DAYS, 4.99852801234917238e-03 * DAYS, 2.37847173959480950e-03 * DAYS, 1.62824170038242295e-03 * DAYS};
12+
static final double[] vz = {0.0, -6.90460016972063023e-05 * DAYS, 2.30417297573763929e-05 * DAYS, -2.96589568540237556e-05 * DAYS, -9.51592254519715870e-05 * DAYS};
13+
static final double[] mass = {SOLAR_MASS, 9.54791938424326609e-04 * SOLAR_MASS, 2.85885980666130812e-04 * SOLAR_MASS, 4.36624404335156298e-05 * SOLAR_MASS, 5.15138902046611451e-05 * SOLAR_MASS};
14+
15+
static void offsetMomentum() {
16+
double px = 0.0, py = 0.0, pz = 0.0;
17+
for (int i = 0; i < 5; i++) {
18+
px += vx[i] * mass[i];
19+
py += vy[i] * mass[i];
20+
pz += vz[i] * mass[i];
21+
}
22+
vx[0] = -px / SOLAR_MASS;
23+
vy[0] = -py / SOLAR_MASS;
24+
vz[0] = -pz / SOLAR_MASS;
25+
}
26+
27+
static void advance(double dt, int steps) {
28+
for (int s = 0; s < steps; s++) {
29+
for (int i = 0; i < 5; i++) {
30+
for (int j = i + 1; j < 5; j++) {
31+
double dx = x[i] - x[j];
32+
double dy = y[i] - y[j];
33+
double dz = z[i] - z[j];
34+
double d2 = dx * dx + dy * dy + dz * dz;
35+
double mag = dt / (d2 * Math.sqrt(d2));
36+
vx[i] -= dx * mass[j] * mag;
37+
vy[i] -= dy * mass[j] * mag;
38+
vz[i] -= dz * mass[j] * mag;
39+
vx[j] += dx * mass[i] * mag;
40+
vy[j] += dy * mass[i] * mag;
41+
vz[j] += dz * mass[i] * mag;
42+
}
43+
}
44+
for (int i = 0; i < 5; i++) {
45+
x[i] += dt * vx[i];
46+
y[i] += dt * vy[i];
47+
z[i] += dt * vz[i];
48+
}
49+
}
50+
}
51+
52+
static double energy() {
53+
double e = 0.0;
54+
for (int i = 0; i < 5; i++) {
55+
e += 0.5 * mass[i] * (vx[i] * vx[i] + vy[i] * vy[i] + vz[i] * vz[i]);
56+
for (int j = i + 1; j < 5; j++) {
57+
double dx = x[i] - x[j];
58+
double dy = y[i] - y[j];
59+
double dz = z[i] - z[j];
60+
e -= mass[i] * mass[j] / Math.sqrt(dx * dx + dy * dy + dz * dz);
61+
}
62+
}
63+
return e;
64+
}
65+
66+
public static void main(String[] args) {
67+
int n = Integer.parseInt(args[0]);
68+
offsetMomentum();
69+
double before = energy();
70+
advance(0.01, n);
71+
double after = energy();
72+
System.out.println(String.format(Locale.ROOT, "%.9f %.9f", before, after));
73+
}
74+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import java.util.Locale;
2+
3+
public class SpectralNorm {
4+
static double evalA(int i, int j) {
5+
return 1.0 / ((i + j) * (i + j + 1) / 2 + i + 1);
6+
}
7+
8+
static void mulAv(int n, double[] v, double[] out) {
9+
for (int i = 0; i < n; i++) {
10+
double s = 0.0;
11+
for (int j = 0; j < n; j++) s += evalA(i, j) * v[j];
12+
out[i] = s;
13+
}
14+
}
15+
16+
static void mulAtv(int n, double[] v, double[] out) {
17+
for (int i = 0; i < n; i++) {
18+
double s = 0.0;
19+
for (int j = 0; j < n; j++) s += evalA(j, i) * v[j];
20+
out[i] = s;
21+
}
22+
}
23+
24+
static void mulAtAv(int n, double[] v, double[] out, double[] tmp) {
25+
mulAv(n, v, tmp);
26+
mulAtv(n, tmp, out);
27+
}
28+
29+
public static void main(String[] args) {
30+
int n = Integer.parseInt(args[0]);
31+
double[] u = new double[n];
32+
double[] v = new double[n];
33+
double[] tmp = new double[n];
34+
java.util.Arrays.fill(u, 1.0);
35+
for (int k = 0; k < 10; k++) {
36+
mulAtAv(n, u, v, tmp);
37+
mulAtAv(n, v, u, tmp);
38+
}
39+
double vbv = 0.0, vv = 0.0;
40+
for (int i = 0; i < n; i++) {
41+
vbv += u[i] * v[i];
42+
vv += v[i] * v[i];
43+
}
44+
System.out.println(String.format(Locale.ROOT, "%.9f", Math.sqrt(vbv / vv)));
45+
}
46+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import java.util.ArrayList;
2+
import java.util.HashMap;
3+
import java.util.List;
4+
import java.util.Map;
5+
6+
public class Wordfreq {
7+
static final long VOCAB = 50000;
8+
static final long MOD = 2147483647L;
9+
10+
static long nextState(long s) { return (s * 48271) % MOD; }
11+
12+
static String wordOf(long id) {
13+
long x = id + 17576;
14+
StringBuilder sb = new StringBuilder();
15+
while (x > 0) {
16+
sb.append((char) (97 + x % 26));
17+
x /= 26;
18+
}
19+
return sb.reverse().toString();
20+
}
21+
22+
public static void main(String[] args) {
23+
int n = Integer.parseInt(args[0]);
24+
Map<String, Integer> counts = new HashMap<>();
25+
long s = 12345;
26+
for (int i = 0; i < n; i++) {
27+
s = nextState(s);
28+
long a = s % VOCAB;
29+
s = nextState(s);
30+
long b = s % VOCAB;
31+
counts.merge(wordOf(a * b / VOCAB), 1, Integer::sum);
32+
}
33+
long weighted = 0;
34+
for (int c : counts.values()) weighted += (long) c * c;
35+
List<String> taken = new ArrayList<>();
36+
List<String> parts = new ArrayList<>();
37+
for (int k = 0; k < 5; k++) {
38+
String bestWord = "";
39+
int bestCount = -1;
40+
for (Map.Entry<String, Integer> e : counts.entrySet()) {
41+
String w = e.getKey();
42+
int c = e.getValue();
43+
if (taken.contains(w)) continue;
44+
if (c > bestCount || (c == bestCount && w.compareTo(bestWord) < 0)) { bestWord = w; bestCount = c; }
45+
}
46+
taken.add(bestWord);
47+
parts.add(bestWord + ":" + bestCount);
48+
}
49+
System.out.println(counts.size() + " " + weighted + " " + String.join(",", parts));
50+
}
51+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class Node {
2+
constructor(left, right) { this.left = left; this.right = right; }
3+
}
4+
function make(depth) {
5+
if (depth > 0) return new Node(make(depth - 1), make(depth - 1));
6+
return new Node(null, null);
7+
}
8+
function check(node) {
9+
const left = node.left, right = node.right;
10+
if (left === null || right === null) return 1;
11+
return 1 + check(left) + check(right);
12+
}
13+
const n = parseInt(process.argv[2], 10);
14+
const minDepth = 4;
15+
const maxDepth = Math.max(minDepth + 2, n);
16+
const stretch = check(make(maxDepth + 1));
17+
const longLived = make(maxDepth);
18+
let total = 0;
19+
for (let depth = minDepth; depth <= maxDepth; depth += 2) {
20+
const iterations = 1 << (maxDepth - depth + minDepth);
21+
let chk = 0;
22+
for (let i = 0; i < iterations; i++) chk += check(make(depth));
23+
total += chk;
24+
}
25+
console.log(`${stretch} ${total} ${check(longLived)}`);
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
function fannkuch(n) {
2+
const perm1 = Array.from({ length: n }, (_, i) => i);
3+
const count = new Array(n).fill(0);
4+
let maxFlips = 0, checksum = 0, permCount = 0, r = n;
5+
for (;;) {
6+
while (r !== 1) { count[r - 1] = r; r--; }
7+
const perm = perm1.slice();
8+
let flips = 0;
9+
let k = perm[0];
10+
while (k !== 0) {
11+
let lo = 0, hi = k;
12+
while (lo < hi) {
13+
const t = perm[lo]; perm[lo] = perm[hi]; perm[hi] = t;
14+
lo++; hi--;
15+
}
16+
flips++;
17+
k = perm[0];
18+
}
19+
if (flips > maxFlips) maxFlips = flips;
20+
if (permCount % 2 === 0) checksum += flips; else checksum -= flips;
21+
for (;;) {
22+
if (r === n) return [checksum, maxFlips];
23+
const p0 = perm1[0];
24+
for (let i = 0; i < r; i++) perm1[i] = perm1[i + 1];
25+
perm1[r] = p0;
26+
count[r]--;
27+
if (count[r] > 0) break;
28+
r++;
29+
}
30+
permCount++;
31+
}
32+
}
33+
const [checksum, maxFlips] = fannkuch(parseInt(process.argv[2], 10));
34+
console.log(`${checksum} ${maxFlips}`);

0 commit comments

Comments
 (0)