Skip to content

Commit

Permalink
Add versions of repeat_until_full for other index sizes
Browse files Browse the repository at this point in the history
  • Loading branch information
wezm committed Sep 1, 2022
1 parent 688f6ec commit 5063353
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 30 deletions.
16 changes: 14 additions & 2 deletions fathom/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,10 +381,22 @@ def_prims! {
FormatArray64Map => "array64_map",
/// Repeat a format until the length of the given parse scope is reached.
FormatRepeatUntilEnd => "repeat_until_end",
/// Repeat a format until the array is filled.
/// Repeat a format until the array with 8-bit indices is filled.
///
/// The value read by the format is replicated according to a supplied function.
FormatRepeatUntilFull => "repeat_until_full",
FormatRepeatUntilFull8 => "repeat_until_full8",
/// Repeat a format until the array with 16-bit indices is filled.
///
/// The value read by the format is replicated according to a supplied function.
FormatRepeatUntilFull16 => "repeat_until_full16",
/// Repeat a format until the array with 32-bit indices is filled.
///
/// The value read by the format is replicated according to a supplied function.
FormatRepeatUntilFull32 => "repeat_until_full32",
/// Repeat a format until the array with 64-bit indices is filled.
///
/// The value read by the format is replicated according to a supplied function.
FormatRepeatUntilFull64 => "repeat_until_full64",
/// Limit the format to an unsigned 8-bit byte length.
FormatLimit8 => "limit8",
/// Limit the format to an unsigned 16-bit byte length.
Expand Down
35 changes: 19 additions & 16 deletions fathom/src/core/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,19 +411,22 @@ impl<'arena, 'env, 'data> Context<'arena, 'env, 'data> {
(Prim::FormatF32Le, []) => read_const(reader, span, read_f32le, Const::F32),
(Prim::FormatF64Be, []) => read_const(reader, span, read_f64be, Const::F64),
(Prim::FormatF64Le, []) => read_const(reader, span, read_f64le, Const::F64),
(Prim::FormatArray8, [FunApp(len), FunApp(format)]) => self.read_array(reader, span, len, format),
(Prim::FormatArray16, [FunApp(len), FunApp(format)]) => self.read_array(reader, span, len, format),
(Prim::FormatArray32, [FunApp(len), FunApp(format)]) => self.read_array(reader, span, len, format),
(Prim::FormatArray8, [FunApp(len), FunApp(format)]) |
(Prim::FormatArray16, [FunApp(len), FunApp(format)]) |
(Prim::FormatArray32, [FunApp(len), FunApp(format)]) |
(Prim::FormatArray64, [FunApp(len), FunApp(format)]) => self.read_array(reader, span, len, format),
(Prim::FormatArray8Map, [_, _, FunApp(map_fn), FunApp(array)]) => self.array_map(reader, span, map_fn, array),
(Prim::FormatArray16Map, [_, _, FunApp(map_fn), FunApp(array)]) => self.array_map(reader, span, map_fn, array),
(Prim::FormatArray32Map, [_, _, FunApp(map_fn), FunApp(array)]) => self.array_map(reader, span, map_fn, array),
(Prim::FormatArray8Map, [_, _, FunApp(map_fn), FunApp(array)]) |
(Prim::FormatArray16Map, [_, _, FunApp(map_fn), FunApp(array)]) |
(Prim::FormatArray32Map, [_, _, FunApp(map_fn), FunApp(array)]) |
(Prim::FormatArray64Map, [_, _, FunApp(map_fn), FunApp(array)]) => self.array_map(reader, span, map_fn, array),
(Prim::FormatRepeatUntilEnd, [FunApp(format)]) => self.read_repeat_until_end(reader, format),
(Prim::FormatRepeatUntilFull, [FunApp(len), FunApp(format), FunApp(replicate)]) => self.read_repeat_until_full(reader, len, replicate, format),
(Prim::FormatLimit8, [FunApp(limit), FunApp(format)]) => self.read_limit(reader, limit, format),
(Prim::FormatLimit16, [FunApp(limit), FunApp(format)]) => self.read_limit(reader, limit, format),
(Prim::FormatLimit32, [FunApp(limit), FunApp(format)]) => self.read_limit(reader, limit, format),
(Prim::FormatRepeatUntilFull8, [FunApp(len), FunApp(format), FunApp(replicate)]) |
(Prim::FormatRepeatUntilFull16, [FunApp(len), FunApp(format), FunApp(replicate)]) |
(Prim::FormatRepeatUntilFull32, [FunApp(len), FunApp(format), FunApp(replicate)]) |
(Prim::FormatRepeatUntilFull64, [FunApp(len), FunApp(format), FunApp(replicate)]) => self.read_repeat_until_full(reader, len, replicate, format),
(Prim::FormatLimit8, [FunApp(limit), FunApp(format)]) |
(Prim::FormatLimit16, [FunApp(limit), FunApp(format)]) |
(Prim::FormatLimit32, [FunApp(limit), FunApp(format)]) |
(Prim::FormatLimit64, [FunApp(limit), FunApp(format)]) => self.read_limit(reader, limit, format),
(Prim::FormatLink, [FunApp(pos), FunApp(format)]) => self.read_link(span, pos, format),
(Prim::FormatDeref, [FunApp(format), FunApp(r#ref)]) => self.read_deref(format, r#ref),
Expand Down Expand Up @@ -529,9 +532,7 @@ impl<'arena, 'env, 'data> Context<'arena, 'env, 'data> {
_ => return Err(ReadError::InvalidValue(len.span())),
}
.ok_or_else(|| ReadError::InvalidValue(len.span()))?;

// TODO: Do we need to force replicate as well?
// let replicate = self.elim_env().force(replicate);
let replicate = self.elim_env().force(replicate);

let mut elems = Vec::with_capacity(len);
while elems.len() < len {
Expand All @@ -544,9 +545,11 @@ impl<'arena, 'env, 'data> Context<'arena, 'env, 'data> {
_ => return Err(ReadError::InvalidValue(replicate.span())),
};

// Push it that many times onto the array
// TODO: Error/limit if this exceeds len?
elems.extend(std::iter::repeat(elem).take(usize::from(repeat)));
// Push it that many times onto the array, limiting to the length of the
// output array.
elems.extend(
std::iter::repeat(elem).take(usize::from(repeat).min(len - elems.len())),
);
}
Err(err) => return Err(err),
};
Expand Down
11 changes: 10 additions & 1 deletion fathom/src/core/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -869,9 +869,18 @@ impl<'arena, 'env> ElimEnv<'arena, 'env> {
(Prim::FormatRepeatUntilEnd, [Elim::FunApp(elem)]) => {
Value::prim(Prim::ArrayType, [self.format_repr(elem)])
}
(Prim::FormatRepeatUntilFull, [Elim::FunApp(len), Elim::FunApp(elem), _]) => {
(Prim::FormatRepeatUntilFull8, [Elim::FunApp(len), Elim::FunApp(elem), _]) => {
Value::prim(Prim::Array8Type, [len.clone(), self.format_repr(elem)])
}
(Prim::FormatRepeatUntilFull16, [Elim::FunApp(len), Elim::FunApp(elem), _]) => {
Value::prim(Prim::Array16Type, [len.clone(), self.format_repr(elem)])
}
(Prim::FormatRepeatUntilFull32, [Elim::FunApp(len), Elim::FunApp(elem), _]) => {
Value::prim(Prim::Array32Type, [len.clone(), self.format_repr(elem)])
}
(Prim::FormatRepeatUntilFull64, [Elim::FunApp(len), Elim::FunApp(elem), _]) => {
Value::prim(Prim::Array64Type, [len.clone(), self.format_repr(elem)])
}
(Prim::FormatLink, [_, Elim::FunApp(elem)]) => {
Value::prim(Prim::RefType, [elem.clone()])
}
Expand Down
23 changes: 16 additions & 7 deletions fathom/src/surface/elaboration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,11 @@ impl<'arena> RigidEnv<'arena> {
env.define_prim_fun(FormatRepeatUntilEnd, [&FORMAT_TYPE], &FORMAT_TYPE);

// repeat_until_full16 : U16 -> fun (A : Format) -> (Repr A -> U16) -> Format
env.define_prim(
FormatRepeatUntilFull,
let repeat_until_full = |index_type| {
scope.to_scope(core::Term::FunType(
Span::Empty,
None,
&U16_TYPE,
env.name("len"),
index_type,
scope.to_scope(core::Term::FunType(
Span::Empty,
env.name("A"),
Expand All @@ -251,13 +250,23 @@ impl<'arena> RigidEnv<'arena> {
&Term::Prim(Span::Empty, FormatRepr),
&VAR0,
)),
&U16_TYPE,
index_type,
)),
&FORMAT_TYPE,
)),
)),
)),
);
))
};

let repeat_until_full8 = repeat_until_full(&U8_TYPE);
let repeat_until_full16 = repeat_until_full(&U16_TYPE);
let repeat_until_full32 = repeat_until_full(&U32_TYPE);
let repeat_until_full64 = repeat_until_full(&U64_TYPE);
env.define_prim(FormatRepeatUntilFull8, repeat_until_full8);
env.define_prim(FormatRepeatUntilFull16, repeat_until_full16);
env.define_prim(FormatRepeatUntilFull32, repeat_until_full32);
env.define_prim(FormatRepeatUntilFull64, repeat_until_full64);

env.define_prim_fun(FormatLimit8, [&U8_TYPE, &FORMAT_TYPE], &FORMAT_TYPE);
env.define_prim_fun(FormatLimit16, [&U16_TYPE, &FORMAT_TYPE], &FORMAT_TYPE);
env.define_prim_fun(FormatLimit32, [&U32_TYPE, &FORMAT_TYPE], &FORMAT_TYPE);
Expand Down
2 changes: 1 addition & 1 deletion formats/opentype.fathom
Original file line number Diff line number Diff line change
Expand Up @@ -2821,7 +2821,7 @@ def simple_glyph = fun (number_of_contours : U16) => (
},

/// Array of flag elements.
flags <- repeat_until_full number_of_coords flag flag_repeat,
flags <- repeat_until_full16 number_of_coords flag flag_repeat,

let read_coord = fun (is_short : Repr flag -> Bool) => fun (is_same : Repr flag -> Bool) => fun (f : Repr flag) => {
coord <- match (is_short f) {
Expand Down
2 changes: 1 addition & 1 deletion formats/opentype.snap
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ let y_is_same : _ number_of_contours = flag_is_set 0x20;
true => array16_index (_ number_of_contours end_pts_of_contours instruction_length instructions) (_ number_of_contours end_pts_of_contours instruction_length instructions) (number_of_contours - (1 :
U16)) end_pts_of_contours + (1 : U16),
},
flags <- repeat_until_full number_of_coords flag flag_repeat,
flags <- repeat_until_full16 number_of_coords flag flag_repeat,
let read_coord : ({ flag : U8, repeat : U8 } -> Bool) -> ({
flag : U8,
repeat : U8,
Expand Down
5 changes: 4 additions & 1 deletion tests/succeed/primitives.fathom
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ let _ = array16 : U16 -> Format -> Format;
let _ = array32 : U32 -> Format -> Format;
let _ = array64 : U64 -> Format -> Format;
let _ = repeat_until_end : Format -> Format;
let _ = repeat_until_full : U16 -> fun (A : Format) -> (Repr A -> U16) -> Format;
let _ = repeat_until_full8 : U8 -> fun (A : Format) -> (Repr A -> U8) -> Format;
let _ = repeat_until_full16 : U16 -> fun (A : Format) -> (Repr A -> U16) -> Format;
let _ = repeat_until_full32 : U32 -> fun (A : Format) -> (Repr A -> U32) -> Format;
let _ = repeat_until_full64 : U64 -> fun (A : Format) -> (Repr A -> U64) -> Format;
let _ = array8 : U8 -> Format -> Format;
let _ = array16 : U16 -> Format -> Format;
let _ = array32 : U32 -> Format -> Format;
Expand Down
5 changes: 4 additions & 1 deletion tests/succeed/primitives.snap
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ let _ : _ = array16;
let _ : _ = array32;
let _ : _ = array64;
let _ : _ = repeat_until_end;
let _ : _ = repeat_until_full;
let _ : _ = repeat_until_full8;
let _ : _ = repeat_until_full16;
let _ : _ = repeat_until_full32;
let _ : _ = repeat_until_full64;
let _ : _ = array8;
let _ : _ = array16;
let _ : _ = array32;
Expand Down

0 comments on commit 5063353

Please sign in to comment.