Add support for function constants (#37)

pull/844/head
Jonathan Arnett 2022-08-22 14:53:32 +07:00 committed by GitHub
parent 7bfe989c55
commit 81670f48fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 23922 additions and 23064 deletions

@ -52,6 +52,7 @@ There are a few nodes in the generated AST that may be confusing at first:
—there's no way for the parser to know. In this case, it will be parsed to —there's no way for the parser to know. In this case, it will be parsed to
`(function_call function: (field_access ...) ...)` , as I arbitrarily decided `(function_call function: (field_access ...) ...)` , as I arbitrarily decided
to always assume the code is accessing a field on a record. to always assume the code is accessing a field on a record.
- `constant_field_access` :: Recognizes when a reference to a remote function is used as a constant's value. Generally field accesses are indistinguishable from remote function invocations by the parser so `field_access` is the node name used for both (hence this misnomer).
This is not a comprehensive list. If you find a node confusing, search for it This is not a comprehensive list. If you find a node confusing, search for it
in `grammar.js`, as it might have an explanatory comment. Either way, feel free in `grammar.js`, as it might have an explanatory comment. Either way, feel free

@ -25,6 +25,7 @@ module.exports = grammar({
], ],
[$.case_subjects], [$.case_subjects],
[$.source_file], [$.source_file],
[$._constant_value, $._case_clause_guard_unit],
], ],
rules: { rules: {
/* General rules */ /* General rules */
@ -93,7 +94,9 @@ module.exports = grammar({
alias($.constant_tuple, $.tuple), alias($.constant_tuple, $.tuple),
alias($.constant_list, $.list), alias($.constant_list, $.list),
alias($._constant_bit_string, $.bit_string), alias($._constant_bit_string, $.bit_string),
alias($.constant_record, $.record) alias($.constant_record, $.record),
$.identifier,
alias($.constant_field_access, $.field_access)
), ),
constant_tuple: ($) => constant_tuple: ($) =>
seq("#", "(", optional(series_of($._constant_value, ",")), ")"), seq("#", "(", optional(series_of($._constant_value, ",")), ")"),
@ -118,6 +121,12 @@ module.exports = grammar({
optional(seq(field("label", $.label), ":")), optional(seq(field("label", $.label), ":")),
field("value", $._constant_value) field("value", $._constant_value)
), ),
// This is definitely a misnomer at this time as field access are actually
// not allowed as constant values (yet). This rule exists to parse remote
// function references which are generally indistinguishable from field
// accesses and so share an AST node.
constant_field_access: ($) =>
seq(field("record", $.identifier), ".", field("field", $.label)),
/* Special constant types */ /* Special constant types */
// Versions of $._type, $._type_annotation, etc, that have constraints // Versions of $._type, $._type_annotation, etc, that have constraints
@ -126,11 +135,29 @@ module.exports = grammar({
choice( choice(
$.type_hole, $.type_hole,
alias($.constant_tuple_type, $.tuple_type), alias($.constant_tuple_type, $.tuple_type),
alias($.constant_function_type, $.function_type),
alias($.constant_type, $.type) alias($.constant_type, $.type)
), ),
_constant_type_annotation: ($) => seq(":", field("type", $._constant_type)), _constant_type_annotation: ($) => seq(":", field("type", $._constant_type)),
constant_tuple_type: ($) => constant_tuple_type: ($) =>
seq("#", "(", optional(series_of($._constant_type, ",")), ")"), seq("#", "(", optional(series_of($._constant_type, ",")), ")"),
constant_function_type: ($) =>
seq(
"fn",
optional(
field(
"parameter_types",
alias(
$.constant_function_parameter_types,
$.function_parameter_types
)
)
),
"->",
field("return_type", $._constant_type)
),
constant_function_parameter_types: ($) =>
seq("(", optional(series_of($._constant_type, ",")), ")"),
constant_type: ($) => constant_type: ($) =>
seq( seq(
field("name", choice($.type_identifier, $.remote_type_identifier)), field("name", choice($.type_identifier, $.remote_type_identifier)),

151
src/grammar.json generated

@ -481,6 +481,19 @@
}, },
"named": true, "named": true,
"value": "record" "value": "record"
},
{
"type": "SYMBOL",
"name": "identifier"
},
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "constant_field_access"
},
"named": true,
"value": "field_access"
} }
] ]
}, },
@ -953,6 +966,31 @@
} }
] ]
}, },
"constant_field_access": {
"type": "SEQ",
"members": [
{
"type": "FIELD",
"name": "record",
"content": {
"type": "SYMBOL",
"name": "identifier"
}
},
{
"type": "STRING",
"value": "."
},
{
"type": "FIELD",
"name": "field",
"content": {
"type": "SYMBOL",
"name": "label"
}
}
]
},
"_constant_type": { "_constant_type": {
"type": "CHOICE", "type": "CHOICE",
"members": [ "members": [
@ -969,6 +1007,15 @@
"named": true, "named": true,
"value": "tuple_type" "value": "tuple_type"
}, },
{
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "constant_function_type"
},
"named": true,
"value": "function_type"
},
{ {
"type": "ALIAS", "type": "ALIAS",
"content": { "content": {
@ -1059,6 +1106,106 @@
} }
] ]
}, },
"constant_function_type": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "fn"
},
{
"type": "CHOICE",
"members": [
{
"type": "FIELD",
"name": "parameter_types",
"content": {
"type": "ALIAS",
"content": {
"type": "SYMBOL",
"name": "constant_function_parameter_types"
},
"named": true,
"value": "function_parameter_types"
}
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": "->"
},
{
"type": "FIELD",
"name": "return_type",
"content": {
"type": "SYMBOL",
"name": "_constant_type"
}
}
]
},
"constant_function_parameter_types": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": "("
},
{
"type": "CHOICE",
"members": [
{
"type": "SEQ",
"members": [
{
"type": "SYMBOL",
"name": "_constant_type"
},
{
"type": "REPEAT",
"content": {
"type": "SEQ",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "SYMBOL",
"name": "_constant_type"
}
]
}
},
{
"type": "CHOICE",
"members": [
{
"type": "STRING",
"value": ","
},
{
"type": "BLANK"
}
]
}
]
},
{
"type": "BLANK"
}
]
},
{
"type": "STRING",
"value": ")"
}
]
},
"constant_type": { "constant_type": {
"type": "SEQ", "type": "SEQ",
"members": [ "members": [
@ -5900,6 +6047,10 @@
], ],
[ [
"source_file" "source_file"
],
[
"_constant_value",
"_case_clause_guard_unit"
] ]
], ],
"precedences": [], "precedences": [],

16
src/node-types.json generated

@ -1072,6 +1072,10 @@
"type": "bit_string", "type": "bit_string",
"named": true "named": true
}, },
{
"type": "field_access",
"named": true
},
{ {
"type": "float", "type": "float",
"named": true "named": true
@ -1308,6 +1312,10 @@
"multiple": false, "multiple": false,
"required": false, "required": false,
"types": [ "types": [
{
"type": "function_type",
"named": true
},
{ {
"type": "tuple_type", "type": "tuple_type",
"named": true "named": true
@ -1330,10 +1338,18 @@
"type": "bit_string", "type": "bit_string",
"named": true "named": true
}, },
{
"type": "field_access",
"named": true
},
{ {
"type": "float", "type": "float",
"named": true "named": true
}, },
{
"type": "identifier",
"named": true
},
{ {
"type": "integer", "type": "integer",
"named": true "named": true

46720
src/parser.c generated

File diff suppressed because it is too large Load Diff

@ -26,6 +26,9 @@ const a = Cat("Ginny", 1950)
const a = Person(name: "Billy", age: 52) const a = Person(name: "Billy", age: 52)
const a = uri.Uri(host: "github.com") const a = uri.Uri(host: "github.com")
const a: option.Option(String) = option.Some("Hello, World!") const a: option.Option(String) = option.Some("Hello, World!")
const var_alias = b
const int_identity_alias: fn(Int) -> Int = int_identity
const fun_tuple: #(fn(Float) -> String, fn(Int) -> String) = #(float.to_string, int.to_string)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -206,7 +209,41 @@ const a: option.Option(String) = option.Some("Hello, World!")
arguments: (arguments arguments: (arguments
(argument (argument
value: (string value: (string
(quoted_content))))))) (quoted_content))))))
(constant
name: (identifier)
value: (identifier))
(constant
name: (identifier)
type: (function_type
parameter_types: (function_parameter_types
(type
name: (type_identifier)))
return_type: (type
name: (type_identifier)))
value: (identifier))
(constant
name: (identifier)
type: (tuple_type
(function_type
parameter_types: (function_parameter_types
(type
name: (type_identifier)))
return_type: (type
name: (type_identifier)))
(function_type
parameter_types: (function_parameter_types
(type
name: (type_identifier)))
return_type: (type
name: (type_identifier))))
value: (tuple
(field_access
record: (identifier)
field: (label))
(field_access
record: (identifier)
field: (label)))))
================================================================================ ================================================================================
Public constants Public constants

@ -780,6 +780,36 @@ fn try_try_again(x, y) -> Int {
(identifier)) (identifier))
value: (todo))))) value: (todo)))))
================================================================================
Let expressions
================================================================================
let foo: fn(Int) -> Int = fn(x) { x }
let fun_ref = float.to_string
--------------------------------------------------------------------------------
(source_file
(let
pattern: (identifier)
type: (function_type
parameter_types: (function_parameter_types
(type
name: (type_identifier)))
return_type: (type
name: (type_identifier)))
value: (anonymous_function
parameters: (function_parameters
(function_parameter
name: (identifier)))
body: (function_body
(identifier))))
(let
pattern: (identifier)
value: (field_access
record: (identifier)
field: (label))))
================================================================================ ================================================================================
Complex binary expressions Complex binary expressions
================================================================================ ================================================================================