Skip to content

Commit f141c38

Browse files
Explicit capture for Oct.
1 parent 857979d commit f141c38

29 files changed

Lines changed: 967 additions & 274 deletions

Language/Functions/FunctionValues/invalid/anonymous_function_not_supported.octfail

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
expect error: "function expects Int, but return is Bool"
2+
3+
package Main
4+
5+
fn Main() -> Int {
6+
let bad = fn() -> Int { return true }
7+
return bad()
8+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
expect error: "cannot assign to captured value 'count'; captures are immutable snapshots"
2+
3+
package Main
4+
5+
fn Main() -> Int {
6+
var outer = 1
7+
let f = fn() -> Int with { count: outer } {
8+
count = count + 1
9+
return count
10+
}
11+
return f()
12+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
expect error: "capture 'x' conflicts with parameter 'x'"
2+
3+
package Main
4+
5+
fn Main() -> Int {
6+
let outer = 1
7+
let f = fn(x: Int) -> Int with { x: outer } { return x }
8+
return f(2)
9+
}
10+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
expect error: "capture 'value': undefined variable: unknownName"
2+
3+
package Main
4+
5+
fn Main() -> Int {
6+
let f = fn() -> Int with { value: unknownName } { return value }
7+
return f()
8+
}
9+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
expect error: "duplicate capture 'value'"
2+
3+
package Main
4+
5+
fn Main() -> Int {
6+
let a = 1
7+
let b = 2
8+
let f = fn() -> Int with { value: a value: b } { return value }
9+
return f()
10+
}
11+

Language/Functions/FunctionValues/invalid/function_return_type_not_supported.octfail

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
expect error: "outer local 'offset' is not captured; add it to 'with { ... }'"
2+
3+
package Main
4+
5+
fn Main() -> Int {
6+
let offset = 10
7+
let add = fn(x: Int) -> Int { return x + offset }
8+
return add(5)
9+
}
10+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
expect error: "outer local 'offset' is not captured; add it to 'with { ... }'"
2+
3+
package Main
4+
5+
fn Make(offset: Int) -> fn(Int) -> Int {
6+
return fn(value: Int) -> Int { return value + offset }
7+
}
8+
9+
fn Main() -> Int { return 0 }
10+
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package FunctionValuesValid
2+
3+
fn Apply(f: fn(Int) -> Int, value: Int) -> Int {
4+
return f(value)
5+
}
6+
7+
fn Triple(value: Int) -> Int {
8+
return value * 3
9+
}
10+
11+
fn ApplyFallible(f: fn(Int) -> Int ! Error, value: Int) -> Int ! Error {
12+
return f(value)?
13+
}
14+
15+
template fn MakeIdentity<T>() -> fn(T) -> T {
16+
return fn(value: T) -> T { return value }
17+
}
18+
19+
fn MakeAdder(offset: Int) -> fn(Int) -> Int {
20+
return fn(x: Int) -> Int with {
21+
offset: offset
22+
} {
23+
return x + offset
24+
}
25+
}
26+
27+
[Fact]
28+
fn AnonymousFunctionWithoutCaptures() -> Void {
29+
let square = fn(x: Int) -> Int {
30+
return x * x
31+
}
32+
Assert.Equal(25, square(5), "anonymous function is callable")
33+
}
34+
35+
[Fact]
36+
fn ExplicitCaptureIsRenamedSnapshot() -> Void {
37+
var multiplier = 3
38+
let scale = fn(x: Int) -> Int with {
39+
factor: multiplier
40+
} {
41+
return x * factor
42+
}
43+
multiplier = 10
44+
Assert.Equal(12, Apply(scale, 4), "capture is evaluated by value at construction")
45+
}
46+
47+
[Fact]
48+
fn ArrayCaptureSnapshotsAtConstruction() -> Void {
49+
var factors = [2]
50+
let scale = fn(value: Int) -> Int with {
51+
factors: factors
52+
} {
53+
return value * factors[0]
54+
}
55+
factors[0] = 10
56+
Assert.Equal(8, scale(4), "captured arrays are value snapshots, not shared cells")
57+
}
58+
59+
[Fact]
60+
fn CapturedFunctionEscapesCreatorScope() -> Void {
61+
let add10 = MakeAdder(10)
62+
Assert.Equal(15, add10(5), "captured environment outlives creator invocation")
63+
}
64+
65+
[Fact]
66+
fn NestedFunctionsCaptureExplicitlyAtEachLevel() -> Void {
67+
let factor = 3
68+
let outer = fn() -> fn(Int) -> Int with {
69+
factor: factor
70+
} {
71+
return fn(x: Int) -> Int with {
72+
factor: factor
73+
} {
74+
return x * factor
75+
}
76+
}
77+
Assert.Equal(12, outer()(4), "nested environments are independently explicit")
78+
}
79+
80+
[Fact]
81+
fn PackageFunctionsDoNotRequireCapture() -> Void {
82+
let applyTriple = fn(value: Int) -> Int { return Triple(value) }
83+
Assert.Equal(12, applyTriple(4), "package function remains globally resolvable")
84+
}
85+
86+
[Fact]
87+
fn FallibleAnonymousFunctionMatchesFallibleFunctionType() -> Void ! Error {
88+
let nonnegative = fn(value: Int) -> Int ! Error {
89+
if value < 0 { return error("negative") }
90+
return value
91+
}
92+
Assert.Equal(4, ApplyFallible(nonnegative, 4)?, "fallible anonymous function is callable")
93+
}
94+
95+
[Fact]
96+
fn TemplateElaborationPreservesAnonymousFunction() -> Void {
97+
let identity = MakeIdentity<Int>()
98+
Assert.Equal(7, identity(7), "template-generated anonymous function works")
99+
}
100+
101+
[Fact]
102+
fn CapturedFunctionWorksWithScientificMatrixCallback() -> Void {
103+
let base = 10
104+
let entry = fn(row: Int, column: Int) -> Int with {
105+
base: base
106+
} {
107+
return base + row + column
108+
}
109+
let result = Matrix.tabulate(2, 2, entry)
110+
Assert.Equal(12, result[1, 1], "captured callback composes with Matrix.tabulate")
111+
}

0 commit comments

Comments
 (0)