Support some, ok and err wrappers and untyped function inputs

This commit is contained in:
paul committed 2026-10-18 18:18:31 -04:00
1 parent 6e4f9cd65a
commit 79533e9537
20 files changed
+36187 -35406

No files matched your search

+105 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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), "]"),
"?",
"!",
))),
)),
+4 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+207 -7
View File
@@ -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
View File
@@ -1 +0,0 @@
identity :: @ value { value }
+1
View File
@@ -0,0 +1 @@
value :: @ x: i32 -> i32 ! str { x! }
+1
View File
@@ -0,0 +1 @@
value :: @ x: str -> i32 ! str { !x }
+1
View File
@@ -0,0 +1 @@
ok :: @ value { value }
+1
View File
@@ -0,0 +1 @@
some := 1
+1
View File
@@ -0,0 +1 @@
value: i32?: 1->|.some
+1
View File
@@ -0,0 +1 @@
value :: @ x: i32? { match x { |.some y => y; nil => 0 } }
+1 -1
View File
@@ -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'
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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
+24
View File
@@ -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
}
}