Merge pull request #390 from aiken-lang/acceptance-test-060--record-and-tuple-constants
Remove complex constants.
This commit is contained in:
		
						commit
						1aea586cab
					
				| 
						 | 
				
			
			@ -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<PackageName> {
 | 
			
		|||
    pub unqualified: Vec<UnqualifiedImport>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub type TypedModuleConstant = ModuleConstant<Arc<Type>, String>;
 | 
			
		||||
pub type UntypedModuleConstant = ModuleConstant<(), ()>;
 | 
			
		||||
pub type TypedModuleConstant = ModuleConstant<Arc<Type>>;
 | 
			
		||||
pub type UntypedModuleConstant = ModuleConstant<()>;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
pub struct ModuleConstant<T, ConstantRecordTag> {
 | 
			
		||||
pub struct ModuleConstant<T> {
 | 
			
		||||
    pub doc: Option<String>,
 | 
			
		||||
    pub location: Span,
 | 
			
		||||
    pub public: bool,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub annotation: Option<Annotation>,
 | 
			
		||||
    pub value: Box<Constant<T, ConstantRecordTag>>,
 | 
			
		||||
    pub value: Box<Constant>,
 | 
			
		||||
    pub tipo: T,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -270,11 +270,11 @@ pub struct Validator<T, Expr> {
 | 
			
		|||
    pub params: Vec<Arg<T>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub type TypedDefinition = Definition<Arc<Type>, TypedExpr, String, String>;
 | 
			
		||||
pub type UntypedDefinition = Definition<(), UntypedExpr, (), ()>;
 | 
			
		||||
pub type TypedDefinition = Definition<Arc<Type>, TypedExpr, String>;
 | 
			
		||||
pub type UntypedDefinition = Definition<(), UntypedExpr, ()>;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
pub enum Definition<T, Expr, ConstantRecordTag, PackageName> {
 | 
			
		||||
pub enum Definition<T, Expr, PackageName> {
 | 
			
		||||
    Fn(Function<T, Expr>),
 | 
			
		||||
 | 
			
		||||
    TypeAlias(TypeAlias<T>),
 | 
			
		||||
| 
						 | 
				
			
			@ -283,14 +283,14 @@ pub enum Definition<T, Expr, ConstantRecordTag, PackageName> {
 | 
			
		|||
 | 
			
		||||
    Use(Use<PackageName>),
 | 
			
		||||
 | 
			
		||||
    ModuleConstant(ModuleConstant<T, ConstantRecordTag>),
 | 
			
		||||
    ModuleConstant(ModuleConstant<T>),
 | 
			
		||||
 | 
			
		||||
    Test(Function<T, Expr>),
 | 
			
		||||
 | 
			
		||||
    Validator(Validator<T, Expr>),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<A, B, C, E> Definition<A, B, C, E> {
 | 
			
		||||
impl<A, B, C> Definition<A, B, C> {
 | 
			
		||||
    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<Arc<Type>, String>;
 | 
			
		||||
pub type UntypedConstant = Constant<(), ()>;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
pub enum Constant<T, RecordTag> {
 | 
			
		||||
    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<Self>,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    List {
 | 
			
		||||
        location: Span,
 | 
			
		||||
        elements: Vec<Self>,
 | 
			
		||||
        tipo: T,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Record {
 | 
			
		||||
        location: Span,
 | 
			
		||||
        module: Option<String>,
 | 
			
		||||
        name: String,
 | 
			
		||||
        args: Vec<CallArg<Self>>,
 | 
			
		||||
        tag: RecordTag,
 | 
			
		||||
        tipo: T,
 | 
			
		||||
        field_map: Option<FieldMap>,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    ByteArray {
 | 
			
		||||
        location: Span,
 | 
			
		||||
        bytes: Vec<u8>,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Var {
 | 
			
		||||
        location: Span,
 | 
			
		||||
        module: Option<String>,
 | 
			
		||||
        name: String,
 | 
			
		||||
        constructor: Option<Box<ValueConstructor>>,
 | 
			
		||||
        tipo: T,
 | 
			
		||||
    },
 | 
			
		||||
    ByteArray { location: Span, bytes: Vec<u8> },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TypedConstant {
 | 
			
		||||
impl Constant {
 | 
			
		||||
    pub fn tipo(&self) -> Arc<Type> {
 | 
			
		||||
        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<A, B> Constant<A, B> {
 | 
			
		||||
    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<TypedExpr>;
 | 
			
		||||
| 
						 | 
				
			
			@ -836,15 +776,15 @@ pub type MultiPattern<PatternConstructor, Type> = Vec<Pattern<PatternConstructor
 | 
			
		|||
pub type UntypedMultiPattern = MultiPattern<(), ()>;
 | 
			
		||||
pub type TypedMultiPattern = MultiPattern<PatternConstructor, Arc<Type>>;
 | 
			
		||||
 | 
			
		||||
pub type TypedClause = Clause<TypedExpr, PatternConstructor, Arc<Type>, String>;
 | 
			
		||||
pub type UntypedClause = Clause<UntypedExpr, (), (), ()>;
 | 
			
		||||
pub type TypedClause = Clause<TypedExpr, PatternConstructor, Arc<Type>>;
 | 
			
		||||
pub type UntypedClause = Clause<UntypedExpr, (), ()>;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
pub struct Clause<Expr, PatternConstructor, Type, RecordTag> {
 | 
			
		||||
pub struct Clause<Expr, PatternConstructor, Type> {
 | 
			
		||||
    pub location: Span,
 | 
			
		||||
    pub pattern: MultiPattern<PatternConstructor, Type>,
 | 
			
		||||
    pub alternative_patterns: Vec<MultiPattern<PatternConstructor, Type>>,
 | 
			
		||||
    pub guard: Option<ClauseGuard<Type, RecordTag>>,
 | 
			
		||||
    pub guard: Option<ClauseGuard<Type>>,
 | 
			
		||||
    pub then: Expr,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -861,11 +801,11 @@ impl TypedClause {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub type UntypedClauseGuard = ClauseGuard<(), ()>;
 | 
			
		||||
pub type TypedClauseGuard = ClauseGuard<Arc<Type>, String>;
 | 
			
		||||
pub type UntypedClauseGuard = ClauseGuard<()>;
 | 
			
		||||
pub type TypedClauseGuard = ClauseGuard<Arc<Type>>;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone, PartialEq)]
 | 
			
		||||
pub enum ClauseGuard<Type, RecordTag> {
 | 
			
		||||
pub enum ClauseGuard<Type> {
 | 
			
		||||
    Not {
 | 
			
		||||
        location: Span,
 | 
			
		||||
        value: Box<Self>,
 | 
			
		||||
| 
						 | 
				
			
			@ -925,10 +865,10 @@ pub enum ClauseGuard<Type, RecordTag> {
 | 
			
		|||
        name: String,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    Constant(Constant<Type, RecordTag>),
 | 
			
		||||
    Constant(Constant),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<A, B> ClauseGuard<A, B> {
 | 
			
		||||
impl<A> ClauseGuard<A> {
 | 
			
		||||
    pub fn location(&self) -> Span {
 | 
			
		||||
        match self {
 | 
			
		||||
            ClauseGuard::Constant(constant) => constant.location(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -397,8 +397,8 @@ pub fn convert_data_to_type(term: Term<Name>, field_type: &Arc<Type>) -> Term<Na
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
pub fn rearrange_clauses(
 | 
			
		||||
    clauses: Vec<Clause<TypedExpr, PatternConstructor, Arc<Type>, String>>,
 | 
			
		||||
) -> Vec<Clause<TypedExpr, PatternConstructor, Arc<Type>, String>> {
 | 
			
		||||
    clauses: Vec<Clause<TypedExpr, PatternConstructor, Arc<Type>>>,
 | 
			
		||||
) -> Vec<Clause<TypedExpr, PatternConstructor, Arc<Type>>> {
 | 
			
		||||
    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<Arc<Type>, String>,
 | 
			
		||||
    ir_stack: &mut Vec<Air>,
 | 
			
		||||
    scope: Vec<u64>,
 | 
			
		||||
) {
 | 
			
		||||
pub fn constants_ir(literal: &Constant, ir_stack: &mut Vec<Air>, scope: Vec<u64>) {
 | 
			
		||||
    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<Type>, data_types: IndexMap<DataTypeKey,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
pub fn handle_clause_guard(
 | 
			
		||||
    clause_guard: &ClauseGuard<Arc<Type>, String>,
 | 
			
		||||
    clause_guard: &ClauseGuard<Arc<Type>>,
 | 
			
		||||
    clause_guard_vec: &mut Vec<Air>,
 | 
			
		||||
    scope: Vec<u64>,
 | 
			
		||||
) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ pub enum TypedExpr {
 | 
			
		|||
        location: Span,
 | 
			
		||||
        tipo: Arc<Type>,
 | 
			
		||||
        subjects: Vec<Self>,
 | 
			
		||||
        clauses: Vec<Clause<Self, PatternConstructor, Arc<Type>, String>>,
 | 
			
		||||
        clauses: Vec<Clause<Self, PatternConstructor, Arc<Type>>>,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    If {
 | 
			
		||||
| 
						 | 
				
			
			@ -390,7 +390,7 @@ pub enum UntypedExpr {
 | 
			
		|||
    When {
 | 
			
		||||
        location: Span,
 | 
			
		||||
        subjects: Vec<Self>,
 | 
			
		||||
        clauses: Vec<Clause<Self, (), (), ()>>,
 | 
			
		||||
        clauses: Vec<Clause<Self, (), ()>>,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    If {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<A, B>) -> 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<Constant<A, B>>) -> 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)],
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -386,162 +386,32 @@ fn constant_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
 | 
			
		|||
        })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn constant_value_parser() -> impl Parser<Token, ast::UntypedConstant, Error = ParseError> {
 | 
			
		||||
    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<Token, ast::Constant, Error = ParseError> {
 | 
			
		||||
    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<Token, Vec<u8>, Error = ParseError> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1407,8 +1277,7 @@ pub fn expr_parser(
 | 
			
		|||
    })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn when_clause_guard_parser() -> impl Parser<Token, ast::ClauseGuard<(), ()>, Error = ParseError>
 | 
			
		||||
{
 | 
			
		||||
pub fn when_clause_guard_parser() -> impl Parser<Token, ast::ClauseGuard<()>, Error = ParseError> {
 | 
			
		||||
    recursive(|r| {
 | 
			
		||||
        let var_parser = select! {
 | 
			
		||||
            Token::Name { name } => name,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<Arc<Type>, String>,
 | 
			
		||||
        literal: Constant,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /// A function belonging to the module
 | 
			
		||||
| 
						 | 
				
			
			@ -744,7 +744,7 @@ pub enum ModuleValueConstructor {
 | 
			
		|||
    },
 | 
			
		||||
 | 
			
		||||
    Constant {
 | 
			
		||||
        literal: TypedConstant,
 | 
			
		||||
        literal: Constant,
 | 
			
		||||
        location: Span,
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<Type>],
 | 
			
		||||
        typed_clauses: &[Clause<TypedExpr, PatternConstructor, Arc<Type>, String>],
 | 
			
		||||
        typed_clauses: &[Clause<TypedExpr, PatternConstructor, Arc<Type>>],
 | 
			
		||||
        location: Span,
 | 
			
		||||
    ) -> Result<(), Vec<String>> {
 | 
			
		||||
        // 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<UntypedConstant>,
 | 
			
		||||
        location: Span,
 | 
			
		||||
    ) -> Result<TypedConstant, Error> {
 | 
			
		||||
        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<Annotation>,
 | 
			
		||||
        value: UntypedConstant,
 | 
			
		||||
    ) -> Result<TypedConstant, Error> {
 | 
			
		||||
        value: Constant,
 | 
			
		||||
    ) -> Result<Constant, Error> {
 | 
			
		||||
        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<UntypedConstant>,
 | 
			
		||||
        location: Span,
 | 
			
		||||
    ) -> Result<TypedConstant, Error> {
 | 
			
		||||
        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<UntypedIfBranch>,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -689,7 +689,7 @@ impl<'a> CodeGenerator<'a> {
 | 
			
		|||
        &mut self,
 | 
			
		||||
        ir_stack: &mut Vec<Air>,
 | 
			
		||||
        clause_properties: &mut ClauseProperties,
 | 
			
		||||
        clauses: &[Clause<TypedExpr, PatternConstructor, Arc<Type>, String>],
 | 
			
		||||
        clauses: &[Clause<TypedExpr, PatternConstructor, Arc<Type>>],
 | 
			
		||||
        subject_type: &Arc<Type>,
 | 
			
		||||
        scope: Vec<u64>,
 | 
			
		||||
    ) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
# This file was generated by Aiken
 | 
			
		||||
# You typically do not need to edit this file
 | 
			
		||||
 | 
			
		||||
requirements = []
 | 
			
		||||
packages = []
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
name = "aiken-lang/acceptance_test_060"
 | 
			
		||||
version = "0.0.0"
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
const int_constant = 42
 | 
			
		||||
 | 
			
		||||
test int() {
 | 
			
		||||
  int_constant == 42
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const bytearray_constant = #"abcd"
 | 
			
		||||
 | 
			
		||||
test bytearray() {
 | 
			
		||||
  bytearray_constant == #"abcd"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const string_constant = "FOO"
 | 
			
		||||
 | 
			
		||||
test string() {
 | 
			
		||||
  string_constant == "FOO"
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue