Skip to content

Commit 109ba50

Browse files
Jonathan D.A. Jewellclaude
andcommitted
feat: add mode support to CLI and create dyadic examples
**CLI Enhancement:** - Added `--mode` flag to `check` command (linear|affine) - Defaults to linear mode for backward compatibility - Imports Mode and type_check_module_with_mode from typing crate **Example Files Created:** 1. `examples/affine/01-implicit-drops.eph` - Demonstrates affine mode flexibility - Unconsumed resources allowed - Implicit drops at scope exit - ✓ Type-checks with `--mode affine` 2. `examples/linear/01-explicit-consumption.eph` - Shows linear mode strictness - ALL resources must be explicitly consumed - No implicit drops - ✓ Type-checks with `--mode linear` 3. `examples/comparison-affine-vs-linear.eph` - Side-by-side comparison - Same problems solved in both modes - Highlights trade-offs - Database connections, file processing, error handling 4. `examples/advanced-features.eph` - Advanced language features - Product types (pairs/tuples) - Lambda expressions - Borrow checking - (Note: Some lambda features need parser fixes) **Testing:** ```bash ./target/release/ephapax check --mode affine examples/affine/01-implicit-drops.eph ✓ 1 file(s) checked successfully ./target/release/ephapax check --mode linear examples/linear/01-explicit-consumption.eph ✓ 1 file(s) checked successfully ``` **Key Insight:** Demonstrates Ephapax's dyadic design - affine for prototyping, linear for production. Both modes prevent double-use, but differ in implicit drop semantics. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent c6181af commit 109ba50

5 files changed

Lines changed: 507 additions & 5 deletions

File tree

examples/advanced-features.eph

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
// Advanced Ephapax Features
3+
//
4+
// Demonstrates product types, sum types, lambdas, and borrows
5+
6+
// ============================================================================
7+
// Product Types (Pairs and Tuples)
8+
// ============================================================================
9+
10+
// Simple pair creation and access
11+
fn pair_basics(_unit: ()): I32 =
12+
let p = (10, 20) in
13+
let x = p.0 in
14+
let y = p.1 in
15+
x + y
16+
17+
// Nested pairs
18+
fn nested_pairs(_unit: ()): I32 =
19+
let p1 = (1, 2) in
20+
let p2 = (3, 4) in
21+
let nested = (p1, p2) in
22+
let first_pair = nested.0 in
23+
let a = first_pair.0 in
24+
let b = first_pair.1 in
25+
a + b
26+
27+
// Pair swapping
28+
fn swap_pair(p: (I32, I32)): (I32, I32) =
29+
let x = p.0 in
30+
let y = p.1 in
31+
(y, x)
32+
33+
// ============================================================================
34+
// Lambda Expressions
35+
// ============================================================================
36+
37+
// Basic lambda
38+
fn apply_lambda(_unit: ()): I32 =
39+
let increment = fn (x: I32) -> x + 1 in
40+
let result = increment(5) in
41+
result
42+
43+
// Lambda with multiple operations
44+
fn complex_lambda(_unit: ()): I32 =
45+
let compute = fn (x: I32) ->
46+
let doubled = x * 2 in
47+
let incremented = doubled + 1 in
48+
incremented
49+
in
50+
compute(10)
51+
52+
// Using lambdas for abstraction
53+
fn apply_twice(f: I32 -> I32, x: I32): I32 =
54+
let once = f(x) in
55+
f(once)
56+
57+
fn lambda_composition(_unit: ()): I32 =
58+
let add_five = fn (n: I32) -> n + 5 in
59+
apply_twice(add_five, 0)
60+
61+
// ============================================================================
62+
// Borrow Checking
63+
// ============================================================================
64+
65+
// Borrowing allows reading without consuming
66+
fn borrow_example(_unit: ()): I32 =
67+
region r {
68+
let s = String.new@r("hello") in
69+
70+
// Borrow for reading (doesn't consume)
71+
let len1 = String.len(&s) in
72+
73+
// Can borrow multiple times
74+
let len2 = String.len(&s) in
75+
76+
// Finally consume
77+
let _ = drop(s) in
78+
79+
len1 + len2
80+
}
81+
82+
// Multiple borrows in sequence
83+
fn multiple_borrows(_unit: ()): I32 =
84+
region r {
85+
let s = String.new@r("test") in
86+
87+
let len = String.len(&s) in
88+
let len_again = String.len(&s) in
89+
let len_third = String.len(&s) in
90+
91+
let _ = drop(s) in
92+
len + len_again + len_third
93+
}
94+
95+
// ============================================================================
96+
// Combining Features
97+
// ============================================================================
98+
99+
// Pairs with lambdas
100+
fn pair_with_lambda(_unit: ()): I32 =
101+
let p = (5, 3) in
102+
let process = fn (pair: (I32, I32)) ->
103+
let x = pair.0 in
104+
let y = pair.1 in
105+
x * y
106+
in
107+
process(p)
108+
109+
// Region with pairs and borrows
110+
fn complex_region(_unit: ()): I32 =
111+
region r {
112+
let s1 = String.new@r("first") in
113+
let s2 = String.new@r("second") in
114+
115+
let len1 = String.len(&s1) in
116+
let len2 = String.len(&s2) in
117+
118+
let pair = (len1, len2) in
119+
let sum = pair.0 + pair.1 in
120+
121+
let _ = drop(s1) in
122+
let _ = drop(s2) in
123+
124+
sum
125+
}
126+
127+
// ============================================================================
128+
// Practical Example: Data Pipeline
129+
// ============================================================================
130+
131+
fn process_data(input: I32): I32 =
132+
// Stage 1: Transform
133+
let transformed = fn (x: I32) -> x * 2 in
134+
let stage1 = transformed(input) in
135+
136+
// Stage 2: Filter (as conditional)
137+
let stage2 = if stage1 > 10 then stage1 else 0 in
138+
139+
// Stage 3: Aggregate
140+
let finalize = fn (x: I32) -> x + 100 in
141+
finalize(stage2)
142+
143+
fn pipeline_example(_unit: ()): I32 =
144+
let data = (5, 10, 15) in
145+
146+
let r1 = process_data(data.0) in
147+
let r2 = process_data(data.1) in
148+
let r3 = process_data(data.2) in
149+
150+
r1 + r2 + r3
151+
152+
// ============================================================================
153+
// Main: Run all examples
154+
// ============================================================================
155+
156+
fn main(_unit: ()): I32 =
157+
let ex1 = pair_basics(()) in
158+
let ex2 = nested_pairs(()) in
159+
let ex3 = apply_lambda(()) in
160+
let ex4 = complex_lambda(()) in
161+
let ex5 = borrow_example(()) in
162+
let ex6 = pair_with_lambda(()) in
163+
let ex7 = pipeline_example(()) in
164+
165+
ex1 + ex2 + ex3 + ex4 + ex5 + ex6 + ex7
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// SPDX-License-Identifier: PMPL-1.0-or-later
2+
// Affine Mode Example: Implicit Drops Allowed
3+
//
4+
// In affine mode, linear values can be left unconsumed.
5+
// This is useful for prototyping and exploration where strict
6+
// resource tracking isn't required.
7+
8+
// Example 1: Unconsumed string (allowed in affine mode)
9+
fn create_and_ignore(_unit: ()): I32 =
10+
region r {
11+
let s = String.new@r("hello") in
12+
42
13+
}
14+
// Note: 's' is not explicitly dropped
15+
// Affine mode allows implicit drops at scope exit
16+
17+
// Example 2: Conditional computation (still must agree on consumption)
18+
fn conditional_use(should_use: Bool): I32 =
19+
region r {
20+
let s = String.new@r("data") in
21+
let result = if should_use then
22+
String.len(&s)
23+
else
24+
0
25+
in
26+
// 's' not consumed in either branch
27+
// Affine mode allows implicit drop here
28+
result
29+
}
30+
31+
// Example 3: Multiple resources, partial consumption
32+
fn partial_cleanup(_unit: ()): I32 =
33+
region r {
34+
let s1 = String.new@r("first") in
35+
let s2 = String.new@r("second") in
36+
let s3 = String.new@r("third") in
37+
38+
// Only drop s2 explicitly
39+
let _ = drop(s2) in
40+
41+
// s1 and s3 are implicitly dropped
42+
100
43+
}
44+
45+
// Example 4: Simple unconsumed resource
46+
fn simple_cleanup(flag: Bool): I32 =
47+
region r {
48+
let resource = String.new@r("important") in
49+
50+
let result = if flag then
51+
42
52+
else
53+
String.len(&resource)
54+
in
55+
56+
// Resource not consumed in either branch
57+
// Affine mode allows implicit drop
58+
result
59+
}
60+
61+
// Main: demonstrate affine flexibility
62+
fn main(_unit: ()): I32 =
63+
let r1 = create_and_ignore(()) in
64+
let r2 = conditional_use(true) in
65+
let r3 = partial_cleanup(()) in
66+
let r4 = simple_cleanup(false) in
67+
r1 + r2 + r3 + r4

0 commit comments

Comments
 (0)