Skip to content

Commit 6da000f

Browse files
committed
Add or_succeed primitive
1 parent bd3ebfd commit 6da000f

File tree

6 files changed

+39
-0
lines changed

6 files changed

+39
-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
@@ -860,6 +860,7 @@ impl<'arena, 'env> ElimEnv<'arena, 'env> {
860860
(Prim::FormatDeref, [Elim::FunApp(elem), _]) => return self.format_repr(elem),
861861
(Prim::FormatStreamPos, []) => Value::prim(Prim::PosType, []),
862862
(Prim::FormatSucceed, [Elim::FunApp(elem), _]) => return elem.clone(),
863+
(Prim::FormatOrSucceed, [_, Elim::FunApp(elem), _]) => return self.format_repr(elem),
863864
(Prim::FormatFail, []) => Value::prim(Prim::VoidType, []),
864865
(Prim::FormatUnwrap, [Elim::FunApp(elem), _]) => return elem.clone(),
865866
(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,

tests/succeed/primitives.fathom

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ let _ = link : Pos -> Format -> Format;
6464
let _ = deref : fun (f : Format) -> Ref f -> Format;
6565
let _ = stream_pos : Format;
6666
let _ = succeed : fun (Elem : Type) -> Elem -> Format;
67+
let _ = or_succeed : Bool -> fun (A : Format) -> Repr A -> Format;
6768
let _ = fail : Format;
6869
let _ = unwrap : fun (A : Type) -> Option A -> Format;
6970
let _ = Repr : Format -> Type;

tests/succeed/primitives.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ let _ : _ = link;
6161
let _ : _ = deref;
6262
let _ : _ = stream_pos;
6363
let _ : _ = succeed;
64+
let _ : _ = or_succeed;
6465
let _ : _ = fail;
6566
let _ : _ = unwrap;
6667
let _ : _ = Repr;

0 commit comments

Comments
 (0)