From cd4ceb219c35dfe91f75f25438b1b8d1cc8040e3 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Fri, 17 Feb 2023 17:30:24 +0100 Subject: [PATCH] Remove complex and compound constants. This is not supported by the code generation, so it's a bit of a lie to have them in the language in the first place. There's arguably not even any use for constant records, list and tuples to begin with. So this cleans this up everywhere for the sake of moving forward with the alpha release. This now reduces constants to: - Integer - ByteArray - String Anything else can be declared via a function anyway. We can revisit this choice later.... or not. --- crates/aiken-lang/src/ast.rs | 110 ++------- crates/aiken-lang/src/builder.rs | 32 +-- crates/aiken-lang/src/expr.rs | 4 +- crates/aiken-lang/src/format.rs | 86 +------ crates/aiken-lang/src/parser.rs | 177 ++------------ crates/aiken-lang/src/tipo.rs | 6 +- crates/aiken-lang/src/tipo/expr.rs | 264 +-------------------- crates/aiken-lang/src/uplc.rs | 2 +- examples/acceptance_tests/060/lib/tests.ak | 18 +- 9 files changed, 81 insertions(+), 618 deletions(-) diff --git a/crates/aiken-lang/src/ast.rs b/crates/aiken-lang/src/ast.rs index fe6723ad..6c807bc9 100644 --- a/crates/aiken-lang/src/ast.rs +++ b/crates/aiken-lang/src/ast.rs @@ -3,7 +3,7 @@ use std::{fmt, ops::Range, sync::Arc}; use crate::{ builtins::{self, bool}, expr::{TypedExpr, UntypedExpr}, - tipo::{fields::FieldMap, PatternConstructor, Type, TypeInfo, ValueConstructor}, + tipo::{PatternConstructor, Type, TypeInfo}, }; pub const ASSERT_VARIABLE: &str = "_try"; @@ -244,17 +244,17 @@ pub struct Use { pub unqualified: Vec, } -pub type TypedModuleConstant = ModuleConstant, String>; -pub type UntypedModuleConstant = ModuleConstant<(), ()>; +pub type TypedModuleConstant = ModuleConstant>; +pub type UntypedModuleConstant = ModuleConstant<()>; #[derive(Debug, Clone, PartialEq)] -pub struct ModuleConstant { +pub struct ModuleConstant { pub doc: Option, pub location: Span, pub public: bool, pub name: String, pub annotation: Option, - pub value: Box>, + pub value: Box, pub tipo: T, } @@ -270,11 +270,11 @@ pub struct Validator { pub params: Vec>, } -pub type TypedDefinition = Definition, TypedExpr, String, String>; -pub type UntypedDefinition = Definition<(), UntypedExpr, (), ()>; +pub type TypedDefinition = Definition, TypedExpr, String>; +pub type UntypedDefinition = Definition<(), UntypedExpr, ()>; #[derive(Debug, Clone, PartialEq)] -pub enum Definition { +pub enum Definition { Fn(Function), TypeAlias(TypeAlias), @@ -283,14 +283,14 @@ pub enum Definition { Use(Use), - ModuleConstant(ModuleConstant), + ModuleConstant(ModuleConstant), Test(Function), Validator(Validator), } -impl Definition { +impl Definition { pub fn location(&self) -> Span { match self { Definition::Fn(Function { location, .. }) @@ -324,91 +324,31 @@ pub struct DefinitionLocation<'module> { pub span: Span, } -pub type TypedConstant = Constant, String>; -pub type UntypedConstant = Constant<(), ()>; - #[derive(Debug, Clone, PartialEq)] -pub enum Constant { - Int { - location: Span, - value: String, - }, +pub enum Constant { + Int { location: Span, value: String }, - String { - location: Span, - value: String, - }, + String { location: Span, value: String }, - Tuple { - location: Span, - elements: Vec, - }, - - List { - location: Span, - elements: Vec, - tipo: T, - }, - - Record { - location: Span, - module: Option, - name: String, - args: Vec>, - tag: RecordTag, - tipo: T, - field_map: Option, - }, - - ByteArray { - location: Span, - bytes: Vec, - }, - - Var { - location: Span, - module: Option, - name: String, - constructor: Option>, - tipo: T, - }, + ByteArray { location: Span, bytes: Vec }, } -impl TypedConstant { +impl Constant { pub fn tipo(&self) -> Arc { match self { Constant::Int { .. } => builtins::int(), Constant::String { .. } => builtins::string(), Constant::ByteArray { .. } => builtins::byte_array(), - Constant::Tuple { elements, .. } => { - builtins::tuple(elements.iter().map(|e| e.tipo()).collect()) - } - Constant::List { tipo, .. } - | Constant::Record { tipo, .. } - | Constant::Var { tipo, .. } => tipo.clone(), } } -} -impl Constant { pub fn location(&self) -> Span { match self { Constant::Int { location, .. } - | Constant::Tuple { location, .. } - | Constant::List { location, .. } | Constant::String { location, .. } - | Constant::Record { location, .. } - | Constant::ByteArray { location, .. } - | Constant::Var { location, .. } => *location, + | Constant::ByteArray { location, .. } => *location, } } - - pub fn is_simple(&self) -> bool { - matches!( - self, - Self::Int { .. } | Self::ByteArray { .. } | Self::String { .. } - ) - } } pub type TypedCallArg = CallArg; @@ -836,15 +776,15 @@ pub type MultiPattern = Vec; pub type TypedMultiPattern = MultiPattern>; -pub type TypedClause = Clause, String>; -pub type UntypedClause = Clause; +pub type TypedClause = Clause>; +pub type UntypedClause = Clause; #[derive(Debug, Clone, PartialEq)] -pub struct Clause { +pub struct Clause { pub location: Span, pub pattern: MultiPattern, pub alternative_patterns: Vec>, - pub guard: Option>, + pub guard: Option>, pub then: Expr, } @@ -861,11 +801,11 @@ impl TypedClause { } } -pub type UntypedClauseGuard = ClauseGuard<(), ()>; -pub type TypedClauseGuard = ClauseGuard, String>; +pub type UntypedClauseGuard = ClauseGuard<()>; +pub type TypedClauseGuard = ClauseGuard>; #[derive(Debug, Clone, PartialEq)] -pub enum ClauseGuard { +pub enum ClauseGuard { Not { location: Span, value: Box, @@ -925,10 +865,10 @@ pub enum ClauseGuard { name: String, }, - Constant(Constant), + Constant(Constant), } -impl ClauseGuard { +impl ClauseGuard { pub fn location(&self) -> Span { match self { ClauseGuard::Constant(constant) => constant.location(), diff --git a/crates/aiken-lang/src/builder.rs b/crates/aiken-lang/src/builder.rs index 876626f3..3d9c0a64 100644 --- a/crates/aiken-lang/src/builder.rs +++ b/crates/aiken-lang/src/builder.rs @@ -397,8 +397,8 @@ pub fn convert_data_to_type(term: Term, field_type: &Arc) -> Term, String>>, -) -> Vec, String>> { + clauses: Vec>>, +) -> Vec>> { let mut sorted_clauses = clauses; // if we have a list sort clauses so we can plug holes for cases not covered by clauses @@ -1066,11 +1066,7 @@ pub fn check_when_pattern_needs( } } -pub fn constants_ir( - literal: &Constant, String>, - ir_stack: &mut Vec, - scope: Vec, -) { +pub fn constants_ir(literal: &Constant, ir_stack: &mut Vec, scope: Vec) { match literal { Constant::Int { value, .. } => { ir_stack.push(Air::Int { @@ -1084,32 +1080,12 @@ pub fn constants_ir( value: value.clone(), }); } - Constant::Tuple { .. } => { - todo!() - } - Constant::List { elements, tipo, .. } => { - ir_stack.push(Air::List { - scope: scope.clone(), - count: elements.len(), - tipo: tipo.clone(), - tail: false, - }); - - for element in elements { - constants_ir(element, ir_stack, scope.clone()); - } - } - Constant::Record { .. } => { - // ir_stack.push(Air::Record { scope, }); - todo!() - } Constant::ByteArray { bytes, .. } => { ir_stack.push(Air::ByteArray { scope, bytes: bytes.clone(), }); } - Constant::Var { .. } => todo!(), }; } @@ -2072,7 +2048,7 @@ pub fn replace_opaque_type(t: &mut Arc, data_types: IndexMap, String>, + clause_guard: &ClauseGuard>, clause_guard_vec: &mut Vec, scope: Vec, ) { diff --git a/crates/aiken-lang/src/expr.rs b/crates/aiken-lang/src/expr.rs index 36cfb1f0..2ce99d3b 100644 --- a/crates/aiken-lang/src/expr.rs +++ b/crates/aiken-lang/src/expr.rs @@ -103,7 +103,7 @@ pub enum TypedExpr { location: Span, tipo: Arc, subjects: Vec, - clauses: Vec, String>>, + clauses: Vec>>, }, If { @@ -390,7 +390,7 @@ pub enum UntypedExpr { When { location: Span, subjects: Vec, - clauses: Vec>, + clauses: Vec>, }, If { diff --git a/crates/aiken-lang/src/format.rs b/crates/aiken-lang/src/format.rs index 9b8cd0d3..ffeeca5d 100644 --- a/crates/aiken-lang/src/format.rs +++ b/crates/aiken-lang/src/format.rs @@ -7,10 +7,10 @@ use crate::{ ast::{ Annotation, Arg, ArgName, AssignmentKind, BinOp, CallArg, ClauseGuard, Constant, DataType, Definition, Function, IfBranch, ModuleConstant, Pattern, RecordConstructor, - RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypeAlias, TypedArg, - TypedConstant, UnOp, UnqualifiedImport, UntypedArg, UntypedClause, UntypedClauseGuard, - UntypedDefinition, UntypedFunction, UntypedModule, UntypedPattern, UntypedRecordUpdateArg, - Use, Validator, CAPTURE_VARIABLE, + RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypeAlias, TypedArg, UnOp, + UnqualifiedImport, UntypedArg, UntypedClause, UntypedClauseGuard, UntypedDefinition, + UntypedFunction, UntypedModule, UntypedPattern, UntypedRecordUpdateArg, Use, Validator, + CAPTURE_VARIABLE, }, docvec, expr::{UntypedExpr, DEFAULT_ERROR_STR, DEFAULT_TODO_STR}, @@ -324,82 +324,15 @@ impl<'comments> Formatter<'comments> { }) } - fn const_expr<'a, A, B>(&mut self, value: &'a Constant) -> Document<'a> { + fn const_expr<'a>(&mut self, value: &'a Constant) -> Document<'a> { match value { Constant::ByteArray { bytes, .. } => self.bytearray(bytes), Constant::Int { value, .. } => value.to_doc(), - Constant::String { value, .. } => self.string(value), - - Constant::List { elements, .. } => { - let comma: fn() -> Document<'a> = if elements.iter().all(Constant::is_simple) { - || flex_break(",", ", ") - } else { - || break_(",", ", ") - }; - let elements_document = join(elements.iter().map(|e| self.const_expr(e)), comma()); - list(elements_document, elements.len(), None) - } - - Constant::Record { - name, - args, - module: None, - .. - } if args.is_empty() => name.to_doc(), - - Constant::Record { - name, - args, - module: Some(m), - .. - } if args.is_empty() => m.to_doc().append(".").append(name.as_str()), - - Constant::Record { - name, - args, - module: None, - .. - } => name - .to_doc() - .append(wrap_args( - args.iter() - .map(|a| (self.constant_call_arg(a), a.label.is_some())), - )) - .group(), - - Constant::Record { - name, - args, - module: Some(m), - .. - } => m - .to_doc() - .append(".") - .append(name.as_str()) - .append(wrap_args( - args.iter() - .map(|a| (self.constant_call_arg(a), a.label.is_some())), - )) - .group(), - - Constant::Var { - name, module: None, .. - } => name.to_doc(), - - Constant::Var { - name, - module: Some(module), - .. - } => docvec![module, ".", name], - - Constant::Tuple { elements, .. } => { - wrap_args(elements.iter().map(|e| (self.const_expr(e), false))).group() - } } } - pub fn docs_const_expr<'a>(&mut self, name: &'a str, value: &'a TypedConstant) -> Document<'a> { + pub fn docs_const_expr<'a>(&mut self, name: &'a str, value: &'a Constant) -> Document<'a> { let mut printer = tipo::pretty::Printer::new(); name.to_doc() .append(": ") @@ -1631,13 +1564,6 @@ impl<'comments> Formatter<'comments> { } } - fn constant_call_arg<'a, A, B>(&mut self, arg: &'a CallArg>) -> Document<'a> { - match &arg.label { - None => self.const_expr(&arg.value), - Some(s) => s.to_doc().append(": ").append(self.const_expr(&arg.value)), - } - } - fn un_op<'a>(&mut self, value: &'a UntypedExpr, op: &'a UnOp) -> Document<'a> { match op { UnOp::Not => docvec!["!", self.wrap_unary_op(value)], diff --git a/crates/aiken-lang/src/parser.rs b/crates/aiken-lang/src/parser.rs index 2a3fd7bd..fabdec17 100644 --- a/crates/aiken-lang/src/parser.rs +++ b/crates/aiken-lang/src/parser.rs @@ -386,162 +386,32 @@ fn constant_parser() -> impl Parser impl Parser { - recursive(|r| { - let constant_string_parser = - select! {Token::String {value} => value}.map_with_span(|value, span| { - ast::UntypedConstant::String { - location: span, - value, - } - }); - - let constant_int_parser = - select! {Token::Int {value} => value}.map_with_span(|value, span| { - ast::UntypedConstant::Int { - location: span, - value, - } - }); - - let constant_tuple_parser = r - .clone() - .separated_by(just(Token::Comma)) - .at_least(2) - .allow_trailing() - .delimited_by( - choice((just(Token::LeftParen), just(Token::NewLineLeftParen))), - just(Token::RightParen), - ) - .map_with_span(|elements, span| ast::UntypedConstant::Tuple { +fn constant_value_parser() -> impl Parser { + let constant_string_parser = + select! {Token::String {value} => value}.map_with_span(|value, span| { + ast::Constant::String { location: span, - elements, - }); + value, + } + }); - let constant_bytearray_parser = - bytearray_parser().map_with_span(|bytes, span| ast::UntypedConstant::ByteArray { - location: span, - bytes, - }); + let constant_int_parser = + select! {Token::Int {value} => value}.map_with_span(|value, span| ast::Constant::Int { + location: span, + value, + }); - let constant_list_parser = r - .clone() - .separated_by(just(Token::Comma)) - .allow_trailing() - .delimited_by(just(Token::LeftSquare), just(Token::RightSquare)) - .map_with_span(|elements, span| ast::UntypedConstant::List { - location: span, - elements, - tipo: (), - }); + let constant_bytearray_parser = + bytearray_parser().map_with_span(|bytes, span| ast::Constant::ByteArray { + location: span, + bytes, + }); - let constant_record_parser = choice(( - choice(( - select! {Token::Name { name } => name} - .then_ignore(just(Token::Dot)) - .or_not() - .then(select! {Token::UpName { name } => name}) - .then( - select! {Token::Name {name} => name} - .then_ignore(just(Token::Colon)) - .or_not() - .then(r.clone()) - .validate(|(label_opt, value), span, emit| { - let label = if label_opt.is_some() { - label_opt - } else if let ast::UntypedConstant::Var { name, .. } = &value { - Some(name.clone()) - } else { - emit(ParseError::expected_input_found( - value.location(), - None, - Some(error::Pattern::RecordPunning), - )); - - None - }; - - ast::CallArg { - location: span, - value, - label, - } - }) - .separated_by(just(Token::Comma)) - .allow_trailing() - .delimited_by(just(Token::LeftBrace), just(Token::RightBrace)), - ) - .map_with_span( - |((module, name), args), span| ast::UntypedConstant::Record { - location: span, - module, - name, - args, - tag: (), - tipo: (), - field_map: None, - }, - ), - select! {Token::Name { name } => name} - .then_ignore(just(Token::Dot)) - .or_not() - .then(select! {Token::UpName { name } => name}) - .then( - r.clone() - .map_with_span(|value, span| ast::CallArg { - location: span, - value, - label: None, - }) - .separated_by(just(Token::Comma)) - .allow_trailing() - .delimited_by(just(Token::LeftParen), just(Token::RightParen)), - ) - .map_with_span( - |((module, name), args), span| ast::UntypedConstant::Record { - location: span, - module, - name, - args, - tag: (), - tipo: (), - field_map: None, - }, - ), - )), - select! {Token::Name { name } => name} - .then_ignore(just(Token::Dot)) - .then(select! {Token::Name{name} => name}) - .map_with_span(|(module, name), span: Span| ast::UntypedConstant::Var { - location: span.union(span), - module: Some(module), - name, - constructor: None, - tipo: (), - }), - )); - - let constant_var_parser = - select! {Token::Name {name} => name}.map_with_span(|name, span| { - ast::UntypedConstant::Var { - location: span, - module: None, - name, - constructor: None, - tipo: (), - } - }); - - choice(( - constant_string_parser, - constant_int_parser, - constant_bytearray_parser, - constant_tuple_parser, - constant_list_parser, - constant_record_parser, - constant_var_parser, - )) - }) + choice(( + constant_string_parser, + constant_int_parser, + constant_bytearray_parser, + )) } pub fn bytearray_parser() -> impl Parser, Error = ParseError> { @@ -1407,8 +1277,7 @@ pub fn expr_parser( }) } -pub fn when_clause_guard_parser() -> impl Parser, Error = ParseError> -{ +pub fn when_clause_guard_parser() -> impl Parser, Error = ParseError> { recursive(|r| { let var_parser = select! { Token::Name { name } => name, diff --git a/crates/aiken-lang/src/tipo.rs b/crates/aiken-lang/src/tipo.rs index fa8f31e3..693a193b 100644 --- a/crates/aiken-lang/src/tipo.rs +++ b/crates/aiken-lang/src/tipo.rs @@ -3,7 +3,7 @@ use std::{cell::RefCell, collections::HashMap, ops::Deref, sync::Arc}; use uplc::{ast::Type as UplcType, builtins::DefaultFunction}; use crate::{ - ast::{Constant, DefinitionLocation, ModuleKind, Span, TypedConstant}, + ast::{Constant, DefinitionLocation, ModuleKind, Span}, tipo::fields::FieldMap, }; @@ -584,7 +584,7 @@ pub enum ValueConstructorVariant { ModuleConstant { location: Span, module: String, - literal: Constant, String>, + literal: Constant, }, /// A function belonging to the module @@ -744,7 +744,7 @@ pub enum ModuleValueConstructor { }, Constant { - literal: TypedConstant, + literal: Constant, location: Span, }, } diff --git a/crates/aiken-lang/src/tipo/expr.rs b/crates/aiken-lang/src/tipo/expr.rs index 7eabeb90..8bb97739 100644 --- a/crates/aiken-lang/src/tipo/expr.rs +++ b/crates/aiken-lang/src/tipo/expr.rs @@ -6,9 +6,9 @@ use crate::{ ast::{ Annotation, Arg, ArgName, AssignmentKind, BinOp, CallArg, Clause, ClauseGuard, Constant, IfBranch, RecordUpdateSpread, Span, TraceKind, Tracing, TypedArg, TypedCallArg, - TypedClause, TypedClauseGuard, TypedConstant, TypedIfBranch, TypedMultiPattern, - TypedRecordUpdateArg, UnOp, UntypedArg, UntypedClause, UntypedClauseGuard, UntypedConstant, - UntypedIfBranch, UntypedMultiPattern, UntypedPattern, UntypedRecordUpdateArg, + TypedClause, TypedClauseGuard, TypedIfBranch, TypedMultiPattern, TypedRecordUpdateArg, + UnOp, UntypedArg, UntypedClause, UntypedClauseGuard, UntypedIfBranch, UntypedMultiPattern, + UntypedPattern, UntypedRecordUpdateArg, }, builtins::{bool, byte_array, function, int, list, string, tuple}, expr::{TypedExpr, UntypedExpr}, @@ -22,8 +22,7 @@ use super::{ hydrator::Hydrator, pattern::PatternTyper, pipe::PipeTyper, - ModuleValueConstructor, PatternConstructor, RecordAccessor, Type, ValueConstructor, - ValueConstructorVariant, + PatternConstructor, RecordAccessor, Type, ValueConstructor, ValueConstructorVariant, }; #[derive(Debug)] @@ -48,7 +47,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { &mut self, subjects_count: usize, subjects: &[Arc], - typed_clauses: &[Clause, String>], + typed_clauses: &[Clause>], location: Span, ) -> Result<(), Vec> { // Because exhaustiveness checking in presence of multiple subjects is similar @@ -1338,29 +1337,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> { Ok((typed_pattern, typed_alternatives)) } - fn infer_const_tuple( - &mut self, - untyped_elements: Vec, - location: Span, - ) -> Result { - let mut elements = Vec::with_capacity(untyped_elements.len()); - - for element in untyped_elements { - let element = self.infer_const(&None, element)?; - - elements.push(element); - } - - Ok(Constant::Tuple { elements, location }) - } - // TODO: extract the type annotation checking into a infer_module_const // function that uses this function internally pub fn infer_const( &mut self, annotation: &Option, - value: UntypedConstant, - ) -> Result { + value: Constant, + ) -> Result { let inferred = match value { Constant::Int { location, value, .. @@ -1370,216 +1353,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { location, value, .. } => Ok(Constant::String { location, value }), - Constant::Tuple { - elements, location, .. - } => self.infer_const_tuple(elements, location), - - Constant::List { - elements, location, .. - } => self.infer_const_list(elements, location), - Constant::ByteArray { location, bytes } => Ok(Constant::ByteArray { location, bytes }), - - Constant::Record { - module, - location, - name, - args, - // field_map, is always None here because untyped not yet unified - .. - } if args.is_empty() => { - // Register the module as having been used if it was imported - if let Some(ref module) = &module { - self.environment.unused_modules.remove(module); - } - - // Type check the record constructor - let constructor = self.infer_value_constructor(&module, &name, &location)?; - - let (tag, field_map) = match &constructor.variant { - ValueConstructorVariant::Record { - name, field_map, .. - } => (name.clone(), field_map.clone()), - - ValueConstructorVariant::ModuleFn { .. } - | ValueConstructorVariant::LocalVariable { .. } => { - return Err(Error::NonLocalClauseGuardVariable { location, name }) - } - - // TODO: remove this clone. Could use an rc instead - ValueConstructorVariant::ModuleConstant { literal, .. } => { - return Ok(literal.clone()) - } - }; - - Ok(Constant::Record { - module, - location, - name, - args: vec![], - tipo: constructor.tipo, - tag, - field_map, - }) - } - - Constant::Record { - module, - location, - name, - mut args, - // field_map, is always None here because untyped not yet unified - .. - } => { - // Register the module as having been used if it was imported - if let Some(ref module) = &module { - self.environment.unused_modules.remove(module); - } - - let constructor = self.infer_value_constructor(&module, &name, &location)?; - - let (tag, field_map) = match &constructor.variant { - ValueConstructorVariant::Record { - name, field_map, .. - } => (name.clone(), field_map.clone()), - - ValueConstructorVariant::ModuleFn { .. } - | ValueConstructorVariant::LocalVariable { .. } => { - return Err(Error::NonLocalClauseGuardVariable { location, name }) - } - - // TODO: remove this clone. Could be an rc instead - ValueConstructorVariant::ModuleConstant { literal, .. } => { - return Ok(literal.clone()) - } - }; - - // Pretty much all the other infer functions operate on UntypedExpr - // or TypedExpr rather than ClauseGuard. To make things easier we - // build the TypedExpr equivalent of the constructor and use that - // TODO: resvisit this. It is rather awkward at present how we - // have to convert to this other data structure. - let fun = match &module { - Some(module_name) => { - let tipo = Arc::clone(&constructor.tipo); - - let module_name = self - .environment - .imported_modules - .get(module_name) - .expect("Failed to find previously located module import") - .1 - .name - .clone(); - - let module_value_constructor = ModuleValueConstructor::Record { - name: name.clone(), - field_map: field_map.clone(), - arity: args.len(), - tipo: Arc::clone(&tipo), - location: constructor.variant.location(), - }; - - TypedExpr::ModuleSelect { - label: name.clone(), - module_alias: module_name.clone(), - module_name, - tipo, - constructor: module_value_constructor, - location, - } - } - - None => TypedExpr::Var { - constructor, - location, - name: name.clone(), - }, - }; - - // This is basically the same code as do_infer_call_with_known_fun() - // except the args are typed with infer_clause_guard() here. - // This duplication is a bit awkward but it works! - // Potentially this could be improved later - match self.get_field_map(&fun, location)? { - // The fun has a field map so labelled arguments may be present and need to be reordered. - Some(field_map) => field_map.reorder(&mut args, location)?, - - // The fun has no field map and so we error if arguments have been labelled - None => assert_no_labeled_arguments(&args) - .map(|(location, label)| { - Err(Error::UnexpectedLabeledArg { location, label }) - }) - .unwrap_or(Ok(()))?, - } - - let (mut args_types, return_type) = self.environment.match_fun_type( - fun.tipo(), - args.len(), - fun.location(), - location, - )?; - - let mut typed_args = Vec::new(); - - for (tipo, arg) in args_types.iter_mut().zip(args) { - let CallArg { - label, - value, - location, - } = arg; - - let value = self.infer_const(&None, value)?; - - self.unify(tipo.clone(), value.tipo(), value.location(), tipo.is_data())?; - - typed_args.push(CallArg { - label, - value, - location, - }); - } - - Ok(Constant::Record { - module, - location, - name, - args: typed_args, - tipo: return_type, - tag, - field_map, - }) - } - Constant::Var { - location, - module, - name, - .. - } => { - // Register the module as having been used if it was imported - if let Some(ref module) = &module { - self.environment.unused_modules.remove(module); - } - - // Infer the type of this constant - let constructor = self.infer_value_constructor(&module, &name, &location)?; - - match constructor.variant { - ValueConstructorVariant::ModuleConstant { .. } - | ValueConstructorVariant::ModuleFn { .. } => Ok(Constant::Var { - location, - module, - name, - tipo: Arc::clone(&constructor.tipo), - constructor: Some(Box::from(constructor)), - }), - // constructor.variant cannot be a LocalVariable because module constants can - // only be defined at module scope. It also cannot be a Record because then - // this constant would have been parsed as a Constant::Record. Therefore this - // code is unreachable. - _ => unreachable!(), - } - } }?; // Check type annotation is accurate. @@ -1597,30 +1371,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> { Ok(inferred) } - fn infer_const_list( - &mut self, - untyped_elements: Vec, - location: Span, - ) -> Result { - let tipo = self.new_unbound_var(); - - let mut elements = Vec::with_capacity(untyped_elements.len()); - - for element in untyped_elements { - let element = self.infer_const(&None, element)?; - - self.unify(tipo.clone(), element.tipo(), element.location(), false)?; - - elements.push(element); - } - - Ok(Constant::List { - elements, - location, - tipo: list(tipo), - }) - } - fn infer_if( &mut self, branches: Vec1, diff --git a/crates/aiken-lang/src/uplc.rs b/crates/aiken-lang/src/uplc.rs index 8e3004eb..0e451146 100644 --- a/crates/aiken-lang/src/uplc.rs +++ b/crates/aiken-lang/src/uplc.rs @@ -689,7 +689,7 @@ impl<'a> CodeGenerator<'a> { &mut self, ir_stack: &mut Vec, clause_properties: &mut ClauseProperties, - clauses: &[Clause, String>], + clauses: &[Clause>], subject_type: &Arc, scope: Vec, ) { diff --git a/examples/acceptance_tests/060/lib/tests.ak b/examples/acceptance_tests/060/lib/tests.ak index 54edb79d..1a7c8776 100644 --- a/examples/acceptance_tests/060/lib/tests.ak +++ b/examples/acceptance_tests/060/lib/tests.ak @@ -1,15 +1,17 @@ -type Foo { - foo: Int, +const int_constant = 42 + +test int() { + int_constant == 42 } -const foo_constant = Foo { foo: 42 } +const bytearray_constant = #"abcd" -test foo() { - foo_constant == Foo { foo: 42 } +test bytearray() { + bytearray_constant == #"abcd" } -const tuple_constant = (1, 2, 3) +const string_constant = "FOO" -test bar() { - tuple_constant == (1, 2, 3) +test string() { + string_constant == "FOO" }