Allow serialisable (Data-able) arguments to trace

Somehow, we have to patch some function in gen_uplc because of the
  module name. I have to look further into this because it isn't normal.
This commit is contained in:
KtorZ 2024-07-18 17:19:12 +02:00
parent beb5ac4643
commit f8236817fe
No known key found for this signature in database
GPG Key ID: 33173CB6F77F4277
2 changed files with 108 additions and 21 deletions

View File

@ -43,7 +43,6 @@ use itertools::Itertools;
use petgraph::{algo, Graph}; use petgraph::{algo, Graph};
use std::{collections::HashMap, rc::Rc}; use std::{collections::HashMap, rc::Rc};
use tree::Fields; use tree::Fields;
use uplc::{ use uplc::{
ast::{Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType}, ast::{Constant as UplcConstant, Name, NamedDeBruijn, Program, Term, Type as UplcType},
builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER, EXPECT_ON_LIST}, builder::{CONSTR_FIELDS_EXPOSER, CONSTR_INDEX_EXPOSER, EXPECT_ON_LIST},
@ -749,7 +748,11 @@ impl<'a> CodeGenerator<'a> {
} }
ModuleValueConstructor::Fn { name, module, .. } => { ModuleValueConstructor::Fn { name, module, .. } => {
let func = self.functions.get(&FunctionAccessKey { let func = self.functions.get(&FunctionAccessKey {
module_name: module_name.clone(), module_name: if module_name == "aiken" {
"".to_string()
} else {
module_name.clone()
},
function_name: name.clone(), function_name: name.clone(),
}); });

View File

@ -19,8 +19,8 @@ use crate::{
UntypedRecordUpdateArg, UntypedRecordUpdateArg,
}, },
builtins::{ builtins::{
bool, byte_array, from_default_function, function, g1_element, g2_element, int, list, pair, bool, byte_array, data, from_default_function, function, g1_element, g2_element, int, list,
string, tuple, void, BUILTIN, pair, string, tuple, void, BUILTIN, PRELUDE,
}, },
expr::{FnStyle, TypedExpr, UntypedExpr}, expr::{FnStyle, TypedExpr, UntypedExpr},
format, format,
@ -2407,6 +2407,17 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
TypedExpr::ErrorTerm { location, tipo } TypedExpr::ErrorTerm { location, tipo }
} }
fn infer_trace_arg(&mut self, arg: UntypedExpr) -> Result<TypedExpr, Error> {
let typed_arg = self.infer(arg)?;
match self.unify(string(), typed_arg.tipo(), typed_arg.location(), false) {
Err(_) => {
self.unify(data(), typed_arg.tipo(), typed_arg.location(), true)?;
Ok(diagnose_expr(typed_arg))
}
Ok(()) => Ok(typed_arg),
}
}
fn infer_trace( fn infer_trace(
&mut self, &mut self,
kind: TraceKind, kind: TraceKind,
@ -2415,16 +2426,11 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
label: UntypedExpr, label: UntypedExpr,
arguments: Vec<UntypedExpr>, arguments: Vec<UntypedExpr>,
) -> Result<TypedExpr, Error> { ) -> Result<TypedExpr, Error> {
let label = self.infer(label)?; let label = self.infer_trace_arg(label)?;
self.unify(string(), label.tipo(), label.location(), false)?;
let typed_arguments = arguments let typed_arguments = arguments
.into_iter() .into_iter()
.map(|arg| { .map(|arg| self.infer_trace_arg(arg))
let arg = self.infer(arg)?;
self.unify(string(), arg.tipo(), arg.location(), false)?;
Ok(arg)
})
.collect::<Result<Vec<_>, Error>>()?; .collect::<Result<Vec<_>, Error>>()?;
let text = if typed_arguments.is_empty() { let text = if typed_arguments.is_empty() {
@ -2815,15 +2821,84 @@ pub fn ensure_serialisable(is_top_level: bool, t: Rc<Type>, location: Span) -> R
} }
} }
pub fn append_string_expr(left: TypedExpr, right: TypedExpr) -> TypedExpr { fn diagnose_expr(expr: TypedExpr) -> TypedExpr {
let value_constructor = // NOTE: The IdGenerator is unused. See similar note in 'append_string_expr'
from_default_function(DefaultFunction::AppendString, &IdGenerator::new()); let decode_utf8_constructor =
let append_string = TypedExpr::ModuleSelect { from_default_function(DefaultFunction::DecodeUtf8, &IdGenerator::new());
let decode_utf8 = TypedExpr::ModuleSelect {
location: Span::empty(), location: Span::empty(),
tipo: value_constructor.tipo, tipo: decode_utf8_constructor.tipo.clone(),
label: DefaultFunction::AppendString.aiken_name(), label: DefaultFunction::DecodeUtf8.aiken_name(),
module_name: BUILTIN.to_string(), module_name: BUILTIN.to_string(),
module_alias: BUILTIN.to_string(), module_alias: BUILTIN.to_string(),
constructor: decode_utf8_constructor.variant.to_module_value_constructor(
decode_utf8_constructor.tipo,
BUILTIN,
&DefaultFunction::AppendString.aiken_name(),
),
};
let diagnostic_constructor = ValueConstructor::public(
function(vec![data(), byte_array()], byte_array()),
ValueConstructorVariant::ModuleFn {
name: "diagnostic".to_string(),
field_map: None,
module: PRELUDE.to_string(),
arity: 2,
location: Span::empty(),
builtin: None,
},
);
let diagnostic = TypedExpr::ModuleSelect {
location: Span::empty(),
tipo: diagnostic_constructor.tipo.clone(),
label: "diagnostic".to_string(),
module_name: PRELUDE.to_string(),
module_alias: "".to_string(),
constructor: diagnostic_constructor.variant.to_module_value_constructor(
diagnostic_constructor.tipo,
"",
"diagnostic",
),
};
let location = expr.location();
TypedExpr::Call {
tipo: string(),
fun: Box::new(decode_utf8.clone()),
args: vec![CallArg {
label: None,
location: expr.location(),
value: TypedExpr::Call {
tipo: string(),
fun: Box::new(diagnostic.clone()),
args: vec![
CallArg {
label: None,
value: expr,
location,
},
CallArg {
label: None,
location,
value: TypedExpr::ByteArray {
tipo: byte_array(),
bytes: vec![],
location,
},
},
],
location,
},
}],
location,
}
}
fn append_string_expr(left: TypedExpr, right: TypedExpr) -> TypedExpr {
// NOTE: The IdGenerator is unused here, as it's only necessary for generic builtin // NOTE: The IdGenerator is unused here, as it's only necessary for generic builtin
// functions such as if_then_else or head_list. However, if such functions were needed, // functions such as if_then_else or head_list. However, if such functions were needed,
// passing a brand new IdGenerator here would be WRONG and cause issues down the line. // passing a brand new IdGenerator here would be WRONG and cause issues down the line.
@ -2831,8 +2906,17 @@ pub fn append_string_expr(left: TypedExpr, right: TypedExpr) -> TypedExpr {
// So this is merely a small work-around for convenience. The proper way here would be to // So this is merely a small work-around for convenience. The proper way here would be to
// pull the function definition for append_string from the pre-registered builtins // pull the function definition for append_string from the pre-registered builtins
// functions somewhere in the environment. // functions somewhere in the environment.
let value_constructor =
from_default_function(DefaultFunction::AppendString, &IdGenerator::new());
let append_string = TypedExpr::ModuleSelect {
location: Span::empty(),
tipo: value_constructor.tipo.clone(),
label: DefaultFunction::AppendString.aiken_name(),
module_name: BUILTIN.to_string(),
module_alias: BUILTIN.to_string(),
constructor: value_constructor.variant.to_module_value_constructor( constructor: value_constructor.variant.to_module_value_constructor(
string(), value_constructor.tipo,
BUILTIN, BUILTIN,
&DefaultFunction::AppendString.aiken_name(), &DefaultFunction::AppendString.aiken_name(),
), ),