add generics
This commit is contained in:
1 parent
79533e9537
commit
2204d58102
22 files changed
+47358
-37579
No files matched your search
+270
-13
@@ -196,10 +196,10 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exposes_wrappers_and_untyped_inputs() {
|
||||
let source = "present: i32?: some 1\n\
|
||||
fn exposes_sum_spelled_optionals_and_untyped_inputs() {
|
||||
let source = "present: i32?: 1->|.some\n\
|
||||
double :: @ value { value * 2 }\n\
|
||||
unwrap :: @ result { match result { ok inner => inner; err _ => 0 } }\n";
|
||||
unwrap :: @ result { match result { |.ok inner => inner; |.err _ => 0 } }\n";
|
||||
let tree = parse(source);
|
||||
assert!(
|
||||
!tree.root_node().has_error(),
|
||||
@@ -209,10 +209,22 @@ mod tests {
|
||||
|
||||
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.kind(), "pipeline_expression");
|
||||
assert_eq!(
|
||||
wrapped
|
||||
.child_by_field_name("operator")
|
||||
wrapped.child_by_field_name("input").unwrap().kind(),
|
||||
"signed_numeric_literal"
|
||||
);
|
||||
let stage = wrapped.named_child(1).unwrap();
|
||||
assert_eq!(stage.kind(), "direct_pipeline_stage");
|
||||
let constructor = stage
|
||||
.child_by_field_name("callable")
|
||||
.unwrap()
|
||||
.named_child(0)
|
||||
.unwrap();
|
||||
assert_eq!(constructor.kind(), "sum_constructor");
|
||||
assert_eq!(
|
||||
constructor
|
||||
.child_by_field_name("variant")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
@@ -233,25 +245,270 @@ mod tests {
|
||||
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");
|
||||
let variant = pattern.named_child(0).unwrap();
|
||||
assert_eq!(variant.kind(), "sum_pattern");
|
||||
assert_eq!(
|
||||
wrapper
|
||||
.child_by_field_name("wrapper")
|
||||
variant
|
||||
.child_by_field_name("variant")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"ok"
|
||||
);
|
||||
assert_eq!(
|
||||
variant.child_by_field_name("payload").unwrap().kind(),
|
||||
"identifier"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_removed_wrapper_forms() {
|
||||
fn binds_same_line_stages_tighter_than_operators() {
|
||||
let source = "mixed :: -3->add_ten + 2 * 3->double - {1 + 1}->double\n";
|
||||
let tree = parse(source);
|
||||
assert!(
|
||||
!tree.root_node().has_error(),
|
||||
"{}",
|
||||
tree.root_node().to_sexp()
|
||||
);
|
||||
|
||||
let declaration = tree.root_node().named_child(0).unwrap();
|
||||
let subtraction = declaration.child_by_field_name("value").unwrap();
|
||||
assert_eq!(subtraction.kind(), "binary_expression");
|
||||
assert_eq!(
|
||||
subtraction
|
||||
.child_by_field_name("operator")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"-"
|
||||
);
|
||||
|
||||
let addition = subtraction.child_by_field_name("left").unwrap();
|
||||
assert_eq!(addition.kind(), "binary_expression");
|
||||
let negation = addition.child_by_field_name("left").unwrap();
|
||||
assert_eq!(negation.kind(), "unary_expression");
|
||||
let negated = negation.child_by_field_name("operand").unwrap();
|
||||
assert_eq!(negated.kind(), "pipeline_expression");
|
||||
assert_eq!(
|
||||
negated
|
||||
.child_by_field_name("input")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"3"
|
||||
);
|
||||
|
||||
let product = addition.child_by_field_name("right").unwrap();
|
||||
assert_eq!(product.kind(), "binary_expression");
|
||||
assert_eq!(
|
||||
product.child_by_field_name("right").unwrap().kind(),
|
||||
"pipeline_expression"
|
||||
);
|
||||
|
||||
let grouped = subtraction.child_by_field_name("right").unwrap();
|
||||
assert_eq!(grouped.kind(), "pipeline_expression");
|
||||
assert_eq!(
|
||||
grouped.child_by_field_name("input").unwrap().kind(),
|
||||
"block"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn applies_continuation_stages_to_the_whole_preceding_expression() {
|
||||
let source = "flat := value->first\n->second\nwhole := a + b->f\n->g\n";
|
||||
let tree = parse(source);
|
||||
assert!(
|
||||
!tree.root_node().has_error(),
|
||||
"{}",
|
||||
tree.root_node().to_sexp()
|
||||
);
|
||||
|
||||
let flat = tree
|
||||
.root_node()
|
||||
.named_child(0)
|
||||
.unwrap()
|
||||
.child_by_field_name("value")
|
||||
.unwrap();
|
||||
assert_eq!(flat.kind(), "pipeline_expression");
|
||||
assert_eq!(
|
||||
flat.child_by_field_name("input").unwrap().kind(),
|
||||
"identifier"
|
||||
);
|
||||
assert_eq!(flat.named_child(1).unwrap().kind(), "direct_pipeline_stage");
|
||||
assert_eq!(
|
||||
flat.named_child(2).unwrap().kind(),
|
||||
"continuation_pipeline_stage"
|
||||
);
|
||||
assert_eq!(flat.named_child_count(), 3);
|
||||
|
||||
let whole = tree
|
||||
.root_node()
|
||||
.named_child(1)
|
||||
.unwrap()
|
||||
.child_by_field_name("value")
|
||||
.unwrap();
|
||||
assert_eq!(whole.kind(), "pipeline_expression");
|
||||
let head = whole.child_by_field_name("input").unwrap();
|
||||
assert_eq!(head.kind(), "binary_expression");
|
||||
assert_eq!(
|
||||
head.child_by_field_name("right").unwrap().kind(),
|
||||
"pipeline_expression"
|
||||
);
|
||||
assert_eq!(
|
||||
whole.named_child(1).unwrap().kind(),
|
||||
"continuation_pipeline_stage"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exposes_generic_binders_constraints_and_output_types() {
|
||||
let source = "Show :: <>{ to_str: str; ...Display }\n\
|
||||
pick: <T: Show> (T, T) -> T: @ (first, second): (T, T) { first }\n\
|
||||
Card :: &{ label: Output<make_label: Show>: }\n";
|
||||
let tree = parse(source);
|
||||
assert!(
|
||||
!tree.root_node().has_error(),
|
||||
"{}",
|
||||
tree.root_node().to_sexp()
|
||||
);
|
||||
|
||||
let show = tree.root_node().named_child(0).unwrap();
|
||||
let definition = show.child_by_field_name("value").unwrap();
|
||||
assert_eq!(definition.kind(), "type_definition");
|
||||
let constraint = definition.named_child(0).unwrap();
|
||||
assert_eq!(constraint.kind(), "constraint_body");
|
||||
let entry = constraint.named_child(0).unwrap();
|
||||
assert_eq!(entry.kind(), "constraint_entry");
|
||||
assert_eq!(
|
||||
entry
|
||||
.child_by_field_name("name")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"to_str"
|
||||
);
|
||||
assert_eq!(
|
||||
entry.child_by_field_name("output").unwrap().kind(),
|
||||
"primitive_type"
|
||||
);
|
||||
let spread = constraint.named_child(1).unwrap();
|
||||
assert_eq!(spread.kind(), "constraint_spread");
|
||||
assert_eq!(
|
||||
spread
|
||||
.child_by_field_name("constraint")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"Display"
|
||||
);
|
||||
|
||||
let pick = tree.root_node().named_child(1).unwrap();
|
||||
let binder = pick.child_by_field_name("binder").unwrap();
|
||||
assert_eq!(binder.kind(), "binder");
|
||||
let parameter = binder.named_child(0).unwrap();
|
||||
assert_eq!(parameter.kind(), "binder_entry");
|
||||
assert_eq!(
|
||||
parameter
|
||||
.child_by_field_name("type")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"T"
|
||||
);
|
||||
assert_eq!(
|
||||
parameter
|
||||
.child_by_field_name("constraint")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"Show"
|
||||
);
|
||||
assert_eq!(
|
||||
pick.child_by_field_name("type").unwrap().kind(),
|
||||
"function_type"
|
||||
);
|
||||
assert_eq!(
|
||||
pick.child_by_field_name("value").unwrap().kind(),
|
||||
"function_literal"
|
||||
);
|
||||
|
||||
let card = tree.root_node().named_child(2).unwrap();
|
||||
let field = card
|
||||
.child_by_field_name("value")
|
||||
.unwrap()
|
||||
.named_child(0)
|
||||
.unwrap()
|
||||
.named_child(0)
|
||||
.unwrap();
|
||||
assert_eq!(field.kind(), "product_field");
|
||||
let output = field.child_by_field_name("type").unwrap();
|
||||
assert_eq!(output.kind(), "output_type");
|
||||
assert_eq!(
|
||||
output
|
||||
.child_by_field_name("function")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"make_label"
|
||||
);
|
||||
assert_eq!(
|
||||
output
|
||||
.child_by_field_name("output")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"Show"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn exposes_import_filters() {
|
||||
let source = "use math.{sqrt for f64, pi}\nuse .shapes.area for Circle\npub { area for Circle; sqrt }\n";
|
||||
let tree = parse(source);
|
||||
assert!(
|
||||
!tree.root_node().has_error(),
|
||||
"{}",
|
||||
tree.root_node().to_sexp()
|
||||
);
|
||||
|
||||
let group = tree.root_node().named_child(0).unwrap();
|
||||
assert_eq!(group.kind(), "use_declaration");
|
||||
let member = group.named_child(1).unwrap();
|
||||
assert_eq!(member.kind(), "import_member");
|
||||
let filter = member.named_child(1).unwrap();
|
||||
assert_eq!(filter.kind(), "import_filter");
|
||||
assert_eq!(
|
||||
filter.child_by_field_name("type").unwrap().kind(),
|
||||
"primitive_type"
|
||||
);
|
||||
assert_eq!(group.named_child(2).unwrap().named_child_count(), 1);
|
||||
|
||||
let single = tree.root_node().named_child(1).unwrap();
|
||||
assert_eq!(single.named_child(1).unwrap().kind(), "import_filter");
|
||||
|
||||
let publication = tree.root_node().named_child(2).unwrap();
|
||||
assert_eq!(publication.kind(), "pub_declaration");
|
||||
let filtered = publication.named_child(0).unwrap();
|
||||
assert_eq!(filtered.kind(), "pub_entry");
|
||||
assert_eq!(
|
||||
filtered
|
||||
.child_by_field_name("name")
|
||||
.unwrap()
|
||||
.utf8_text(source.as_bytes())
|
||||
.unwrap(),
|
||||
"area"
|
||||
);
|
||||
assert_eq!(filtered.named_child(1).unwrap().kind(), "import_filter");
|
||||
assert_eq!(publication.named_child(1).unwrap().named_child_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_removed_wrapper_forms_and_reserved_words() {
|
||||
for source in [
|
||||
"old: i32?: 1->|.some\n",
|
||||
"present: i32?: some 1\n",
|
||||
"old :: @ value: i32 -> i32 ! str { value! }\n",
|
||||
"old :: @ value: str -> i32 ! str { !value }\n",
|
||||
"some := 1\n",
|
||||
"context := 1\n",
|
||||
] {
|
||||
assert!(parse(source).root_node().has_error(), "accepted {source}");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user