Skip to content

Commit 6c0db63

Browse files
authored
Merge pull request #382 from yeslogic/wezm/array-index
Add array*_index function
2 parents 9039d13 + afbb170 commit 6c0db63

File tree

9 files changed

+94
-0
lines changed

9 files changed

+94
-0
lines changed

doc/reference.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,11 +994,29 @@ fixed-length array type.
994994

995995
The following operations are defined on arrays:
996996

997+
#### find
998+
999+
`array*_find` takes a function that returns true or false. It applies this
1000+
function to each element of the array. If the function returns true, then
1001+
`array*_find` returns `some element`. If they all return false, it returns
1002+
`none`.
1003+
9971004
- `array8_find : fun (len : U8) -> fun (A : Type) -> (A -> Bool) -> Array8 len A -> Option A`
9981005
- `array16_find : fun (len : U16) -> fun (A : Type) -> (A -> Bool) -> Array16 len A -> Option A`
9991006
- `array32_find : fun (len : U32) -> fun (A : Type) -> (A -> Bool) -> Array32 len A -> Option A`
10001007
- `array64_find : fun (len : U64) -> fun (A : Type) -> (A -> Bool) -> Array64 len A -> Option A`
10011008

1009+
#### index
1010+
1011+
`array*_index` returns the item at the supplied index in the array. The
1012+
operation will not evaluate fully if the index is out of bounds. If this
1013+
happens when parsing a binary format, a parse failure will be triggered.
1014+
1015+
- `array8_index : fun (len : U8) -> fun (A : Type) -> fun (index : U8) -> Array8 len A -> A`
1016+
- `array16_index : fun (len : U16) -> fun (A : Type) -> fun (index : U16) -> Array16 len A -> A`
1017+
- `array32_index : fun (len : U32) -> fun (A : Type) -> fun (index : U32) -> Array32 len A -> A`
1018+
- `array64_index : fun (len : U64) -> fun (A : Type) -> fun (index : U64) -> Array64 len A -> A`
1019+
10021020
## Positions
10031021

10041022
Position types represent locations in the binary stream, relative to the

fathom/src/core.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,11 @@ def_prims! {
493493
Array32Find => "array32_find",
494494
Array64Find => "array64_find",
495495

496+
Array8Index => "array8_index",
497+
Array16Index => "array16_index",
498+
Array32Index => "array32_index",
499+
Array64Index => "array64_index",
500+
496501
PosAddU8 => "pos_add_u8",
497502
PosAddU16 => "pos_add_u16",
498503
PosAddU32 => "pos_add_u32",

fathom/src/core/semantics.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,22 @@ fn prim_step(prim: Prim) -> Option<PrimStep> {
598598
})
599599
}
600600

601+
Prim::Array8Index | Prim::Array16Index | Prim::Array32Index | Prim::Array64Index => {
602+
step!(_context, [_, _, index, array] => match array.as_ref() {
603+
Value::ArrayLit(elems) => {
604+
let index = match (index).as_ref() {
605+
Value::ConstLit(Const::U8(index, _)) => Some(usize::from(*index)),
606+
Value::ConstLit(Const::U16(index, _)) => Some(usize::from(*index)),
607+
Value::ConstLit(Const::U32(index, _)) => usize::try_from(*index).ok(),
608+
Value::ConstLit(Const::U64(index, _)) => usize::try_from(*index).ok(),
609+
_ => return None,
610+
}?;
611+
elems.get(index).cloned()?
612+
}
613+
_ => return None,
614+
})
615+
}
616+
601617
Prim::PosAddU8 => const_step!([x: Pos, y: U8] => Const::Pos(usize::checked_add(*x, usize::from(*y))?)),
602618
Prim::PosAddU16 => const_step!([x: Pos, y: U16] => Const::Pos(usize::checked_add(*x, usize::from(*y))?)),
603619
Prim::PosAddU32 => const_step!([x: Pos, y: U32] => Const::Pos(usize::checked_add(*x, usize::try_from(*y).ok()?)?)),

fathom/src/surface/elaboration.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,45 @@ impl<'arena> RigidEnv<'arena> {
468468
env.define_prim(Array32Find, array32_find_type);
469469
env.define_prim(Array64Find, array64_find_type);
470470

471+
// fun (len : UN) -> (A : Type) -> (index : UN) -> ArrayN len A -> A
472+
// fun (len : UN) -> (A : Type) -> (index : UN) -> ArrayN len@2 A@1 -> A@2
473+
let array_index_type = |index_type, array_type| {
474+
scope.to_scope(core::Term::FunType(
475+
Span::Empty,
476+
env.name("len"),
477+
index_type,
478+
scope.to_scope(core::Term::FunType(
479+
Span::Empty,
480+
env.name("A"),
481+
&UNIVERSE,
482+
scope.to_scope(core::Term::FunType(
483+
Span::Empty,
484+
env.name("index"),
485+
&index_type,
486+
scope.to_scope(core::Term::FunType(
487+
Span::Empty,
488+
None,
489+
// ArrayN len@2 A@1
490+
scope.to_scope(Term::FunApp(
491+
Span::Empty,
492+
scope.to_scope(Term::FunApp(Span::Empty, array_type, &VAR2)),
493+
&VAR1,
494+
)),
495+
&VAR2, // A@2
496+
)),
497+
)),
498+
)),
499+
))
500+
};
501+
let array8_index_type = array_index_type(&U8_TYPE, &ARRAY8_TYPE);
502+
let array16_index_type = array_index_type(&U16_TYPE, &ARRAY16_TYPE);
503+
let array32_index_type = array_index_type(&U32_TYPE, &ARRAY32_TYPE);
504+
let array64_index_type = array_index_type(&U64_TYPE, &ARRAY64_TYPE);
505+
env.define_prim(Array8Index, array8_index_type);
506+
env.define_prim(Array16Index, array16_index_type);
507+
env.define_prim(Array32Index, array32_index_type);
508+
env.define_prim(Array64Index, array64_index_type);
509+
471510
env.define_prim_fun(PosAddU8, [&POS_TYPE, &U8_TYPE], &POS_TYPE);
472511
env.define_prim_fun(PosAddU16, [&POS_TYPE, &U16_TYPE], &POS_TYPE);
473512
env.define_prim_fun(PosAddU32, [&POS_TYPE, &U32_TYPE], &POS_TYPE);

formats/data/opentype/woff/valid-005.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,8 @@ stdout = '''
756756
end_pts_of_contours = [ 7, 17, 23, 27, 30 ],
757757
instruction_length = 0,
758758
instructions = [],
759+
last_end_point_index = 30,
760+
number_of_coords = 31,
759761
},
760762
},
761763
],

formats/opentype.fathom

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2801,6 +2801,8 @@ def simple_glyph = fun (number_of_contours : U16) => {
28012801
instruction_length <- u16be,
28022802
/// Array of instruction byte code for the glyph.
28032803
instructions <- array16 instruction_length u8,
2804+
let last_end_point_index = array16_index _ _ (number_of_contours - (1 : U16)) end_pts_of_contours,
2805+
let number_of_coords = last_end_point_index + (1 : U16),
28042806
/// Array of flag elements.
28052807
// flags[variable] <- uint8,
28062808
/// xCoordinates[variable] Contour point x-coordinates. Coordinate for the first point is relative to (0,0);

formats/opentype.snap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ def simple_glyph : U16 -> Format = fun number_of_contours => {
384384
end_pts_of_contours <- array16 number_of_contours u16be,
385385
instruction_length <- u16be,
386386
instructions <- array16 instruction_length u8,
387+
let last_end_point_index : U16 = 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 :
388+
U16)) end_pts_of_contours,
389+
let number_of_coords : U16 = last_end_point_index + (1 : U16),
387390
};
388391
def glyph : Format = {
389392
header <- glyph_header,

tests/succeed/primitives.fathom

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ let _ = array16_find : fun (len : U16) -> fun (A : Type) -> (A -> Bool) -> Array
208208
let _ = array32_find : fun (len : U32) -> fun (A : Type) -> (A -> Bool) -> Array32 len A -> Option A;
209209
let _ = array64_find : fun (len : U64) -> fun (A : Type) -> (A -> Bool) -> Array64 len A -> Option A;
210210

211+
let _ = array8_index : fun (len : U8) -> fun (A : Type) -> U8 -> Array8 len A -> A;
212+
let _ = array16_index : fun (len : U16) -> fun (A : Type) -> U16 -> Array16 len A -> A;
213+
let _ = array32_index : fun (len : U32) -> fun (A : Type) -> U32 -> Array32 len A -> A;
214+
let _ = array64_index : fun (len : U64) -> fun (A : Type) -> U64 -> Array64 len A -> A;
215+
211216
let _ = pos_add_u8 : Pos -> U8 -> Pos;
212217
let _ = pos_add_u16 : Pos -> U16 -> Pos;
213218
let _ = pos_add_u32 : Pos -> U32 -> Pos;

tests/succeed/primitives.snap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,10 @@ let _ : _ = array8_find;
193193
let _ : _ = array16_find;
194194
let _ : _ = array32_find;
195195
let _ : _ = array64_find;
196+
let _ : _ = array8_index;
197+
let _ : _ = array16_index;
198+
let _ : _ = array32_index;
199+
let _ : _ = array64_index;
196200
let _ : _ = pos_add_u8;
197201
let _ : _ = pos_add_u16;
198202
let _ : _ = pos_add_u32;

0 commit comments

Comments
 (0)