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:
KtorZ 2024-08-02 17:23:14 +02:00
parent 79cf0b8d97
commit cd0a9440e8
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
17 changed files with 192 additions and 282 deletions

View File

@ -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>>;

View File

@ -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> {

View File

@ -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,

View File

@ -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();

View File

@ -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;

View File

@ -49,6 +49,5 @@ ModuleConstant(
),
preferred_format: HexadecimalString,
},
tipo: (),
},
)

View File

@ -91,6 +91,5 @@ ModuleConstant(
),
preferred_format: HexadecimalString,
},
tipo: (),
},
)

View File

@ -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,
))
}

View File

@ -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,
},
}

View File

@ -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>,

View File

@ -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,
}))
}
}

View File

@ -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,
})
}
}

View File

@ -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,
)?;

View File

@ -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 {

View File

@ -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]

View File

@ -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(

View File

@ -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)| {