From 4d42c6cb19f8018eab2d98b14710f73cae3e852c Mon Sep 17 00:00:00 2001 From: KtorZ Date: Fri, 7 Jun 2024 11:17:16 +0200 Subject: [PATCH] Introduce 'ArgBy' to allow defining function arg not only by name. --- crates/aiken-lang/src/ast.rs | 123 +++-- crates/aiken-lang/src/builtins.rs | 18 +- crates/aiken-lang/src/expr.rs | 23 +- crates/aiken-lang/src/format.rs | 48 +- .../src/parser/definition/function.rs | 6 +- .../snapshots/def_invalid_property_test.snap | 36 +- .../snapshots/def_property_test.snap | 18 +- .../def_property_test_annotated_fuzzer.snap | 34 +- .../snapshots/double_validator.snap | 85 ++-- .../definition/snapshots/validator.snap | 51 +- .../aiken-lang/src/parser/definition/test.rs | 10 +- .../src/parser/expr/anonymous_binop.rs | 17 +- .../src/parser/expr/anonymous_function.rs | 8 +- .../snapshots/anonymous_function_basic.snap | 17 +- .../anonymous_function_body_sequence.snap | 77 +++ .../expr/snapshots/first_class_binop.snap | 442 +++++++++--------- .../expr/snapshots/function_invoke.snap | 34 +- crates/aiken-lang/src/tipo/environment.rs | 2 +- crates/aiken-lang/src/tipo/expr.rs | 22 +- crates/aiken-lang/src/tipo/infer.rs | 41 +- crates/aiken-project/src/test_framework.rs | 27 +- 21 files changed, 651 insertions(+), 488 deletions(-) create mode 100644 crates/aiken-lang/src/parser/expr/snapshots/anonymous_function_body_sequence.snap diff --git a/crates/aiken-lang/src/ast.rs b/crates/aiken-lang/src/ast.rs index fecbef99..1e03e402 100644 --- a/crates/aiken-lang/src/ast.rs +++ b/crates/aiken-lang/src/ast.rs @@ -7,6 +7,7 @@ use crate::{ }; use indexmap::IndexMap; use miette::Diagnostic; +use ordinal::Ordinal; use owo_colors::{OwoColorize, Stream::Stdout}; use std::{ fmt::{self, Display}, @@ -517,17 +518,17 @@ pub struct ModuleConstant { pub tipo: T, } -pub type TypedValidator = Validator, TypedExpr>; -pub type UntypedValidator = Validator<(), UntypedExpr>; +pub type TypedValidator = Validator, TypedArg, TypedExpr>; +pub type UntypedValidator = Validator<(), UntypedArg, UntypedExpr>; #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct Validator { +pub struct Validator { pub doc: Option, pub end_position: usize, - pub fun: Function>, - pub other_fun: Option>>, + pub fun: Function, + pub other_fun: Option>, pub location: Span, - pub params: Vec>, + pub params: Vec, } impl TypedValidator { @@ -575,12 +576,12 @@ impl TypedValidator { } } -pub type TypedDefinition = Definition, TypedExpr, String>; -pub type UntypedDefinition = Definition<(), UntypedExpr, ()>; +pub type TypedDefinition = Definition, TypedArg, TypedExpr, String>; +pub type UntypedDefinition = Definition<(), UntypedArg, UntypedExpr, ()>; #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub enum Definition { - Fn(Function>), +pub enum Definition { + Fn(Function), TypeAlias(TypeAlias), @@ -590,12 +591,12 @@ pub enum Definition { ModuleConstant(ModuleConstant), - Test(Function>), + Test(Function>), - Validator(Validator), + Validator(Validator), } -impl Definition { +impl Definition { pub fn location(&self) -> Span { match self { Definition::Fn(Function { location, .. }) @@ -790,28 +791,64 @@ impl RecordConstructorArg { } } -pub type TypedArg = Arg>; -pub type UntypedArg = Arg<()>; +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub enum ArgBy { + ByName(ArgName), + ByPattern(UntypedPattern), +} #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct Arg { - pub arg_name: ArgName, +pub struct UntypedArg { + pub by: ArgBy, pub location: Span, pub annotation: Option, pub doc: Option, - pub tipo: T, } -impl Arg { - pub fn set_type(self, tipo: B) -> Arg { - Arg { +impl UntypedArg { + pub fn arg_name(&self, ix: usize) -> ArgName { + match self.by { + ArgBy::ByName(ref name) => name.clone(), + ArgBy::ByPattern(..) => { + // NOTE: We use ordinal here not only because it's cute, but because + // such a name cannot be parsed to begin with and thus, will not clash + // with any user-defined name. + let name = format!("{}_arg", Ordinal::(ix).suffix()); + ArgName::Named { + label: name.clone(), + name, + location: self.location, + // TODO: This should likely be moved up inside 'UntypedArg'. + is_validator_param: false, + } + } + } + } + + pub fn set_type(self, tipo: Rc, ix: usize) -> TypedArg { + TypedArg { tipo, - arg_name: self.arg_name, + arg_name: self.arg_name(ix), location: self.location, annotation: self.annotation, doc: self.doc, } } +} + +#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] +pub struct TypedArg { + pub arg_name: ArgName, + pub location: Span, + pub annotation: Option, + pub doc: Option, + pub tipo: Rc, +} + +impl TypedArg { + pub fn put_doc(&mut self, new_doc: String) { + self.doc = Some(new_doc); + } pub fn get_variable_name(&self) -> Option<&str> { self.arg_name.get_variable_name() @@ -830,12 +867,6 @@ impl Arg { false } - pub fn put_doc(&mut self, new_doc: String) { - self.doc = Some(new_doc); - } -} - -impl TypedArg { pub fn find_node(&self, byte_index: usize) -> Option> { if self.arg_name.location().contains(byte_index) { Some(Located::Argument(&self.arg_name, self.tipo.clone())) @@ -847,40 +878,38 @@ impl TypedArg { } } -pub type TypedArgVia = ArgVia, TypedExpr>; -pub type UntypedArgVia = ArgVia<(), UntypedExpr>; +pub type TypedArgVia = ArgVia; +pub type UntypedArgVia = ArgVia; #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub struct ArgVia { - pub arg_name: ArgName, - pub location: Span, +pub struct ArgVia { + pub arg: Arg, pub via: Expr, - pub tipo: T, - pub annotation: Option, } -impl From> for Arg { - fn from(arg: ArgVia) -> Arg { - Arg { - arg_name: arg.arg_name, - location: arg.location, - tipo: arg.tipo, - annotation: None, - doc: None, - } +impl From> for TypedArg { + fn from(this: ArgVia) -> TypedArg { + this.arg + } +} + +impl From> for UntypedArg { + fn from(this: ArgVia) -> UntypedArg { + this.arg } } impl TypedArgVia { pub fn find_node(&self, byte_index: usize) -> Option> { - if self.arg_name.location().contains(byte_index) { - Some(Located::Argument(&self.arg_name, self.tipo.clone())) + if self.arg.arg_name.location().contains(byte_index) { + Some(Located::Argument(&self.arg.arg_name, self.arg.tipo.clone())) } else { // `via` is done first here because when there is no manually written // annotation, it seems one is injected leading to a `found` returning too early // because the span of the filled in annotation matches the span of the via expr. self.via.find_node(byte_index).or_else(|| { - self.annotation + self.arg + .annotation .as_ref() .and_then(|annotation| annotation.find_node(byte_index)) }) diff --git a/crates/aiken-lang/src/builtins.rs b/crates/aiken-lang/src/builtins.rs index d5131909..4a2b379e 100644 --- a/crates/aiken-lang/src/builtins.rs +++ b/crates/aiken-lang/src/builtins.rs @@ -1,7 +1,7 @@ use crate::{ ast::{ - Annotation, Arg, ArgName, CallArg, DataTypeKey, Function, FunctionAccessKey, ModuleKind, - OnTestFailure, Span, TypedDataType, TypedFunction, UnOp, + Annotation, ArgName, CallArg, DataTypeKey, Function, FunctionAccessKey, ModuleKind, + OnTestFailure, Span, TypedArg, TypedDataType, TypedFunction, UnOp, }, expr::TypedExpr, tipo::{ @@ -932,7 +932,7 @@ pub fn prelude_functions(id_gen: &IdGenerator) -> IndexMap IndexMap IndexMap IndexMap IndexMap IndexMap IndexMap, is_capture: bool, - args: Vec>>, + args: Vec, body: Box, return_annotation: Option, }, @@ -495,7 +496,7 @@ pub enum UntypedExpr { Fn { location: Span, fn_style: FnStyle, - arguments: Vec>, + arguments: Vec, body: Box, return_annotation: Option, }, @@ -1192,17 +1193,16 @@ impl UntypedExpr { } => { let name = format!("{}__{index}", ast::CAPTURE_VARIABLE); - holes.push(ast::Arg { + holes.push(ast::UntypedArg { location: Span::empty(), annotation: None, doc: None, - arg_name: ast::ArgName::Named { + by: ArgBy::ByName(ast::ArgName::Named { label: name.clone(), name, location: Span::empty(), is_validator_param: false, - }, - tipo: (), + }), }); ast::CallArg { @@ -1358,12 +1358,11 @@ impl UntypedExpr { fn_style: FnStyle::Plain, arguments: names .into_iter() - .map(|(arg_name, location, annotation)| Arg { + .map(|(arg_name, location, annotation)| UntypedArg { location, doc: None, annotation, - tipo: (), - arg_name, + by: ArgBy::ByName(arg_name), }) .collect(), body: Self::Sequence { diff --git a/crates/aiken-lang/src/format.rs b/crates/aiken-lang/src/format.rs index efa5ec89..7350a949 100644 --- a/crates/aiken-lang/src/format.rs +++ b/crates/aiken-lang/src/format.rs @@ -1,6 +1,6 @@ use crate::{ ast::{ - Annotation, Arg, ArgName, ArgVia, AssignmentKind, AssignmentPattern, BinOp, + Annotation, ArgBy, ArgName, ArgVia, AssignmentKind, AssignmentPattern, BinOp, ByteArrayFormatPreference, CallArg, ClauseGuard, Constant, CurveType, DataType, Definition, Function, IfBranch, LogicalOpChainKind, ModuleConstant, OnTestFailure, Pattern, RecordConstructor, RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypeAlias, @@ -459,41 +459,39 @@ impl<'comments> Formatter<'comments> { .append(line().append(self.annotation(typ)).group().nest(INDENT)) } - fn fn_arg<'a, A>(&mut self, arg: &'a Arg) -> Document<'a> { + fn fn_arg<'a>(&mut self, arg: &'a UntypedArg) -> Document<'a> { let comments = self.pop_comments(arg.location.start); let doc_comments = self.doc_comments(arg.location.start); - let doc = match &arg.annotation { - None => arg.arg_name.to_doc(), - Some(a) => arg - .arg_name - .to_doc() - .append(": ") - .append(self.annotation(a)), - } - .group(); + let doc = match arg.by { + ArgBy::ByName(ref arg_name) => match &arg.annotation { + None => arg_name.to_doc(), + Some(a) => arg_name.to_doc().append(": ").append(self.annotation(a)), + } + .group(), + ArgBy::ByPattern(..) => todo!(), + }; let doc = doc_comments.append(doc.group()).group(); commented(doc, comments) } - fn fn_arg_via<'a, A>(&mut self, arg: &'a ArgVia) -> Document<'a> { - let comments = self.pop_comments(arg.location.start); + fn fn_arg_via<'a>(&mut self, arg_via: &'a ArgVia) -> Document<'a> { + let comments = self.pop_comments(arg_via.arg.location.start); - let doc_comments = self.doc_comments(arg.location.start); + let doc_comments = self.doc_comments(arg_via.arg.location.start); - let doc = match &arg.annotation { - None => arg.arg_name.to_doc(), - Some(a) => arg - .arg_name - .to_doc() - .append(": ") - .append(self.annotation(a)), + let doc = match arg_via.arg.by { + ArgBy::ByName(ref arg_name) => match &arg_via.arg.annotation { + None => arg_name.to_doc(), + Some(a) => arg_name.to_doc().append(": ").append(self.annotation(a)), + }, + ArgBy::ByPattern(..) => todo!(), } .append(" via ") - .append(self.expr(&arg.via, false)) + .append(self.expr(&arg_via.via, false)) .group(); let doc = doc_comments.append(doc.group()).group(); @@ -1983,11 +1981,7 @@ impl<'a> Documentable<'a> for &'a ArgName { } fn pub_(public: bool) -> Document<'static> { - if public { - "pub ".to_doc() - } else { - nil() - } + if public { "pub ".to_doc() } else { nil() } } impl<'a> Documentable<'a> for &'a UnqualifiedImport { diff --git a/crates/aiken-lang/src/parser/definition/function.rs b/crates/aiken-lang/src/parser/definition/function.rs index bfd68006..555fd925 100644 --- a/crates/aiken-lang/src/parser/definition/function.rs +++ b/crates/aiken-lang/src/parser/definition/function.rs @@ -1,5 +1,6 @@ use crate::{ ast, + ast::ArgBy::ByName, expr::UntypedExpr, parser::{annotation, error::ParseError, expr, token::Token, utils}, }; @@ -78,12 +79,11 @@ pub fn param(is_validator_param: bool) -> impl Parser impl Parser { .then_ignore(just(Token::Via)) .then(fuzzer()) .map(|((arg_name, annotation, location), via)| ast::ArgVia { - arg_name, + arg: ast::UntypedArg { + by: ast::ArgBy::ByName(arg_name), + annotation, + location, + doc: None, + }, via, - annotation, - tipo: (), - location, }) } diff --git a/crates/aiken-lang/src/parser/expr/anonymous_binop.rs b/crates/aiken-lang/src/parser/expr/anonymous_binop.rs index db3b91e1..146e1cba 100644 --- a/crates/aiken-lang/src/parser/expr/anonymous_binop.rs +++ b/crates/aiken-lang/src/parser/expr/anonymous_binop.rs @@ -1,10 +1,9 @@ -use chumsky::prelude::*; - use crate::{ ast, expr::{FnStyle, UntypedExpr}, parser::{error::ParseError, token::Token}, }; +use chumsky::prelude::*; pub fn parser() -> impl Parser { select! { @@ -41,29 +40,27 @@ pub fn parser() -> impl Parser { }; let arguments = vec![ - ast::Arg { - arg_name: ast::ArgName::Named { + ast::UntypedArg { + by: ast::ArgBy::ByName(ast::ArgName::Named { name: "left".to_string(), label: "left".to_string(), location, is_validator_param: false, - }, + }), annotation: arg_annotation.clone(), doc: None, location, - tipo: (), }, - ast::Arg { - arg_name: ast::ArgName::Named { + ast::UntypedArg { + by: ast::ArgBy::ByName(ast::ArgName::Named { name: "right".to_string(), label: "right".to_string(), location, is_validator_param: false, - }, + }), annotation: arg_annotation, doc: None, location, - tipo: (), }, ]; diff --git a/crates/aiken-lang/src/parser/expr/anonymous_function.rs b/crates/aiken-lang/src/parser/expr/anonymous_function.rs index ba413534..1963a584 100644 --- a/crates/aiken-lang/src/parser/expr/anonymous_function.rs +++ b/crates/aiken-lang/src/parser/expr/anonymous_function.rs @@ -1,10 +1,9 @@ -use chumsky::prelude::*; - use crate::{ ast, expr::{FnStyle, UntypedExpr}, parser::{annotation, error::ParseError, token::Token}, }; +use chumsky::prelude::*; pub fn parser( sequence: Recursive<'_, Token, UntypedExpr, ParseError>, @@ -47,12 +46,11 @@ pub fn params() -> impl Parser { }), )) .then(just(Token::Colon).ignore_then(annotation()).or_not()) - .map_with_span(|(arg_name, annotation), span| ast::Arg { + .map_with_span(|(arg_name, annotation), span| ast::UntypedArg { location: span, annotation, doc: None, - tipo: (), - arg_name, + by: ast::ArgBy::ByName(arg_name), }) } diff --git a/crates/aiken-lang/src/parser/expr/snapshots/anonymous_function_basic.snap b/crates/aiken-lang/src/parser/expr/snapshots/anonymous_function_basic.snap index d8584847..95e04ce0 100644 --- a/crates/aiken-lang/src/parser/expr/snapshots/anonymous_function_basic.snap +++ b/crates/aiken-lang/src/parser/expr/snapshots/anonymous_function_basic.snap @@ -6,13 +6,15 @@ Fn { location: 0..28, fn_style: Plain, arguments: [ - Arg { - arg_name: Named { - name: "a", - label: "a", - location: 4..5, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "a", + label: "a", + location: 4..5, + is_validator_param: false, + }, + ), location: 4..10, annotation: Some( Constructor { @@ -23,7 +25,6 @@ Fn { }, ), doc: None, - tipo: (), }, ], body: BinOp { diff --git a/crates/aiken-lang/src/parser/expr/snapshots/anonymous_function_body_sequence.snap b/crates/aiken-lang/src/parser/expr/snapshots/anonymous_function_body_sequence.snap new file mode 100644 index 00000000..128e1d5f --- /dev/null +++ b/crates/aiken-lang/src/parser/expr/snapshots/anonymous_function_body_sequence.snap @@ -0,0 +1,77 @@ +--- +source: crates/aiken-lang/src/parser/expr/anonymous_function.rs +description: "Code:\n\nfn (a: Int) -> Int {\n let b = 1\n a + b\n}" +--- +Fn { + location: 0..46, + fn_style: Plain, + arguments: [ + Arg { + arg_name: Named { + name: "a", + label: "a", + location: 4..5, + is_validator_param: false, + }, + location: 4..10, + annotation: Some( + Constructor { + location: 7..10, + module: None, + name: "Int", + arguments: [], + }, + ), + doc: None, + tipo: (), + }, + ], + body: Sequence { + location: 39..44, + expressions: [ + Assignment { + location: 25..34, + value: UInt { + location: 33..34, + value: "1", + base: Decimal { + numeric_underscore: false, + }, + }, + patterns: [ + AssignmentPattern { + pattern: Var { + location: 29..30, + name: "b", + }, + annotation: None, + location: 29..30, + }, + ], + kind: Let { + backpassing: false, + }, + }, + BinOp { + location: 39..44, + name: AddInt, + left: Var { + location: 39..40, + name: "a", + }, + right: Var { + location: 43..44, + name: "b", + }, + }, + ], + }, + return_annotation: Some( + Constructor { + location: 15..18, + module: None, + name: "Int", + arguments: [], + }, + ), +} diff --git a/crates/aiken-lang/src/parser/expr/snapshots/first_class_binop.snap b/crates/aiken-lang/src/parser/expr/snapshots/first_class_binop.snap index 3a021757..fb216f72 100644 --- a/crates/aiken-lang/src/parser/expr/snapshots/first_class_binop.snap +++ b/crates/aiken-lang/src/parser/expr/snapshots/first_class_binop.snap @@ -24,13 +24,15 @@ Sequence { GtInt, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 16..17, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 16..17, + is_validator_param: false, + }, + ), location: 16..17, annotation: Some( Constructor { @@ -41,15 +43,16 @@ Sequence { }, ), doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 16..17, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 16..17, + is_validator_param: false, + }, + ), location: 16..17, annotation: Some( Constructor { @@ -60,7 +63,6 @@ Sequence { }, ), doc: None, - tipo: (), }, ], body: BinOp { @@ -119,13 +121,15 @@ Sequence { GtEqInt, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 38..40, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 38..40, + is_validator_param: false, + }, + ), location: 38..40, annotation: Some( Constructor { @@ -136,15 +140,16 @@ Sequence { }, ), doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 38..40, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 38..40, + is_validator_param: false, + }, + ), location: 38..40, annotation: Some( Constructor { @@ -155,7 +160,6 @@ Sequence { }, ), doc: None, - tipo: (), }, ], body: BinOp { @@ -214,13 +218,15 @@ Sequence { LtInt, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 61..62, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 61..62, + is_validator_param: false, + }, + ), location: 61..62, annotation: Some( Constructor { @@ -231,15 +237,16 @@ Sequence { }, ), doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 61..62, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 61..62, + is_validator_param: false, + }, + ), location: 61..62, annotation: Some( Constructor { @@ -250,7 +257,6 @@ Sequence { }, ), doc: None, - tipo: (), }, ], body: BinOp { @@ -309,13 +315,15 @@ Sequence { LtEqInt, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 83..85, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 83..85, + is_validator_param: false, + }, + ), location: 83..85, annotation: Some( Constructor { @@ -326,15 +334,16 @@ Sequence { }, ), doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 83..85, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 83..85, + is_validator_param: false, + }, + ), location: 83..85, annotation: Some( Constructor { @@ -345,7 +354,6 @@ Sequence { }, ), doc: None, - tipo: (), }, ], body: BinOp { @@ -404,29 +412,31 @@ Sequence { Eq, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 106..108, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 106..108, + is_validator_param: false, + }, + ), location: 106..108, annotation: None, doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 106..108, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 106..108, + is_validator_param: false, + }, + ), location: 106..108, annotation: None, doc: None, - tipo: (), }, ], body: BinOp { @@ -485,29 +495,31 @@ Sequence { NotEq, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 129..131, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 129..131, + is_validator_param: false, + }, + ), location: 129..131, annotation: None, doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 129..131, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 129..131, + is_validator_param: false, + }, + ), location: 129..131, annotation: None, doc: None, - tipo: (), }, ], body: BinOp { @@ -566,13 +578,15 @@ Sequence { And, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 152..154, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 152..154, + is_validator_param: false, + }, + ), location: 152..154, annotation: Some( Constructor { @@ -583,15 +597,16 @@ Sequence { }, ), doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 152..154, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 152..154, + is_validator_param: false, + }, + ), location: 152..154, annotation: Some( Constructor { @@ -602,7 +617,6 @@ Sequence { }, ), doc: None, - tipo: (), }, ], body: BinOp { @@ -661,13 +675,15 @@ Sequence { Or, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 175..177, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 175..177, + is_validator_param: false, + }, + ), location: 175..177, annotation: Some( Constructor { @@ -678,15 +694,16 @@ Sequence { }, ), doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 175..177, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 175..177, + is_validator_param: false, + }, + ), location: 175..177, annotation: Some( Constructor { @@ -697,7 +714,6 @@ Sequence { }, ), doc: None, - tipo: (), }, ], body: BinOp { @@ -756,13 +772,15 @@ Sequence { AddInt, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 198..199, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 198..199, + is_validator_param: false, + }, + ), location: 198..199, annotation: Some( Constructor { @@ -773,15 +791,16 @@ Sequence { }, ), doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 198..199, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 198..199, + is_validator_param: false, + }, + ), location: 198..199, annotation: Some( Constructor { @@ -792,7 +811,6 @@ Sequence { }, ), doc: None, - tipo: (), }, ], body: BinOp { @@ -851,13 +869,15 @@ Sequence { SubInt, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 220..221, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 220..221, + is_validator_param: false, + }, + ), location: 220..221, annotation: Some( Constructor { @@ -868,15 +888,16 @@ Sequence { }, ), doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 220..221, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 220..221, + is_validator_param: false, + }, + ), location: 220..221, annotation: Some( Constructor { @@ -887,7 +908,6 @@ Sequence { }, ), doc: None, - tipo: (), }, ], body: BinOp { @@ -946,13 +966,15 @@ Sequence { DivInt, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 242..243, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 242..243, + is_validator_param: false, + }, + ), location: 242..243, annotation: Some( Constructor { @@ -963,15 +985,16 @@ Sequence { }, ), doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 242..243, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 242..243, + is_validator_param: false, + }, + ), location: 242..243, annotation: Some( Constructor { @@ -982,7 +1005,6 @@ Sequence { }, ), doc: None, - tipo: (), }, ], body: BinOp { @@ -1041,13 +1063,15 @@ Sequence { MultInt, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 264..265, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 264..265, + is_validator_param: false, + }, + ), location: 264..265, annotation: Some( Constructor { @@ -1058,15 +1082,16 @@ Sequence { }, ), doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 264..265, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 264..265, + is_validator_param: false, + }, + ), location: 264..265, annotation: Some( Constructor { @@ -1077,7 +1102,6 @@ Sequence { }, ), doc: None, - tipo: (), }, ], body: BinOp { @@ -1136,13 +1160,15 @@ Sequence { ModInt, ), arguments: [ - Arg { - arg_name: Named { - name: "left", - label: "left", - location: 286..287, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "left", + label: "left", + location: 286..287, + is_validator_param: false, + }, + ), location: 286..287, annotation: Some( Constructor { @@ -1153,15 +1179,16 @@ Sequence { }, ), doc: None, - tipo: (), }, - Arg { - arg_name: Named { - name: "right", - label: "right", - location: 286..287, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "right", + label: "right", + location: 286..287, + is_validator_param: false, + }, + ), location: 286..287, annotation: Some( Constructor { @@ -1172,7 +1199,6 @@ Sequence { }, ), doc: None, - tipo: (), }, ], body: BinOp { diff --git a/crates/aiken-lang/src/parser/expr/snapshots/function_invoke.snap b/crates/aiken-lang/src/parser/expr/snapshots/function_invoke.snap index b1e1a4d5..77ab2d30 100644 --- a/crates/aiken-lang/src/parser/expr/snapshots/function_invoke.snap +++ b/crates/aiken-lang/src/parser/expr/snapshots/function_invoke.snap @@ -47,17 +47,18 @@ Sequence { location: 36..65, fn_style: Capture, arguments: [ - Arg { - arg_name: Named { - name: "_capture__0", - label: "_capture__0", - location: 0..0, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "_capture__0", + label: "_capture__0", + location: 0..0, + is_validator_param: false, + }, + ), location: 0..0, annotation: None, doc: None, - tipo: (), }, ], body: Call { @@ -77,17 +78,18 @@ Sequence { location: 48..64, fn_style: Plain, arguments: [ - Arg { - arg_name: Named { - name: "y", - label: "y", - location: 52..53, - is_validator_param: false, - }, + UntypedArg { + by: ByName( + Named { + name: "y", + label: "y", + location: 52..53, + is_validator_param: false, + }, + ), location: 52..53, annotation: None, doc: None, - tipo: (), }, ], body: BinOp { diff --git a/crates/aiken-lang/src/tipo/environment.rs b/crates/aiken-lang/src/tipo/environment.rs index a5b6300a..81753bf4 100644 --- a/crates/aiken-lang/src/tipo/environment.rs +++ b/crates/aiken-lang/src/tipo/environment.rs @@ -1149,7 +1149,7 @@ impl<'a> Environment<'a> { let mut field_map = FieldMap::new(arguments.len(), true); for (i, arg) in arguments.iter().enumerate() { - field_map.insert(arg.arg_name.get_label(), i, &arg.location)?; + field_map.insert(arg.arg_name(i).get_label(), i, &arg.location)?; } let field_map = field_map.into_option(); diff --git a/crates/aiken-lang/src/tipo/expr.rs b/crates/aiken-lang/src/tipo/expr.rs index f0b22562..920022d3 100644 --- a/crates/aiken-lang/src/tipo/expr.rs +++ b/crates/aiken-lang/src/tipo/expr.rs @@ -10,7 +10,7 @@ use super::{ }; use crate::{ ast::{ - self, Annotation, Arg, ArgName, AssignmentKind, AssignmentPattern, BinOp, Bls12_381Point, + self, Annotation, ArgName, AssignmentKind, AssignmentPattern, BinOp, Bls12_381Point, ByteArrayFormatPreference, CallArg, ClauseGuard, Constant, Curve, Function, IfBranch, LogicalOpChainKind, Pattern, RecordUpdateSpread, Span, TraceKind, TraceLevel, Tracing, TypedArg, TypedCallArg, TypedClause, TypedClauseGuard, TypedIfBranch, TypedPattern, @@ -79,7 +79,8 @@ pub(crate) fn infer_function( let arguments = arguments .iter() .zip(&args_types) - .map(|(arg_name, tipo)| arg_name.to_owned().set_type(tipo.clone())) + .enumerate() + .map(|(ix, (arg_name, tipo))| arg_name.to_owned().set_type(tipo.clone(), ix)) .collect(); let hydrator = hydrators @@ -331,7 +332,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { let mut arguments = Vec::new(); for (i, arg) in args.into_iter().enumerate() { - let arg = self.infer_param(arg, expected_args.get(i).cloned())?; + let arg = self.infer_param(arg, expected_args.get(i).cloned(), i)?; arguments.push(arg); } @@ -1070,18 +1071,21 @@ impl<'a, 'b> ExprTyper<'a, 'b> { }) } + // TODO: Handle arg pattern fn infer_param( &mut self, - arg: UntypedArg, + untyped_arg: UntypedArg, expected: Option>, + ix: usize, ) -> Result { - let Arg { - arg_name, + let arg_name = untyped_arg.arg_name(ix); + + let UntypedArg { + by, annotation, location, doc, - tipo: _, - } = arg; + } = untyped_arg; let tipo = annotation .clone() @@ -1097,7 +1101,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { self.unify(expected, tipo.clone(), location, false)?; } - Ok(Arg { + Ok(TypedArg { arg_name, location, annotation, diff --git a/crates/aiken-lang/src/tipo/infer.rs b/crates/aiken-lang/src/tipo/infer.rs index f4f21e85..0309e148 100644 --- a/crates/aiken-lang/src/tipo/infer.rs +++ b/crates/aiken-lang/src/tipo/infer.rs @@ -7,8 +7,8 @@ use super::{ }; use crate::{ ast::{ - Annotation, Arg, ArgName, ArgVia, DataType, Definition, Function, ModuleConstant, - ModuleKind, RecordConstructor, RecordConstructorArg, Tracing, TypeAlias, TypedDefinition, + Annotation, ArgName, ArgVia, DataType, Definition, Function, ModuleConstant, ModuleKind, + RecordConstructor, RecordConstructorArg, Tracing, TypeAlias, TypedArg, TypedDefinition, TypedFunction, TypedModule, UntypedDefinition, UntypedModule, Use, Validator, }, builtins, @@ -198,8 +198,12 @@ fn infer_definition( .function_types() .expect("Preregistered type for fn was not a fn"); - for (arg, t) in params.iter().zip(args_types[0..params.len()].iter()) { - match &arg.arg_name { + for (ix, (arg, t)) in params + .iter() + .zip(args_types[0..params.len()].iter()) + .enumerate() + { + match &arg.arg_name(ix) { ArgName::Named { name, is_validator_param, @@ -326,7 +330,12 @@ fn infer_definition( if f.arguments.len() > 1 { return Err(Error::IncorrectTestArity { count: f.arguments.len(), - location: f.arguments.get(1).expect("arguments.len() > 1").location, + location: f + .arguments + .get(1) + .expect("arguments.len() > 1") + .arg + .location, }); } @@ -336,6 +345,7 @@ fn infer_definition( let hydrator: &mut Hydrator = hydrators.get_mut(&f.name).unwrap(); let provided_inner_type = arg + .arg .annotation .as_ref() .map(|ann| hydrator.type_from_annotation(ann, environment)) @@ -352,13 +362,14 @@ fn infer_definition( // Fuzzer. if let Some(provided_inner_type) = provided_inner_type { if !arg + .arg .annotation .as_ref() .unwrap() .is_logically_equal(&inferred_annotation) { return Err(Error::CouldNotUnify { - location: arg.location, + location: arg.arg.location, expected: inferred_inner_type.clone(), given: provided_inner_type.clone(), situation: Some(UnifyErrorSituation::FuzzerAnnotationMismatch), @@ -417,23 +428,17 @@ fn infer_definition( public: typed_f.public, arguments: match typed_via { Some((via, tipo)) => { - let Arg { - arg_name, - location, - annotation: _, - doc: _, - tipo: _, - } = typed_f + let arg = typed_f .arguments .first() .expect("has exactly one argument") .to_owned(); - vec![ArgVia { - annotation, - arg_name, - location, - tipo, + arg: TypedArg { + tipo, + annotation, + ..arg + }, via, }] } diff --git a/crates/aiken-project/src/test_framework.rs b/crates/aiken-project/src/test_framework.rs index 305c76c4..d42a39c0 100644 --- a/crates/aiken-project/src/test_framework.rs +++ b/crates/aiken-project/src/test_framework.rs @@ -1,6 +1,6 @@ use aiken_lang::ast::OnTestFailure; pub(crate) use aiken_lang::{ - ast::{Arg, BinOp, DataTypeKey, IfBranch, Span, TypedDataType, TypedTest}, + ast::{BinOp, DataTypeKey, IfBranch, Span, TypedArg, TypedDataType, TypedTest}, builtins::bool, expr::{TypedExpr, UntypedExpr}, format::Formatter, @@ -124,13 +124,13 @@ impl Test { let via = parameter.via.clone(); - let type_info = parameter.tipo.clone(); + let type_info = parameter.arg.tipo.clone(); let stripped_type_info = convert_opaque_type(&type_info, generator.data_types(), true); let program = generator.clone().generate_raw( &test.body, - &[Arg { + &[TypedArg { tipo: stripped_type_info.clone(), ..parameter.clone().into() }], @@ -507,8 +507,10 @@ impl Prng { fn as_prng(cst: &PlutusData) -> Prng { if let PlutusData::Constr(Constr { tag, fields, .. }) = cst { if *tag == 121 + Prng::SEEDED { - if let [PlutusData::BoundedBytes(bytes), PlutusData::BoundedBytes(choices)] = - &fields[..] + if let [ + PlutusData::BoundedBytes(bytes), + PlutusData::BoundedBytes(choices), + ] = &fields[..] { return Prng::Seeded { choices: choices.to_vec(), @@ -1087,9 +1089,11 @@ impl TryFrom for Assertion { final_else, .. } => { - if let [IfBranch { - condition, body, .. - }] = &branches[..] + if let [ + IfBranch { + condition, body, .. + }, + ] = &branches[..] { let then_is_true = match body { TypedExpr::Var { @@ -1508,13 +1512,14 @@ mod test { } "#}); - assert!(prop - .run::<()>( + assert!( + prop.run::<()>( 42, PropertyTest::DEFAULT_MAX_SUCCESS, &PlutusVersion::default() ) - .is_success()); + .is_success() + ); } #[test]