Support some, ok and err wrappers and untyped function inputs
Track the LScript changes since the grammar was first written: - some, ok and err are reserved prefix operators and wrapper patterns; the old |.some/|.ok/|.err forms and postfix/prefix ! are rejected - function literal inputs may omit their type annotation, and tuple components may omit theirs; an empty typed tuple pattern is now just the unit pattern - migrate fixtures, corpus, queries, CST contract and Rust tests Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6e4f9cd65a
commit
61ea7166e3
20 files changed
+36187
-35406
No files matched your search
+105
-1
@@ -152,12 +152,116 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn distinguishes_whole_argument_annotation_from_tuple_component_annotations() {
|
||||
let source = "whole :: @ (left, right): (i32, i32) { left + right }\n\
|
||||
components :: @ (left: i32, right: i32) { left + right }\n\
|
||||
product :: @ {value}: &{value: i32:} { value }\n";
|
||||
let tree = parse(source);
|
||||
assert!(
|
||||
!tree.root_node().has_error(),
|
||||
"{}",
|
||||
tree.root_node().to_sexp()
|
||||
);
|
||||
|
||||
let whole = tree.root_node().named_child(0).unwrap();
|
||||
let whole_function = whole.child_by_field_name("value").unwrap();
|
||||
let whole_input = whole_function.child_by_field_name("parameter").unwrap();
|
||||
assert_eq!(whole_input.kind(), "typed_parameter");
|
||||
assert_eq!(
|
||||
whole_input.child_by_field_name("pattern").unwrap().kind(),
|
||||
"tuple_pattern"
|
||||
);
|
||||
assert_eq!(
|
||||
whole_input.child_by_field_name("type").unwrap().kind(),
|
||||
"tuple_type"
|
||||
);
|
||||
|
||||
let components = tree.root_node().named_child(1).unwrap();
|
||||
let components_function = components.child_by_field_name("value").unwrap();
|
||||
let component_input = components_function
|
||||
.child_by_field_name("parameter")
|
||||
.unwrap();
|
||||
assert_eq!(component_input.kind(), "typed_tuple_pattern");
|
||||
assert_eq!(component_input.named_child_count(), 2);
|
||||
|
||||
let product = tree.root_node().named_child(2).unwrap();
|
||||
let product_function = product.child_by_field_name("value").unwrap();
|
||||
let product_input = product_function.child_by_field_name("parameter").unwrap();
|
||||
assert_eq!(product_input.kind(), "typed_parameter");
|
||||
assert_eq!(
|
||||
product_input.child_by_field_name("pattern").unwrap().kind(),
|
||||
"product_pattern"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exposes_wrappers_and_untyped_inputs() {
|
||||
let source = "present: i32?: some 1\n\
|
||||
double :: @ value { value * 2 }\n\
|
||||
unwrap :: @ result { match result { ok inner => inner; err _ => 0 } }\n";
|
||||
let tree = parse(source);
|
||||
assert!(
|
||||
!tree.root_node().has_error(),
|
||||
"{}",
|
||||
tree.root_node().to_sexp()
|
||||
);
|
||||
|
||||
let present = tree.root_node().named_child(0).unwrap();
|
||||
let wrapped = present.child_by_field_name("value").unwrap();
|
||||
assert_eq!(wrapped.kind(), "unary_expression");
|
||||
assert_eq!(
|
||||
wrapped
|
||||
.child_by_field_name("operator")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"some"
|
||||
);
|
||||
|
||||
let double = tree.root_node().named_child(1).unwrap();
|
||||
let input = double
|
||||
.child_by_field_name("value")
|
||||
.unwrap()
|
||||
.child_by_field_name("parameter")
|
||||
.unwrap();
|
||||
assert_eq!(input.kind(), "typed_parameter");
|
||||
assert!(input.child_by_field_name("type").is_none());
|
||||
|
||||
let unwrap = tree.root_node().named_child(2).unwrap();
|
||||
let function = unwrap.child_by_field_name("value").unwrap();
|
||||
let body = function.child_by_field_name("body").unwrap();
|
||||
let arm = body.named_child(0).unwrap().named_child(1).unwrap();
|
||||
let pattern = arm.child_by_field_name("pattern").unwrap();
|
||||
let wrapper = pattern.named_child(0).unwrap();
|
||||
assert_eq!(wrapper.kind(), "wrapper_pattern");
|
||||
assert_eq!(
|
||||
wrapper
|
||||
.child_by_field_name("wrapper")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"ok"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_removed_wrapper_forms() {
|
||||
for source in [
|
||||
"old: i32?: 1->|.some\n",
|
||||
"old :: @ value: i32 -> i32 ! str { value! }\n",
|
||||
"old :: @ value: str -> i32 ! str { !value }\n",
|
||||
"some := 1\n",
|
||||
] {
|
||||
assert!(parse(source).root_node().has_error(), "accepted {source}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_removed_function_literal_forms() {
|
||||
for source in [
|
||||
"old: i32 -> i32: value@ value\n",
|
||||
"old: i32 -> i32:\n@ value: i32 { value }\n",
|
||||
"old :: @ value\n",
|
||||
"old :: @ (value:i32) { value }\n",
|
||||
"old :: @ (value:i32,) { value }\n",
|
||||
"old :: @ (\nvalue:i32\n) -> i32 { value }\n",
|
||||
|
||||
+27
-7
@@ -43,13 +43,33 @@ Literal leaves are named. Boolean and nil values use `boolean_literal` and
|
||||
`nil_literal`; numeric, string, character, and unit literals retain their
|
||||
specific nodes. `default_expression` is also named.
|
||||
|
||||
`function_literal` takes one input and owns the `body` field. Direct binding
|
||||
appears as `parameter: (typed_parameter)`; tuple destructuring appears as
|
||||
`parameter: (typed_tuple_pattern)`. A `typed_tuple_pattern` contains zero or at
|
||||
least two `typed_tuple_component` nodes. These bind components of one tuple
|
||||
input, not separate function arguments. `()` matches unit; singleton tuple
|
||||
patterns are invalid. Typed bindings expose `pattern` and `type`; a header may
|
||||
also expose `effect` (`->` or `=>`) and `result`.
|
||||
`some`, `ok`, and `err` construct optional and result values. They are prefix
|
||||
operators, so `some value` and `ok {x->f}` appear as `unary_expression` nodes
|
||||
whose `operator` is the keyword. They bind like `-` and `~`, so `ok x->f`
|
||||
wraps `x` and then pipes the result into `f`, while `ok {x->f}` wraps the
|
||||
pipeline. The older `|.some`/`|.ok`/`|.err`
|
||||
constructors, postfix `value!`, and prefix `!error` are no longer accepted.
|
||||
|
||||
`function_literal` takes one input and owns the `body` field. A pattern with
|
||||
one annotation for the whole input, such as `@ value: i32` or
|
||||
`@ (left, right): (i32, i32)`, appears as `parameter: (typed_parameter)`.
|
||||
The annotation is optional: an input whose type comes from the expected
|
||||
function type, such as `@ value` or `@ (left, right)`, is also a
|
||||
`typed_parameter` without a `type` field. Component-annotated tuple
|
||||
destructuring, such as `@ (left: i32, right)`, appears as
|
||||
`parameter: (typed_tuple_pattern)`. A `typed_tuple_pattern` contains at least
|
||||
two `typed_tuple_component` nodes, each with an optional `type`. These bind
|
||||
components of one tuple input, not separate function arguments. `()` matches
|
||||
unit and is a `typed_parameter` over a `unit_pattern`; singleton tuple patterns
|
||||
are invalid. Bindings expose `pattern` and, when annotated, `type`; a header
|
||||
may also expose `effect` (`->` or `=>`) and `result`.
|
||||
|
||||
## Patterns
|
||||
|
||||
`wrapper_pattern` matches `some`, `ok`, or `err` applied to one pattern atom.
|
||||
It exposes `wrapper` (the keyword) and `value` (the inner pattern). `nil` is
|
||||
still a `nil_literal` pattern. Sum patterns retain `sum_pattern` with a
|
||||
`variant` field.
|
||||
|
||||
## Types
|
||||
|
||||
|
||||
+19
-15
@@ -19,8 +19,8 @@ const PREC = {
|
||||
|
||||
const RESERVED_WORDS = [
|
||||
"and", "as", "bits", "break", "continue", "default", "distinct", "else",
|
||||
"false", "for", "if", "in", "loop", "match", "nil", "not", "or", "pub",
|
||||
"return", "true", "use",
|
||||
"err", "false", "for", "if", "in", "loop", "match", "nil", "not", "ok", "or",
|
||||
"pub", "return", "some", "true", "use",
|
||||
"bit", "chr", "f32", "f64", "i8", "i16", "i32", "i64", "nvr", "str",
|
||||
"u8", "u16", "u32", "u64",
|
||||
];
|
||||
@@ -55,6 +55,7 @@ module.exports = grammar({
|
||||
],
|
||||
|
||||
conflicts: $ => [
|
||||
[$.binding_pattern, $.pattern_atom],
|
||||
[$.product_pattern_field, $.primary_expression],
|
||||
[$.pattern_atom, $.literal],
|
||||
[$.pattern_atom, $.primary_expression],
|
||||
@@ -312,18 +313,16 @@ module.exports = grammar({
|
||||
prec(1, seq("@", field("body", $.block))),
|
||||
),
|
||||
|
||||
typed_tuple_pattern: $ => seq("(", optional(listBodyAtLeastTwo($, $.typed_tuple_component)), ")"),
|
||||
typed_tuple_pattern: $ => seq("(", listBodyAtLeastTwo($, $.typed_tuple_component), ")"),
|
||||
|
||||
typed_parameter: $ => seq(
|
||||
typed_parameter: $ => prec.dynamic(1, seq(
|
||||
field("pattern", $.binding_pattern),
|
||||
":",
|
||||
field("type", $._result_type),
|
||||
),
|
||||
optional(seq(":", field("type", $._result_type))),
|
||||
)),
|
||||
|
||||
typed_tuple_component: $ => seq(
|
||||
field("pattern", $.binding_pattern),
|
||||
":",
|
||||
field("type", $.type_expression),
|
||||
optional(seq(":", field("type", $.type_expression))),
|
||||
),
|
||||
|
||||
return_expression: $ => prec.right(seq("return", optional($.expression))),
|
||||
@@ -385,6 +384,7 @@ module.exports = grammar({
|
||||
$.character_literal,
|
||||
$.boolean_literal,
|
||||
$.nil_literal,
|
||||
$.wrapper_pattern,
|
||||
$.sum_pattern,
|
||||
$.bits_pattern,
|
||||
$.unit_pattern,
|
||||
@@ -407,6 +407,11 @@ module.exports = grammar({
|
||||
optional($.pattern_atom),
|
||||
),
|
||||
|
||||
wrapper_pattern: $ => seq(
|
||||
field("wrapper", choice("some", "ok", "err")),
|
||||
field("value", $.pattern_atom),
|
||||
),
|
||||
|
||||
bits_pattern: $ => seq(
|
||||
"|",
|
||||
optional($.type_name),
|
||||
@@ -430,27 +435,27 @@ module.exports = grammar({
|
||||
seq(
|
||||
$._direct_pipeline_continuation,
|
||||
field("callable", $.pipeline_callable),
|
||||
repeat(choice("?", "!")),
|
||||
repeat("?"),
|
||||
),
|
||||
seq(
|
||||
$._aggregate_pipeline_continuation,
|
||||
field("callable", $.aggregate_pipeline_callable),
|
||||
field("arguments", $.aggregate_tail),
|
||||
repeat(choice("?", "!")),
|
||||
repeat("?"),
|
||||
),
|
||||
),
|
||||
|
||||
direct_pipeline_stage: $ => seq(
|
||||
"->",
|
||||
field("callable", $.pipeline_callable),
|
||||
repeat(choice("?", "!")),
|
||||
repeat("?"),
|
||||
),
|
||||
|
||||
aggregate_pipeline_stage: $ => seq(
|
||||
"|>",
|
||||
field("callable", $.aggregate_pipeline_callable),
|
||||
field("arguments", $.aggregate_tail),
|
||||
repeat(choice("?", "!")),
|
||||
repeat("?"),
|
||||
),
|
||||
|
||||
aggregate_tail: $ => choice(
|
||||
@@ -524,7 +529,7 @@ module.exports = grammar({
|
||||
),
|
||||
|
||||
unary_expression: $ => prec.right(PREC.PREFIX, seq(
|
||||
field("operator", choice("not", "!", "-", "~")),
|
||||
field("operator", choice("not", "-", "~", "some", "ok", "err")),
|
||||
field("operand", $._prefix_expression),
|
||||
)),
|
||||
|
||||
@@ -534,7 +539,6 @@ module.exports = grammar({
|
||||
seq(".", field("member", $.identifier)),
|
||||
seq("[", field("index", $.expression), "]"),
|
||||
"?",
|
||||
"!",
|
||||
))),
|
||||
)),
|
||||
|
||||
|
||||
@@ -6,15 +6,18 @@
|
||||
"continue"
|
||||
"distinct"
|
||||
"else"
|
||||
"err"
|
||||
"for"
|
||||
"if"
|
||||
"in"
|
||||
"loop"
|
||||
"match"
|
||||
"not"
|
||||
"ok"
|
||||
"or"
|
||||
"pub"
|
||||
"return"
|
||||
"some"
|
||||
"use"
|
||||
] @keyword
|
||||
|
||||
@@ -41,6 +44,6 @@
|
||||
[
|
||||
"=" "+=" "-=" "*=" "/=" "%=" "&=" "^=" "|="
|
||||
"==" "<" "<=" ">" ">="
|
||||
"+" "-" "*" "/" "%" "&" "|" "^" "~" "!"
|
||||
"+" "-" "*" "/" "%" "&" "|" "^" "~"
|
||||
"->" "=>" "|>" "..<" "..=" "@"
|
||||
] @operator
|
||||
+215
-171
@@ -1742,111 +1742,103 @@
|
||||
"value": "("
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_newline"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "typed_tuple_component"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_newline"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "typed_tuple_component"
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ","
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_newline"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_newlines"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "typed_tuple_component"
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ","
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_newline"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_newlines"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "typed_tuple_component"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ","
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_newline"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_newline"
|
||||
}
|
||||
"type": "SYMBOL",
|
||||
"name": "_newlines"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
"type": "SYMBOL",
|
||||
"name": "typed_tuple_component"
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ","
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_newline"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "_newlines"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "typed_tuple_component"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ","
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_newline"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -1857,29 +1849,46 @@
|
||||
]
|
||||
},
|
||||
"typed_parameter": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "pattern",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "binding_pattern"
|
||||
"type": "PREC_DYNAMIC",
|
||||
"value": 1,
|
||||
"content": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "pattern",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "binding_pattern"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ":"
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "type",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_result_type"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ":"
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "type",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "_result_type"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"typed_tuple_component": {
|
||||
"type": "SEQ",
|
||||
@@ -1893,16 +1902,29 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ":"
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "type",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "type_expression"
|
||||
}
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": ":"
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "type",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "type_expression"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -2416,6 +2438,10 @@
|
||||
"type": "SYMBOL",
|
||||
"name": "nil_literal"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "wrapper_pattern"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "sum_pattern"
|
||||
@@ -2742,6 +2768,40 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"wrapper_pattern": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "wrapper",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "some"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "ok"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "err"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "FIELD",
|
||||
"name": "value",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "pattern_atom"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"bits_pattern": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
@@ -3115,17 +3175,8 @@
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "?"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "!"
|
||||
}
|
||||
]
|
||||
"type": "STRING",
|
||||
"value": "?"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -3156,17 +3207,8 @@
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "?"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "!"
|
||||
}
|
||||
]
|
||||
"type": "STRING",
|
||||
"value": "?"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -3191,17 +3233,8 @@
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "?"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "!"
|
||||
}
|
||||
]
|
||||
"type": "STRING",
|
||||
"value": "?"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -3232,17 +3265,8 @@
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "?"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "!"
|
||||
}
|
||||
]
|
||||
"type": "STRING",
|
||||
"value": "?"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -4293,10 +4317,6 @@
|
||||
"type": "STRING",
|
||||
"value": "not"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "!"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "-"
|
||||
@@ -4304,6 +4324,18 @@
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "~"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "some"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "ok"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "err"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -4382,10 +4414,6 @@
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "?"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "!"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5331,6 +5359,10 @@
|
||||
}
|
||||
],
|
||||
"conflicts": [
|
||||
[
|
||||
"binding_pattern",
|
||||
"pattern_atom"
|
||||
],
|
||||
[
|
||||
"product_pattern_field",
|
||||
"primary_expression"
|
||||
@@ -5519,6 +5551,10 @@
|
||||
"type": "STRING",
|
||||
"value": "else"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "err"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "false"
|
||||
@@ -5551,6 +5587,10 @@
|
||||
"type": "STRING",
|
||||
"value": "not"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "ok"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "or"
|
||||
@@ -5563,6 +5603,10 @@
|
||||
"type": "STRING",
|
||||
"value": "return"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "some"
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
"value": "true"
|
||||
|
||||
+65
-11
@@ -156,6 +156,10 @@
|
||||
{
|
||||
"type": "unit_pattern",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "wrapper_pattern",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -1622,10 +1626,6 @@
|
||||
"multiple": true,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "!",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": ".",
|
||||
"named": false
|
||||
@@ -2247,7 +2247,7 @@
|
||||
},
|
||||
"type": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"required": false,
|
||||
"types": [
|
||||
{
|
||||
"type": "array_type",
|
||||
@@ -2321,7 +2321,7 @@
|
||||
},
|
||||
"type": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"required": false,
|
||||
"types": [
|
||||
{
|
||||
"type": "type_expression",
|
||||
@@ -2337,7 +2337,7 @@
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": true,
|
||||
"required": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "typed_tuple_component",
|
||||
@@ -2372,18 +2372,26 @@
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "!",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "-",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "err",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "not",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "ok",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "some",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "~",
|
||||
"named": false
|
||||
@@ -2442,6 +2450,40 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "wrapper_pattern",
|
||||
"named": true,
|
||||
"fields": {
|
||||
"value": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "pattern_atom",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"wrapper": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "err",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "ok",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "some",
|
||||
"named": false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "!",
|
||||
"named": false
|
||||
@@ -2655,6 +2697,10 @@
|
||||
"type": "else",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "err",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "f32",
|
||||
"named": false
|
||||
@@ -2727,6 +2773,10 @@
|
||||
"type": "nvr",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "ok",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "or",
|
||||
"named": false
|
||||
@@ -2739,6 +2789,10 @@
|
||||
"type": "return",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "some",
|
||||
"named": false
|
||||
},
|
||||
{
|
||||
"type": "str",
|
||||
"named": false
|
||||
|
||||
+35492
-35188
File diff suppressed because it is too large.
Load diff
+207
-7
@@ -36,7 +36,7 @@ Point :: &{
|
||||
y: i32 = 0
|
||||
}
|
||||
point := &Point.{ x: 1; y = 2 }
|
||||
maybe: []{i32?}: [nil, 1->|.some]
|
||||
maybe: []{i32?}: [nil, some 1]
|
||||
|
||||
---
|
||||
|
||||
@@ -75,13 +75,9 @@ maybe: []{i32?}: [nil, 1->|.some]
|
||||
(collection_entry
|
||||
(nil_literal))
|
||||
(collection_entry
|
||||
(pipeline_expression
|
||||
(unary_expression
|
||||
(signed_numeric_literal
|
||||
(integer_literal))
|
||||
(direct_pipeline_stage
|
||||
(pipeline_callable
|
||||
(sum_constructor
|
||||
(identifier)))))))))
|
||||
(integer_literal)))))))
|
||||
|
||||
==================
|
||||
Control flow and patterns
|
||||
@@ -157,6 +153,7 @@ ready :: first
|
||||
(binary_expression
|
||||
(identifier)
|
||||
(identifier))))
|
||||
|
||||
==================
|
||||
Compact range after an integer
|
||||
==================
|
||||
@@ -233,3 +230,206 @@ unit :: @ { () }
|
||||
(function_literal
|
||||
(block
|
||||
(unit_literal)))))
|
||||
|
||||
==================
|
||||
Whole-argument function patterns
|
||||
==================
|
||||
|
||||
pair :: @ (left, right): (i32, i32) { left + right }
|
||||
product :: @ {value}: &{value: i32:} { value }
|
||||
callback :: @ operation: {i32 -> i32} { 1->operation }
|
||||
unit :: @ () -> i32 { 42 }
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(declaration
|
||||
(identifier)
|
||||
(function_literal
|
||||
(typed_parameter
|
||||
(tuple_pattern
|
||||
(pattern
|
||||
(identifier))
|
||||
(pattern
|
||||
(identifier)))
|
||||
(tuple_type
|
||||
(primitive_type)
|
||||
(primitive_type)))
|
||||
(block
|
||||
(binary_expression
|
||||
(identifier)
|
||||
(identifier)))))
|
||||
(declaration
|
||||
(identifier)
|
||||
(function_literal
|
||||
(typed_parameter
|
||||
(product_pattern
|
||||
(product_pattern_field
|
||||
(identifier)))
|
||||
(product_type
|
||||
(product_field
|
||||
(identifier)
|
||||
(primitive_type))))
|
||||
(block
|
||||
(identifier))))
|
||||
(declaration
|
||||
(identifier)
|
||||
(function_literal
|
||||
(typed_parameter
|
||||
(identifier)
|
||||
(grouped_type
|
||||
(function_type
|
||||
(primitive_type)
|
||||
(primitive_type))))
|
||||
(block
|
||||
(pipeline_expression
|
||||
(signed_numeric_literal
|
||||
(integer_literal))
|
||||
(direct_pipeline_stage
|
||||
(pipeline_callable
|
||||
(identifier)))))))
|
||||
(declaration
|
||||
(identifier)
|
||||
(function_literal
|
||||
(typed_parameter
|
||||
(unit_pattern))
|
||||
(primitive_type)
|
||||
(block
|
||||
(signed_numeric_literal
|
||||
(integer_literal))))))
|
||||
|
||||
==================
|
||||
Optional and result wrappers
|
||||
==================
|
||||
|
||||
wrap :: @ value: i32 -> i32 ! str { ok value }
|
||||
first :: @ items: []i32 -> i32? {
|
||||
match items {
|
||||
[] => nil
|
||||
[head, ...rest] => some head
|
||||
}
|
||||
}
|
||||
unwrap :: @ result: i32 ! str -> i32 {
|
||||
match result {
|
||||
ok value => value
|
||||
err _ => 0
|
||||
}
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(declaration
|
||||
(identifier)
|
||||
(function_literal
|
||||
(typed_parameter
|
||||
(identifier)
|
||||
(primitive_type))
|
||||
(result_type
|
||||
(primitive_type)
|
||||
(primitive_type))
|
||||
(block
|
||||
(unary_expression
|
||||
(identifier)))))
|
||||
(declaration
|
||||
(identifier)
|
||||
(function_literal
|
||||
(typed_parameter
|
||||
(identifier)
|
||||
(array_type
|
||||
(primitive_type)))
|
||||
(optional_type
|
||||
(primitive_type))
|
||||
(block
|
||||
(match_expression
|
||||
(identifier)
|
||||
(match_arm
|
||||
(pattern
|
||||
(array_pattern))
|
||||
(nil_literal))
|
||||
(match_arm
|
||||
(pattern
|
||||
(array_pattern
|
||||
(array_pattern_entry
|
||||
(pattern
|
||||
(identifier)))
|
||||
(array_pattern_entry
|
||||
(identifier))))
|
||||
(unary_expression
|
||||
(identifier)))))))
|
||||
(declaration
|
||||
(identifier)
|
||||
(function_literal
|
||||
(typed_parameter
|
||||
(identifier)
|
||||
(result_type
|
||||
(primitive_type)
|
||||
(primitive_type)))
|
||||
(primitive_type)
|
||||
(block
|
||||
(match_expression
|
||||
(identifier)
|
||||
(match_arm
|
||||
(pattern
|
||||
(wrapper_pattern
|
||||
(identifier)))
|
||||
(identifier))
|
||||
(match_arm
|
||||
(pattern
|
||||
(wrapper_pattern))
|
||||
(signed_numeric_literal
|
||||
(integer_literal))))))))
|
||||
|
||||
==================
|
||||
Untyped function inputs
|
||||
==================
|
||||
|
||||
double :: @ value { value * 2 }
|
||||
sum: (i32, i32) -> i32: @ (left, right) { left + right }
|
||||
mixed :: @ (left: i32, right) -> i32 { left + right }
|
||||
|
||||
---
|
||||
|
||||
(source_file
|
||||
(declaration
|
||||
(identifier)
|
||||
(function_literal
|
||||
(typed_parameter
|
||||
(identifier))
|
||||
(block
|
||||
(binary_expression
|
||||
(identifier)
|
||||
(signed_numeric_literal
|
||||
(integer_literal))))))
|
||||
(declaration
|
||||
(identifier)
|
||||
(function_type
|
||||
(tuple_type
|
||||
(primitive_type)
|
||||
(primitive_type))
|
||||
(primitive_type))
|
||||
(function_literal
|
||||
(typed_parameter
|
||||
(tuple_pattern
|
||||
(pattern
|
||||
(identifier))
|
||||
(pattern
|
||||
(identifier))))
|
||||
(block
|
||||
(binary_expression
|
||||
(identifier)
|
||||
(identifier)))))
|
||||
(declaration
|
||||
(identifier)
|
||||
(function_literal
|
||||
(typed_tuple_pattern
|
||||
(typed_tuple_component
|
||||
(identifier)
|
||||
(primitive_type))
|
||||
(typed_tuple_component
|
||||
(identifier)))
|
||||
(primitive_type)
|
||||
(block
|
||||
(binary_expression
|
||||
(identifier)
|
||||
(identifier))))))
|
||||
@@ -1 +0,0 @@
|
||||
identity :: @ value { value }
|
||||
+1
@@ -0,0 +1 @@
|
||||
value :: @ x: i32 -> i32 ! str { x! }
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
value :: @ x: str -> i32 ! str { !x }
|
||||
@@ -0,0 +1 @@
|
||||
ok :: @ value { value }
|
||||
@@ -0,0 +1 @@
|
||||
some := 1
|
||||
@@ -0,0 +1 @@
|
||||
value: i32?: 1->|.some
|
||||
@@ -0,0 +1 @@
|
||||
value :: @ x: i32? { match x { |.some y => y; nil => 0 } }
|
||||
Vendored
+1
-1
@@ -7,7 +7,7 @@ more_codes := [...codes, 'failed' => 500]
|
||||
empty_numbers: []i32: []
|
||||
empty_codes: [str]i32: []
|
||||
optional_numbers: []i32?: nil
|
||||
optional_elements: []{i32?}: [nil, 1->|.some]
|
||||
optional_elements: []{i32?}: [nil, some 1]
|
||||
|
||||
Options :: &{
|
||||
name: str: 'default'
|
||||
|
||||
Vendored
+1
-1
@@ -11,7 +11,7 @@ choose_block: (bit, i32, i32) -> i32: @ (condition: bit, when_true: i32, when_fa
|
||||
first_positive: []i32 -> i32?: @ values: []i32 {
|
||||
for value in values {
|
||||
if value > 0 {
|
||||
return value->|.some
|
||||
return some value
|
||||
}
|
||||
}
|
||||
nil
|
||||
|
||||
Vendored
+2
-2
@@ -15,9 +15,9 @@ commented := 'value' # an inline comment preserves continuation
|
||||
computed := 1 + 2
|
||||
->to_str
|
||||
|
||||
fallible: i32 -> i32 ! Error: @ value: i32 { value! }
|
||||
fallible: i32 -> i32 ! Error: @ value: i32 { ok value }
|
||||
|
||||
propagate: i32 -> i32 ! Error: @ value: i32 {
|
||||
result := {value->fallible}?
|
||||
result!
|
||||
ok result
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
use math.{pi, sqrt}
|
||||
use math as m
|
||||
use random.{Pcg32, pcg32, draw_u32}
|
||||
use time.{Duration, TimeError, duration_neg}
|
||||
use time as t
|
||||
|
||||
circle: f64: pi
|
||||
root: f64: 4.0->sqrt
|
||||
# Host overloads are selected by the operand, so the literal is typed first.
|
||||
nine: f32: 9.0
|
||||
qualified_root: f32: nine->m.sqrt
|
||||
qualified_pi: f32: m.pi
|
||||
|
||||
seed: u64: 42
|
||||
generator: Pcg32: seed->pcg32
|
||||
draw: u32: generator->draw_u32
|
||||
|
||||
negate: Duration => Duration ! TimeError: duration_neg
|
||||
qualified_negate: t.Duration => t.Duration ! t.TimeError: t.duration_neg
|
||||
Vendored
+24
@@ -0,0 +1,24 @@
|
||||
present: i32?: some 1
|
||||
absent: i32?: nil
|
||||
success: i32 ! str: ok 1
|
||||
failure: i32 ! str: err 'failed'
|
||||
piped: i32?: some 4->double
|
||||
grouped: i32?: some {4->double}
|
||||
|
||||
double :: @ value { value * 2 }
|
||||
describe :: @ (label: str, count) -> str { label }
|
||||
|
||||
unwrap_or: i32? -> i32: @ value {
|
||||
match value {
|
||||
some inner => inner
|
||||
nil => 0
|
||||
}
|
||||
}
|
||||
|
||||
handle: i32 ! str -> i32: @ result {
|
||||
match result {
|
||||
ok value if value > 0 => value
|
||||
ok _ => 0
|
||||
err message => message->length
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user