// 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`).
///|
/// 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)
///|
/// The deepest JSON nesting the decoder reads: deeper input raises a
/// `DecodeError` instead of overflowing the stack (wasm has a small one).
/// Each AST level is at least one JSON level, so this bounds the AST depth
/// a decoded module can have; the parser keeps generated ASTs within it.
pub let max_depth : Int32 = 150
///|
priv enum Path {
Root
Key(Path, String)
Index(Path, Int32)
}
///|
/// The number of steps from the root.
fn Path::depth(self : Path) -> Int32 {
let mut n = 0
let mut p = self
while true {
match p {
Root => break
Key(parent, _) | Index(parent, _) => {
n += 1
p = parent
}
}
}
n
}
///|
fn check_depth(path : Path) -> Unit raise DecodeError {
if path.depth() > max_depth {
fail(path, "nesting deeper than \{max_depth} levels")
}
}
///|
fn Path::render(self : Path) -> String {
let sb = StringBuilder()
self.write_to(sb)
sb.to_string()
}
///|
fn Path::write_to(self : Path, sb : StringBuilder) -> Unit {
match self {
Root => sb.write_string("$")
Key(parent, key) => {
parent.write_to(sb)
sb.write_string(".")
sb.write_string(key)
}
Index(parent, i) => {
parent.write_to(sb)
sb.write_string("[")
sb.write_string(i.to_string())
sb.write_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) => {
let child = Key(path, key)
check_depth(child)
f(v, child)
}
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 {
let child = Index(path, i)
check_depth(child)
out.push(f(item, child))
}
out[:]
}
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 {
dec_parsed(json, Root)
}
///|
fn dec_parsed(j : Json, path : Path) -> Parsed raise DecodeError {
{
module_: dec_field(j, path, "module", dec_module),
extra: dec_field(j, path, "extra", dec_extra),
warnings: dec_field(j, path, "warnings", (v, p) => {
dec_array(v, p, dec_warning)
}),
}
}
///|
pub fn decode_module(json : Json) -> Module raise DecodeError {
dec_module(json, Root)
}
///|
fn dec_module(j : Json, path : Path) -> Module raise DecodeError {
{
definitions: dec_field(j, path, "definitions", (v, p) => {
dec_array(v, p, dec_targeted_definition)
}),
}
}
///|
fn dec_targeted_definition(
j : Json,
path : Path,
) -> TargetedDefinition raise DecodeError {
{
definition: dec_field(j, path, "definition", dec_definition),
target: dec_field(j, path, "target", (v, p) => {
dec_nullable(v, p, dec_target)
}),
}
}
///|
pub fn decode_definition(json : Json) -> Definition raise DecodeError {
dec_definition(json, Root)
}
///|
fn dec_definition(j : Json, path : Path) -> Definition raise DecodeError {
match dec_kind_of(j, path) {
"function" => Function(dec_function(j, path))
"type_alias" =>
TypeAlias({
location: dec_field(j, path, "location", dec_span),
alias_: dec_field(j, path, "alias", dec_string),
name_location: dec_field(j, path, "name_location", dec_span),
parameters: dec_field(j, path, "parameters", (v, p) => {
dec_array(v, p, dec_spanned_string)
}),
type_ast: dec_field(j, path, "type_ast", dec_type_ast),
publicity: dec_field(j, path, "publicity", dec_publicity),
documentation: dec_field(j, path, "documentation", (v, p) => {
dec_nullable(v, p, dec_documentation)
}),
deprecation: dec_field(j, path, "deprecation", dec_deprecation),
})
"custom_type" =>
CustomType({
location: dec_field(j, path, "location", dec_span),
end_position: dec_field(j, path, "end_position", dec_int),
name: dec_field(j, path, "name", dec_string),
name_location: dec_field(j, path, "name_location", dec_span),
publicity: dec_field(j, path, "publicity", dec_publicity),
constructors: dec_field(j, path, "constructors", (v, p) => {
dec_array(v, p, dec_record_constructor)
}),
documentation: dec_field(j, path, "documentation", (v, p) => {
dec_nullable(v, p, dec_documentation)
}),
deprecation: dec_field(j, path, "deprecation", dec_deprecation),
opaque_: dec_field(j, path, "opaque", dec_bool),
parameters: dec_field(j, path, "parameters", (v, p) => {
dec_array(v, p, dec_spanned_string)
}),
external_erlang: dec_field(j, path, "external_erlang", (v, p) => {
dec_nullable(v, p, dec_external)
}),
external_javascript: dec_field(j, path, "external_javascript", (v, p) => {
dec_nullable(v, p, dec_external)
}),
})
"import" =>
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" =>
ModuleConstant({
documentation: dec_field(j, path, "documentation", (v, p) => {
dec_nullable(v, p, dec_documentation)
}),
location: dec_field(j, path, "location", dec_span),
publicity: dec_field(j, path, "publicity", dec_publicity),
name: dec_field(j, path, "name", dec_string),
name_location: dec_field(j, path, "name_location", dec_span),
annotation: dec_field(j, path, "annotation", (v, p) => {
dec_nullable(v, p, dec_type_ast)
}),
value: dec_field(j, path, "value", dec_constant),
deprecation: dec_field(j, path, "deprecation", dec_deprecation),
})
other => fail(Key(path, "kind"), "unknown definition kind \"\{other}\"")
}
}
///|
fn dec_function(j : Json, path : Path) -> Function raise DecodeError {
{
location: dec_field(j, path, "location", dec_span),
body_start: dec_field(j, path, "body_start", (v, p) => {
dec_nullable(v, p, dec_int)
}),
end_position: dec_field(j, path, "end_position", dec_int),
name: dec_field(j, path, "name", (v, p) => {
dec_nullable(v, p, dec_spanned_string)
}),
arguments: dec_field(j, path, "arguments", (v, p) => {
dec_array(v, p, dec_arg)
}),
body: dec_field(j, path, "body", (v, p) => dec_array(v, p, dec_statement)),
publicity: dec_field(j, path, "publicity", dec_publicity),
deprecation: dec_field(j, path, "deprecation", dec_deprecation),
return_annotation: dec_field(j, path, "return_annotation", (v, p) => {
dec_nullable(v, p, dec_type_ast)
}),
documentation: dec_field(j, path, "documentation", (v, p) => {
dec_nullable(v, p, dec_documentation)
}),
external_erlang: dec_field(j, path, "external_erlang", (v, p) => {
dec_nullable(v, p, dec_external)
}),
external_javascript: dec_field(j, path, "external_javascript", (v, p) => {
dec_nullable(v, p, dec_external)
}),
}
}
///|
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 dec_record_constructor(
j : Json,
path : Path,
) -> RecordConstructor raise DecodeError {
{
location: dec_field(j, path, "location", dec_span),
name_location: dec_field(j, path, "name_location", dec_span),
name: dec_field(j, path, "name", dec_string),
arguments: dec_field(j, path, "arguments", (v, p) => {
dec_array(v, p, dec_record_constructor_arg)
}),
documentation: dec_field(j, path, "documentation", (v, p) => {
dec_nullable(v, p, dec_documentation)
}),
deprecation: dec_field(j, path, "deprecation", dec_deprecation),
}
}
///|
fn dec_record_constructor_arg(
j : Json,
path : Path,
) -> RecordConstructorArg raise DecodeError {
{
label: dec_field(j, path, "label", (v, p) => {
dec_nullable(v, p, dec_spanned_string)
}),
ast: dec_field(j, path, "ast", dec_type_ast),
location: dec_field(j, path, "location", dec_span),
doc: dec_field(j, path, "doc", (v, p) => {
dec_nullable(v, p, dec_documentation)
}),
}
}
///|
fn dec_arg(j : Json, path : Path) -> Arg raise DecodeError {
{
names: dec_field(j, path, "names", dec_arg_names),
location: dec_field(j, path, "location", dec_span),
annotation: dec_field(j, path, "annotation", (v, p) => {
dec_nullable(v, p, dec_type_ast)
}),
}
}
///|
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 {
dec_type_ast(json, Root)
}
///|
fn dec_type_ast(j : Json, path : Path) -> TypeAst raise DecodeError {
match dec_kind_of(j, path) {
"constructor" =>
Constructor({
location: dec_field(j, path, "location", dec_span),
name: dec_field(j, path, "name", dec_type_ast_constructor_name),
arguments: dec_field(j, path, "arguments", (v, p) => {
dec_array(v, p, dec_type_ast)
}),
start_parentheses: dec_field(j, path, "start_parentheses", (v, p) => {
dec_nullable(v, p, dec_int)
}),
})
"fn" =>
Fn({
location: dec_field(j, path, "location", dec_span),
arguments: dec_field(j, path, "arguments", (v, p) => {
dec_array(v, p, dec_type_ast)
}),
return_: dec_field(j, path, "return_", dec_type_ast),
})
"var" =>
Var({
location: dec_field(j, path, "location", dec_span),
name: dec_field(j, path, "name", dec_string),
})
"tuple" =>
Tuple({
location: dec_field(j, path, "location", dec_span),
elements: dec_field(j, path, "elements", (v, p) => {
dec_array(v, p, dec_type_ast)
}),
})
"hole" =>
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 {
dec_statement(json, Root)
}
///|
fn dec_statement(j : Json, path : Path) -> Statement raise DecodeError {
match dec_kind_of(j, path) {
"expression" => Expression(dec_field(j, path, "expression", dec_expr))
"assignment" =>
Assignment({
location: dec_field(j, path, "location", dec_span),
value: dec_field(j, path, "value", dec_expr),
pattern: dec_field(j, path, "pattern", dec_pattern),
kind: dec_field(j, path, "assignment_kind", dec_assignment_kind),
annotation: dec_field(j, path, "annotation", (v, p) => {
dec_nullable(v, p, dec_type_ast)
}),
})
"use" =>
Use({
call: dec_field(j, path, "call", dec_expr),
location: dec_field(j, path, "location", dec_span),
right_hand_side_location: dec_field(
j, path, "right_hand_side_location", dec_span,
),
assignments_location: dec_field(
j, path, "assignments_location", dec_span,
),
assignments: dec_field(j, path, "assignments", (v, p) => {
dec_array(v, p, dec_use_assignment)
}),
})
"assert" =>
Assert({
location: dec_field(j, path, "location", dec_span),
value: dec_field(j, path, "value", dec_expr),
message: dec_field(j, path, "message", (v, p) => {
dec_nullable(v, p, dec_expr)
}),
})
other => fail(Key(path, "kind"), "unknown statement kind \"\{other}\"")
}
}
///|
fn dec_assignment_kind(
j : Json,
path : Path,
) -> AssignmentKind raise DecodeError {
match dec_kind_of(j, path) {
"let" => Let
"generated" => Generated
"assert" =>
Assert(
location=dec_field(j, path, "location", dec_span),
assert_keyword_start=dec_field(j, path, "assert_keyword_start", dec_int),
message=dec_field(j, path, "message", (v, p) => {
dec_nullable(v, p, dec_expr)
}),
)
other => fail(Key(path, "kind"), "unknown assignment kind \"\{other}\"")
}
}
///|
fn dec_use_assignment(j : Json, path : Path) -> UseAssignment raise DecodeError {
{
location: dec_field(j, path, "location", dec_span),
pattern: dec_field(j, path, "pattern", dec_pattern),
annotation: dec_field(j, path, "annotation", (v, p) => {
dec_nullable(v, p, dec_type_ast)
}),
}
}
///|
fn[A] dec_call_arg(
j : Json,
path : Path,
f : (Json, Path) -> A raise DecodeError,
) -> CallArg[A] raise DecodeError {
{
label: dec_field(j, path, "label", (v, p) => dec_nullable(v, p, dec_string)),
location: dec_field(j, path, "location", dec_span),
value: dec_field(j, path, "value", f),
implicit: dec_field(j, path, "implicit", (v, p) => {
dec_nullable(v, p, dec_implicit)
}),
}
}
///|
fn[A] dec_record_being_updated(
j : Json,
path : Path,
f : (Json, Path) -> A raise DecodeError,
) -> RecordBeingUpdated[A] raise DecodeError {
{
base: dec_field(j, path, "base", f),
location: dec_field(j, path, "location", dec_span),
}
}
///|
fn[A] dec_record_update_arg(
j : Json,
path : Path,
f : (Json, Path) -> A raise DecodeError,
) -> RecordUpdateArg[A] raise DecodeError {
{
label: dec_field(j, path, "label", dec_string),
location: dec_field(j, path, "location", dec_span),
value: dec_field(j, path, "value", f),
}
}
///|
fn[V] dec_bit_array_segment(
j : Json,
path : Path,
f : (Json, Path) -> V raise DecodeError,
) -> BitArraySegment[V] raise DecodeError {
{
location: dec_field(j, path, "location", dec_span),
value: dec_field(j, path, "value", f),
options: dec_field(j, path, "options", (v, p) => {
dec_array(v, p, (v2, p2) => dec_bit_array_option(v2, p2, f))
}),
}
}
///|
fn[V] dec_bit_array_option(
j : Json,
path : Path,
f : (Json, Path) -> V raise DecodeError,
) -> BitArrayOption[V] raise DecodeError {
let location = dec_field(j, path, "location", dec_span)
match dec_kind_of(j, path) {
"bytes" => Bytes(location~)
"int" => Int(location~)
"float" => Float(location~)
"bits" => Bits(location~)
"utf8" => Utf8(location~)
"utf16" => Utf16(location~)
"utf32" => Utf32(location~)
"utf8_codepoint" => Utf8Codepoint(location~)
"utf16_codepoint" => Utf16Codepoint(location~)
"utf32_codepoint" => Utf32Codepoint(location~)
"signed" => Signed(location~)
"unsigned" => Unsigned(location~)
"big" => Big(location~)
"little" => Little(location~)
"native" => Native(location~)
"size" =>
Size(
location~,
value=dec_field(j, path, "value", f),
short_form=dec_field(j, path, "short_form", dec_bool),
)
"unit" => 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 {
dec_expr(json, Root)
}
///|
fn dec_expr(j : Json, path : Path) -> Expr raise DecodeError {
match dec_kind_of(j, path) {
"int" =>
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)
Float(
location=dec_field(j, path, "location", dec_span),
value~,
float_value=dec_float_value(value, path),
)
}
"string" =>
String(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_string),
)
"block" =>
Block(
location=dec_field(j, path, "location", dec_span),
statements=dec_field(j, path, "statements", (v, p) => {
dec_array(v, p, dec_statement)
}),
)
"var" =>
Var(
location=dec_field(j, path, "location", dec_span),
name=dec_field(j, path, "name", dec_string),
)
"fn" =>
Fn(
location=dec_field(j, path, "location", dec_span),
kind=dec_field(j, path, "fn_kind", dec_function_literal_kind),
end_of_head_byte_index=dec_field(
j, path, "end_of_head_byte_index", dec_int,
),
arguments=dec_field(j, path, "arguments", (v, p) => {
dec_array(v, p, dec_arg)
}),
body=dec_field(j, path, "body", (v, p) => dec_array(v, p, dec_statement)),
return_annotation=dec_field(j, path, "return_annotation", (v, p) => {
dec_nullable(v, p, dec_type_ast)
}),
)
"list" =>
List(
location=dec_field(j, path, "location", dec_span),
elements=dec_field(j, path, "elements", (v, p) => {
dec_array(v, p, dec_expr)
}),
tail=dec_field(j, path, "tail", (v, p) => dec_nullable(v, p, dec_expr)),
)
"call" =>
Call(
location=dec_field(j, path, "location", dec_span),
fun=dec_field(j, path, "fun", dec_expr),
arguments=dec_field(j, path, "arguments", (v, p) => {
dec_array(v, p, (v2, p2) => dec_call_arg(v2, p2, dec_expr))
}),
open_parenthesis=dec_field(j, path, "open_parenthesis", dec_int),
)
"bin_op" =>
BinOp(
location=dec_field(j, path, "location", dec_span),
operator=dec_field(j, path, "operator", dec_bin_op),
operator_start=dec_field(j, path, "operator_start", dec_int),
left=dec_field(j, path, "left", dec_expr),
right=dec_field(j, path, "right", dec_expr),
)
"pipeline" =>
Pipeline(
expressions=dec_field(j, path, "expressions", (v, p) => {
dec_array(v, p, dec_expr)
}),
)
"case" =>
Case(
location=dec_field(j, path, "location", dec_span),
subjects=dec_field(j, path, "subjects", (v, p) => {
dec_array(v, p, dec_expr)
}),
clauses=dec_field(j, path, "clauses", (v, p) => {
dec_nullable(v, p, (v2, p2) => dec_array(v2, p2, dec_clause))
}),
)
"field_access" =>
FieldAccess(
location=dec_field(j, path, "location", dec_span),
label_location=dec_field(j, path, "label_location", dec_span),
label=dec_field(j, path, "label", dec_string),
container=dec_field(j, path, "container", dec_expr),
)
"tuple" =>
Tuple(
location=dec_field(j, path, "location", dec_span),
elements=dec_field(j, path, "elements", (v, p) => {
dec_array(v, p, dec_expr)
}),
)
"tuple_index" =>
TupleIndex(
location=dec_field(j, path, "location", dec_span),
index=dec_field(j, path, "index", dec_uint64),
tuple=dec_field(j, path, "tuple", dec_expr),
)
"todo" =>
Todo(
kind=dec_field(j, path, "todo_kind", dec_todo_kind),
location=dec_field(j, path, "location", dec_span),
message=dec_field(j, path, "message", (v, p) => {
dec_nullable(v, p, dec_expr)
}),
)
"panic" =>
Panic(
location=dec_field(j, path, "location", dec_span),
message=dec_field(j, path, "message", (v, p) => {
dec_nullable(v, p, dec_expr)
}),
)
"echo" =>
Echo(
location=dec_field(j, path, "location", dec_span),
keyword_end=dec_field(j, path, "keyword_end", dec_int),
expression=dec_field(j, path, "expression", (v, p) => {
dec_nullable(v, p, dec_expr)
}),
message=dec_field(j, path, "message", (v, p) => {
dec_nullable(v, p, dec_expr)
}),
)
"bit_array" =>
BitArray(
location=dec_field(j, path, "location", dec_span),
segments=dec_field(j, path, "segments", (v, p) => {
dec_array(v, p, (v2, p2) => dec_bit_array_segment(v2, p2, dec_expr))
}),
)
"record_update" =>
RecordUpdate(
location=dec_field(j, path, "location", dec_span),
spread_start=dec_field(j, path, "spread_start", dec_int),
constructor_=dec_field(j, path, "constructor", dec_expr),
record=dec_field(j, path, "record", (v, p) => {
dec_record_being_updated(v, p, dec_expr)
}),
arguments=dec_field(j, path, "arguments", (v, p) => {
dec_array(v, p, (v2, p2) => dec_record_update_arg(v2, p2, dec_expr))
}),
)
"negate_bool" =>
NegateBool(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_expr),
)
"negate_int" =>
NegateInt(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_expr),
)
other => fail(Key(path, "kind"), "unknown expression kind \"\{other}\"")
}
}
///|
fn dec_clause(j : Json, path : Path) -> Clause raise DecodeError {
{
location: dec_field(j, path, "location", dec_span),
pattern: dec_field(j, path, "pattern", (v, p) => {
dec_array(v, p, dec_pattern)
}),
alternative_patterns: dec_field(j, path, "alternative_patterns", (v, p) => {
dec_array(v, p, (v2, p2) => dec_array(v2, p2, dec_pattern))
}),
guard_: dec_field(j, path, "guard", (v, p) => {
dec_nullable(v, p, dec_clause_guard)
}),
then: dec_field(j, path, "then", dec_expr),
}
}
///|
pub fn decode_clause_guard(json : Json) -> ClauseGuard raise DecodeError {
dec_clause_guard(json, Root)
}
///|
fn dec_clause_guard(j : Json, path : Path) -> ClauseGuard raise DecodeError {
match dec_kind_of(j, path) {
"block" =>
Block(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_clause_guard),
)
"binary_operator" =>
BinaryOperator(
location=dec_field(j, path, "location", dec_span),
operator=dec_field(j, path, "operator", dec_bin_op),
operator_start=dec_field(j, path, "operator_start", dec_int),
left=dec_field(j, path, "left", dec_clause_guard),
right=dec_field(j, path, "right", dec_clause_guard),
)
"not" =>
Not(
location=dec_field(j, path, "location", dec_span),
expression=dec_field(j, path, "expression", dec_clause_guard),
)
"var" =>
Var(
location=dec_field(j, path, "location", dec_span),
name=dec_field(j, path, "name", dec_string),
)
"tuple_index" =>
TupleIndex(
location=dec_field(j, path, "location", dec_span),
index=dec_field(j, path, "index", dec_uint64),
tuple=dec_field(j, path, "tuple", dec_clause_guard),
)
"field_access" =>
FieldAccess(
label_location=dec_field(j, path, "label_location", dec_span),
index=dec_field(j, path, "index", (v, p) => {
dec_nullable(v, p, dec_uint64)
}),
label=dec_field(j, path, "label", dec_string),
container=dec_field(j, path, "container", dec_clause_guard),
)
"constant" => Constant(dec_field(j, path, "constant", dec_constant))
other => fail(Key(path, "kind"), "unknown clause guard kind \"\{other}\"")
}
}
///|
pub fn decode_pattern(json : Json) -> Pattern raise DecodeError {
dec_pattern(json, Root)
}
///|
fn dec_pattern(j : Json, path : Path) -> Pattern raise DecodeError {
match dec_kind_of(j, path) {
"int" =>
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)
Float(
location=dec_field(j, path, "location", dec_span),
value~,
float_value=dec_float_value(value, path),
)
}
"string" =>
String(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_string),
)
"variable" =>
Variable(
location=dec_field(j, path, "location", dec_span),
name=dec_field(j, path, "name", dec_string),
)
"bit_array_size" =>
BitArraySize(dec_field(j, path, "size", dec_bit_array_size))
"assign" =>
Assign(
name=dec_field(j, path, "name", dec_string),
location=dec_field(j, path, "location", dec_span),
pattern=dec_field(j, path, "pattern", dec_pattern),
)
"discard" =>
Discard(
name=dec_field(j, path, "name", dec_string),
location=dec_field(j, path, "location", dec_span),
)
"list" =>
List(
location=dec_field(j, path, "location", dec_span),
elements=dec_field(j, path, "elements", (v, p) => {
dec_array(v, p, dec_pattern)
}),
tail=dec_field(j, path, "tail", (v, p) => {
dec_nullable(v, p, (v2, p2) => {
location: dec_field(v2, p2, "location", dec_span),
pattern: dec_field(v2, p2, "pattern", dec_pattern),
})
}),
)
"constructor" =>
Constructor(
location=dec_field(j, path, "location", dec_span),
name_location=dec_field(j, path, "name_location", dec_span),
name=dec_field(j, path, "name", dec_string),
arguments=dec_field(j, path, "arguments", (v, p) => {
dec_array(v, p, (v2, p2) => dec_call_arg(v2, p2, dec_pattern))
}),
module_=dec_field(j, path, "module", (v, p) => {
dec_nullable(v, p, dec_spanned_string)
}),
spread=dec_field(j, path, "spread", (v, p) => {
dec_nullable(v, p, dec_span)
}),
)
"tuple" =>
Tuple(
location=dec_field(j, path, "location", dec_span),
elements=dec_field(j, path, "elements", (v, p) => {
dec_array(v, p, dec_pattern)
}),
)
"bit_array" =>
BitArray(
location=dec_field(j, path, "location", dec_span),
segments=dec_field(j, path, "segments", (v, p) => {
dec_array(v, p, (v2, p2) => dec_bit_array_segment(v2, p2, dec_pattern))
}),
)
"string_prefix" =>
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 dec_bit_array_size(j : Json, path : Path) -> BitArraySize raise DecodeError {
match dec_kind_of(j, path) {
"int" =>
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" =>
Variable(
location=dec_field(j, path, "location", dec_span),
name=dec_field(j, path, "name", dec_string),
)
"binary_operator" =>
BinaryOperator(
location=dec_field(j, path, "location", dec_span),
operator=dec_field(j, path, "operator", dec_int_operator),
left=dec_field(j, path, "left", dec_bit_array_size),
right=dec_field(j, path, "right", dec_bit_array_size),
)
"block" =>
Block(
location=dec_field(j, path, "location", dec_span),
inner=dec_field(j, path, "inner", dec_bit_array_size),
)
other => fail(Key(path, "kind"), "unknown bit array size kind \"\{other}\"")
}
}
///|
pub fn decode_constant(json : Json) -> Constant raise DecodeError {
dec_constant(json, Root)
}
///|
fn dec_constant(j : Json, path : Path) -> Constant raise DecodeError {
match dec_kind_of(j, path) {
"int" =>
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)
Float(
location=dec_field(j, path, "location", dec_span),
value~,
float_value=dec_float_value(value, path),
)
}
"string" =>
String(
location=dec_field(j, path, "location", dec_span),
value=dec_field(j, path, "value", dec_string),
)
"tuple" =>
Tuple(
location=dec_field(j, path, "location", dec_span),
elements=dec_field(j, path, "elements", (v, p) => {
dec_array(v, p, dec_constant)
}),
)
"list" =>
List(
location=dec_field(j, path, "location", dec_span),
elements=dec_field(j, path, "elements", (v, p) => {
dec_array(v, p, dec_constant)
}),
tail=dec_field(j, path, "tail", (v, p) => {
dec_nullable(v, p, dec_constant)
}),
)
"record" =>
Record(
location=dec_field(j, path, "location", dec_span),
arguments_start_position=dec_field(
j, path, "arguments_start_position", dec_int,
),
module_=dec_field(j, path, "module", (v, p) => {
dec_nullable(v, p, dec_spanned_string)
}),
name=dec_field(j, path, "name", dec_string),
arguments=dec_field(j, path, "arguments", (v, p) => {
dec_nullable(v, p, (v2, p2) => {
dec_array(v2, p2, (v3, p3) => dec_call_arg(v3, p3, dec_constant))
})
}),
)
"record_update" =>
RecordUpdate(
location=dec_field(j, path, "location", dec_span),
constructor_location=dec_field(
j, path, "constructor_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),
record=dec_field(j, path, "record", (v, p) => {
dec_record_being_updated(v, p, dec_constant)
}),
arguments=dec_field(j, path, "arguments", (v, p) => {
dec_array(v, p, (v2, p2) => {
dec_record_update_arg(v2, p2, dec_constant)
})
}),
)
"bit_array" =>
BitArray(
location=dec_field(j, path, "location", dec_span),
segments=dec_field(j, path, "segments", (v, p) => {
dec_array(v, p, (v2, p2) => {
dec_bit_array_segment(v2, p2, dec_constant)
})
}),
)
"var" =>
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" =>
BinaryOperator(
location=dec_field(j, path, "location", dec_span),
operator_start=dec_field(j, path, "operator_start", dec_int),
operator=dec_field(j, path, "operator", dec_bin_op),
left=dec_field(j, path, "left", dec_constant),
right=dec_field(j, path, "right", dec_constant),
)
"todo" =>
Todo(
location=dec_field(j, path, "location", dec_span),
message=dec_field(j, path, "message", (v, p) => {
dec_nullable(v, p, dec_constant)
}),
)
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}\"")
}
}