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