Skip to content

Commit 5a55785

Browse files
committed
Add or_succeed primitive
1 parent 53dcccd commit 5a55785

File tree

4 files changed

+37
-0
lines changed

4 files changed

+37
-0
lines changed

fathom/src/core.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ def_prims! {
390390
FormatDeref => "deref",
391391
/// A format that always succeeds with some data.
392392
FormatSucceed => "succeed",
393+
/// A format that always succeeds with a default value if a supplied condition is false.
394+
FormatOrSucceed => "or_succeed",
393395
/// A format that always fails to parse.
394396
FormatFail => "fail",
395397
/// Unwrap an option, or fail to parse.

fathom/src/core/binary.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ impl<'arena, 'env, 'data> Context<'arena, 'env, 'data> {
424424
(Prim::FormatDeref, [FunApp(format), FunApp(r#ref)]) => self.read_deref(format, r#ref),
425425
(Prim::FormatStreamPos, []) => read_stream_pos(reader, span),
426426
(Prim::FormatSucceed, [_, FunApp(elem)]) => Ok(elem.clone()),
427+
(Prim::FormatOrSucceed, [FunApp(cond), FunApp(format), FunApp(default)]) => self.read_or_succeed(reader, cond, format, default),
427428
(Prim::FormatFail, []) => Err(ReadError::ReadFailFormat(span)),
428429
(Prim::FormatUnwrap, [_, FunApp(option)]) => match option.match_prim_spine() {
429430
Some((Prim::OptionSome, [FunApp(elem)])) => Ok(elem.clone()),
@@ -540,6 +541,20 @@ impl<'arena, 'env, 'data> Context<'arena, 'env, 'data> {
540541
self.lookup_or_read_ref(pos, format)
541542
}
542543

544+
fn read_or_succeed(
545+
&mut self,
546+
reader: &mut BufferReader<'data>,
547+
cond: &ArcValue<'arena>,
548+
format: &ArcValue<'arena>,
549+
default: &ArcValue<'arena>,
550+
) -> Result<ArcValue<'arena>, ReadError<'arena>> {
551+
match cond.as_ref() {
552+
Value::ConstLit(Const::Bool(true)) => self.read_format(reader, format),
553+
Value::ConstLit(Const::Bool(false)) => Ok(default.clone()),
554+
_ => Err(ReadError::InvalidValue(Span::Empty)),
555+
}
556+
}
557+
543558
fn lookup_ref<'context>(
544559
&'context self,
545560
pos: usize,

fathom/src/core/semantics.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,7 @@ impl<'arena, 'env> ElimEnv<'arena, 'env> {
862862
(Prim::FormatDeref, [Elim::FunApp(elem), _]) => return self.format_repr(elem),
863863
(Prim::FormatStreamPos, []) => Value::prim(Prim::PosType, []),
864864
(Prim::FormatSucceed, [Elim::FunApp(elem), _]) => return elem.clone(),
865+
(Prim::FormatOrSucceed, [_, Elim::FunApp(elem), _]) => return self.format_repr(elem),
865866
(Prim::FormatFail, []) => Value::prim(Prim::VoidType, []),
866867
(Prim::FormatUnwrap, [Elim::FunApp(elem), _]) => return elem.clone(),
867868
(Prim::ReportedError, []) => Value::prim(Prim::ReportedError, []),

fathom/src/surface/elaboration.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,25 @@ impl<'arena> RigidEnv<'arena> {
216216
&Term::FunType(Span::Empty, None, &VAR0, &FORMAT_TYPE),
217217
),
218218
);
219+
env.define_prim(
220+
FormatOrSucceed,
221+
scope.to_scope(Term::FunType(
222+
Span::Empty,
223+
env.name("cond"),
224+
&BOOL_TYPE,
225+
scope.to_scope(Term::FunType(
226+
Span::Empty,
227+
env.name("A"),
228+
&FORMAT_TYPE,
229+
&Term::FunType(
230+
Span::Empty,
231+
None,
232+
&Term::FunApp(Span::Empty, &Term::Prim(Span::Empty, FormatRepr), &VAR0),
233+
&FORMAT_TYPE,
234+
),
235+
)),
236+
)),
237+
);
219238
env.define_prim(FormatFail, &FORMAT_TYPE);
220239
env.define_prim(
221240
FormatUnwrap,

0 commit comments

Comments
 (0)