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.
This commit is contained in:
		
							parent
							
								
									79cf0b8d97
								
							
						
					
					
						commit
						cd0a9440e8
					
				|  | @ -161,6 +161,7 @@ impl TypedModule { | |||
|     pub fn register_definitions( | ||||
|         &self, | ||||
|         functions: &mut IndexMap<FunctionAccessKey, TypedFunction>, | ||||
|         constants: &mut IndexMap<FunctionAccessKey, TypedExpr>, | ||||
|         data_types: &mut IndexMap<DataTypeKey, TypedDataType>, | ||||
|     ) { | ||||
|         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<PackageName> { | |||
|     pub unqualified: Vec<UnqualifiedImport>, | ||||
| } | ||||
| 
 | ||||
| pub type TypedModuleConstant = ModuleConstant<Rc<Type>>; | ||||
| pub type UntypedModuleConstant = ModuleConstant<()>; | ||||
| pub type TypedModuleConstant = ModuleConstant<TypedExpr>; | ||||
| pub type UntypedModuleConstant = ModuleConstant<UntypedExpr>; | ||||
| 
 | ||||
| #[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)] | ||||
| pub struct ModuleConstant<T> { | ||||
| pub struct ModuleConstant<Expr> { | ||||
|     pub doc: Option<String>, | ||||
|     pub location: Span, | ||||
|     pub public: bool, | ||||
|     pub name: String, | ||||
|     pub annotation: Option<Annotation>, | ||||
|     pub value: Box<Constant>, | ||||
|     pub tipo: T, | ||||
|     pub value: Expr, | ||||
| } | ||||
| 
 | ||||
| pub type TypedValidator = Validator<Rc<Type>, TypedArg, TypedExpr>; | ||||
|  | @ -746,7 +756,7 @@ pub enum Definition<T, Arg, Expr, PackageName> { | |||
| 
 | ||||
|     Use(Use<PackageName>), | ||||
| 
 | ||||
|     ModuleConstant(ModuleConstant<T>), | ||||
|     ModuleConstant(ModuleConstant<Expr>), | ||||
| 
 | ||||
|     Test(Function<T, Expr, ArgVia<Arg, Expr>>), | ||||
| 
 | ||||
|  | @ -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<u8>, | ||||
|         preferred_format: ByteArrayFormatPreference, | ||||
|     }, | ||||
| 
 | ||||
|     CurvePoint { | ||||
|         location: Span, | ||||
|         point: Box<Curve>, | ||||
|         preferred_format: ByteArrayFormatPreference, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
| impl Constant { | ||||
|     pub fn tipo(&self) -> Rc<Type> { | ||||
|         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<TypedExpr>; | ||||
| pub type ParsedCallArg = CallArg<Option<UntypedExpr>>; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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> { | ||||
|  |  | |||
|  | @ -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<Name> = 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<NamedDeBruijn> = | ||||
|                         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, | ||||
|  |  | |||
|  | @ -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<Type>) -> String { | ||||
|     let uplc_type = t.get_uplc_type(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<Token, ast::UntypedDefinition, Error = ParseError> { | ||||
|     utils::optional_flag(Token::Pub) | ||||
|  | @ -16,7 +14,9 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError | |||
|                 .or_not(), | ||||
|         ) | ||||
|         .then_ignore(just(Token::Equal)) | ||||
|         .then(value()) | ||||
|         .then(recursive(|expression| { | ||||
|             recursive(|sequence| pure_expression(sequence, expression)) | ||||
|         })) | ||||
|         .map_with_span(|(((public, name), annotation), value), span| { | ||||
|             ast::UntypedDefinition::ModuleConstant(ast::ModuleConstant { | ||||
|                 doc: None, | ||||
|  | @ -24,67 +24,11 @@ pub fn parser() -> impl Parser<Token, ast::UntypedDefinition, Error = ParseError | |||
|                 public, | ||||
|                 name, | ||||
|                 annotation, | ||||
|                 value: Box::new(value), | ||||
|                 tipo: (), | ||||
|                 value, | ||||
|             }) | ||||
|         }) | ||||
| } | ||||
| 
 | ||||
| pub fn value() -> 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, | ||||
|                 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; | ||||
|  |  | |||
|  | @ -49,6 +49,5 @@ ModuleConstant( | |||
|             ), | ||||
|             preferred_format: HexadecimalString, | ||||
|         }, | ||||
|         tipo: (), | ||||
|     }, | ||||
| ) | ||||
|  |  | |||
|  | @ -91,6 +91,5 @@ ModuleConstant( | |||
|             ), | ||||
|             preferred_format: HexadecimalString, | ||||
|         }, | ||||
|         tipo: (), | ||||
|     }, | ||||
| ) | ||||
|  |  | |||
|  | @ -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<Token, ast::UntypedClauseGuard, Error = ParseErro | |||
|         } | ||||
|         .map_with_span(|_name, _span| ast::UntypedClauseGuard {}); | ||||
| 
 | ||||
|         let constant_parser = definition::constant::value().map(|_| ast::UntypedClauseGuard {}); | ||||
| 
 | ||||
|         let block_parser = expression | ||||
|             .clone() | ||||
|             .delimited_by(just(Token::LeftParen), just(Token::RightParen)); | ||||
| 
 | ||||
|         let leaf_parser = choice((var_parser, constant_parser, block_parser)).boxed(); | ||||
|         let leaf_parser = choice((var_parser, constant(), block_parser)).boxed(); | ||||
| 
 | ||||
|         let unary_op = just(Token::Bang); | ||||
| 
 | ||||
|  | @ -57,3 +55,20 @@ pub fn parser() -> impl Parser<Token, ast::UntypedClauseGuard, Error = ParseErro | |||
|             .foldl(|_left, (_tok, _right)| ast::UntypedClauseGuard {}) | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| // NOTE: This is only there for backward-compatibility, in order to provide nicer error message
 | ||||
| // when a clause guard is found. However, Aiken no longer supports clause guards.
 | ||||
| pub fn constant() -> impl Parser<Token, ast::UntypedClauseGuard, Error = ParseError> { | ||||
|     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, | ||||
|     )) | ||||
| } | ||||
|  |  | |||
|  | @ -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, | ||||
|     }, | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<Annotation>, | ||||
|         value: Constant, | ||||
|     ) -> Result<Constant, Error> { | ||||
|         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<UntypedIfBranch>, | ||||
|  |  | |||
|  | @ -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, | ||||
|             })) | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -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, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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<usize>, | ||||
|     event_listener: T, | ||||
|     functions: IndexMap<FunctionAccessKey, TypedFunction>, | ||||
|     constants: IndexMap<FunctionAccessKey, TypedExpr>, | ||||
|     data_types: IndexMap<DataTypeKey, TypedDataType>, | ||||
|     module_sources: HashMap<String, (String, LineNumbers)>, | ||||
| } | ||||
|  | @ -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, | ||||
|                 )?; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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<String, (String, LineNumbers)>, | ||||
|         module_types: &mut HashMap<String, TypeInfo>, | ||||
|         functions: &mut IndexMap<FunctionAccessKey, TypedFunction>, | ||||
|         constants: &mut IndexMap<FunctionAccessKey, TypedExpr>, | ||||
|         data_types: &mut IndexMap<DataTypeKey, TypedDataType>, | ||||
|     ) -> Result<(CheckedModule, Vec<Warning>), 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 { | ||||
|  |  | |||
|  | @ -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] | ||||
|  |  | |||
|  | @ -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<FunctionAccessKey, TypedFunction>, | ||||
|     pub constants: IndexMap<FunctionAccessKey, TypedExpr>, | ||||
|     pub data_types: IndexMap<DataTypeKey, TypedDataType>, | ||||
|     pub module_types: HashMap<String, TypeInfo>, | ||||
|     pub module_sources: HashMap<String, (String, LineNumbers)>, | ||||
|  | @ -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( | ||||
|  |  | |||
|  | @ -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)| { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 KtorZ
						KtorZ