// Decoders for the canonical JSON of docs/ast-json.md. Every decoder takes
// the JSON path of its input, so an error names the exact location
// (`$.module.definitions[3].definition.body[0].value`).
//
// Leaves (spans, strings, numbers, payload-free enums) decode directly.
// Nodes (`dec_*` with a continuation) run on the step trampoline of
// `step.mbt`: they enter a child only through `child`, `child_opt`,
// `child_list` or `children`, and hand their value to the continuation
// through `yield_`.
///|
/// Raised on malformed input. `path` is a JSONPath-like location (`$` is
/// the value given to the public decoder).
pub(all) suberror DecodeError {
DecodeError(path~ : String, message~ : String)
} derive(Eq, Debug)
///|
priv enum Path {
Root
Key(Path, String)
Index(Path, Int32)
}
///|
/// The path as text (`$.module.definitions[3].definition`). A loop over the
/// parents, so a path of any depth renders.
fn Path::render(self : Path) -> String {
let segments = for p = self, acc = @list.List([]) {
match p {
Root => break acc
Key(parent, key) => continue parent, acc.prepend(".\{key}")
Index(parent, i) => continue parent, acc.prepend("[\{i}]")
}
}
let sb = StringBuilder()
sb.write_string("$")
for segment in segments {
sb.write_string(segment)
}
sb.to_string()
}
///|
fn[T] fail(path : Path, message : String) -> T raise DecodeError {
raise DecodeError(path=path.render(), message~)
}
///|
fn json_kind(j : Json) -> String {
match j {
Null => "null"
True | False => "a BOOL"
Number(_, ..) => "a NUMBER"
String(_) => "a STRING"
Array(_) => "an ARRAY"
Object(_) => "an OBJECT"
}
}
///|
fn dec_object(j : Json, path : Path) -> Map[String, Json] raise DecodeError {
match j {
Object(m) => m
other => fail(path, "expected an OBJECT, found \{json_kind(other)}")
}
}
///|
/// The dec_field `key`; it must be present.
fn[T] dec_field(
j : Json,
path : Path,
key : String,
f : (Json, Path) -> T raise DecodeError,
) -> T raise DecodeError {
let m = dec_object(j, path)
match m.get(key) {
Some(v) => f(v, Key(path, key))
None => fail(Key(path, key), "missing field")
}
}
///|
fn dec_string(j : Json, path : Path) -> String raise DecodeError {
match j {
String(s) => s
other => fail(path, "expected a STRING, found \{json_kind(other)}")
}
}
///|
fn dec_int(j : Json, path : Path) -> Int32 raise DecodeError {
match j {
Number(d, ..) => {
let i = d.to_int()
if i.to_double() != d {
fail(path, "expected an integer, found \{d}")
}
i
}
other => fail(path, "expected a number, found \{json_kind(other)}")
}
}
///|
/// A `u64` of the compiler: exact digits from `repr` when the number is
/// too big for a `Double`, else the `Double` itself.
fn dec_uint64(j : Json, path : Path) -> UInt64 raise DecodeError {
match j {
Number(d, repr~) =>
match repr {
Some(digits) =>
@string.parse_uint64(digits) catch {
_ =>
fail(path, "expected an unsigned 64-bit integer, found \{digits}")
}
None => {
if d < 0.0 || d != d.floor() || d >= 18446744073709551616.0 {
fail(path, "expected an unsigned 64-bit integer, found \{d}")
}
d.to_uint64()
}
}
other => fail(path, "expected a number, found \{json_kind(other)}")
}
}
///|
fn dec_bool(j : Json, path : Path) -> Bool raise DecodeError {
match j {
True => true
False => false
other => fail(path, "expected a BOOL, found \{json_kind(other)}")
}
}
///|
fn[T] dec_nullable(
j : Json,
path : Path,
f : (Json, Path) -> T raise DecodeError,
) -> T? raise DecodeError {
match j {
Null => None
other => Some(f(other, path))
}
}
///|
fn[T] dec_array(
j : Json,
path : Path,
f : (Json, Path) -> T raise DecodeError,
) -> ArrayView[T] raise DecodeError {
match j {
Array(items) => {
let out : Array[T] = []
for i, item in items {
out.push(f(item, Index(path, i)))
}
out[:]
}
other => fail(path, "expected an ARRAY, found \{json_kind(other)}")
}
}
///|
/// Decode the child node under `key` with `f` as a new step and hand the
/// value to `k`. The field must be present.
fn[T, R] child(
j : Json,
path : Path,
key : String,
f : (Json, Path, (T) -> Decode[R] raise DecodeError) -> Decode[R] raise DecodeError,
k : (T) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_object(j, path).get(key) {
Some(v) => Decoding(() => f(v, Key(path, key), k))
None => fail(Key(path, key), "missing field")
}
}
///|
/// Decode an optional child node under `key`: `null` gives `None`.
fn[T, R] child_opt(
j : Json,
path : Path,
key : String,
f : (Json, Path, (T) -> Decode[R] raise DecodeError) -> Decode[R] raise DecodeError,
k : (T?) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_object(j, path).get(key) {
Some(Null) => yield_(k, None)
Some(v) => Decoding(() => f(v, Key(path, key), v2 => yield_(k, Some(v2))))
None => fail(Key(path, key), "missing field")
}
}
///|
/// Decode the array of child nodes under `key`, element by element.
fn[T, R] child_list(
j : Json,
path : Path,
key : String,
f : (Json, Path, (T) -> Decode[R] raise DecodeError) -> Decode[R] raise DecodeError,
k : (ArrayView[T]) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_object(j, path).get(key) {
Some(v) => Decoding(() => children(v, Key(path, key), f, k))
None => fail(Key(path, key), "missing field")
}
}
///|
/// Decode every element of an array of child nodes; element `i` gets the
/// path `path[i]`.
fn[T, R] children(
j : Json,
path : Path,
f : (Json, Path, (T) -> Decode[R] raise DecodeError) -> Decode[R] raise DecodeError,
k : (ArrayView[T]) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match j {
Array(items) =>
each_decode(items[:], (v, i, k2) => f(v, Index(path, i), k2), k)
other => fail(path, "expected an ARRAY, found \{json_kind(other)}")
}
}
///|
fn dec_kind_of(j : Json, path : Path) -> String raise DecodeError {
dec_field(j, path, "kind", dec_string)
}
///|
fn dec_big_int(j : Json, path : Path) -> BigInt raise DecodeError {
let s = dec_string(j, path)
let digits = if s.has_prefix("-") { s[1:] } else { s[:] }
if digits.length() == 0 {
fail(path, "not a decimal integer")
}
for i = 0; i < digits.length(); i = i + 1 {
let c = digits.code_unit_at(i).to_int()
if c < '0'.to_int() || c > '9'.to_int() {
fail(path, "not a decimal integer")
}
}
BigInt::from_string(s)
}
///|
fn dec_span(j : Json, path : Path) -> @span.SrcSpan raise DecodeError {
@span.SrcSpan::new(
dec_field(j, path, "start", dec_int),
dec_field(j, path, "end", dec_int),
)
}
///|
fn dec_spanned_string(j : Json, path : Path) -> SpannedString raise DecodeError {
{
location: dec_field(j, path, "location", dec_span),
name: dec_field(j, path, "name", dec_string),
}
}
///|
fn dec_documentation(j : Json, path : Path) -> Documentation raise DecodeError {
{
start: dec_field(j, path, "start", dec_int),
text: dec_field(j, path, "text", dec_string),
}
}
///|
fn dec_external(j : Json, path : Path) -> External raise DecodeError {
{
module_: dec_field(j, path, "module", dec_string),
function: dec_field(j, path, "function", dec_string),
location: dec_field(j, path, "location", dec_span),
}
}
///|
fn dec_publicity(j : Json, path : Path) -> Publicity raise DecodeError {
match dec_kind_of(j, path) {
"public" => Public
"private" => Private
"internal" =>
Internal(
attribute_location=dec_field(j, path, "attribute_location", (v, p) => {
dec_nullable(v, p, dec_span)
}),
)
other => fail(Key(path, "kind"), "unknown publicity \"\{other}\"")
}
}
///|
fn dec_deprecation(j : Json, path : Path) -> Deprecation raise DecodeError {
match dec_kind_of(j, path) {
"not_deprecated" => NotDeprecated
"deprecated" =>
Deprecated(message=dec_field(j, path, "message", dec_string))
other => fail(Key(path, "kind"), "unknown deprecation \"\{other}\"")
}
}
///|
fn dec_assign_name(j : Json, path : Path) -> AssignName raise DecodeError {
match dec_kind_of(j, path) {
"variable" => Variable(dec_field(j, path, "name", dec_string))
"discard" => Discard(dec_field(j, path, "name", dec_string))
other => fail(Key(path, "kind"), "unknown assign name \"\{other}\"")
}
}
///|
fn dec_target(j : Json, path : Path) -> Target raise DecodeError {
let s = dec_string(j, path)
match Target::of(s) {
Some(t) => t
None => fail(path, "unknown target \"\{s}\"")
}
}
///|
fn dec_bin_op(j : Json, path : Path) -> BinOp raise DecodeError {
let s = dec_string(j, path)
match BinOp::of(s) {
Some(op) => op
None => fail(path, "unknown operator \"\{s}\"")
}
}
///|
fn dec_int_operator(j : Json, path : Path) -> IntOperator raise DecodeError {
let s = dec_string(j, path)
match IntOperator::of(s) {
Some(op) => op
None => fail(path, "unknown int operator \"\{s}\"")
}
}
///|
fn dec_implicit(
j : Json,
path : Path,
) -> ImplicitCallArgOrigin raise DecodeError {
let s = dec_string(j, path)
match ImplicitCallArgOrigin::of(s) {
Some(i) => i
None => fail(path, "unknown implicit call arg origin \"\{s}\"")
}
}
///|
/// A `Float` node's double, derived from its lexeme.
fn dec_float_value(value : String, path : Path) -> Double raise DecodeError {
match @scanner.parse_float_value(value) {
Some(d) => d
None => fail(Key(path, "value"), "not a float literal")
}
}
///|
pub fn decode_parsed(json : Json) -> Parsed raise DecodeError {
run_decode(dec_parsed(json, Root, v => Decoded(v)))
}
///|
fn[R] dec_parsed(
j : Json,
path : Path,
k : (Parsed) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let extra = dec_field(j, path, "extra", dec_extra)
let warnings = dec_field(j, path, "warnings", (v, p) => {
dec_array(v, p, dec_warning)
})
child(j, path, "module", dec_module, module_ => {
yield_(k, { module_, extra, warnings, })
})
}
///|
pub fn decode_module(json : Json) -> Module raise DecodeError {
run_decode(dec_module(json, Root, v => Decoded(v)))
}
///|
fn[R] dec_module(
j : Json,
path : Path,
k : (Module) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
child_list(j, path, "definitions", dec_targeted_definition, definitions => {
yield_(k, { definitions, })
})
}
///|
fn[R] dec_targeted_definition(
j : Json,
path : Path,
k : (TargetedDefinition) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let target = dec_field(j, path, "target", (v, p) => {
dec_nullable(v, p, dec_target)
})
child(j, path, "definition", dec_definition, definition => {
yield_(k, { definition, target, })
})
}
///|
pub fn decode_definition(json : Json) -> Definition raise DecodeError {
run_decode(dec_definition(json, Root, v => Decoded(v)))
}
///|
fn[R] dec_definition(
j : Json,
path : Path,
k : (Definition) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_kind_of(j, path) {
"function" => dec_function(j, path, f => yield_(k, Function(f)))
"type_alias" => {
let location = dec_field(j, path, "location", dec_span)
let alias_ = dec_field(j, path, "alias", dec_string)
let name_location = dec_field(j, path, "name_location", dec_span)
let parameters = dec_field(j, path, "parameters", (v, p) => {
dec_array(v, p, dec_spanned_string)
})
let publicity = dec_field(j, path, "publicity", dec_publicity)
let documentation = dec_field(j, path, "documentation", (v, p) => {
dec_nullable(v, p, dec_documentation)
})
let deprecation = dec_field(j, path, "deprecation", dec_deprecation)
child(j, path, "type_ast", dec_type_ast, type_ast => {
yield_(
k,
TypeAlias({
location,
alias_,
name_location,
parameters,
type_ast,
publicity,
documentation,
deprecation,
}),
)
})
}
"custom_type" => {
let location = dec_field(j, path, "location", dec_span)
let end_position = dec_field(j, path, "end_position", dec_int)
let name = dec_field(j, path, "name", dec_string)
let name_location = dec_field(j, path, "name_location", dec_span)
let publicity = dec_field(j, path, "publicity", dec_publicity)
let documentation = dec_field(j, path, "documentation", (v, p) => {
dec_nullable(v, p, dec_documentation)
})
let deprecation = dec_field(j, path, "deprecation", dec_deprecation)
let opaque_ = dec_field(j, path, "opaque", dec_bool)
let parameters = dec_field(j, path, "parameters", (v, p) => {
dec_array(v, p, dec_spanned_string)
})
let external_erlang = dec_field(j, path, "external_erlang", (v, p) => {
dec_nullable(v, p, dec_external)
})
let external_javascript = dec_field(j, path, "external_javascript", (v, p) => {
dec_nullable(v, p, dec_external)
})
child_list(j, path, "constructors", dec_record_constructor, constructors => {
yield_(
k,
CustomType({
location,
end_position,
name,
name_location,
publicity,
constructors,
documentation,
deprecation,
opaque_,
parameters,
external_erlang,
external_javascript,
}),
)
})
}
"import" =>
yield_(
k,
Import({
documentation: dec_field(j, path, "documentation", (v, p) => {
dec_nullable(v, p, dec_string)
}),
location: dec_field(j, path, "location", dec_span),
module_location: dec_field(j, path, "module_location", dec_span),
module_: dec_field(j, path, "module", dec_string),
as_name: dec_field(j, path, "as_name", (v, p) => {
dec_nullable(v, p, (v2, p2) => {
name: dec_field(v2, p2, "name", dec_assign_name),
location: dec_field(v2, p2, "location", dec_span),
})
}),
unqualified_values: dec_field(j, path, "unqualified_values", (v, p) => {
dec_array(v, p, dec_unqualified_import)
}),
unqualified_types: dec_field(j, path, "unqualified_types", (v, p) => {
dec_array(v, p, dec_unqualified_import)
}),
}),
)
"module_constant" => {
let documentation = dec_field(j, path, "documentation", (v, p) => {
dec_nullable(v, p, dec_documentation)
})
let location = dec_field(j, path, "location", dec_span)
let publicity = dec_field(j, path, "publicity", dec_publicity)
let name = dec_field(j, path, "name", dec_string)
let name_location = dec_field(j, path, "name_location", dec_span)
let deprecation = dec_field(j, path, "deprecation", dec_deprecation)
child_opt(j, path, "annotation", dec_type_ast, annotation => {
child(j, path, "value", dec_constant, value => {
yield_(
k,
ModuleConstant({
documentation,
location,
publicity,
name,
name_location,
annotation,
value,
deprecation,
}),
)
})
})
}
other => fail(Key(path, "kind"), "unknown definition kind \"\{other}\"")
}
}
///|
fn[R] dec_function(
j : Json,
path : Path,
k : (Function) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let location = dec_field(j, path, "location", dec_span)
let body_start = dec_field(j, path, "body_start", (v, p) => {
dec_nullable(v, p, dec_int)
})
let end_position = dec_field(j, path, "end_position", dec_int)
let name = dec_field(j, path, "name", (v, p) => {
dec_nullable(v, p, dec_spanned_string)
})
let publicity = dec_field(j, path, "publicity", dec_publicity)
let deprecation = dec_field(j, path, "deprecation", dec_deprecation)
let documentation = dec_field(j, path, "documentation", (v, p) => {
dec_nullable(v, p, dec_documentation)
})
let external_erlang = dec_field(j, path, "external_erlang", (v, p) => {
dec_nullable(v, p, dec_external)
})
let external_javascript = dec_field(j, path, "external_javascript", (v, p) => {
dec_nullable(v, p, dec_external)
})
child_list(j, path, "arguments", dec_arg, arguments => {
child_list(j, path, "body", dec_statement, body => {
child_opt(j, path, "return_annotation", dec_type_ast, return_annotation => {
yield_(k, {
location,
body_start,
end_position,
name,
arguments,
body,
publicity,
deprecation,
return_annotation,
documentation,
external_erlang,
external_javascript,
})
})
})
})
}
///|
fn dec_unqualified_import(
j : Json,
path : Path,
) -> UnqualifiedImport raise DecodeError {
{
location: dec_field(j, path, "location", dec_span),
name: dec_field(j, path, "name", dec_string),
name_position: dec_field(j, path, "name_position", dec_int),
as_name: dec_field(j, path, "as_name", (v, p) => {
dec_nullable(v, p, dec_string)
}),
}
}
///|
fn[R] dec_record_constructor(
j : Json,
path : Path,
k : (RecordConstructor) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let location = dec_field(j, path, "location", dec_span)
let name_location = dec_field(j, path, "name_location", dec_span)
let name = dec_field(j, path, "name", dec_string)
let documentation = dec_field(j, path, "documentation", (v, p) => {
dec_nullable(v, p, dec_documentation)
})
let deprecation = dec_field(j, path, "deprecation", dec_deprecation)
child_list(j, path, "arguments", dec_record_constructor_arg, arguments => {
yield_(k, {
location,
name_location,
name,
arguments,
documentation,
deprecation,
})
})
}
///|
fn[R] dec_record_constructor_arg(
j : Json,
path : Path,
k : (RecordConstructorArg) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let label = dec_field(j, path, "label", (v, p) => {
dec_nullable(v, p, dec_spanned_string)
})
let location = dec_field(j, path, "location", dec_span)
let doc = dec_field(j, path, "doc", (v, p) => {
dec_nullable(v, p, dec_documentation)
})
child(j, path, "ast", dec_type_ast, ast => {
yield_(k, { label, ast, location, doc, })
})
}
///|
fn[R] dec_arg(
j : Json,
path : Path,
k : (Arg) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let names = dec_field(j, path, "names", dec_arg_names)
let location = dec_field(j, path, "location", dec_span)
child_opt(j, path, "annotation", dec_type_ast, annotation => {
yield_(k, { names, location, annotation, })
})
}
///|
fn dec_arg_names(j : Json, path : Path) -> ArgNames raise DecodeError {
match dec_kind_of(j, path) {
"discard" =>
Discard(
name=dec_field(j, path, "name", dec_string),
location=dec_field(j, path, "location", dec_span),
)
"labelled_discard" =>
LabelledDiscard(
label=dec_field(j, path, "label", dec_string),
label_location=dec_field(j, path, "label_location", dec_span),
name=dec_field(j, path, "name", dec_string),
name_location=dec_field(j, path, "name_location", dec_span),
)
"named" =>
Named(
name=dec_field(j, path, "name", dec_string),
location=dec_field(j, path, "location", dec_span),
)
"named_labelled" =>
NamedLabelled(
label=dec_field(j, path, "label", dec_string),
label_location=dec_field(j, path, "label_location", dec_span),
name=dec_field(j, path, "name", dec_string),
name_location=dec_field(j, path, "name_location", dec_span),
)
other => fail(Key(path, "kind"), "unknown arg names kind \"\{other}\"")
}
}
///|
pub fn decode_type_ast(json : Json) -> TypeAst raise DecodeError {
run_decode(dec_type_ast(json, Root, v => Decoded(v)))
}
///|
fn[R] dec_type_ast(
j : Json,
path : Path,
k : (TypeAst) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_kind_of(j, path) {
"constructor" => {
let location = dec_field(j, path, "location", dec_span)
let name = dec_field(j, path, "name", dec_type_ast_constructor_name)
let start_parentheses = dec_field(j, path, "start_parentheses", (v, p) => {
dec_nullable(v, p, dec_int)
})
child_list(j, path, "arguments", dec_type_ast, arguments => {
yield_(
k,
Constructor({ location, name, arguments, start_parentheses, }),
)
})
}
"fn" => {
let location = dec_field(j, path, "location", dec_span)
child_list(j, path, "arguments", dec_type_ast, arguments => {
child(j, path, "return_", dec_type_ast, return_ => {
yield_(k, Fn({ location, arguments, return_, }))
})
})
}
"var" =>
yield_(
k,
Var({
location: dec_field(j, path, "location", dec_span),
name: dec_field(j, path, "name", dec_string),
}),
)
"tuple" => {
let location = dec_field(j, path, "location", dec_span)
child_list(j, path, "elements", dec_type_ast, elements => {
yield_(k, Tuple({ location, elements, }))
})
}
"hole" =>
yield_(
k,
Hole({
location: dec_field(j, path, "location", dec_span),
name: dec_field(j, path, "name", dec_string),
}),
)
other => fail(Key(path, "kind"), "unknown type kind \"\{other}\"")
}
}
///|
fn dec_type_ast_constructor_name(
j : Json,
path : Path,
) -> TypeAstConstructorName raise DecodeError {
match dec_kind_of(j, path) {
"qualified" =>
Qualified(
module_=dec_field(j, path, "module", dec_string),
module_location=dec_field(j, path, "module_location", dec_span),
dot_location=dec_field(j, path, "dot_location", dec_int),
name=dec_field(j, path, "name", (v, p) => {
dec_nullable(v, p, dec_spanned_string)
}),
)
"unqualified" =>
Unqualified(
name=dec_field(j, path, "name", dec_string),
location=dec_field(j, path, "location", dec_span),
)
other =>
fail(Key(path, "kind"), "unknown type constructor name kind \"\{other}\"")
}
}
///|
pub fn decode_statement(json : Json) -> Statement raise DecodeError {
run_decode(dec_statement(json, Root, v => Decoded(v)))
}
///|
fn[R] dec_statement(
j : Json,
path : Path,
k : (Statement) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_kind_of(j, path) {
"expression" =>
child(j, path, "expression", dec_expr, e => yield_(k, Expression(e)))
"assignment" => {
let location = dec_field(j, path, "location", dec_span)
child(j, path, "value", dec_expr, value => {
child(j, path, "pattern", dec_pattern, pattern => {
child(j, path, "assignment_kind", dec_assignment_kind, kind => {
child_opt(j, path, "annotation", dec_type_ast, annotation => {
yield_(
k,
Assignment({ location, value, pattern, kind, annotation, }),
)
})
})
})
})
}
"use" => {
let location = dec_field(j, path, "location", dec_span)
let right_hand_side_location = dec_field(
j, path, "right_hand_side_location", dec_span,
)
let assignments_location = dec_field(
j, path, "assignments_location", dec_span,
)
child(j, path, "call", dec_expr, call => {
child_list(j, path, "assignments", dec_use_assignment, assignments => {
yield_(
k,
Use({
call,
location,
right_hand_side_location,
assignments_location,
assignments,
}),
)
})
})
}
"assert" => {
let location = dec_field(j, path, "location", dec_span)
child(j, path, "value", dec_expr, value => {
child_opt(j, path, "message", dec_expr, message => {
yield_(k, Assert({ location, value, message, }))
})
})
}
other => fail(Key(path, "kind"), "unknown statement kind \"\{other}\"")
}
}
///|
fn[R] dec_assignment_kind(
j : Json,
path : Path,
k : (AssignmentKind) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_kind_of(j, path) {
"let" => yield_(k, Let)
"generated" => yield_(k, Generated)
"assert" => {
let location = dec_field(j, path, "location", dec_span)
let assert_keyword_start = dec_field(
j, path, "assert_keyword_start", dec_int,
)
child_opt(j, path, "message", dec_expr, message => {
yield_(k, Assert(location~, assert_keyword_start~, message~))
})
}
other => fail(Key(path, "kind"), "unknown assignment kind \"\{other}\"")
}
}
///|
fn[R] dec_use_assignment(
j : Json,
path : Path,
k : (UseAssignment) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let location = dec_field(j, path, "location", dec_span)
child(j, path, "pattern", dec_pattern, pattern => {
child_opt(j, path, "annotation", dec_type_ast, annotation => {
yield_(k, { location, pattern, annotation, })
})
})
}
///|
fn[A, R] dec_call_arg(
j : Json,
path : Path,
f : (Json, Path, (A) -> Decode[R] raise DecodeError) -> Decode[R] raise DecodeError,
k : (CallArg[A]) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let label = dec_field(j, path, "label", (v, p) => {
dec_nullable(v, p, dec_string)
})
let location = dec_field(j, path, "location", dec_span)
let implicit = dec_field(j, path, "implicit", (v, p) => {
dec_nullable(v, p, dec_implicit)
})
child(j, path, "value", f, value => {
yield_(k, { label, location, value, implicit, })
})
}
///|
fn[A, R] dec_record_being_updated(
j : Json,
path : Path,
f : (Json, Path, (A) -> Decode[R] raise DecodeError) -> Decode[R] raise DecodeError,
k : (RecordBeingUpdated[A]) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let location = dec_field(j, path, "location", dec_span)
child(j, path, "base", f, base => yield_(k, { base, location, }))
}
///|
fn[A, R] dec_record_update_arg(
j : Json,
path : Path,
f : (Json, Path, (A) -> Decode[R] raise DecodeError) -> Decode[R] raise DecodeError,
k : (RecordUpdateArg[A]) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let label = dec_field(j, path, "label", dec_string)
let location = dec_field(j, path, "location", dec_span)
child(j, path, "value", f, value => yield_(k, { label, location, value, }))
}
///|
fn[V, R] dec_bit_array_segment(
j : Json,
path : Path,
f : (Json, Path, (V) -> Decode[R] raise DecodeError) -> Decode[R] raise DecodeError,
k : (BitArraySegment[V]) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let location = dec_field(j, path, "location", dec_span)
child(j, path, "value", f, value => {
child_list(
j,
path,
"options",
(v, p, k2) => dec_bit_array_option(v, p, f, k2),
options => yield_(k, { location, value, options, }),
)
})
}
///|
fn[V, R] dec_bit_array_option(
j : Json,
path : Path,
f : (Json, Path, (V) -> Decode[R] raise DecodeError) -> Decode[R] raise DecodeError,
k : (BitArrayOption[V]) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let location = dec_field(j, path, "location", dec_span)
match dec_kind_of(j, path) {
"bytes" => yield_(k, Bytes(location~))
"int" => yield_(k, Int(location~))
"float" => yield_(k, Float(location~))
"bits" => yield_(k, Bits(location~))
"utf8" => yield_(k, Utf8(location~))
"utf16" => yield_(k, Utf16(location~))
"utf32" => yield_(k, Utf32(location~))
"utf8_codepoint" => yield_(k, Utf8Codepoint(location~))
"utf16_codepoint" => yield_(k, Utf16Codepoint(location~))
"utf32_codepoint" => yield_(k, Utf32Codepoint(location~))
"signed" => yield_(k, Signed(location~))
"unsigned" => yield_(k, Unsigned(location~))
"big" => yield_(k, Big(location~))
"little" => yield_(k, Little(location~))
"native" => yield_(k, Native(location~))
"size" => {
let short_form = dec_field(j, path, "short_form", dec_bool)
child(j, path, "value", f, value => {
yield_(k, Size(location~, value~, short_form~))
})
}
"unit" =>
yield_(k, Unit(location~, value=dec_field(j, path, "value", dec_int)))
other => fail(Key(path, "kind"), "unknown bit array option \"\{other}\"")
}
}
///|
fn dec_todo_kind(j : Json, path : Path) -> TodoKind raise DecodeError {
match dec_kind_of(j, path) {
"keyword" => Keyword
"empty_function" =>
EmptyFunction(
function_location=dec_field(j, path, "function_location", dec_span),
)
"incomplete_use" => IncompleteUse
"empty_block" => EmptyBlock
other => fail(Key(path, "kind"), "unknown todo kind \"\{other}\"")
}
}
///|
fn dec_function_literal_kind(
j : Json,
path : Path,
) -> FunctionLiteralKind raise DecodeError {
match dec_kind_of(j, path) {
"capture" => Capture(hole=dec_field(j, path, "hole", dec_span))
"anonymous" => Anonymous(head=dec_field(j, path, "head", dec_span))
"use" => Use(location=dec_field(j, path, "location", dec_span))
other =>
fail(Key(path, "kind"), "unknown function literal kind \"\{other}\"")
}
}
///|
pub fn decode_expr(json : Json) -> Expr raise DecodeError {
run_decode(dec_expr(json, Root, v => Decoded(v)))
}
///|
fn[R] dec_expr(
j : Json,
path : Path,
k : (Expr) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_kind_of(j, path) {
"int" =>
yield_(
k,
Int(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_string),
int_value=dec_field(j, path, "int_value", dec_big_int),
),
)
"float" => {
let value = dec_field(j, path, "value", dec_string)
yield_(
k,
Float(
location=dec_field(j, path, "location", dec_span),
value~,
float_value=dec_float_value(value, path),
),
)
}
"string" =>
yield_(
k,
String(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_string),
),
)
"block" => {
let location = dec_field(j, path, "location", dec_span)
child_list(j, path, "statements", dec_statement, statements => {
yield_(k, Block(location~, statements~))
})
}
"var" =>
yield_(
k,
Var(
location=dec_field(j, path, "location", dec_span),
name=dec_field(j, path, "name", dec_string),
),
)
"fn" => {
let location = dec_field(j, path, "location", dec_span)
let kind = dec_field(j, path, "fn_kind", dec_function_literal_kind)
let end_of_head_byte_index = dec_field(
j, path, "end_of_head_byte_index", dec_int,
)
child_list(j, path, "arguments", dec_arg, arguments => {
child_list(j, path, "body", dec_statement, body => {
child_opt(j, path, "return_annotation", dec_type_ast, return_annotation => {
yield_(
k,
Fn(
location~,
kind~,
end_of_head_byte_index~,
arguments~,
body~,
return_annotation~,
),
)
})
})
})
}
"list" => {
let location = dec_field(j, path, "location", dec_span)
child_list(j, path, "elements", dec_expr, elements => {
child_opt(j, path, "tail", dec_expr, tail => {
yield_(k, List(location~, elements~, tail~))
})
})
}
"call" => {
let location = dec_field(j, path, "location", dec_span)
let open_parenthesis = dec_field(j, path, "open_parenthesis", dec_int)
child(j, path, "fun", dec_expr, fun => {
child_list(
j,
path,
"arguments",
(v, p, k2) => dec_call_arg(v, p, dec_expr, k2),
arguments => {
yield_(k, Call(location~, fun~, arguments~, open_parenthesis~))
},
)
})
}
"bin_op" => {
let location = dec_field(j, path, "location", dec_span)
let operator = dec_field(j, path, "operator", dec_bin_op)
let operator_start = dec_field(j, path, "operator_start", dec_int)
child(j, path, "left", dec_expr, left => {
child(j, path, "right", dec_expr, right => {
yield_(k, BinOp(location~, operator~, operator_start~, left~, right~))
})
})
}
"pipeline" =>
child_list(j, path, "expressions", dec_expr, expressions => {
yield_(k, Pipeline(expressions~))
})
"case" => {
let location = dec_field(j, path, "location", dec_span)
child_list(j, path, "subjects", dec_expr, subjects => {
child_opt(
j,
path,
"clauses",
(v, p, k2) => children(v, p, dec_clause, k2),
clauses => yield_(k, Case(location~, subjects~, clauses~)),
)
})
}
"field_access" => {
let location = dec_field(j, path, "location", dec_span)
let label_location = dec_field(j, path, "label_location", dec_span)
let label = dec_field(j, path, "label", dec_string)
child(j, path, "container", dec_expr, container => {
yield_(k, FieldAccess(location~, label_location~, label~, container~))
})
}
"tuple" => {
let location = dec_field(j, path, "location", dec_span)
child_list(j, path, "elements", dec_expr, elements => {
yield_(k, Tuple(location~, elements~))
})
}
"tuple_index" => {
let location = dec_field(j, path, "location", dec_span)
let index = dec_field(j, path, "index", dec_uint64)
child(j, path, "tuple", dec_expr, tuple => {
yield_(k, TupleIndex(location~, index~, tuple~))
})
}
"todo" => {
let kind = dec_field(j, path, "todo_kind", dec_todo_kind)
let location = dec_field(j, path, "location", dec_span)
child_opt(j, path, "message", dec_expr, message => {
yield_(k, Todo(kind~, location~, message~))
})
}
"panic" => {
let location = dec_field(j, path, "location", dec_span)
child_opt(j, path, "message", dec_expr, message => {
yield_(k, Panic(location~, message~))
})
}
"echo" => {
let location = dec_field(j, path, "location", dec_span)
let keyword_end = dec_field(j, path, "keyword_end", dec_int)
child_opt(j, path, "expression", dec_expr, expression => {
child_opt(j, path, "message", dec_expr, message => {
yield_(k, Echo(location~, keyword_end~, expression~, message~))
})
})
}
"bit_array" => {
let location = dec_field(j, path, "location", dec_span)
child_list(
j,
path,
"segments",
(v, p, k2) => dec_bit_array_segment(v, p, dec_expr, k2),
segments => yield_(k, BitArray(location~, segments~)),
)
}
"record_update" => {
let location = dec_field(j, path, "location", dec_span)
let spread_start = dec_field(j, path, "spread_start", dec_int)
child(j, path, "constructor", dec_expr, constructor_ => {
child(
j,
path,
"record",
(v, p, k2) => dec_record_being_updated(v, p, dec_expr, k2),
record => {
child_list(
j,
path,
"arguments",
(v, p, k2) => dec_record_update_arg(v, p, dec_expr, k2),
arguments => {
yield_(
k,
RecordUpdate(
location~,
spread_start~,
constructor_~,
record~,
arguments~,
),
)
},
)
},
)
})
}
"negate_bool" => {
let location = dec_field(j, path, "location", dec_span)
child(j, path, "value", dec_expr, value => {
yield_(k, NegateBool(location~, value~))
})
}
"negate_int" => {
let location = dec_field(j, path, "location", dec_span)
child(j, path, "value", dec_expr, value => {
yield_(k, NegateInt(location~, value~))
})
}
other => fail(Key(path, "kind"), "unknown expression kind \"\{other}\"")
}
}
///|
fn[R] dec_clause(
j : Json,
path : Path,
k : (Clause) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
let location = dec_field(j, path, "location", dec_span)
child_list(j, path, "pattern", dec_pattern, pattern => {
child_list(
j,
path,
"alternative_patterns",
(v, p, k2) => children(v, p, dec_pattern, k2),
alternative_patterns => {
child_opt(j, path, "guard", dec_clause_guard, guard_ => {
child(j, path, "then", dec_expr, then => {
yield_(k, { location, pattern, alternative_patterns, guard_, then, })
})
})
},
)
})
}
///|
pub fn decode_clause_guard(json : Json) -> ClauseGuard raise DecodeError {
run_decode(dec_clause_guard(json, Root, v => Decoded(v)))
}
///|
fn[R] dec_clause_guard(
j : Json,
path : Path,
k : (ClauseGuard) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_kind_of(j, path) {
"block" => {
let location = dec_field(j, path, "location", dec_span)
child(j, path, "value", dec_clause_guard, value => {
yield_(k, Block(location~, value~))
})
}
"binary_operator" => {
let location = dec_field(j, path, "location", dec_span)
let operator = dec_field(j, path, "operator", dec_bin_op)
let operator_start = dec_field(j, path, "operator_start", dec_int)
child(j, path, "left", dec_clause_guard, left => {
child(j, path, "right", dec_clause_guard, right => {
yield_(
k,
BinaryOperator(location~, operator~, operator_start~, left~, right~),
)
})
})
}
"not" => {
let location = dec_field(j, path, "location", dec_span)
child(j, path, "expression", dec_clause_guard, expression => {
yield_(k, Not(location~, expression~))
})
}
"var" =>
yield_(
k,
Var(
location=dec_field(j, path, "location", dec_span),
name=dec_field(j, path, "name", dec_string),
),
)
"tuple_index" => {
let location = dec_field(j, path, "location", dec_span)
let index = dec_field(j, path, "index", dec_uint64)
child(j, path, "tuple", dec_clause_guard, tuple => {
yield_(k, TupleIndex(location~, index~, tuple~))
})
}
"field_access" => {
let label_location = dec_field(j, path, "label_location", dec_span)
let index = dec_field(j, path, "index", (v, p) => {
dec_nullable(v, p, dec_uint64)
})
let label = dec_field(j, path, "label", dec_string)
child(j, path, "container", dec_clause_guard, container => {
yield_(k, FieldAccess(label_location~, index~, label~, container~))
})
}
"constant" =>
child(j, path, "constant", dec_constant, c => yield_(k, Constant(c)))
other => fail(Key(path, "kind"), "unknown clause guard kind \"\{other}\"")
}
}
///|
pub fn decode_pattern(json : Json) -> Pattern raise DecodeError {
run_decode(dec_pattern(json, Root, v => Decoded(v)))
}
///|
fn[R] dec_pattern(
j : Json,
path : Path,
k : (Pattern) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_kind_of(j, path) {
"int" =>
yield_(
k,
Int(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_string),
int_value=dec_field(j, path, "int_value", dec_big_int),
),
)
"float" => {
let value = dec_field(j, path, "value", dec_string)
yield_(
k,
Float(
location=dec_field(j, path, "location", dec_span),
value~,
float_value=dec_float_value(value, path),
),
)
}
"string" =>
yield_(
k,
String(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_string),
),
)
"variable" =>
yield_(
k,
Variable(
location=dec_field(j, path, "location", dec_span),
name=dec_field(j, path, "name", dec_string),
),
)
"bit_array_size" =>
child(j, path, "size", dec_bit_array_size, s => yield_(k, BitArraySize(s)))
"assign" => {
let name = dec_field(j, path, "name", dec_string)
let location = dec_field(j, path, "location", dec_span)
child(j, path, "pattern", dec_pattern, pattern => {
yield_(k, Assign(name~, location~, pattern~))
})
}
"discard" =>
yield_(
k,
Discard(
name=dec_field(j, path, "name", dec_string),
location=dec_field(j, path, "location", dec_span),
),
)
"list" => {
let location = dec_field(j, path, "location", dec_span)
child_list(j, path, "elements", dec_pattern, elements => {
child_opt(
j,
path,
"tail",
(v, p, k2) => {
let location = dec_field(v, p, "location", dec_span)
child(v, p, "pattern", dec_pattern, pattern => {
yield_(k2, { location, pattern, })
})
},
tail => yield_(k, List(location~, elements~, tail~)),
)
})
}
"constructor" => {
let location = dec_field(j, path, "location", dec_span)
let name_location = dec_field(j, path, "name_location", dec_span)
let name = dec_field(j, path, "name", dec_string)
let module_ = dec_field(j, path, "module", (v, p) => {
dec_nullable(v, p, dec_spanned_string)
})
let spread = dec_field(j, path, "spread", (v, p) => {
dec_nullable(v, p, dec_span)
})
child_list(
j,
path,
"arguments",
(v, p, k2) => dec_call_arg(v, p, dec_pattern, k2),
arguments => {
yield_(
k,
Constructor(
location~,
name_location~,
name~,
arguments~,
module_~,
spread~,
),
)
},
)
}
"tuple" => {
let location = dec_field(j, path, "location", dec_span)
child_list(j, path, "elements", dec_pattern, elements => {
yield_(k, Tuple(location~, elements~))
})
}
"bit_array" => {
let location = dec_field(j, path, "location", dec_span)
child_list(
j,
path,
"segments",
(v, p, k2) => dec_bit_array_segment(v, p, dec_pattern, k2),
segments => yield_(k, BitArray(location~, segments~)),
)
}
"string_prefix" =>
yield_(
k,
StringPrefix(
location=dec_field(j, path, "location", dec_span),
left_location=dec_field(j, path, "left_location", dec_span),
left_side_assignment=dec_field(j, path, "left_side_assignment", (v, p) => {
dec_nullable(v, p, (v2, p2) => {
name: dec_field(v2, p2, "name", dec_string),
name_start_position: dec_field(
v2, p2, "name_start_position", dec_int,
),
location: dec_field(v2, p2, "location", dec_span),
})
}),
right_location=dec_field(j, path, "right_location", dec_span),
left_side_string=dec_field(j, path, "left_side_string", dec_string),
right_side_assignment=dec_field(
j, path, "right_side_assignment", dec_assign_name,
),
),
)
other => fail(Key(path, "kind"), "unknown pattern kind \"\{other}\"")
}
}
///|
fn[R] dec_bit_array_size(
j : Json,
path : Path,
k : (BitArraySize) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_kind_of(j, path) {
"int" =>
yield_(
k,
Int(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_string),
int_value=dec_field(j, path, "int_value", dec_big_int),
),
)
"variable" =>
yield_(
k,
Variable(
location=dec_field(j, path, "location", dec_span),
name=dec_field(j, path, "name", dec_string),
),
)
"binary_operator" => {
let location = dec_field(j, path, "location", dec_span)
let operator = dec_field(j, path, "operator", dec_int_operator)
child(j, path, "left", dec_bit_array_size, left => {
child(j, path, "right", dec_bit_array_size, right => {
yield_(k, BinaryOperator(location~, operator~, left~, right~))
})
})
}
"block" => {
let location = dec_field(j, path, "location", dec_span)
child(j, path, "inner", dec_bit_array_size, inner => {
yield_(k, Block(location~, inner~))
})
}
other => fail(Key(path, "kind"), "unknown bit array size kind \"\{other}\"")
}
}
///|
pub fn decode_constant(json : Json) -> Constant raise DecodeError {
run_decode(dec_constant(json, Root, v => Decoded(v)))
}
///|
fn[R] dec_constant(
j : Json,
path : Path,
k : (Constant) -> Decode[R] raise DecodeError,
) -> Decode[R] raise DecodeError {
match dec_kind_of(j, path) {
"int" =>
yield_(
k,
Int(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_string),
int_value=dec_field(j, path, "int_value", dec_big_int),
),
)
"float" => {
let value = dec_field(j, path, "value", dec_string)
yield_(
k,
Float(
location=dec_field(j, path, "location", dec_span),
value~,
float_value=dec_float_value(value, path),
),
)
}
"string" =>
yield_(
k,
String(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_string),
),
)
"tuple" => {
let location = dec_field(j, path, "location", dec_span)
child_list(j, path, "elements", dec_constant, elements => {
yield_(k, Tuple(location~, elements~))
})
}
"list" => {
let location = dec_field(j, path, "location", dec_span)
child_list(j, path, "elements", dec_constant, elements => {
child_opt(j, path, "tail", dec_constant, tail => {
yield_(k, List(location~, elements~, tail~))
})
})
}
"record" => {
let location = dec_field(j, path, "location", dec_span)
let arguments_start_position = dec_field(
j, path, "arguments_start_position", dec_int,
)
let module_ = dec_field(j, path, "module", (v, p) => {
dec_nullable(v, p, dec_spanned_string)
})
let name = dec_field(j, path, "name", dec_string)
child_opt(
j,
path,
"arguments",
(v, p, k2) => {
children(
v,
p,
(v2, p2, k3) => dec_call_arg(v2, p2, dec_constant, k3),
k2,
)
},
arguments => {
yield_(
k,
Record(
location~,
arguments_start_position~,
module_~,
name~,
arguments~,
),
)
},
)
}
"record_update" => {
let location = dec_field(j, path, "location", dec_span)
let constructor_location = dec_field(
j, path, "constructor_location", dec_span,
)
let module_ = dec_field(j, path, "module", (v, p) => {
dec_nullable(v, p, dec_spanned_string)
})
let name = dec_field(j, path, "name", dec_string)
child(
j,
path,
"record",
(v, p, k2) => dec_record_being_updated(v, p, dec_constant, k2),
record => {
child_list(
j,
path,
"arguments",
(v, p, k2) => dec_record_update_arg(v, p, dec_constant, k2),
arguments => {
yield_(
k,
RecordUpdate(
location~,
constructor_location~,
module_~,
name~,
record~,
arguments~,
),
)
},
)
},
)
}
"bit_array" => {
let location = dec_field(j, path, "location", dec_span)
child_list(
j,
path,
"segments",
(v, p, k2) => dec_bit_array_segment(v, p, dec_constant, k2),
segments => yield_(k, BitArray(location~, segments~)),
)
}
"var" =>
yield_(
k,
Var(
location=dec_field(j, path, "location", dec_span),
module_=dec_field(j, path, "module", (v, p) => {
dec_nullable(v, p, dec_spanned_string)
}),
name=dec_field(j, path, "name", dec_string),
),
)
"binary_operator" => {
let location = dec_field(j, path, "location", dec_span)
let operator_start = dec_field(j, path, "operator_start", dec_int)
let operator = dec_field(j, path, "operator", dec_bin_op)
child(j, path, "left", dec_constant, left => {
child(j, path, "right", dec_constant, right => {
yield_(
k,
BinaryOperator(location~, operator_start~, operator~, left~, right~),
)
})
})
}
"todo" => {
let location = dec_field(j, path, "location", dec_span)
child_opt(j, path, "message", dec_constant, message => {
yield_(k, Todo(location~, message~))
})
}
other => fail(Key(path, "kind"), "unknown constant kind \"\{other}\"")
}
}
///|
pub fn decode_extra(json : Json) -> ModuleExtra raise DecodeError {
dec_extra(json, Root)
}
///|
fn dec_extra(j : Json, path : Path) -> ModuleExtra raise DecodeError {
{
module_comments: dec_field(j, path, "module_comments", (v, p) => {
dec_array(v, p, dec_span)
}),
doc_comments: dec_field(j, path, "doc_comments", (v, p) => {
dec_array(v, p, dec_span)
}),
comments: dec_field(j, path, "comments", (v, p) => dec_array(v, p, dec_span)),
empty_lines: dec_field(j, path, "empty_lines", (v, p) => {
dec_array(v, p, dec_int)
}),
new_lines: dec_field(j, path, "new_lines", (v, p) => {
dec_array(v, p, dec_int)
}),
trailing_commas: dec_field(j, path, "trailing_commas", (v, p) => {
dec_array(v, p, dec_int)
}),
}
}
///|
pub fn decode_warning(json : Json) -> Warning raise DecodeError {
dec_warning(json, Root)
}
///|
fn dec_warning(j : Json, path : Path) -> Warning raise DecodeError {
let location = dec_field(j, path, "location", dec_span)
match dec_kind_of(j, path) {
"deprecated_list_prepend" => DeprecatedListPrepend(location~)
"deprecated_list_pattern" => DeprecatedListPattern(location~)
"deprecated_list_catch_all_pattern" =>
DeprecatedListCatchAllPattern(location~)
"deprecated_list_spread_as_variable_pattern" =>
DeprecatedListSpreadAsVariablePattern(
location~,
name=dec_field(j, path, "name", dec_string),
)
"deprecated_record_spread_pattern" =>
DeprecatedRecordSpreadPattern(location~)
"deprecated_empty_clause_guard" => DeprecatedEmptyClauseGuard(location~)
"deprecated_target_shorthand" =>
DeprecatedTargetShorthand(
target=dec_field(j, path, "target", dec_target),
location~,
)
"detached_doc_comment" => DetachedDocComment(location~)
other => fail(Key(path, "kind"), "unknown warning kind \"\{other}\"")
}
}