Skip to content

Commit 0588779

Browse files
committed
Add Pipeline/FalliblePipeline types, replace std::io::Error with FileError, guard AGENT.md snippets
- Add Pipeline<T> and FalliblePipeline<T,E> with map/filter/each/try_map/collect - Implement full pipeline runtime (RssPipeline, RssFalliblePipeline) in collections - Register pipeline intrinsics in runtime ABI and type lowering - Fix receiver call generic type param substitution in checker and HIR - Replace std::io::Error with structured FileError across fs module - Add CsvError From<FileError> conversion in domain - Add AGENT.md rust block syntax guard test (agent_md_doctest.rs) - Add pipeline lowering and end-to-end compile tests - Update AGENT.md with call examples and type/const declarations
1 parent 4bbf86d commit 0588779

13 files changed

Lines changed: 717 additions & 65 deletions

File tree

AGENT.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,11 @@ Each param is `name: <effect> Type`. Return may be `fresh T` (newly created, see
133133

134134
```rust
135135
fn resize_all(image: mut Image, width: Int) -> Unit { ... }
136+
```
137+
138+
Called as:
136139

140+
```rust
137141
resize_all(image: mut image, width: 800) // `mut` arg matches `mut` param; Int bare
138142
```
139143

@@ -308,6 +312,11 @@ trait resolution).
308312

309313
```rust
310314
let cfg = Config(name: "default", rules: read rules, workspace: take workspace)
315+
```
316+
317+
Type aliases and constants are top-level declarations:
318+
319+
```rust
311320
type WorkspacePath = Path // type alias
312321
const MAX: Int = 16 // const
313322
```

core/collections/pipeline.rssi

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
features: local
2+
3+
struct Pipeline<T>
4+
5+
struct FalliblePipeline<T, E>
6+
7+
pub fn List.pipeline<T>(
8+
list: read List<T>,
9+
) -> fresh Pipeline<T>
10+
11+
pub fn Pipeline.from_list<T>(
12+
list: read List<T>,
13+
) -> fresh Pipeline<T>
14+
15+
pub fn Pipeline.map<T, U>(
16+
pipeline: read Pipeline<T>,
17+
mapper: noescape Fn(T) -> U,
18+
) -> fresh Pipeline<U>
19+
20+
pub fn Pipeline.filter<T>(
21+
pipeline: read Pipeline<T>,
22+
predicate: noescape Fn(T) -> Bool,
23+
) -> fresh Pipeline<T>
24+
25+
pub fn Pipeline.each<T>(
26+
pipeline: read Pipeline<T>,
27+
action: noescape Fn(T) -> Unit,
28+
) -> fresh Pipeline<T>
29+
30+
pub fn Pipeline.try_map<T, U, E>(
31+
pipeline: read Pipeline<T>,
32+
mapper: noescape Fn(T) -> Result<fresh U, E>,
33+
) -> fresh FalliblePipeline<U, E>
34+
35+
pub fn Pipeline.collect<T>(
36+
pipeline: read Pipeline<T>,
37+
) -> fresh List<T>
38+
39+
pub fn FalliblePipeline.map<T, U, E>(
40+
pipeline: read FalliblePipeline<T, E>,
41+
mapper: noescape Fn(T) -> U,
42+
) -> fresh FalliblePipeline<U, E>
43+
44+
pub fn FalliblePipeline.filter<T, E>(
45+
pipeline: read FalliblePipeline<T, E>,
46+
predicate: noescape Fn(T) -> Bool,
47+
) -> fresh FalliblePipeline<T, E>
48+
49+
pub fn FalliblePipeline.each<T, E>(
50+
pipeline: read FalliblePipeline<T, E>,
51+
action: noescape Fn(T) -> Unit,
52+
) -> fresh FalliblePipeline<T, E>
53+
54+
pub fn FalliblePipeline.try_map<T, U, E>(
55+
pipeline: read FalliblePipeline<T, E>,
56+
mapper: noescape Fn(T) -> Result<fresh U, E>,
57+
) -> fresh FalliblePipeline<U, E>
58+
59+
pub fn FalliblePipeline.collect<T, E>(
60+
pipeline: read FalliblePipeline<T, E>,
61+
) -> Result<fresh List<T>, E>

runtime/src/collections.rs

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
use std::collections::{HashMap, HashSet};
22
use std::hash::Hash;
33

4+
#[derive(Debug, Clone, PartialEq, Eq)]
5+
pub struct RssPipeline<T> {
6+
pub items: Vec<T>,
7+
}
8+
9+
#[derive(Debug, Clone, PartialEq, Eq)]
10+
pub struct RssFalliblePipeline<T, E> {
11+
pub result: Result<Vec<T>, E>,
12+
}
13+
414
pub fn ord_compare<T: Ord>(left: &T, right: &T) -> i64 {
515
match left.cmp(right) {
616
std::cmp::Ordering::Less => -1,
@@ -94,6 +104,139 @@ pub fn list_try_fold<T: Clone, U: Clone, E>(
94104
Ok(state)
95105
}
96106

107+
pub fn pipeline_from_list<T: Clone>(list: &[T]) -> RssPipeline<T> {
108+
RssPipeline {
109+
items: list.to_vec(),
110+
}
111+
}
112+
113+
pub fn pipeline_map<T: Clone, U>(
114+
pipeline: &RssPipeline<T>,
115+
mapper: impl FnMut(T) -> U,
116+
) -> RssPipeline<U> {
117+
RssPipeline {
118+
items: pipeline.items.iter().cloned().map(mapper).collect(),
119+
}
120+
}
121+
122+
pub fn pipeline_filter<T: Clone>(
123+
pipeline: &RssPipeline<T>,
124+
mut predicate: impl FnMut(T) -> bool,
125+
) -> RssPipeline<T> {
126+
RssPipeline {
127+
items: pipeline
128+
.items
129+
.iter()
130+
.filter(|item| predicate((*item).clone()))
131+
.cloned()
132+
.collect(),
133+
}
134+
}
135+
136+
pub fn pipeline_each<T: Clone>(
137+
pipeline: &RssPipeline<T>,
138+
mut action: impl FnMut(T),
139+
) -> RssPipeline<T> {
140+
for item in pipeline.items.iter().cloned() {
141+
action(item);
142+
}
143+
RssPipeline {
144+
items: pipeline.items.clone(),
145+
}
146+
}
147+
148+
pub fn pipeline_try_map<T: Clone, U, E>(
149+
pipeline: &RssPipeline<T>,
150+
mut mapper: impl FnMut(T) -> Result<U, E>,
151+
) -> RssFalliblePipeline<U, E> {
152+
let mut mapped = Vec::new();
153+
for item in pipeline.items.iter().cloned() {
154+
match mapper(item) {
155+
Ok(value) => mapped.push(value),
156+
Err(error) => return RssFalliblePipeline { result: Err(error) },
157+
}
158+
}
159+
RssFalliblePipeline { result: Ok(mapped) }
160+
}
161+
162+
pub fn pipeline_collect<T: Clone>(pipeline: &RssPipeline<T>) -> Vec<T> {
163+
pipeline.items.clone()
164+
}
165+
166+
pub fn fallible_pipeline_map<T: Clone, U, E: Clone>(
167+
pipeline: &RssFalliblePipeline<T, E>,
168+
mapper: impl FnMut(T) -> U,
169+
) -> RssFalliblePipeline<U, E> {
170+
RssFalliblePipeline {
171+
result: pipeline
172+
.result
173+
.as_ref()
174+
.map(|items| items.iter().cloned().map(mapper).collect::<Vec<_>>())
175+
.map_err(Clone::clone),
176+
}
177+
}
178+
179+
pub fn fallible_pipeline_filter<T: Clone, E: Clone>(
180+
pipeline: &RssFalliblePipeline<T, E>,
181+
mut predicate: impl FnMut(T) -> bool,
182+
) -> RssFalliblePipeline<T, E> {
183+
RssFalliblePipeline {
184+
result: pipeline
185+
.result
186+
.as_ref()
187+
.map(|items| {
188+
items
189+
.iter()
190+
.filter(|item| predicate((*item).clone()))
191+
.cloned()
192+
.collect::<Vec<_>>()
193+
})
194+
.map_err(Clone::clone),
195+
}
196+
}
197+
198+
pub fn fallible_pipeline_each<T: Clone, E: Clone>(
199+
pipeline: &RssFalliblePipeline<T, E>,
200+
mut action: impl FnMut(T),
201+
) -> RssFalliblePipeline<T, E> {
202+
if let Ok(items) = &pipeline.result {
203+
for item in items.iter().cloned() {
204+
action(item);
205+
}
206+
}
207+
RssFalliblePipeline {
208+
result: pipeline.result.clone(),
209+
}
210+
}
211+
212+
pub fn fallible_pipeline_try_map<T: Clone, U, E: Clone>(
213+
pipeline: &RssFalliblePipeline<T, E>,
214+
mut mapper: impl FnMut(T) -> Result<U, E>,
215+
) -> RssFalliblePipeline<U, E> {
216+
let items = match &pipeline.result {
217+
Ok(items) => items,
218+
Err(error) => {
219+
return RssFalliblePipeline {
220+
result: Err(error.clone()),
221+
};
222+
}
223+
};
224+
let mut mapped = Vec::new();
225+
for item in items.iter().cloned() {
226+
match mapper(item) {
227+
Ok(value) => mapped.push(value),
228+
Err(error) => return RssFalliblePipeline { result: Err(error) },
229+
}
230+
}
231+
RssFalliblePipeline { result: Ok(mapped) }
232+
}
233+
234+
pub fn fallible_pipeline_collect<T: Clone, E: Clone>(
235+
pipeline: &RssFalliblePipeline<T, E>,
236+
) -> Result<Vec<T>, E> {
237+
pipeline.result.clone()
238+
}
239+
97240
pub fn list_consume<T>(list: Vec<T>) {
98241
drop(list);
99242
}

runtime/src/domain.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,12 @@ impl From<std::io::Error> for CsvError {
362362
}
363363
}
364364

365+
impl From<crate::fs::FileError> for CsvError {
366+
fn from(error: crate::fs::FileError) -> Self {
367+
Self::new(error.to_string())
368+
}
369+
}
370+
365371
impl From<Utf8Error> for CsvError {
366372
fn from(error: Utf8Error) -> Self {
367373
Self::new(error.to_string())

0 commit comments

Comments
 (0)