From cd0a9440e86f2fd0c4f069789052ed26022ab564 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Fri, 2 Aug 2024 17:23:14 +0200 Subject: [PATCH] Allow any expression as constants This is only a start. It compiles, but with a few TODOs left open. In particular, it doesn't currently handle constants depending on other constants or functions; nor does it hoist constants. --- crates/aiken-lang/src/ast.rs | 73 +++++------------- crates/aiken-lang/src/format.rs | 34 +++------ crates/aiken-lang/src/gen_uplc.rs | 76 +++++++++++++++---- crates/aiken-lang/src/gen_uplc/builder.rs | 13 +--- .../src/parser/definition/constant.rs | 68 ++--------------- .../snapshots/g1_element_constant.snap | 1 - .../snapshots/g2_element_constant.snap | 1 - .../aiken-lang/src/parser/expr/when/guard.rs | 23 +++++- crates/aiken-lang/src/tipo.rs | 30 +++++--- crates/aiken-lang/src/tipo/expr.rs | 70 ++--------------- crates/aiken-lang/src/tipo/infer.rs | 26 +++++-- crates/aiken-project/src/config.rs | 25 ++---- crates/aiken-project/src/lib.rs | 6 +- crates/aiken-project/src/module.rs | 4 +- crates/aiken-project/src/test_framework.rs | 11 ++- crates/aiken-project/src/tests/mod.rs | 11 ++- crates/uplc/src/tx/error.rs | 2 +- 17 files changed, 192 insertions(+), 282 deletions(-) diff --git a/crates/aiken-lang/src/ast.rs b/crates/aiken-lang/src/ast.rs index ae90feda..a76ab0f7 100644 --- a/crates/aiken-lang/src/ast.rs +++ b/crates/aiken-lang/src/ast.rs @@ -161,6 +161,7 @@ impl TypedModule { pub fn register_definitions( &self, functions: &mut IndexMap, + constants: &mut IndexMap, data_types: &mut IndexMap, ) { for def in self.definitions() { @@ -203,7 +204,17 @@ impl TypedModule { } } - Definition::TypeAlias(_) | Definition::ModuleConstant(_) | Definition::Use(_) => {} + Definition::ModuleConstant(ModuleConstant { name, value, .. }) => { + constants.insert( + FunctionAccessKey { + module_name: self.name.clone(), + function_name: name.clone(), + }, + value.clone(), + ); + } + + Definition::TypeAlias(_) | Definition::Use(_) => {} } } } @@ -459,18 +470,17 @@ pub struct Use { pub unqualified: Vec, } -pub type TypedModuleConstant = ModuleConstant>; -pub type UntypedModuleConstant = ModuleConstant<()>; +pub type TypedModuleConstant = ModuleConstant; +pub type UntypedModuleConstant = ModuleConstant; #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -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 tipo: T, + pub value: Expr, } pub type TypedValidator = Validator, TypedArg, TypedExpr>; @@ -746,7 +756,7 @@ pub enum Definition { Use(Use), - ModuleConstant(ModuleConstant), + ModuleConstant(ModuleConstant), Test(Function>), @@ -843,55 +853,6 @@ pub struct DefinitionLocation<'module> { pub span: Span, } -#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] -pub enum Constant { - Int { - location: Span, - value: String, - base: Base, - }, - - String { - location: Span, - value: String, - }, - - ByteArray { - location: Span, - bytes: Vec, - preferred_format: ByteArrayFormatPreference, - }, - - CurvePoint { - location: Span, - point: Box, - preferred_format: ByteArrayFormatPreference, - }, -} - -impl Constant { - pub fn tipo(&self) -> Rc { - match self { - Constant::Int { .. } => Type::int(), - Constant::String { .. } => Type::string(), - Constant::ByteArray { .. } => Type::byte_array(), - Constant::CurvePoint { point, .. } => match point.as_ref() { - Curve::Bls12_381(Bls12_381Point::G1(_)) => Type::g1_element(), - Curve::Bls12_381(Bls12_381Point::G2(_)) => Type::g2_element(), - }, - } - } - - pub fn location(&self) -> Span { - match self { - Constant::Int { location, .. } - | Constant::String { location, .. } - | Constant::ByteArray { location, .. } - | Constant::CurvePoint { location, .. } => *location, - } - } -} - pub type TypedCallArg = CallArg; pub type ParsedCallArg = CallArg>; diff --git a/crates/aiken-lang/src/format.rs b/crates/aiken-lang/src/format.rs index f3294673..040fac29 100644 --- a/crates/aiken-lang/src/format.rs +++ b/crates/aiken-lang/src/format.rs @@ -1,7 +1,7 @@ use crate::{ ast::{ Annotation, ArgBy, ArgName, ArgVia, AssignmentKind, AssignmentPattern, BinOp, - ByteArrayFormatPreference, CallArg, Constant, CurveType, DataType, Definition, Function, + ByteArrayFormatPreference, CallArg, CurveType, DataType, Definition, Function, LogicalOpChainKind, ModuleConstant, OnTestFailure, Pattern, RecordConstructor, RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypeAlias, TypedArg, TypedValidator, UnOp, UnqualifiedImport, UntypedArg, UntypedArgVia, UntypedAssignmentKind, @@ -9,7 +9,7 @@ use crate::{ UntypedPattern, UntypedRecordUpdateArg, Use, Validator, CAPTURE_VARIABLE, }, docvec, - expr::{FnStyle, UntypedExpr, DEFAULT_ERROR_STR, DEFAULT_TODO_STR}, + expr::{FnStyle, TypedExpr, UntypedExpr, DEFAULT_ERROR_STR, DEFAULT_TODO_STR}, parser::{ extra::{Comment, ModuleExtra}, token::Base, @@ -338,34 +338,20 @@ impl<'comments> Formatter<'comments> { }) } - fn const_expr<'a>(&mut self, value: &'a Constant) -> Document<'a> { - match value { - Constant::ByteArray { - bytes, - preferred_format, - .. - } => self.bytearray(bytes, None, preferred_format), - Constant::CurvePoint { - point, - preferred_format, - .. - } => self.bytearray( - &point.compress(), - Some(point.as_ref().into()), - preferred_format, - ), - Constant::Int { value, base, .. } => self.int(value, base), - Constant::String { value, .. } => self.string(value), - } + fn const_expr<'a>(&mut self, _value: &'a UntypedExpr) -> Document<'a> { + todo!( + "format const_expr: surround complex expressions with a block, and leave simple expression without" + ); } - pub fn docs_const_expr<'a>(&mut self, name: &'a str, value: &'a Constant) -> Document<'a> { + pub fn docs_const_expr<'a>(&mut self, name: &'a str, value: &'a TypedExpr) -> Document<'a> { let mut printer = tipo::pretty::Printer::new(); name.to_doc() .append(": ") .append(printer.print(&value.tipo())) - .append(" = ") - .append(self.const_expr(value)) + // TODO: Show full expression in docs when simple enough + // .append(" = ") + // .append(self.const_expr(value)) } fn documented_definition<'a>(&mut self, s: &'a UntypedDefinition) -> Document<'a> { diff --git a/crates/aiken-lang/src/gen_uplc.rs b/crates/aiken-lang/src/gen_uplc.rs index 5e8e3757..352da36a 100644 --- a/crates/aiken-lang/src/gen_uplc.rs +++ b/crates/aiken-lang/src/gen_uplc.rs @@ -5,9 +5,9 @@ pub mod tree; use self::{ air::Air, builder::{ - cast_validator_args, constants_ir, convert_type_to_data, extract_constant, - modify_cyclic_calls, modify_self_calls, rearrange_list_clauses, AssignmentProperties, - ClauseProperties, CodeGenSpecialFuncs, CycleFunctionNames, HoistableFunction, Variant, + cast_validator_args, convert_type_to_data, extract_constant, modify_cyclic_calls, + modify_self_calls, rearrange_list_clauses, AssignmentProperties, ClauseProperties, + CodeGenSpecialFuncs, CycleFunctionNames, HoistableFunction, Variant, }, tree::{AirTree, TreePath}, }; @@ -58,6 +58,7 @@ pub struct CodeGenerator<'a> { plutus_version: PlutusVersion, /// immutable index maps functions: IndexMap<&'a FunctionAccessKey, &'a TypedFunction>, + constants: IndexMap<&'a FunctionAccessKey, &'a TypedExpr>, data_types: IndexMap<&'a DataTypeKey, &'a TypedDataType>, module_types: IndexMap<&'a str, &'a TypeInfo>, module_src: IndexMap<&'a str, &'a (String, LineNumbers)>, @@ -82,6 +83,7 @@ impl<'a> CodeGenerator<'a> { pub fn new( plutus_version: PlutusVersion, functions: IndexMap<&'a FunctionAccessKey, &'a TypedFunction>, + constants: IndexMap<&'a FunctionAccessKey, &'a TypedExpr>, data_types: IndexMap<&'a DataTypeKey, &'a TypedDataType>, module_types: IndexMap<&'a str, &'a TypeInfo>, module_src: IndexMap<&'a str, &'a (String, LineNumbers)>, @@ -90,6 +92,7 @@ impl<'a> CodeGenerator<'a> { CodeGenerator { plutus_version, functions, + constants, data_types, module_types, module_src, @@ -268,12 +271,7 @@ impl<'a> CodeGenerator<'a> { TypedExpr::Var { constructor, name, .. - } => match &constructor.variant { - ValueConstructorVariant::ModuleConstant { literal, .. } => { - constants_ir(literal) - } - _ => AirTree::var(constructor.clone(), name, ""), - }, + } => AirTree::var(constructor.clone(), name, ""), TypedExpr::Fn { args, body, .. } => AirTree::anon_func( args.iter() @@ -743,8 +741,16 @@ impl<'a> CodeGenerator<'a> { AirTree::builtin(*builtin, tipo.clone(), vec![]) } } - ModuleValueConstructor::Constant { literal, .. } => { - builder::constants_ir(literal) + ModuleValueConstructor::Constant { module, name, .. } => { + let type_info = self.module_types.get(module_name.as_str()).unwrap(); + + let value = type_info.values.get(name).unwrap(); + + AirTree::var( + ValueConstructor::public(tipo.clone(), value.variant.clone()), + format!("{module}_{name}"), + "", + ) } }, @@ -4245,8 +4251,52 @@ impl<'a> CodeGenerator<'a> { } .into(), )), - ValueConstructorVariant::ModuleConstant { .. } => { - unreachable!("{:#?}, {}", constructor, name) + ValueConstructorVariant::ModuleConstant { module, name, .. } => { + let access_key = FunctionAccessKey { + module_name: module.clone(), + function_name: name.clone(), + }; + + let definition = self + .constants + .get(&access_key) + .unwrap_or_else(|| panic!("unknown constant {module}.{name}")); + + let mut value = + AirTree::no_op(self.build(definition, &access_key.module_name, &[])); + + value.traverse_tree_with( + &mut |air_tree, _| { + erase_opaque_type_operations(air_tree, &self.data_types); + }, + true, + ); + + let term = self + .uplc_code_gen(value.to_vec()) + .constr_fields_exposer() + .constr_index_exposer(); + + let mut program: Program = Program { + version: (1, 0, 0), + term: self.special_functions.apply_used_functions(term), + }; + + let mut interner = CodeGenInterner::new(); + + interner.program(&mut program); + + let eval_program: Program = + program.remove_no_inlines().try_into().unwrap(); + + Some( + eval_program + .eval(ExBudget::max()) + .result() + .unwrap_or_else(|e| panic!("Failed to evaluate constant: {e:#?}")) + .try_into() + .unwrap(), + ) } ValueConstructorVariant::ModuleFn { name: func_name, diff --git a/crates/aiken-lang/src/gen_uplc/builder.rs b/crates/aiken-lang/src/gen_uplc/builder.rs index d2f166ac..a05d7d39 100644 --- a/crates/aiken-lang/src/gen_uplc/builder.rs +++ b/crates/aiken-lang/src/gen_uplc/builder.rs @@ -4,8 +4,8 @@ use super::{ }; use crate::{ ast::{ - Constant, DataTypeKey, FunctionAccessKey, Pattern, Span, TraceLevel, TypedArg, - TypedAssignmentKind, TypedClause, TypedDataType, TypedPattern, + DataTypeKey, FunctionAccessKey, Pattern, Span, TraceLevel, TypedArg, TypedAssignmentKind, + TypedClause, TypedDataType, TypedPattern, }, expr::TypedExpr, line_numbers::{LineColumn, LineNumbers}, @@ -287,15 +287,6 @@ impl Default for CodeGenSpecialFuncs { } } -pub fn constants_ir(literal: &Constant) -> AirTree { - match literal { - Constant::Int { value, .. } => AirTree::int(value), - Constant::String { value, .. } => AirTree::string(value), - Constant::ByteArray { bytes, .. } => AirTree::byte_array(bytes.clone()), - Constant::CurvePoint { point, .. } => AirTree::curve(*point.as_ref()), - } -} - pub fn get_generic_variant_name(t: &Rc) -> String { let uplc_type = t.get_uplc_type(); diff --git a/crates/aiken-lang/src/parser/definition/constant.rs b/crates/aiken-lang/src/parser/definition/constant.rs index 469f1abc..c8205be8 100644 --- a/crates/aiken-lang/src/parser/definition/constant.rs +++ b/crates/aiken-lang/src/parser/definition/constant.rs @@ -1,10 +1,8 @@ -use chumsky::prelude::*; -use uplc::machine::runtime::Compressable; - use crate::{ ast, - parser::{annotation, error::ParseError, literal, token::Token, utils}, + parser::{annotation, error::ParseError, expr::pure_expression, token::Token, utils}, }; +use chumsky::prelude::*; pub fn parser() -> impl Parser { utils::optional_flag(Token::Pub) @@ -16,7 +14,9 @@ pub fn parser() -> impl Parser impl Parser impl Parser { - let constant_string_parser = - select! {Token::String {value} => value}.map_with_span(|value, span| { - ast::Constant::String { - location: span, - value, - } - }); - - let constant_int_parser = - literal::int().map_with_span(|(value, base), location| ast::Constant::Int { - location, - value, - base, - }); - - let constant_bytearray_parser = literal::bytearray( - |bytes, preferred_format, curve, location, emit| match curve { - Some(curve @ ast::CurveType::Bls12_381(point)) => { - let point = match point { - ast::Bls12_381PointType::G1 => { - blst::blst_p1::uncompress(&bytes).map(ast::Bls12_381Point::G1) - } - ast::Bls12_381PointType::G2 => { - blst::blst_p2::uncompress(&bytes).map(ast::Bls12_381Point::G2) - } - }; - - let point = point.unwrap_or_else(|_err| { - emit(ParseError::point_not_on_curve(curve, location)); - - ast::Bls12_381Point::default() - }); - - ast::Constant::CurvePoint { - location, - point: ast::Curve::Bls12_381(point).into(), - preferred_format, - } - } - None => ast::Constant::ByteArray { - location, - bytes, - preferred_format, - }, - }, - ); - - choice(( - constant_string_parser, - constant_int_parser, - constant_bytearray_parser, - )) -} - #[cfg(test)] mod tests { use crate::assert_definition; diff --git a/crates/aiken-lang/src/parser/definition/snapshots/g1_element_constant.snap b/crates/aiken-lang/src/parser/definition/snapshots/g1_element_constant.snap index 4a009447..acaac4aa 100644 --- a/crates/aiken-lang/src/parser/definition/snapshots/g1_element_constant.snap +++ b/crates/aiken-lang/src/parser/definition/snapshots/g1_element_constant.snap @@ -49,6 +49,5 @@ ModuleConstant( ), preferred_format: HexadecimalString, }, - tipo: (), }, ) diff --git a/crates/aiken-lang/src/parser/definition/snapshots/g2_element_constant.snap b/crates/aiken-lang/src/parser/definition/snapshots/g2_element_constant.snap index 060b55a0..c9d455d8 100644 --- a/crates/aiken-lang/src/parser/definition/snapshots/g2_element_constant.snap +++ b/crates/aiken-lang/src/parser/definition/snapshots/g2_element_constant.snap @@ -91,6 +91,5 @@ ModuleConstant( ), preferred_format: HexadecimalString, }, - tipo: (), }, ) diff --git a/crates/aiken-lang/src/parser/expr/when/guard.rs b/crates/aiken-lang/src/parser/expr/when/guard.rs index 9a38cdf1..2bda8ac0 100644 --- a/crates/aiken-lang/src/parser/expr/when/guard.rs +++ b/crates/aiken-lang/src/parser/expr/when/guard.rs @@ -1,6 +1,6 @@ use crate::{ ast, - parser::{definition, error::ParseError, token::Token}, + parser::{error::ParseError, literal, token::Token}, }; use chumsky::prelude::*; @@ -12,13 +12,11 @@ pub fn parser() -> impl Parser impl Parser impl Parser { + let constant_string_parser = + select! {Token::String {value} => value}.map(|_| ast::UntypedClauseGuard {}); + + let constant_int_parser = literal::int().map(|_| ast::UntypedClauseGuard {}); + + let constant_bytearray_parser = literal::bytearray(|_, _, _, _, _| ast::UntypedClauseGuard {}); + + choice(( + constant_string_parser, + constant_int_parser, + constant_bytearray_parser, + )) +} diff --git a/crates/aiken-lang/src/tipo.rs b/crates/aiken-lang/src/tipo.rs index fad2f08e..3ea349e1 100644 --- a/crates/aiken-lang/src/tipo.rs +++ b/crates/aiken-lang/src/tipo.rs @@ -1,8 +1,8 @@ use self::{environment::Environment, pretty::Printer}; use crate::{ ast::{ - well_known, Annotation, Constant, DataType, DataTypeKey, DefinitionLocation, ModuleKind, - Span, TypedDataType, + well_known, Annotation, DataType, DataTypeKey, DefinitionLocation, ModuleKind, Span, + TypedDataType, }, tipo::fields::FieldMap, }; @@ -1101,11 +1101,13 @@ impl TypeVar { Self::Link { tipo } => tipo.get_inner_types(), Self::Unbound { .. } => vec![], var => { - vec![Type::Var { - tipo: RefCell::new(var.clone()).into(), - alias: None, - } - .into()] + vec![ + Type::Var { + tipo: RefCell::new(var.clone()).into(), + alias: None, + } + .into(), + ] } } } @@ -1216,7 +1218,7 @@ pub enum ValueConstructorVariant { ModuleConstant { location: Span, module: String, - literal: Constant, + name: String, }, /// A function belonging to the module @@ -1262,11 +1264,14 @@ impl ValueConstructorVariant { location: *location, }, - // TODO: remove this clone with an rc clone Self::ModuleConstant { - literal, location, .. + name, + module, + location, + .. } => ModuleValueConstructor::Constant { - literal: literal.clone(), + name: name.clone(), + module: module.clone(), location: *location, }, @@ -1400,8 +1405,9 @@ pub enum ModuleValueConstructor { }, Constant { - literal: Constant, location: Span, + module: String, + name: String, }, } diff --git a/crates/aiken-lang/src/tipo/expr.rs b/crates/aiken-lang/src/tipo/expr.rs index 2e2e16e0..376281db 100644 --- a/crates/aiken-lang/src/tipo/expr.rs +++ b/crates/aiken-lang/src/tipo/expr.rs @@ -11,11 +11,11 @@ use super::{ use crate::{ ast::{ self, Annotation, ArgName, AssignmentKind, AssignmentPattern, BinOp, Bls12_381Point, - ByteArrayFormatPreference, CallArg, Constant, Curve, Function, IfBranch, - LogicalOpChainKind, Pattern, RecordUpdateSpread, Span, TraceKind, TraceLevel, Tracing, - TypedArg, TypedCallArg, TypedClause, TypedIfBranch, TypedPattern, TypedRecordUpdateArg, - TypedValidator, UnOp, UntypedArg, UntypedAssignmentKind, UntypedClause, UntypedFunction, - UntypedIfBranch, UntypedPattern, UntypedRecordUpdateArg, + ByteArrayFormatPreference, CallArg, Curve, Function, IfBranch, LogicalOpChainKind, Pattern, + RecordUpdateSpread, Span, TraceKind, TraceLevel, Tracing, TypedArg, TypedCallArg, + TypedClause, TypedIfBranch, TypedPattern, TypedRecordUpdateArg, TypedValidator, UnOp, + UntypedArg, UntypedAssignmentKind, UntypedClause, UntypedFunction, UntypedIfBranch, + UntypedPattern, UntypedRecordUpdateArg, }, builtins::{from_default_function, BUILTIN}, expr::{FnStyle, TypedExpr, UntypedExpr}, @@ -1176,7 +1176,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> { Ok((typed_arg, extra_assignment)) } - fn infer_assignment( + pub fn infer_assignment( &mut self, untyped_pattern: UntypedPattern, untyped_value: UntypedExpr, @@ -1466,64 +1466,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> { Ok(typed_patterns) } - // 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: Constant, - ) -> Result { - let inferred = match value { - Constant::Int { - location, - value, - base, - } => Ok(Constant::Int { - location, - value, - base, - }), - - Constant::String { location, value } => Ok(Constant::String { location, value }), - - Constant::ByteArray { - location, - bytes, - preferred_format, - } => { - let _ = self.infer_bytearray(bytes.clone(), preferred_format, location)?; - Ok(Constant::ByteArray { - location, - bytes, - preferred_format, - }) - } - Constant::CurvePoint { - location, - point, - preferred_format, - } => Ok(Constant::CurvePoint { - location, - point, - preferred_format, - }), - }?; - - // Check type annotation is accurate. - if let Some(ann) = annotation { - let const_ann = self.type_from_annotation(ann)?; - - self.unify( - const_ann.clone(), - inferred.tipo(), - inferred.location(), - const_ann.is_data(), - )?; - }; - - Ok(inferred) - } - fn infer_if( &mut self, branches: Vec1, diff --git a/crates/aiken-lang/src/tipo/infer.rs b/crates/aiken-lang/src/tipo/infer.rs index 1c669236..7b469c6f 100644 --- a/crates/aiken-lang/src/tipo/infer.rs +++ b/crates/aiken-lang/src/tipo/infer.rs @@ -9,9 +9,10 @@ use crate::{ ast::{ Annotation, ArgName, ArgVia, DataType, Definition, Function, ModuleConstant, ModuleKind, RecordConstructor, RecordConstructorArg, Tracing, TypeAlias, TypedArg, TypedDefinition, - TypedModule, TypedValidator, UntypedArg, UntypedDefinition, UntypedModule, + TypedModule, TypedValidator, UntypedArg, UntypedDefinition, UntypedModule, UntypedPattern, UntypedValidator, Use, Validator, }, + expr::{TypedExpr, UntypedAssignmentKind}, tipo::{expr::infer_function, Span, Type, TypeVar}, IdGenerator, }; @@ -619,10 +620,22 @@ fn infer_definition( annotation, public, value, - tipo: _, }) => { - let typed_expr = - ExprTyper::new(environment, tracing).infer_const(&annotation, *value)?; + let typed_assignment = ExprTyper::new(environment, tracing).infer_assignment( + UntypedPattern::Var { + location, + name: name.clone(), + }, + value, + UntypedAssignmentKind::Let { backpassing: false }, + &annotation, + location, + )?; + + let typed_expr = match typed_assignment { + TypedExpr::Assignment { value, .. } => value, + _ => unreachable!("infer_assignment inferred something else than an assignment?"), + }; let tipo = typed_expr.tipo(); @@ -630,7 +643,7 @@ fn infer_definition( public, variant: ValueConstructorVariant::ModuleConstant { location, - literal: typed_expr.clone(), + name: name.to_owned(), module: module_name.to_owned(), }, tipo: tipo.clone(), @@ -650,8 +663,7 @@ fn infer_definition( name, annotation, public, - value: Box::new(typed_expr), - tipo, + value: *typed_expr, })) } } diff --git a/crates/aiken-project/src/config.rs b/crates/aiken-project/src/config.rs index 4f5e7153..bbd6bca9 100644 --- a/crates/aiken-project/src/config.rs +++ b/crates/aiken-project/src/config.rs @@ -1,8 +1,6 @@ use crate::{github::repo::LatestRelease, package_name::PackageName, paths, Error}; use aiken_lang::{ - ast::{ - Annotation, ByteArrayFormatPreference, Constant, ModuleConstant, Span, UntypedDefinition, - }, + ast::{Annotation, ByteArrayFormatPreference, ModuleConstant, Span, UntypedDefinition}, expr::UntypedExpr, parser::token::Base, }; @@ -78,24 +76,14 @@ impl SimpleExpr { let (value, annotation) = match self { SimpleExpr::Bool(..) => todo!("requires https://github.com/aiken-lang/aiken/pull/992"), - SimpleExpr::Int(i) => ( + SimpleExpr::Int(_) => ( // TODO: Replace with 'self.as_untyped_expr()' after https://github.com/aiken-lang/aiken/pull/992 - Constant::Int { - location, - value: format!("{i}"), - base: Base::Decimal { - numeric_underscore: false, - }, - }, + self.as_untyped_expr(), Some(Annotation::int(location)), ), - SimpleExpr::ByteArray(bs, preferred_format) => ( + SimpleExpr::ByteArray(_, _) => ( // TODO: Replace with 'self.as_untyped_expr()' after https://github.com/aiken-lang/aiken/pull/992 - Constant::ByteArray { - location, - bytes: bs.to_vec(), - preferred_format: *preferred_format, - }, + self.as_untyped_expr(), Some(Annotation::bytearray(location)), ), SimpleExpr::List(..) => todo!("requires https://github.com/aiken-lang/aiken/pull/992"), @@ -107,8 +95,7 @@ impl SimpleExpr { public: true, name: identifier.to_string(), annotation, - value: Box::new(value), - tipo: (), + value, }) } } diff --git a/crates/aiken-project/src/lib.rs b/crates/aiken-project/src/lib.rs index 32a57a91..c356e093 100644 --- a/crates/aiken-project/src/lib.rs +++ b/crates/aiken-project/src/lib.rs @@ -36,7 +36,7 @@ use aiken_lang::{ TypedFunction, UntypedDefinition, }, builtins, - expr::UntypedExpr, + expr::{TypedExpr, UntypedExpr}, format::{Formatter, MAX_COLUMNS}, gen_uplc::CodeGenerator, line_numbers::LineNumbers, @@ -98,6 +98,7 @@ where checks_count: Option, event_listener: T, functions: IndexMap, + constants: IndexMap, data_types: IndexMap, module_sources: HashMap, } @@ -149,6 +150,7 @@ where checks_count: None, event_listener, functions, + constants: IndexMap::new(), data_types, module_sources: HashMap::new(), } @@ -158,6 +160,7 @@ where CodeGenerator::new( self.config.plutus, utils::indexmap::as_ref_values(&self.functions), + utils::indexmap::as_ref_values(&self.constants), utils::indexmap::as_ref_values(&self.data_types), utils::indexmap::as_str_ref_values(&self.module_types), utils::indexmap::as_str_ref_values(&self.module_sources), @@ -805,6 +808,7 @@ where &mut self.module_sources, &mut self.module_types, &mut self.functions, + &mut self.constants, &mut self.data_types, )?; diff --git a/crates/aiken-project/src/module.rs b/crates/aiken-project/src/module.rs index d7e245e0..30ed0357 100644 --- a/crates/aiken-project/src/module.rs +++ b/crates/aiken-project/src/module.rs @@ -5,6 +5,7 @@ use aiken_lang::{ Tracing, TypedDataType, TypedFunction, TypedModule, TypedValidator, UntypedModule, Validator, }, + expr::TypedExpr, line_numbers::LineNumbers, parser::extra::{comments_before, Comment, ModuleExtra}, tipo::TypeInfo, @@ -49,6 +50,7 @@ impl ParsedModule { module_sources: &mut HashMap, module_types: &mut HashMap, functions: &mut IndexMap, + constants: &mut IndexMap, data_types: &mut IndexMap, ) -> Result<(CheckedModule, Vec), Error> { let mut warnings = Vec::new(); @@ -92,7 +94,7 @@ impl ParsedModule { module_types.insert(self.name.clone(), ast.type_info.clone()); // Register function definitions & data-types for easier access later. - ast.register_definitions(functions, data_types); + ast.register_definitions(functions, constants, data_types); Ok(( CheckedModule { diff --git a/crates/aiken-project/src/test_framework.rs b/crates/aiken-project/src/test_framework.rs index 38f39457..c3ca0303 100644 --- a/crates/aiken-project/src/test_framework.rs +++ b/crates/aiken-project/src/test_framework.rs @@ -62,7 +62,8 @@ mod test { let mut functions = builtins::prelude_functions(&id_gen, &module_types); let mut data_types = builtins::prelude_data_types(&id_gen); - ast.register_definitions(&mut functions, &mut data_types); + let mut constants = IndexMap::new(); + ast.register_definitions(&mut functions, &mut constants, &mut data_types); let mut module_sources = HashMap::new(); module_sources.insert( @@ -87,6 +88,7 @@ mod test { let mut generator = CodeGenerator::new( PlutusVersion::default(), utils::indexmap::as_ref_values(&functions), + utils::indexmap::as_ref_values(&constants), utils::indexmap::as_ref_values(&data_types), utils::indexmap::as_str_ref_values(&module_types), utils::indexmap::as_str_ref_values(&module_sources), @@ -240,13 +242,14 @@ mod test { } "#}); - assert!(prop - .run::<()>( + assert!( + prop.run::<()>( 42, PropertyTest::DEFAULT_MAX_SUCCESS, &PlutusVersion::default() ) - .is_success()); + .is_success() + ); } #[test] diff --git a/crates/aiken-project/src/tests/mod.rs b/crates/aiken-project/src/tests/mod.rs index 6039c89c..21273f82 100644 --- a/crates/aiken-project/src/tests/mod.rs +++ b/crates/aiken-project/src/tests/mod.rs @@ -9,6 +9,7 @@ use aiken_lang::{ DataTypeKey, FunctionAccessKey, ModuleKind, TraceLevel, Tracing, TypedDataType, TypedFunction, }, + expr::TypedExpr, gen_uplc::CodeGenerator, line_numbers::LineNumbers, parser, @@ -28,6 +29,7 @@ pub struct TestProject { pub package: PackageName, pub id_gen: IdGenerator, pub functions: IndexMap, + pub constants: IndexMap, pub data_types: IndexMap, pub module_types: HashMap, pub module_sources: HashMap, @@ -48,12 +50,14 @@ impl TestProject { let functions = builtins::prelude_functions(&id_gen, &module_types); let data_types = builtins::prelude_data_types(&id_gen); + let constants = IndexMap::new(); TestProject { package, id_gen, module_types, functions, + constants, data_types, module_sources: HashMap::new(), } @@ -63,6 +67,7 @@ impl TestProject { CodeGenerator::new( PlutusVersion::default(), utils::indexmap::as_ref_values(&self.functions), + utils::indexmap::as_ref_values(&self.constants), utils::indexmap::as_ref_values(&self.data_types), utils::indexmap::as_str_ref_values(&self.module_types), utils::indexmap::as_str_ref_values(&self.module_sources), @@ -104,7 +109,11 @@ impl TestProject { .expect("Failed to type-check module"); // Register function definitions & data-types for easier access later. - ast.register_definitions(&mut self.functions, &mut self.data_types); + ast.register_definitions( + &mut self.functions, + &mut self.constants, + &mut self.data_types, + ); // Register module sources for an easier access later. self.module_sources.insert( diff --git a/crates/uplc/src/tx/error.rs b/crates/uplc/src/tx/error.rs index c7803e45..17308fa1 100644 --- a/crates/uplc/src/tx/error.rs +++ b/crates/uplc/src/tx/error.rs @@ -19,7 +19,7 @@ pub enum Error { format!( "\n{:>13} {}", "Trace", - if trace.contains("\n") { + if trace.contains('\n') { trace.lines() .enumerate() .map(|(ix, row)| {