Skip to content

Commit

Permalink
Merge pull request #353 from brendanzab/opentype/format-table-depende…
Browse files Browse the repository at this point in the history
…ncies

Implement dependencies on required font tables in OpenType format
  • Loading branch information
brendanzab authored May 2, 2022
2 parents 7563731 + ae36e86 commit b8e8b31
Show file tree
Hide file tree
Showing 29 changed files with 3,110 additions and 444 deletions.
51 changes: 48 additions & 3 deletions doc/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ elaboration, and core language is forthcoming.
- [Deref formats](#deref-formats)
- [Succeed format](#succeed-format)
- [Fail format](#fail-format)
- [Unwrap format](#unwrap-format)
- [Functions](#functions)
- [Function types](#function-types)
- [Function literals](#function-literals)
Expand All @@ -44,9 +45,12 @@ elaboration, and core language is forthcoming.
- [Number literals](#array-literals)
- [String literals](#string-literals)
- [Number operations](#number-operations)
- [Options](#options)
- [Option operations](#option-operations)
- [Arrays](#arrays)
- [Array types](#array-types)
- [Array literals](#array-literals)
- [Array operations](#array-operations)
- [Positions](#positions)
- [Position types](#position-types)
- [Position operations](#position-operations)
Expand Down Expand Up @@ -399,11 +403,12 @@ representation of the referenced format.

### Succeed format

The succeed format allows values to be embedded in the resulting parsed output.
The succeed format consumes no input during parsing, allowing values to be
embedded in the resulting parsed output.

- `succeed : fun (A : Type) -> A -> Format`

#### Representation of succeed format
#### Representation of succeed formats

| format | `Repr` format |
| ------------- | ------------- |
Expand All @@ -416,14 +421,28 @@ parsing.

- `fail : Format`

#### Representation of fail format
#### Representation of fail formats

The fail format should never produce a term, so is represented with [void](#void).

| format | `Repr` format |
| ------ | ------------- |
| `fail` | `Void` |

### Unwrap format

The unwrap format consumes no input during parsing, succeeding with the data
contained in a the `some` case of an [option](#options), or otherwise causing a
parse failure.

- `unwrap : fun (A : Type) -> Option A -> Format`

#### Representation of unwrap formats

| format | `Repr` format |
| ------------------- | ------------- |
| `unwrap A option_a` | `A` |

## Functions

Functions enable terms to be abstracted with parameters. As Fathom is a
Expand Down Expand Up @@ -730,6 +749,23 @@ A number of operations are defined for the numeric types:
- `s64_abs : S64 -> S64`
- `s64_unsigned_abs : S64 -> U64`

## Options

Data that may not be present can be formed with the following primitive:

- `Option : Type -> Type`

Optional data can be introduced with the `some` or `none` primitives:

- `some : fun (A : Type) -> A -> Option A`
- `none : fun (A : Type) -> Option A`

### Option operations

The following operations are defined for option types:

- `option_fold : fun (A : Type) -> fun (B : Type) -> B -> (A -> B) -> Option A -> B`

## Arrays

Arrays are sequences of elements up to a given length.
Expand Down Expand Up @@ -759,6 +795,15 @@ brackets. For example:
[3, 32, -6] : Array8 3 S32
```

### Array operations

The following operations are defined on arrays:

- `array8_find : fun (len : U8) -> fun (A : Type) -> (A -> Bool) -> Array8 len A -> Option A`
- `array16_find : fun (len : U16) -> fun (A : Type) -> (A -> Bool) -> Array16 len A -> Option A`
- `array32_find : fun (len : U32) -> fun (A : Type) -> (A -> Bool) -> Array32 len A -> Option A`
- `array64_find : fun (len : U64) -> fun (A : Type) -> (A -> Bool) -> Array64 len A -> Option A`

## Positions

Position types represent locations in the binary stream, relative to the
Expand Down
23 changes: 18 additions & 5 deletions fathom/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,8 @@ def_prims! {
/// Void type.
VoidType => "Void",

/// Type of booleans.
BoolType => "Bool",

/// Type of unsigned, 8-bit integers.
U8Type => "U8",
/// Type of unsigned, 16-bit integers.
Expand All @@ -196,6 +196,8 @@ def_prims! {
F32Type => "F32",
/// Type of 64-bit, IEEE-754 floating point numbers.
F64Type => "F64",
/// Type of optional data.
OptionType => "Option",
/// Type of arrays, with 8-bit indices.
Array8Type => "Array8",
/// Type of arrays, with 16-bit indices.
Expand All @@ -211,10 +213,6 @@ def_prims! {

/// Type of format descriptions.
FormatType => "Format",
/// A format that always succeeds with some data.
FormatSucceed => "succeed",
/// A format that always fails to parse.
FormatFail => "fail",
/// Unsigned, 8-bit integer formats.
FormatU8 => "u8",
/// Unsigned, 16-bit integer formats (big-endian).
Expand Down Expand Up @@ -266,6 +264,12 @@ def_prims! {
FormatLink => "link",
/// A format that forces a reference to be read eagerly.
FormatDeref => "deref",
/// A format that always succeeds with some data.
FormatSucceed => "succeed",
/// A format that always fails to parse.
FormatFail => "fail",
/// Unwrap an option, or fail to parse.
FormatUnwrap => "unwrap",
/// Format representations.
FormatRepr => "Repr",

Expand Down Expand Up @@ -403,6 +407,15 @@ def_prims! {
S64Abs => "s64_abs",
S64UAbs => "s64_unsigned_abs",

OptionSome => "some",
OptionNone => "none",
OptionFold => "option_fold",

Array8Find => "array8_find",
Array16Find => "array16_find",
Array32Find => "array32_find",
Array64Find => "array64_find",

PosAddU8 => "pos_add_u8",
PosAddU16 => "pos_add_u16",
PosAddU32 => "pos_add_u32",
Expand Down
7 changes: 6 additions & 1 deletion fathom/src/core/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ impl<'arena, 'env> Context<'arena, 'env> {
use crate::core::semantics::Elim::Fun;

match (prim, &slice[..]) {
(Prim::FormatSucceed, [_, Fun(r#elem)]) => Ok(r#elem.clone()),
(Prim::FormatU8, []) => read_const(reader, |num| Const::U8(num, UIntStyle::Decimal), read_u8),
(Prim::FormatU16Be, []) => read_const(reader, |num| Const::U16(num, UIntStyle::Decimal), read_u16be),
(Prim::FormatU16Le, []) => read_const(reader, |num| Const::U16(num, UIntStyle::Decimal), read_u16le),
Expand All @@ -152,7 +151,13 @@ impl<'arena, 'env> Context<'arena, 'env> {
(Prim::FormatLink, [Fun(pos), Fun(elem_format)]) => self.read_link(pos, elem_format),
(Prim::FormatDeref, [Fun(elem_format), Fun(r#ref)]) => self.read_deref(reader, elem_format, r#ref),
(Prim::FormatStreamPos, []) => read_stream_pos(reader),
(Prim::FormatSucceed, [_, Fun(elem)]) => Ok(elem.clone()),
(Prim::FormatFail, []) => Err(io::Error::new(io::ErrorKind::Other, "parse failure")),
(Prim::FormatUnwrap, [_, Fun(option)]) => match option.match_prim_spine() {
Some((Prim::OptionSome, [Fun(elem)])) => Ok(elem.clone()),
Some((Prim::OptionNone, [])) => Err(io::Error::new(io::ErrorKind::Other, "unwrapped none")),
_ => Err(io::Error::new(io::ErrorKind::Other, "invalid option")),
},
_ => Err(io::Error::new(io::ErrorKind::Other, "invalid format")),
}
}
Expand Down
33 changes: 31 additions & 2 deletions fathom/src/core/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,34 @@ fn prim_step(prim: Prim) -> Option<PrimStep> {
Prim::S64Abs => const_step!([x: S64] => Const::S64(i64::abs(*x))),
Prim::S64UAbs => const_step!([x: S64] => Const::U64(i64::unsigned_abs(*x), UIntStyle::Decimal)),

Prim::OptionFold => step!(context, [_, _, on_none, on_some, option] => {
match option.match_prim_spine()? {
(Prim::OptionSome, [Elim::Fun(value)]) => {
context.apply_fun(on_some.clone(), value.clone())
},
(Prim::OptionNone, []) => on_none.clone(),
_ => return None,
}
}),

Prim::Array8Find | Prim::Array16Find | Prim::Array32Find | Prim::Array64Find => {
step!(context, [_, _, pred, array] => match array.as_ref() {
Value::ArrayIntro(elems) => {
for elem in elems {
match context.apply_fun(pred.clone(), elem.clone()).as_ref() {
Value::Const(Const::Bool(true)) => {
return Some(Arc::new(Value::prim(Prim::OptionSome, [elem.clone()])))
},
Value::Const(Const::Bool(false)) => {}
_ => return None,
}
}
Arc::new(Value::prim(Prim::OptionNone, []))
}
_ => return None,
})
}

Prim::PosAddU8 => const_step!([x: Pos, y: U8] => Const::Pos(u64::checked_add(*x, u64::from(*y))?)),
Prim::PosAddU16 => const_step!([x: Pos, y: U16] => Const::Pos(u64::checked_add(*x, u64::from(*y))?)),
Prim::PosAddU32 => const_step!([x: Pos, y: U32] => Const::Pos(u64::checked_add(*x, u64::from(*y))?)),
Expand Down Expand Up @@ -711,8 +739,6 @@ impl<'arena, 'env> ElimContext<'arena, 'env> {
}
Value::Stuck(Head::Prim(prim), spine) => {
match (prim, &spine[..]) {
(Prim::FormatSucceed, [Elim::Fun(elem), _]) => elem.clone(),
(Prim::FormatFail, []) => Arc::new(Value::prim(Prim::VoidType, [])),
(Prim::FormatU8, []) => Arc::new(Value::prim(Prim::U8Type, [])),
(Prim::FormatU16Be, []) => Arc::new(Value::prim(Prim::U16Type, [])),
(Prim::FormatU16Le, []) => Arc::new(Value::prim(Prim::U16Type, [])),
Expand Down Expand Up @@ -748,6 +774,9 @@ impl<'arena, 'env> ElimContext<'arena, 'env> {
}
(Prim::FormatDeref, [Elim::Fun(elem), Elim::Fun(_)]) => self.apply_repr(elem),
(Prim::FormatStreamPos, []) => Arc::new(Value::prim(Prim::PosType, [])),
(Prim::FormatSucceed, [Elim::Fun(elem), _]) => elem.clone(),
(Prim::FormatFail, []) => Arc::new(Value::prim(Prim::VoidType, [])),
(Prim::FormatUnwrap, [Elim::Fun(elem), _]) => elem.clone(),
(Prim::ReportedError, []) => Arc::new(Value::prim(Prim::ReportedError, [])),
_ => Arc::new(Value::prim(Prim::FormatRepr, [format.clone()])),
}
Expand Down
Loading

0 comments on commit b8e8b31

Please sign in to comment.