diff --git a/crates/aiken-lang/src/ast.rs b/crates/aiken-lang/src/ast.rs index c757eb7a..098b80f2 100644 --- a/crates/aiken-lang/src/ast.rs +++ b/crates/aiken-lang/src/ast.rs @@ -801,7 +801,7 @@ impl Pattern { #[derive(Debug, Clone, PartialEq, Eq, Copy)] pub enum AssignmentKind { Let, - Assert, + Expect, } impl AssignmentKind { @@ -809,8 +809,15 @@ impl AssignmentKind { matches!(self, AssignmentKind::Let) } - pub fn is_assert(&self) -> bool { - matches!(self, AssignmentKind::Assert) + pub fn is_expect(&self) -> bool { + matches!(self, AssignmentKind::Expect) + } + + pub fn location_offset(&self) -> usize { + match self { + AssignmentKind::Let => 3, + AssignmentKind::Expect => 6, + } } } diff --git a/crates/aiken-lang/src/format.rs b/crates/aiken-lang/src/format.rs index 5a411b94..1fe00e8f 100644 --- a/crates/aiken-lang/src/format.rs +++ b/crates/aiken-lang/src/format.rs @@ -606,7 +606,7 @@ impl<'comments> Formatter<'comments> { let keyword = match kind { Some(AssignmentKind::Let) => "let ", - Some(AssignmentKind::Assert) => "assert ", + Some(AssignmentKind::Expect) => "expect ", None => "try ", }; diff --git a/crates/aiken-lang/src/parser.rs b/crates/aiken-lang/src/parser.rs index 383257cb..c9944a15 100644 --- a/crates/aiken-lang/src/parser.rs +++ b/crates/aiken-lang/src/parser.rs @@ -1028,7 +1028,7 @@ pub fn expr_parser( }, ); - let assert_parser = just(Token::Assert) + let expect_parser = just(Token::Expect) .ignore_then(pattern_parser()) .then(just(Token::Colon).ignore_then(type_parser()).or_not()) .then_ignore(just(Token::Equal)) @@ -1038,7 +1038,7 @@ pub fn expr_parser( location: span, value: Box::new(value), pattern, - kind: ast::AssignmentKind::Assert, + kind: ast::AssignmentKind::Expect, annotation, }, ); @@ -1093,7 +1093,7 @@ pub fn expr_parser( block_parser, when_parser, let_parser, - assert_parser, + expect_parser, if_parser, )); diff --git a/crates/aiken-lang/src/parser/lexer.rs b/crates/aiken-lang/src/parser/lexer.rs index 84aaa4d2..9b390364 100644 --- a/crates/aiken-lang/src/parser/lexer.rs +++ b/crates/aiken-lang/src/parser/lexer.rs @@ -87,7 +87,8 @@ pub fn lexer() -> impl Parser, Error = ParseError> { "trace" => Token::Trace, "error" => Token::ErrorTerm, "as" => Token::As, - "assert" => Token::Assert, + "assert" => Token::Expect, + "expect" => Token::Expect, "const" => Token::Const, "fn" => Token::Fn, "test" => Token::Test, diff --git a/crates/aiken-lang/src/parser/token.rs b/crates/aiken-lang/src/parser/token.rs index 24c53c2d..e94de71c 100644 --- a/crates/aiken-lang/src/parser/token.rs +++ b/crates/aiken-lang/src/parser/token.rs @@ -60,11 +60,12 @@ pub enum Token { NewLine, // Keywords (alphabetically): As, - Assert, Const, Fn, If, Else, + ErrorTerm, + Expect, Is, Let, Opaque, @@ -75,7 +76,6 @@ pub enum Token { Type, When, Trace, - ErrorTerm, } impl fmt::Display for Token { @@ -140,7 +140,7 @@ impl fmt::Display for Token { Token::EmptyLine => "EMPTYLINE", Token::NewLine => "NEWLINE", Token::As => "as", - Token::Assert => "assert", + Token::Expect => "expect", Token::When => "when", Token::Is => "is", Token::Const => "const", diff --git a/crates/aiken-lang/src/tests/parser.rs b/crates/aiken-lang/src/tests/parser.rs index a3b042a6..129af56a 100644 --- a/crates/aiken-lang/src/tests/parser.rs +++ b/crates/aiken-lang/src/tests/parser.rs @@ -324,6 +324,77 @@ fn empty_function() { ) } +#[test] +fn expect() { + let code = indoc! {r#" + pub fn run() { + expect Some(x) = something.field + x.other_field + } + "#}; + + assert_definitions( + code, + vec![ast::UntypedDefinition::Fn(Function { + arguments: vec![], + body: expr::UntypedExpr::Sequence { + location: Span::new((), 19..69), + expressions: vec![ + expr::UntypedExpr::Assignment { + location: Span::new((), 19..51), + value: expr::UntypedExpr::FieldAccess { + location: Span::new((), 36..51), + label: "field".to_string(), + container: expr::UntypedExpr::Var { + location: Span::new((), 36..45), + name: "something".to_string(), + } + .into(), + } + .into(), + pattern: ast::Pattern::Constructor { + is_record: false, + location: Span::new((), 26..33), + name: "Some".to_string(), + arguments: vec![ast::CallArg { + label: None, + location: Span::new((), 31..32), + value: ast::Pattern::Var { + location: Span::new((), 31..32), + name: "x".to_string(), + }, + }], + module: None, + constructor: (), + with_spread: false, + tipo: (), + }, + kind: ast::AssignmentKind::Expect, + annotation: None, + }, + expr::UntypedExpr::FieldAccess { + location: Span::new((), 56..69), + label: "other_field".to_string(), + container: expr::UntypedExpr::Var { + location: Span::new((), 56..57), + name: "x".to_string(), + } + .into(), + }, + ], + }, + doc: None, + + location: Span::new((), 0..12), + name: "run".to_string(), + public: true, + return_annotation: None, + return_type: (), + end_position: 70, + })], + ) +} + #[test] fn plus_binop() { let code = indoc! {r#" diff --git a/crates/aiken-lang/src/tipo/error.rs b/crates/aiken-lang/src/tipo/error.rs index 2c0fed74..c481ffbf 100644 --- a/crates/aiken-lang/src/tipo/error.rs +++ b/crates/aiken-lang/src/tipo/error.rs @@ -333,7 +333,7 @@ Perhaps, try the following: #[diagnostic(code("illegal::module_name"))] #[diagnostic(help(r#"You cannot use keywords as part of a module path name. As a quick reminder, here's a list of all the keywords (and thus, of invalid module path names): - as, assert, check, const, else, fn, if, is, let, opaque, pub, test, todo, trace, type, use, when"#))] + as, expect, check, const, else, fn, if, is, let, opaque, pub, test, todo, trace, type, use, when"#))] KeywordInModuleName { name: String, keyword: String }, #[error("I discovered a function which is ending with an assignment.\n")] @@ -1076,6 +1076,21 @@ pub enum Warning { sample: UntypedExpr, }, + #[error("I found an {} trying to match a type with one constructor", "expect".purple())] + #[diagnostic( + code("single_constructor_expect"), + help("If your type has one constructor, unless you are casting {} {}, you can\nprefer using a {} binding like so...\n\n{}", "FROM".bold(), "Data".purple(), "let".purple(), format_suggestion(sample)) + )] + SingleConstructorExpect { + #[label("use let")] + location: Span, + #[label("only one constructor")] + pattern_location: Span, + #[label("is not Data")] + value_location: Span, + sample: UntypedExpr, + }, + #[error("I found a todo left in the code.\n")] #[diagnostic(help("You probably want to replace that one with real code... eventually."))] #[diagnostic(code("todo"))] diff --git a/crates/aiken-lang/src/tipo/expr.rs b/crates/aiken-lang/src/tipo/expr.rs index 3787b991..cb745d35 100644 --- a/crates/aiken-lang/src/tipo/expr.rs +++ b/crates/aiken-lang/src/tipo/expr.rs @@ -817,15 +817,18 @@ impl<'a, 'b> ExprTyper<'a, 'b> { fn infer_assignment( &mut self, - pattern: UntypedPattern, - value: UntypedExpr, + untyped_pattern: UntypedPattern, + untyped_value: UntypedExpr, kind: AssignmentKind, annotation: &Option, location: Span, ) -> Result { - let typed_value = self.in_new_scope(|value_typer| value_typer.infer(value.clone()))?; + let typed_value = + self.in_new_scope(|value_typer| value_typer.infer(untyped_value.clone()))?; let mut value_typ = typed_value.tipo(); + let value_is_data = value_typ.is_data(); + // Check that any type annotation is accurate. let pattern = if let Some(ann) = annotation { let ann_typ = self @@ -836,25 +839,25 @@ impl<'a, 'b> ExprTyper<'a, 'b> { ann_typ.clone(), value_typ.clone(), typed_value.type_defining_location(), - (kind.is_let() && ann_typ.is_data()) || (kind.is_assert() && value_typ.is_data()), + (kind.is_let() && ann_typ.is_data()) || (kind.is_expect() && value_is_data), )?; value_typ = ann_typ.clone(); // Ensure the pattern matches the type of the value PatternTyper::new(self.environment, &self.hydrator).unify( - pattern, + untyped_pattern.clone(), value_typ.clone(), Some(ann_typ), )? } else { - if value_typ.is_data() && !pattern.is_var() && !pattern.is_discard() { + if value_is_data && !untyped_pattern.is_var() && !untyped_pattern.is_discard() { return Err(Error::CastDataNoAnn { location, value: UntypedExpr::Assignment { location, - value: value.into(), - pattern, + value: untyped_value.into(), + pattern: untyped_pattern, kind, annotation: Some(Annotation::Constructor { location: Span::empty(), @@ -868,7 +871,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { // Ensure the pattern matches the type of the value PatternTyper::new(self.environment, &self.hydrator).unify( - pattern, + untyped_pattern.clone(), value_typ.clone(), None, )? @@ -877,7 +880,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { // We currently only do limited exhaustiveness checking of custom types // at the top level of patterns. // Do not perform exhaustiveness checking if user explicitly used `assert`. - if kind != AssignmentKind::Assert { + if kind != AssignmentKind::Expect { if let Err(unmatched) = self.environment.check_exhaustiveness( vec![pattern.clone()], collapse_links(value_typ.clone()), @@ -888,6 +891,33 @@ impl<'a, 'b> ExprTyper<'a, 'b> { unmatched, }); } + } else if !value_is_data + && self + .environment + .check_exhaustiveness( + vec![pattern.clone()], + collapse_links(value_typ.clone()), + location, + ) + .is_ok() + { + self.environment + .warnings + .push(Warning::SingleConstructorExpect { + location: Span { + start: location.start, + end: kind.location_offset(), + }, + pattern_location: dbg!(untyped_pattern.location()), + value_location: dbg!(untyped_value.location()), + sample: UntypedExpr::Assignment { + location: Span::empty(), + value: Box::new(untyped_value), + pattern: untyped_pattern, + kind: AssignmentKind::Let, + annotation: None, + }, + }) } Ok(TypedExpr::Assignment { diff --git a/crates/aiken-lang/src/tipo/infer.rs b/crates/aiken-lang/src/tipo/infer.rs index 54037cfd..2aead900 100644 --- a/crates/aiken-lang/src/tipo/infer.rs +++ b/crates/aiken-lang/src/tipo/infer.rs @@ -20,6 +20,8 @@ use super::{ TypeInfo, ValueConstructor, ValueConstructorVariant, }; +const PUB_OFFSET: usize = 3; + impl UntypedModule { pub fn infer( mut self, @@ -162,7 +164,7 @@ fn infer_definition( environment.warnings.push(Warning::PubInValidatorModule { location: Span { start: location.start, - end: location.start + 3, + end: location.start + PUB_OFFSET, }, }) } @@ -270,7 +272,7 @@ fn infer_definition( environment.warnings.push(Warning::PubInValidatorModule { location: Span { start: location.start, - end: location.start + 3, + end: location.start + PUB_OFFSET, }, }) } @@ -306,7 +308,7 @@ fn infer_definition( environment.warnings.push(Warning::PubInValidatorModule { location: Span { start: location.start, - end: location.start + 3, + end: location.start + PUB_OFFSET, }, }) } @@ -449,7 +451,7 @@ fn infer_definition( environment.warnings.push(Warning::PubInValidatorModule { location: Span { start: location.start, - end: location.start + 3, + end: location.start + PUB_OFFSET, }, }) } @@ -511,8 +513,11 @@ fn validate_module_name(name: &str) -> Result<(), Error> { fn str_to_keyword(word: &str) -> Option { // Alphabetical keywords: match word { + "assert" => Some(Token::Expect), + "expect" => Some(Token::Expect), + "else" => Some(Token::Else), + "is" => Some(Token::Is), "as" => Some(Token::As), - "assert" => Some(Token::Assert), "when" => Some(Token::When), "const" => Some(Token::Const), "fn" => Some(Token::Fn), diff --git a/crates/aiken-lang/src/uplc.rs b/crates/aiken-lang/src/uplc.rs index 15384e91..a2679763 100644 --- a/crates/aiken-lang/src/uplc.rs +++ b/crates/aiken-lang/src/uplc.rs @@ -1578,7 +1578,7 @@ impl<'a> CodeGenerator<'a> { pattern_vec.append(value_vec); - if matches!(assignment_properties.kind, AssignmentKind::Assert) + if matches!(assignment_properties.kind, AssignmentKind::Expect) && assignment_properties.value_type.is_data() && !tipo.is_data() { @@ -1604,7 +1604,7 @@ impl<'a> CodeGenerator<'a> { pattern_vec.append(value_vec); } list @ Pattern::List { .. } => { - if matches!(assignment_properties.kind, AssignmentKind::Assert) + if matches!(assignment_properties.kind, AssignmentKind::Expect) && assignment_properties.value_type.is_data() && !tipo.is_data() { @@ -1629,7 +1629,7 @@ impl<'a> CodeGenerator<'a> { } // TODO: Check constr for assert on all cases constr @ Pattern::Constructor { .. } => { - if matches!(assignment_properties.kind, AssignmentKind::Assert) + if matches!(assignment_properties.kind, AssignmentKind::Expect) && assignment_properties.value_type.is_data() && !tipo.is_data() { @@ -1653,7 +1653,7 @@ impl<'a> CodeGenerator<'a> { } } tuple @ Pattern::Tuple { .. } => { - if matches!(assignment_properties.kind, AssignmentKind::Assert) + if matches!(assignment_properties.kind, AssignmentKind::Expect) && assignment_properties.value_type.is_data() && !tipo.is_data() { @@ -2503,7 +2503,7 @@ impl<'a> CodeGenerator<'a> { let id = self.id_gen.next(); let list_name = format!("__list_{id}"); - if matches!(assignment_properties.kind, AssignmentKind::Assert) + if matches!(assignment_properties.kind, AssignmentKind::Expect) && assignment_properties.value_type.is_data() && !tipo.is_data() { @@ -2556,7 +2556,7 @@ impl<'a> CodeGenerator<'a> { let id = self.id_gen.next(); let constr_name = format!("{constr_name}_{id}"); - if matches!(assignment_properties.kind, AssignmentKind::Assert) + if matches!(assignment_properties.kind, AssignmentKind::Expect) && assignment_properties.value_type.is_data() && !tipo.is_data() { @@ -2605,7 +2605,7 @@ impl<'a> CodeGenerator<'a> { let id = self.id_gen.next(); let tuple_name = format!("__tuple_name_{id}"); - if matches!(assignment_properties.kind, AssignmentKind::Assert) + if matches!(assignment_properties.kind, AssignmentKind::Expect) && assignment_properties.value_type.is_data() && !tipo.is_data() { diff --git a/examples/acceptance_tests/008/lib/tests.ak b/examples/acceptance_tests/008/lib/tests.ak index 689fb805..d9fcc3ed 100644 --- a/examples/acceptance_tests/008/lib/tests.ak +++ b/examples/acceptance_tests/008/lib/tests.ak @@ -5,17 +5,17 @@ pub fn is_empty(bytes: ByteArray) -> Bool { } test is_empty_1() { - is_empty(#[]) == True + is_empty(#"") == True } test is_empty_1_alt() { - is_empty(#[]) + is_empty(#"") } test is_empty_2() { - is_empty(#[1]) == False + is_empty(#"01") == False } test is_empty_2_alt() { - !is_empty(#[1]) + !is_empty(#"01") } diff --git a/examples/acceptance_tests/009/lib/tests.ak b/examples/acceptance_tests/009/lib/tests.ak index b4ef2b0d..c3384d04 100644 --- a/examples/acceptance_tests/009/lib/tests.ak +++ b/examples/acceptance_tests/009/lib/tests.ak @@ -5,5 +5,5 @@ pub fn is_empty(bytes: ByteArray) -> Bool { } test is_empty_1() { - is_empty(#[]) == True + is_empty(#"") == True } diff --git a/examples/acceptance_tests/016/lib/tests.ak b/examples/acceptance_tests/016/lib/tests.ak index 9c658c82..72462cea 100644 --- a/examples/acceptance_tests/016/lib/tests.ak +++ b/examples/acceptance_tests/016/lib/tests.ak @@ -13,6 +13,6 @@ pub fn drop(bytes: ByteArray, n: Int) -> ByteArray { } test drop_1() { - let x = #[1, 2, 3, 4, 5, 6, 7] - drop(x, 2) == #[3, 4, 5, 6, 7] + let x = #"01020304050607" + drop(x, 2) == #"0304050607" } diff --git a/examples/acceptance_tests/017/lib/tests.ak b/examples/acceptance_tests/017/lib/tests.ak index af71db7b..62863b0d 100644 --- a/examples/acceptance_tests/017/lib/tests.ak +++ b/examples/acceptance_tests/017/lib/tests.ak @@ -9,5 +9,5 @@ pub fn take(bytes: ByteArray, n: Int) -> ByteArray { } test take_1() { - take(#[1, 2, 3], 2) == #[1, 2] + take(#"010203", 2) == #"0102" } diff --git a/examples/acceptance_tests/023/lib/tests.ak b/examples/acceptance_tests/023/lib/tests.ak index cdafc006..761e86ef 100644 --- a/examples/acceptance_tests/023/lib/tests.ak +++ b/examples/acceptance_tests/023/lib/tests.ak @@ -18,11 +18,7 @@ pub fn insert( AssocList { inner: do_insert(m.inner, k, v) } } -fn do_insert( - elems: List<(key, value)>, - k: key, - v: value, -) -> List<(key, value)> { +fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)> { when elems is { [] -> [(k, v)] [(k2, v2), ..rest] -> diff --git a/examples/acceptance_tests/029/lib/tests.ak b/examples/acceptance_tests/029/lib/tests.ak index 6d74cfac..bc3f1835 100644 --- a/examples/acceptance_tests/029/lib/tests.ak +++ b/examples/acceptance_tests/029/lib/tests.ak @@ -25,11 +25,7 @@ pub fn insert( AssocList { inner: do_insert(m.inner, k, v) } } -fn do_insert( - elems: List<(key, value)>, - k: key, - v: value, -) -> List<(key, value)> { +fn do_insert(elems: List<(key, value)>, k: key, v: value) -> List<(key, value)> { when elems is { [] -> [(k, v)] [(k2, v2), ..rest] -> diff --git a/examples/acceptance_tests/035/lib/aiken/dict.ak b/examples/acceptance_tests/035/lib/aiken/dict.ak index 9640ff8f..a2bbcc2f 100644 --- a/examples/acceptance_tests/035/lib/aiken/dict.ak +++ b/examples/acceptance_tests/035/lib/aiken/dict.ak @@ -20,7 +20,7 @@ pub fn insert( ) -> Dict { Dict { inner: do_insert_with(self.inner, k, v, fn(_, left, _right) { Some(left) })} - + } pub fn union_with( diff --git a/examples/acceptance_tests/035/lib/tests.ak b/examples/acceptance_tests/035/lib/tests.ak index 60279bab..2cf7eade 100644 --- a/examples/acceptance_tests/035/lib/tests.ak +++ b/examples/acceptance_tests/035/lib/tests.ak @@ -22,7 +22,7 @@ pub fn from_asset( } pub fn from_lovelace(quantity: Int) -> Value { - from_asset(#[], #[], quantity) + from_asset(#"", #"", quantity) } pub fn add(left v0: Value, right v1: Value) -> Value { diff --git a/examples/acceptance_tests/036/validators/spend.ak b/examples/acceptance_tests/036/validators/spend.ak index 23094f20..f68427db 100644 --- a/examples/acceptance_tests/036/validators/spend.ak +++ b/examples/acceptance_tests/036/validators/spend.ak @@ -3,7 +3,7 @@ use aiken/list use aiken/transaction.{Output, ScriptContext} use aiken/transaction/value.{PolicyId} -const my_policy_id: PolicyId = #[0, 0, 0, 0, 0] +const my_policy_id: PolicyId = #"0000000000" pub fn has_policy_id(self: Output, policy_id: PolicyId) -> Bool { self.value diff --git a/examples/acceptance_tests/039/lib/tests.ak b/examples/acceptance_tests/039/lib/tests.ak index 22b1bc55..66c5933b 100644 --- a/examples/acceptance_tests/039/lib/tests.ak +++ b/examples/acceptance_tests/039/lib/tests.ak @@ -37,52 +37,52 @@ pub fn update_door_locked_and_wheels( test update_owner1() { let initial_car = Car { - owner: #[], + owner: #"", wheels: 4, - vin: #[1, 1, 1, 1, 1, 1, 1], + vin: #"01010101010101", door: Door { locked: False, hinge_angle: 45 }, } let final_car = Car { - owner: #[244, 244, 244, 244], + owner: #"f4f4f4f4", wheels: 4, - vin: #[1, 1, 1, 1, 1, 1, 1], + vin: #"01010101010101", door: Door { locked: False, hinge_angle: 45 }, } - update_owner(#[244, 244, 244, 244], initial_car) == final_car + update_owner(#"f4f4f4f4", initial_car) == final_car } test update_vin1() { let initial_car = Car { - owner: #[], + owner: #"", wheels: 4, - vin: #[1, 1, 1, 1, 1, 1, 1], + vin: #"01010101010101", door: Door { locked: False, hinge_angle: 45 }, } let final_car = Car { - owner: #[], + owner: #"", wheels: 4, - vin: #[2, 2, 2, 2, 2, 2, 2, 2, 2], + vin: #"020202020202020202", door: Door { locked: False, hinge_angle: 45 }, } - update_vin(#[2, 2, 2, 2, 2, 2, 2, 2, 2], initial_car) == final_car + update_vin(#"020202020202020202", initial_car) == final_car } test update_door_angle1() { let initial_car = Car { - owner: #[], + owner: #"", wheels: 4, - vin: #[1, 1, 1, 1, 1, 1, 1], + vin: #"01010101010101", door: Door { locked: False, hinge_angle: 45 }, } let final_car = Car { - owner: #[], + owner: #"", wheels: 4, - vin: #[1, 1, 1, 1, 1, 1, 1], + vin: #"01010101010101", door: Door { locked: False, hinge_angle: 90 }, } update_door_angle(90, initial_car) == final_car @@ -91,16 +91,16 @@ test update_door_angle1() { test update_door_locked_and_wheels1() { let initial_car = Car { - owner: #[], + owner: #"", wheels: 4, - vin: #[1, 1, 1, 1, 1, 1, 1], + vin: #"01010101010101", door: Door { locked: False, hinge_angle: 45 }, } let final_car = Car { - owner: #[], + owner: #"", wheels: 5, - vin: #[1, 1, 1, 1, 1, 1, 1], + vin: #"01010101010101", door: Door { locked: True, hinge_angle: 45 }, } update_door_locked_and_wheels(True, 5, initial_car) == final_car diff --git a/examples/acceptance_tests/040/lib/tests.ak b/examples/acceptance_tests/040/lib/tests.ak index 5cdb783d..3bd58bd9 100644 --- a/examples/acceptance_tests/040/lib/tests.ak +++ b/examples/acceptance_tests/040/lib/tests.ak @@ -28,6 +28,6 @@ test update_owner1() { builtin.list_data([]), ], ) - assert Ford { owner, wheels, truck_bed_limit, .. }: Car = initial_car + expect Ford { owner, wheels, truck_bed_limit, .. }: Car = initial_car owner == #"" && wheels == 4 && truck_bed_limit == 10000 } diff --git a/examples/acceptance_tests/047/lib/tests.ak b/examples/acceptance_tests/047/lib/tests.ak deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/acceptance_tests/050/lib/tests.ak b/examples/acceptance_tests/050/lib/tests.ak index 4416c0bc..dca9b864 100644 --- a/examples/acceptance_tests/050/lib/tests.ak +++ b/examples/acceptance_tests/050/lib/tests.ak @@ -13,19 +13,19 @@ test let_1() { test let_2() { let x: Data = 1 - assert y: Int = x + expect y: Int = x y == 1 } test assert_1() { - assert thing: Thing = builtin.constr_data(0, [builtin.i_data(1)]) + expect thing: Thing = builtin.constr_data(0, [builtin.i_data(1)]) thing.wow == 1 } fn cast_to_thing(x: Data) -> Thing { - assert x: Thing = x + expect x: Thing = x x } diff --git a/examples/acceptance_tests/fmt b/examples/acceptance_tests/fmt new file mode 100755 index 00000000..4e424e97 --- /dev/null +++ b/examples/acceptance_tests/fmt @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +if [ -z $1 ]; then + echo -e "\033[31mMissing argument: \033[1mACCEPTANCE_TEST\033[0m" + echo "" + echo -e "\033[1mUsage: \033[0m" + echo " run.sh {ACCEPTANCE_TEST}" + echo "" + echo -e "\033[1mExample: \033[0m" + echo " run.sh 034" + exit 1 +fi + +WORKDIR="$(dirname -- "${BASH_SOURCE[0]}")" +TARGET="$WORKDIR/$(basename $1)" + +TMP=$(mktemp) +RESULT=$(cargo run --quiet -- fmt $TARGET 2>$TMP) + +if [ "$?" -eq "0" ]; then + echo "✅ $(basename $TARGET)" +else + echo "❌ $(basename $TARGET)" + cat $TMP + exit 1 +fi diff --git a/examples/acceptance_tests/fmt-all b/examples/acceptance_tests/fmt-all new file mode 100755 index 00000000..fd06db44 --- /dev/null +++ b/examples/acceptance_tests/fmt-all @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +find . -regex ".*[0-9]\{3\}" -type d | xargs -P 8 -I {} -- ./fmt {}