Something went wrong. Try again.
Jam Programming Language jamlang.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160// MVS P2 boundaries: default-mode parameters reject writes (see// reject_param_readonly_write.jam) — these are the writes that stay// legal. `mut` mode writes flow back to the caller; pointer params// write through their pointee, not the parameter; locals copied from// a parameter are freely mutable.
const { assert } = import("test");
const Point = struct { x: f64, y: f64,};
fn pokeArr(arr: mut [4]u16) { arr[0] = 99;}
tfn mutArrayFlowsBack() { var a: [4]u16 = [1, 2, 3, 4]; pokeArr(a); assert(a[0] as u32, 99); assert(a[1] as u32, 2);}
fn scale(p: mut Point, factor: f64) { p.x = p.x * factor; p.y = p.y * factor;}
tfn mutStructFlowsBack() { var pt: Point = Point { x: 3.0, y: 4.0 }; scale(pt, 2.0); assert((pt.x == 6.0) as u8, 1); assert((pt.y == 8.0) as u8, 1);}
fn fill(buf: mut []u8, b: u8) { for v in buf { v = b; }}
tfn mutSliceElementsWritable() { var raw: [3]u8 = [0, 0, 0]; fill(raw[0..3], 9); assert(raw[0], 9); assert(raw[2], 9);}
fn derefWrite(p: *mut u8) { p.* = 77;}
fn manyItemWrite(p: *mut[] u8) { p[1] = 55;}
tfn pointerParamsWriteThrough() { var x: u8 = 1; derefWrite(&x); assert(x, 77); var arr: [3]u8 = [1, 2, 3]; manyItemWrite(&arr[0]); assert(arr[1], 55);}
fn copyThenMutate(arr: [4]u16) u16 { var scratch: [4]u16 = arr; scratch[0] = 42; return scratch[0];}
tfn localCopyIsMutable() { var a: [4]u16 = [1, 2, 3, 4]; assert(copyThenMutate(a) as u32, 42); assert(a[0] as u32, 1); // caller's storage untouched}
fn sumReadonly(arr: [4]u16) u32 { var total: u32 = 0; for v in arr { total = total + (v as u32); } return total;}
tfn readingParamElementsIsFine() { var a: [4]u16 = [10, 20, 30, 40]; assert(sumReadonly(a), 100);}
const { Vec } = import("std").collections;
fn fillThroughView(v: mut Vec(u8), b: u8) { for x in v.asSlice() { x = b; }}
tfn mutParamViewIsWritable() { var v: Vec(u8) = Vec(u8).empty(); v.push(1); v.push(2); fillThroughView(v, 9); assert(v[0] as u32, 9); assert(v[1] as u32, 9);}
tfn localViewIsWritable() { var v: Vec(u8) = Vec(u8).empty(); v.push(1); var s: []u8 = v.asSlice(); s[0] = 7; assert(v[0] as u32, 7);}
tfn rebindRestoresWritability() { var v: Vec(u8) = Vec(u8).empty(); v.push(1); var arr: [2]u8 = [0, 0]; var s: []u8 = v.asSlice(); s = arr[0..2]; // now views owned storage again s[1] = 5; assert(arr[1], 5);}
fn viewLen(v: Vec(u8)) u64 { const s: []u8 = v.asSlice(); return s.len; // reading through a view stays legal}
tfn readingViewsIsFine() { var v: Vec(u8) = Vec(u8).empty(); v.push(4); v.push(5); assert(viewLen(v) as u32, 2);}
const Holder = struct { tag: u32, buf: Vec(u8),};
fn bumpAll(h: mut Holder) { for b in h.buf.asSlice() { b = b + 1; } h.buf.push(9);}
tfn mutParamFieldChainsWritable() { var h: Holder = Holder { tag: 0, buf: Vec(u8).empty() }; h.buf.push(4); bumpAll(h); const view: []u8 = h.buf.asSlice(); assert(view[0] as u32, 5); assert(view[1] as u32, 9); assert(view.len as u32, 2);}