core.bend checks
raw source on the hub · import bend-schema-lib@0.3.0.0/core.bend as Core
1 import
import Base
Types
type NumberBits source · line 65 · raw
Data
NumberBits@hi:U32 -> @lo:U32 -> NumberBits
type Json source · line 68 · raw
Data
JNullJson
JBool@value:Bool -> Json
JNumber@value:NumberBits -> Json
JString@value:String -> Json
JArray@values:List<&2, Json> -> Json
JObject@members:List<&2, JMember> -> Json
type JMember source · line 76 · raw
Data
JMember@key:String -> @value:Json -> JMember
type Int source · line 81 · raw
Data
A whole number of either sign: IPos{n} is n, INeg{n} is -(n+1), so every integer has exactly one form (there is no -0).
IPos@n:Nat -> Int
INeg@n:Nat -> Int
type Raw source · line 85 · raw
Data
RNum@n:Nat -> Raw
RBool@b:Bool -> Raw
RNullRaw
RStr@s:String -> Raw
RBadRaw
RTooBigRaw
RMissingRaw
RNilRaw
RCons@head:Raw -> @tail:Raw -> Raw
REndRaw
RKey@key:String -> @val:Raw -> @rest:Raw -> Raw
RJson@value:Json -> Raw
RNeg@n:Nat -> Raw
type Schema source · line 100 · raw
Data
SNatSchema
SNatIn@lo:Nat -> @hi:Nat -> Schema
SStrSchema
SStrLen@lo:Nat -> @hi:Nat -> @s:Schema -> Schema
SOpt@inner:Schema -> Schema
SList@elem:Schema -> Schema
SField@name:String -> @s:Schema -> @rest:Schema -> Schema
SEndSchema
SRule@s:Schema -> @tag:Nat -> Schema
SStrict@s:Schema -> Schema
STagged@key:String -> @name:String -> @s:Schema -> @rest:Schema -> Schema
STagEnd@key:String -> Schema
SBoolSchema
STrueSchema
SEnum@names:List<&2, String> -> Schema
SVariant@name:String -> @s:Schema -> @rest:Schema -> Schema
SVEndSchema
STuple@s:Schema -> @rest:Schema -> Schema
STEndSchema
SOptional@inner:Schema -> Schema
SListLen@lo:Nat -> @hi:Nat -> @s:Schema -> Schema
SJsonSchema
SIntSchema
SIntIn@lo:Int -> @hi:Int -> Schema
SEither@l:Schema -> @r:Schema -> Schema
type Step source · line 132 · raw
Data
A step of a path. Positions count what was passed on the way, so that
following a path never compares two names: AtIndex{i} is element i of a
list, AtField{skip, name} the field skip places after this one in the
schema, BoundAt{i, key} the bound of element i of a bounded list. The names
are for the host to print.
AtIndex@i:Nat -> Step
AtField@skip:Nat -> @name:String -> Step
BoundAt@i:Nat -> @key:String -> Step
AtKey@key:String -> Step
type Why source · line 138 · raw
Data
MissingWhy
NotNatWhy
NotStringWhy
NotBoolWhy
NotListWhy
NotObjectWhy
NoElementsWhy
OpenNotLastWhy
LastNotOpenWhy
NotIncreasing@prev:Nat -> @got:Nat -> Why
NotTrueWhy
NotOneOfWhy
NoVariantWhy
TwoVariantsWhy
TooShortWhy
TooLongWhy
LengthNotIn@lo:Nat -> @hi:Nat -> Why
NotIn@lo:Nat -> @hi:Nat -> Why
UnknownKeyWhy
RepeatedKey@key:String -> Why
TooLargeWhy
CountNotIn@lo:Nat -> @hi:Nat -> Why
NotJsonWhy
NotIntWhy
IntNotIn@lo:Int -> @hi:Int -> Why
NoAlternative@num:Bool -> @str:Bool -> @bool:Bool -> @list:Bool -> @obj:Bool -> @null:Bool -> Why
type Err source · line 166 · raw
Data
Err@path:List<&2, Step> -> @why:Why -> Err
type JKind source · line 500 · raw
Data
KNumJKind
KStrJKind
KBoolJKind
KListJKind
KObjJKind
KNullJKind
KAbsentJKind
KJsonJKind
KOtherJKind
type Both source · line 1431 · raw
@A:Data -> @B:Data -> Data
Both@A:Data -> @B:Data -> @a:A -> @b:B -> Both<A, B>
Definitions
def finite_number source · line 171 · raw
@bits:NumberBits -> Bool
JSON numbers use IEEE-754 binary64 bits. The exponent occupies the high word's bits 20 through 30; all ones denotes infinity or NaN.
def key_in source · line 177 · raw
@+key:String -> @members:List<&2, JMember> -> Bool
Whether a name is already taken among the members that follow.
def valid_json source · line 187 · raw
@value:Json -> Bool
A value is valid when every number in it is finite and no object holds a name twice. An object is a list of members, so a name's uniqueness is read off the members themselves, not off any layout.
def pick_raw source · line 208 · raw
@b:Bool -> @+x:Raw -> @+y:Raw -> Raw
def lookup source · line 216 · raw
@+name:String -> @r:Raw -> Raw
The value under name in an object, or RMissing.
def pick_bool source · line 223 · raw
@b:Bool -> @+x:Bool -> @+y:Bool -> Bool
def is_rnil source · line 230 · raw
@r:Raw -> Bool
def is_missing source · line 239 · raw
@v:Raw -> Bool
def in_names source · line 246 · raw
@+x:String -> @names:List<&2, String> -> Bool
def none_present source · line 254 · raw
@s:Schema -> @+r:Raw -> Bool
None of the keys of a variant chain is in the object r.
def key_names source · line 265 · raw
@s:Schema -> List<&2, String>
---- a strict object: its keys ----
The names a record or variant chain declares. SStrict refuses a key that is not one of them; wf asks that SStrict wrap such a chain.
def no_extra source · line 275 · raw
@+ns:List<&2, String> -> @r:Raw -> Bool
Every key of the object r is one of ns (anything but an object has none).
def drop_key source · line 290 · raw
@+k:String -> @r:Raw -> Raw
The object r without its first key k (what lookup(k, r) reads).
def is_str source · line 297 · raw
@+n:String -> @v:Raw -> Bool
def is_tag source · line 305 · raw
@+k:String -> @+n:String -> @r:Raw -> Bool
The tag under k is the string n.
def in_err source · line 322 · raw
@b:Bool -> @w:Why -> Maybe<&2, Err>
def str_len_ok source · line 329 · raw
@+lo:Nat -> @+hi:Nat -> @+x:String -> Bool
def num_ok source · line 332 · raw
@+lo:Nat -> @+hi:Nat -> @+n:Nat -> Bool
def int_le source · line 337 · raw
@a:Int -> @b:Int -> Bool
a <= b on integers. A negative is below every non-negative, and between two negatives the larger offset is the smaller number.
def int_ok source · line 348 · raw
@+lo:Int -> @+hi:Int -> @+i:Int -> Bool
def int_raw source · line 352 · raw
@i:Int -> Raw
How an integer is written: a non-negative as RNum, a negative as RNeg.
def len_ok source · line 361 · raw
@+lo:Nat -> @+hi:Nat -> @r:Raw -> Bool
r is a string whose length is in the bounds: what conforms reads at an SStrLen, and what len_err refuses exactly when it fails.
def str_len_in source · line 373 · raw
@+lo:Nat -> @+hi:Nat -> @r:Raw -> Maybe<&2, Err>
The same bounds as ready-made rules: a project's rule calls them by tag
(case 0n: str_len_in(1n, 64n, r)), since a tag carries no numbers. Each
refuses only the value it is about -- a string, a number -- and leaves any
other kind to the schema's own check; the constructors below read the tests
directly, because their bound is in the schema.
def nat_in source · line 380 · raw
@+lo:Nat -> @+hi:Nat -> @r:Raw -> Maybe<&2, Err>
def is_bool source · line 387 · raw
@r:Raw -> Bool
def raw_list source · line 403 · raw
@r:Raw -> Bool
def raw_len source · line 412 · raw
@r:Raw -> Nat
def count_ok source · line 419 · raw
@+lo:Nat -> @+hi:Nat -> @+r:Raw -> Bool
def list_len_ok source · line 422 · raw
@+lo:Nat -> @+hi:Nat -> @+r:Raw -> Bool
def has_key source · line 451 · raw
@+k:String -> @r:Raw -> Bool
k is a key of the object r.
def key_once_at source · line 466 · raw
@r:Raw -> @+b:Bool -> @+name:String -> Bool
name appears at most once among the keys of the object r. b is whether a key read before r was already name; the flag carries forward, and a key that is name while the flag is set is the second one -- refused here and nowhere else. The value is the first argument because a self-call must read its arguments left to right, unchanged until one shrinks, and only the value shrinks; the value is matched first because a match cannot be nested inside the branch of a match on another parameter. One pass, so a walk costs one key per key, the same as the lookup beside it.
def key_once source · line 475 · raw
@+name:String -> @r:Raw -> Bool
name appears at most once among the keys of the object r: nothing has been read yet.
def key_err source · line 483 · raw
@b:Bool -> @+name:String -> Maybe<&2, Err>
The repeated key as check reports it: at the key's own name, with no step after it (the second occurrence is not a place in the schema). The test is passed in rather than read here (a match cannot scrutinize a computed value): b is key_once(name, r), so nothing is reported exactly when key_once holds, which is what check_exact needs.
def kind_eq source · line 511 · raw
@a:JKind -> @b:JKind -> Bool
def kind_of source · line 534 · raw
@r:Raw -> JKind
def has_kind source · line 561 · raw
@s:Schema -> @+k:JKind -> Bool
def apart source · line 615 · raw
@+l:Schema -> @+r:Schema -> @+k:JKind -> Bool
No value of kind k is claimed by both.
def disjoint source · line 618 · raw
@+l:Schema -> @+r:Schema -> Bool
def alt_ok source · line 624 · raw
@+s:Schema -> Bool
An alternative is a value that is present and has a kind of its own: not an absent field (the host writes no key, so no kind is there to pick by), and not s.json(), which takes every kind.
def no_alt source · line 628 · raw
@+s:Schema -> Why
What an SEither would have taken, for the host to say.
def here source · line 700 · raw
@w:Why -> Maybe<&2, Err>
def under source · line 704 · raw
@+st:Step -> @m:Maybe<&2, Err> -> Maybe<&2, Err>
An error found under a step gets the step in front of its path.
def len_err source · line 714 · raw
@+lo:Nat -> @+hi:Nat -> @r:Raw -> Maybe<&2, Err>
At an SStrLen the shape comes first, as everywhere else: a value that is not a string is NotString, a string out of its bounds is LengthNotIn, and a node the codec refused to build or that is absent reads as it does at every kind.
def later_l_path source · line 728 · raw
@p:List<&2, Step> -> List<&2, Step>
An error found further along a list is one element further: its first step, if it counts elements, counts one more. A plain list's steps are AtIndex; a bounded list's are AtIndex and BoundAt.
def later_l source · line 735 · raw
@m:Maybe<&2, Err> -> Maybe<&2, Err>
def later_i_path source · line 742 · raw
@p:List<&2, Step> -> List<&2, Step>
def later_i source · line 751 · raw
@m:Maybe<&2, Err> -> Maybe<&2, Err>
def later_f_path source · line 759 · raw
@p:List<&2, Step> -> List<&2, Step>
An error found in a later field is one field further.
def later_f source · line 766 · raw
@m:Maybe<&2, Err> -> Maybe<&2, Err>
def first source · line 774 · raw
@m:Maybe<&2, Err> -> @n:Maybe<&2, Err> -> Maybe<&2, Err>
The first of two: the second counts only when the first found nothing.
def missing_or source · line 786 · raw
@r:Raw -> @w:Why -> Why
The reason a value that is not the shape is refused, at the place it was found: an absent slot is Missing, a node the host refused to build (RTooBig) is TooLarge, anything else is the schema kind's own reason. check and the defect helpers both answer through here, so the reason a path reports is the same one for both.
def pick_err source · line 795 · raw
@b:Bool -> @+x:Maybe<&2, Err> -> @+y:Maybe<&2, Err> -> Maybe<&2, Err>
def true_err source · line 802 · raw
@b:Bool -> Maybe<&2, Err>
def enum_err source · line 809 · raw
@b:Bool -> Maybe<&2, Err>
def dup_err source · line 817 · raw
@s:Schema -> @+r:Raw -> Maybe<&2, Err>
A second key of a variant chain in the object r: the first one found.
def extra_err source · line 825 · raw
@+ns:List<&2, String> -> @r:Raw -> Maybe<&2, Err>
The first key of r that is not one of ns, at its own name.
def tag_err source · line 834 · raw
@+k:String -> @r:Raw -> Maybe<&2, Err>
At the end of a tagged chain no case matched: the value is not an object, or its tag is missing, or it names no case.
def count_err source · line 848 · raw
@+lo:Nat -> @+hi:Nat -> @r:Raw -> Maybe<&2, Err>
The count, as an error: at an SListLen the count is read before any element, so a list out of bounds is CountNotIn at the list's own path. A value that is not a list has no count to object to, and is refused as a list schema refuses it: NotList, or Missing/TooLarge for the two nodes that are never a shape (the same reasons check's own arms give them).
def guard source · line 971 · raw
@b:Bool -> @m:Maybe<&2, Why> -> Maybe<&2, Why>
def nat_in_defect source · line 981 · raw
@+lo:Nat -> @+hi:Nat -> @r:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
The same two reasons at an SNatIn and an SBool, replayed along a path: the value's own kind is the defect when the path ends here, and it is not a defect at all further along (the walk passed it).
def int_defect source · line 994 · raw
@r:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
The same two reasons at an SInt and an SIntIn: a number of either sign is not the defect, and its bound is the defect only where the path ends.
def int_in_defect source · line 1005 · raw
@+lo:Int -> @+hi:Int -> @r:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
def bool_defect source · line 1020 · raw
@r:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
def no_rule source · line 1037 · raw
@tag:Nat -> @r:Raw -> Maybe<&2, Err>
def first_why source · line 1040 · raw
@m:Maybe<&2, Why> -> @+n:Maybe<&2, Why> -> Maybe<&2, Why>
def step_eq source · line 1047 · raw
@x:Step -> @y:Step -> Bool
def path_eq source · line 1060 · raw
@x:List<&2, Step> -> @y:List<&2, Step> -> Bool
def rule_defect source · line 1069 · raw
@m:Maybe<&2, Err> -> @+p:List<&2, Step> -> Maybe<&2, Why>
def not_list source · line 1076 · raw
@x:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
def not_object source · line 1083 · raw
@x:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
def nat_defect source · line 1090 · raw
@r:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
def str_defect source · line 1099 · raw
@r:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
def pick_why source · line 1108 · raw
@b:Bool -> @+x:Maybe<&2, Why> -> @+y:Maybe<&2, Why> -> Maybe<&2, Why>
def true_defect source · line 1115 · raw
@r:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
def enum_defect source · line 1126 · raw
@names:List<&2, String> -> @r:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
def no_variant source · line 1137 · raw
@p:List<&2, Step> -> Maybe<&2, Why>
def dup_defect source · line 1146 · raw
@s:Schema -> @+r:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
The claim about a second key: every key passed is absent, and the key the path names is there.
def at_end source · line 1155 · raw
@w:Why -> @p:List<&2, Step> -> Maybe<&2, Why>
def extra_defect source · line 1164 · raw
@ns:List<&2, String> -> @+r:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
At a strict object the path is one key, and the replay checks it on its own: the key is there, and it is not one of the names.
def tag_defect source · line 1171 · raw
@+k:String -> @r:Raw -> @p:List<&2, Step> -> Maybe<&2, Why>
def tag_key_defect source · line 1192 · raw
@b:Bool -> @+k:String -> @p:List<&2, Step> -> Maybe<&2, Why>
The tag key of a tagged case, taken twice, as defect replays it. check reports it before the case's own schema is walked -- there is no place in the schema for the second occurrence -- so the path is one field step at the tag's own name and nothing after it. b is whether the key is not read once, so nothing is reported exactly when key_once holds; a path of any other shape is the case's own report, which the walk below answers.
def check0 source · line 1317 · raw
@s:Schema -> @r:Raw -> Maybe<&2, Err>
def conforms0 source · line 1320 · raw
@s:Schema -> @r:Raw -> Bool
def is_chain source · line 1331 · raw
@s:Schema -> Bool
def is_object source · line 1340 · raw
@r:Raw -> Bool
def one_if_there source · line 1349 · raw
@b:Bool -> Nat
def count_present source · line 1356 · raw
@s:Schema -> @+r:Raw -> Nat
def tuple_of source · line 1376 · raw
@ss:List<&2, Schema> -> Schema
def at_raw source · line 1386 · raw
@r:Raw -> @+i:Nat -> Raw
def count_unknown source · line 1407 · raw
@+ns:List<&2, String> -> @r:Raw -> Nat
---- the claim the strict law makes ----
How many keys of r are not in ns, counted rather than walked with a Bool.and: a second algorithm, so that a no_extra that lets a key through (or refuses a named one) disagrees with it.
def Meaning source · line 1434 · raw
@s:Schema -> Data
def enc source · line 1487 · raw
@s:Schema -> @x:Meaning(s) -> Raw
def lcons source · line 1552 · raw
@-A:Data -> @h:Maybe<&2, A> -> @t:Maybe<&2, List<&2, A>> -> Maybe<&2, List<&2, A>>
def both source · line 1559 · raw
@-A:Data -> @-B:Data -> @p:Maybe<&2, A> -> @q:Maybe<&2, B> -> Maybe<&2, Both<A, B>>
def opt_some source · line 1566 · raw
@-A:Data -> @m:Maybe<&2, A> -> Maybe<&2, Maybe<&2, A>>
def map_inl source · line 1573 · raw
@-A:Data -> @-B:Data -> @m:Maybe<&2, A> -> Maybe<&2, Either<&2, &2, A, B>>
def map_inr source · line 1580 · raw
@-A:Data -> @-B:Data -> @m:Maybe<&2, B> -> Maybe<&2, Either<&2, &2, A, B>>
def pick_m source · line 1587 · raw
@-A:Data -> @b:Bool -> @x:A -> @y:A -> A
def true_unit source · line 1594 · raw
@b:Bool -> Maybe<&2, Unit>
def nullish source · line 1601 · raw
@r:Raw -> Bool
def dec source · line 1610 · raw
@s:Schema -> @r:Raw -> Maybe<&2, Meaning(s)>
def opt_at source · line 1704 · raw
@s:Schema -> Bool
An absent value reaches the top of what enc writes for s: s is an SOptional, or it hands the value it was given straight to a schema that is (a rule, a strict object, a bound, or the tail of a variant or tagged chain -- and an SOpt, whose Some case passes the value through). Everything else wraps what it writes in a constructor of its own, so an absent value cannot surface.
def nullable source · line 1725 · raw
@s:Schema -> Bool
def no_key source · line 1762 · raw
@+k:String -> @s:Schema -> Bool
---- the object a schema's encoding lands in ----
enc writes an object as one flat chain of keys. An SField writes its name and its rest continues that object; an SVariant writes its name and the value under it is a chain of its own (REnd ends it, so it is a value and not a continuation). A wrapper -- a rule, a strict object, a bound, an optional -- writes no key of its own and hands its value straight to its inner schema, so a key reaches the top of the object from inside any of them. A tagged case's schema is the same object the tag key was written into, and so is the rest of its chain.
no_key is that, written down: k does not reach the top of the object enc builds for s, for any value of s. wf asks it of a tagged case's own schema, which is what keeps the tag key from being written twice.
def fresh_f source · line 1791 · raw
@+n:String -> @s:Schema -> Bool
n is not a key of the record chain s (a chain ends in SEnd). Both orders are asked, as fresh_v asks them: which of the two names a step puts first depends on which of them is the value's key there, and asking both spares a proof that String.eq is symmetric.
def fresh_v source · line 1803 · raw
@+n:String -> @s:Schema -> Bool
n is not a key of the variant chain s (a chain ends in SVEnd). Both orders are asked: reading a key compares the names one way, reading past it the other, and asking both spares a proof that String.eq is symmetric.
def is_keyed source · line 1816 · raw
@s:Schema -> Bool
A record chain (ending in SEnd) or a variant chain (ending in SVEnd): what SStrict may wrap, so every key its encoding writes is a declared name. A chain of keys (SField or SVariant links, ending in SEnd or SVEnd): what SStrict may wrap, so every key its encoding writes is a name it declares.
def fresh_t source · line 1831 · raw
@+k:String -> @+n:String -> @s:Schema -> Bool
n names no case of the tagged chain s, whose key is k, and the chain ends in STagEnd{k}: one key for the whole chain.
def wf source · line 1840 · raw
@s:Schema -> Bool
def names_ok source · line 1872 · raw
@s:Schema -> @x:Meaning(s) -> Bool
Every enum value in x is one of its names (encode_conforms' premise).
def bounds_ok source · line 1924 · raw
@s:Schema -> @x:Meaning(s) -> Bool
Every bound a constructor states holds of the value that will be written, at every place one sits in the schema (encode_conforms' second premise, beside names_ok). The encoder writes the meaning unchanged, so a value outside a bound is written out as it is and refused by check on the way back: the host that built it is at fault, and this is where it says so. An SStrLen's bound is read off the string its own schema writes, and an SListLen's count off the list it writes, which is why enc appears here.
Templates
template conforms source · line 631 · raw
@-rule:(@_:Nat -> @_:Raw -> Maybe<&2, Err>) -> @s:Schema -> @r:Raw -> @+prev:Maybe<&2, Nat> -> Bool
template check source · line 857 · raw
@-rule:(@_:Nat -> @_:Raw -> Maybe<&2, Err>) -> @s:Schema -> @r:Raw -> @+prev:Maybe<&2, Nat> -> Maybe<&2, Err>
template defect source · line 1201 · raw
@-rule:(@_:Nat -> @_:Raw -> Maybe<&2, Err>) -> @s:Schema -> @r:Raw -> @+prev:Maybe<&2, Nat> -> @p:List<&2, Step> -> Maybe<&2, Why>
template present_conform source · line 1363 · raw
@-rule:(@_:Nat -> @_:Raw -> Maybe<&2, Err>) -> @+s:Schema -> @+r:Raw -> Bool
template each_pos source · line 1395 · raw
@-rule:(@_:Nat -> @_:Raw -> Maybe<&2, Err>) -> @ss:List<&2, Schema> -> @+r:Raw -> @+i:Nat -> Bool