Skip to content

Commit 0f3c9b7

Browse files
committed
Add array16_map primitive
1 parent c392105 commit 0f3c9b7

File tree

5 files changed

+64
-0
lines changed

5 files changed

+64
-0
lines changed

fathom/src/core.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ def_prims! {
367367
FormatArray8 => "array8",
368368
/// Array formats, with unsigned 16-bit indices.
369369
FormatArray16 => "array16",
370+
/// Map a function over an Array16
371+
FormatArray16Map => "array16_map",
370372
/// Array formats, with unsigned 32-bit indices.
371373
FormatArray32 => "array32",
372374
/// Array formats, with unsigned 64-bit indices.

fathom/src/core/binary.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,7 @@ impl<'arena, 'env, 'data> Context<'arena, 'env, 'data> {
415415
(Prim::FormatArray16, [FunApp(len), FunApp(format)]) => self.read_array(reader, span, len, format),
416416
(Prim::FormatArray32, [FunApp(len), FunApp(format)]) => self.read_array(reader, span, len, format),
417417
(Prim::FormatArray64, [FunApp(len), FunApp(format)]) => self.read_array(reader, span, len, format),
418+
(Prim::FormatArray16Map, [_, _, FunApp(map_fn), FunApp(array)]) => self.array_map(reader, span, map_fn, array),
418419
(Prim::FormatRepeatUntilEnd, [FunApp(format)]) => self.read_repeat_until_end(reader, format),
419420
(Prim::FormatRepeatUntilFull, [FunApp(len), FunApp(format), FunApp(replicate)]) => self.read_repeat_until_full(reader, len, replicate, format),
420421
(Prim::FormatLimit8, [FunApp(limit), FunApp(format)]) => self.read_limit(reader, limit, format),
@@ -458,6 +459,30 @@ impl<'arena, 'env, 'data> Context<'arena, 'env, 'data> {
458459
Ok(Spanned::new(span, Arc::new(Value::ArrayLit(elem_exprs))))
459460
}
460461

462+
fn array_map(
463+
&mut self,
464+
reader: &mut BufferReader<'data>,
465+
span: Span,
466+
map_fn: &ArcValue<'arena>,
467+
array: &ArcValue<'arena>,
468+
) -> Result<ArcValue<'arena>, ReadError<'arena>> {
469+
let array = self.elim_env().force(array);
470+
let array = match array.as_ref() {
471+
Value::ArrayLit(ary) => ary,
472+
_ => return Err(ReadError::InvalidValue(array.span())),
473+
};
474+
475+
let elem_exprs = array
476+
.iter()
477+
.map(|elem| {
478+
let elem_format = self.elim_env().fun_app(map_fn.clone(), elem.clone());
479+
self.read_format(reader, &elem_format)
480+
})
481+
.collect::<Result<_, _>>()?;
482+
483+
Ok(Spanned::new(span, Arc::new(Value::ArrayLit(elem_exprs))))
484+
}
485+
461486
fn read_repeat_until_end(
462487
&mut self,
463488
reader: &mut BufferReader<'data>,

fathom/src/core/semantics.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,9 @@ impl<'arena, 'env> ElimEnv<'arena, 'env> {
842842
(Prim::FormatArray16, [Elim::FunApp(len), Elim::FunApp(elem)]) => {
843843
Value::prim(Prim::Array16Type, [len.clone(), self.format_repr(elem)])
844844
}
845+
(Prim::FormatArray16Map, [Elim::FunApp(len), _, Elim::FunApp(map_fn), _]) => {
846+
Value::prim(Prim::Array16Type, [len.clone(), self.format_repr(map_fn)])
847+
}
845848
(Prim::FormatArray32, [Elim::FunApp(len), Elim::FunApp(elem)]) => {
846849
Value::prim(Prim::Array32Type, [len.clone(), self.format_repr(elem)])
847850
}

fathom/src/surface/elaboration.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,39 @@ impl<'arena> RigidEnv<'arena> {
186186
env.define_prim_fun(FormatArray16, [&U16_TYPE, &FORMAT_TYPE], &FORMAT_TYPE);
187187
env.define_prim_fun(FormatArray32, [&U32_TYPE, &FORMAT_TYPE], &FORMAT_TYPE);
188188
env.define_prim_fun(FormatArray64, [&U64_TYPE, &FORMAT_TYPE], &FORMAT_TYPE);
189+
// (A@0 -> Format)
190+
let map_fn = Term::FunType(Span::Empty, None, &VAR0, &FORMAT_TYPE);
191+
// Array16 len@2 A@1
192+
let array_ty = Term::FunApp(
193+
Span::Empty,
194+
scope.to_scope(Term::FunApp(Span::Empty, &ARRAY16_TYPE, &VAR2)),
195+
&VAR1,
196+
);
197+
// array16_map : fun (len : U16) -> fun (A : Type) -> (A -> Format) -> Array16 len A -> Format;
198+
env.define_prim(
199+
FormatArray16Map,
200+
scope.to_scope(Term::FunType(
201+
Span::Empty,
202+
env.name("len"),
203+
&U16_TYPE,
204+
scope.to_scope(Term::FunType(
205+
Span::Empty,
206+
env.name("A"),
207+
&UNIVERSE,
208+
scope.to_scope(Term::FunType(
209+
Span::Empty,
210+
None,
211+
scope.to_scope(map_fn),
212+
scope.to_scope(Term::FunType(
213+
Span::Empty,
214+
None,
215+
scope.to_scope(array_ty),
216+
&FORMAT_TYPE,
217+
)),
218+
)),
219+
)),
220+
)),
221+
);
189222
env.define_prim_fun(FormatRepeatUntilEnd, [&FORMAT_TYPE], &FORMAT_TYPE);
190223
// repeat_until_full16 : U16 -> fun (A : Format) -> (Repr A -> U16) -> Format
191224
env.define_prim(

tests/succeed/primitives.fathom

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ let _ = array8 : U8 -> Format -> Format;
6161
let _ = array16 : U16 -> Format -> Format;
6262
let _ = array32 : U32 -> Format -> Format;
6363
let _ = array64 : U64 -> Format -> Format;
64+
let _ = array16_map : fun (len : U16) -> fun (A : Type) -> (A -> Format) -> Array16 len A -> Format;
6465
let _ = link : Pos -> Format -> Format;
6566
let _ = deref : fun (f : Format) -> Ref f -> Format;
6667
let _ = stream_pos : Format;

0 commit comments

Comments
 (0)