fix blueprint schema definitions for pairs.
This commit is contained in:
parent
d3885ac67a
commit
9162df7c6a
|
@ -1,11 +1,11 @@
|
|||
use crate::{
|
||||
Annotated, Schema,
|
||||
blueprint::{
|
||||
parameter::Parameter,
|
||||
schema::{Data, Declaration, Items},
|
||||
},
|
||||
Annotated, Schema,
|
||||
};
|
||||
use aiken_lang::tipo::{pretty::resolve_alias, Type, TypeAliasAnnotation, TypeVar};
|
||||
use aiken_lang::tipo::{Type, TypeAliasAnnotation, TypeVar, pretty::resolve_alias};
|
||||
use itertools::Itertools;
|
||||
use serde::{
|
||||
self,
|
||||
|
@ -103,7 +103,7 @@ impl Definitions<Annotated<Schema>> {
|
|||
/// Initially, we would clean those Pair definitions right-away, but this would cause
|
||||
/// Pair definitions to be missing in some legit cases when the Pair is also used as a
|
||||
/// standalone type.
|
||||
pub fn prune_orphan_pairs(&mut self, parameters: Vec<&Parameter>) {
|
||||
pub fn prune_orphan_pairs(&mut self, parameters: Vec<&Parameter>) -> &mut Self {
|
||||
fn traverse_schema(
|
||||
src: Reference,
|
||||
schema: &Schema,
|
||||
|
@ -238,6 +238,72 @@ impl Definitions<Annotated<Schema>> {
|
|||
last_len = usage.len();
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn replace_pairs_with_data_lists(&mut self) {
|
||||
fn swap_declaration(declaration: &mut Declaration<Schema>) -> Declaration<Data> {
|
||||
match std::mem::replace(declaration, Declaration::Inline(Schema::Unit.into())) {
|
||||
Declaration::Referenced(reference) => Declaration::Referenced(reference),
|
||||
Declaration::Inline(mut inline) => {
|
||||
schema_to_data(&mut inline);
|
||||
if let Schema::Data(data) = *inline {
|
||||
Declaration::Inline(data.into())
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn schema_to_data(schema: &mut Schema) {
|
||||
let items = match schema {
|
||||
Schema::Data(_) => None,
|
||||
Schema::Pair(ref mut left, ref mut right) => {
|
||||
let left = swap_declaration(left);
|
||||
let right = swap_declaration(right);
|
||||
Some(Items::Many(vec![left, right]))
|
||||
}
|
||||
Schema::List(Items::One(ref mut item)) => {
|
||||
let item = swap_declaration(item);
|
||||
Some(Items::One(item))
|
||||
}
|
||||
Schema::List(Items::Many(ref mut items)) => Some(Items::Many(
|
||||
items.iter_mut().map(swap_declaration).collect(),
|
||||
)),
|
||||
Schema::Integer => {
|
||||
*schema = Schema::Data(Data::Integer);
|
||||
None
|
||||
}
|
||||
Schema::Bytes => {
|
||||
*schema = Schema::Data(Data::Bytes);
|
||||
None
|
||||
}
|
||||
Schema::String => {
|
||||
*schema = Schema::Data(Data::Bytes);
|
||||
None
|
||||
}
|
||||
Schema::Unit => {
|
||||
*schema = Schema::void();
|
||||
None
|
||||
}
|
||||
Schema::Boolean => {
|
||||
*schema = Schema::bool();
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(items) = items {
|
||||
*schema = Schema::Data(Data::List(items));
|
||||
}
|
||||
}
|
||||
|
||||
for (_, entry) in self.inner.iter_mut() {
|
||||
if let Some(ref mut annotated) = entry {
|
||||
schema_to_data(&mut annotated.annotated);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ use super::{
|
|||
};
|
||||
use std::{iter, ops::Deref};
|
||||
use uplc::{
|
||||
ast::{Constant, Data as UplcData},
|
||||
PlutusData,
|
||||
ast::{Constant, Data as UplcData},
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
|
||||
|
|
|
@ -97,6 +97,48 @@ pub enum Schema {
|
|||
Data(Data),
|
||||
}
|
||||
|
||||
impl Schema {
|
||||
pub fn void() -> Self {
|
||||
Schema::Data(Data::AnyOf(vec![Annotated {
|
||||
title: None,
|
||||
description: None,
|
||||
annotated: Constructor {
|
||||
index: 0,
|
||||
fields: vec![],
|
||||
},
|
||||
}]))
|
||||
}
|
||||
|
||||
pub fn int() -> Self {
|
||||
Schema::Data(Data::Integer)
|
||||
}
|
||||
|
||||
pub fn bytes() -> Self {
|
||||
Schema::Data(Data::Bytes)
|
||||
}
|
||||
|
||||
pub fn bool() -> Self {
|
||||
Schema::Data(Data::AnyOf(vec![
|
||||
Annotated {
|
||||
title: Some("False".to_string()),
|
||||
description: None,
|
||||
annotated: Constructor {
|
||||
index: 0,
|
||||
fields: vec![],
|
||||
},
|
||||
},
|
||||
Annotated {
|
||||
title: Some("True".to_string()),
|
||||
description: None,
|
||||
annotated: Constructor {
|
||||
index: 1,
|
||||
fields: vec![],
|
||||
},
|
||||
},
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
||||
/// A schema for Plutus' Data.
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum Data {
|
||||
|
@ -205,46 +247,22 @@ impl Annotated<Schema> {
|
|||
annotated: Schema::Data(Data::Opaque),
|
||||
}),
|
||||
|
||||
"ByteArray" => Ok(with_title(title.as_ref(), Schema::Data(Data::Bytes))),
|
||||
"ByteArray" => Ok(with_title(title.as_ref(), Schema::bytes())),
|
||||
|
||||
"Int" => Ok(with_title(title.as_ref(), Schema::Data(Data::Integer))),
|
||||
"Int" => Ok(with_title(title.as_ref(), Schema::int())),
|
||||
|
||||
"String" => Ok(with_title(title.as_ref(), Schema::String)),
|
||||
|
||||
"Void" => Ok(Annotated {
|
||||
title: title.or(Some("Unit".to_string())),
|
||||
description: None,
|
||||
annotated: Schema::Data(Data::AnyOf(vec![Annotated {
|
||||
title: None,
|
||||
description: None,
|
||||
annotated: Constructor {
|
||||
index: 0,
|
||||
fields: vec![],
|
||||
},
|
||||
}])),
|
||||
annotated: Schema::void(),
|
||||
}),
|
||||
|
||||
"Bool" => Ok(Annotated {
|
||||
title: title.or(Some("Bool".to_string())),
|
||||
description: None,
|
||||
annotated: Schema::Data(Data::AnyOf(vec![
|
||||
Annotated {
|
||||
title: Some("False".to_string()),
|
||||
description: None,
|
||||
annotated: Constructor {
|
||||
index: 0,
|
||||
fields: vec![],
|
||||
},
|
||||
},
|
||||
Annotated {
|
||||
title: Some("True".to_string()),
|
||||
description: None,
|
||||
annotated: Constructor {
|
||||
index: 1,
|
||||
fields: vec![],
|
||||
},
|
||||
},
|
||||
])),
|
||||
annotated: Schema::bool(),
|
||||
}),
|
||||
|
||||
"Ordering" => Ok(Annotated {
|
||||
|
@ -1099,7 +1117,7 @@ Here's the types I followed and that led me to this problem:
|
|||
pub mod tests {
|
||||
use super::*;
|
||||
use proptest::prelude::*;
|
||||
use serde_json::{self, json, Value};
|
||||
use serde_json::{self, Value, json};
|
||||
|
||||
pub fn assert_json(schema: &impl Serialize, expected: Value) {
|
||||
assert_eq!(serde_json::to_value(schema).unwrap(), expected);
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
source: crates/aiken-project/src/blueprint/validator.rs
|
||||
description: "Code:\n\npub type MyPair =\n Pair<List<Int>, Bool>\n\nvalidator placeholder {\n spend(_datum: Option<Data>, _redeemer: MyPair, _utxo: Data, _self: Data,) {\n True\n }\n}\n"
|
||||
---
|
||||
{
|
||||
"title": "test_module.placeholder.spend",
|
||||
"datum": {
|
||||
"title": "_datum",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Data"
|
||||
}
|
||||
},
|
||||
"redeemer": {
|
||||
"title": "_redeemer",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/MyPair"
|
||||
}
|
||||
},
|
||||
"compiledCode": "<redacted>",
|
||||
"hash": "<redacted>",
|
||||
"definitions": {
|
||||
"Bool": {
|
||||
"title": "Bool",
|
||||
"anyOf": [
|
||||
{
|
||||
"title": "False",
|
||||
"dataType": "constructor",
|
||||
"index": 0,
|
||||
"fields": []
|
||||
},
|
||||
{
|
||||
"title": "True",
|
||||
"dataType": "constructor",
|
||||
"index": 1,
|
||||
"fields": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"Data": {
|
||||
"title": "Data",
|
||||
"description": "Any Plutus data."
|
||||
},
|
||||
"Int": {
|
||||
"dataType": "integer"
|
||||
},
|
||||
"List$Int": {
|
||||
"dataType": "list",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Int"
|
||||
}
|
||||
},
|
||||
"MyPair": {
|
||||
"title": "MyPair",
|
||||
"dataType": "list",
|
||||
"items": [
|
||||
{
|
||||
"$ref": "#/definitions/List$Int"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/Bool"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,13 +33,15 @@ description: "Code:\n\npub type MyPair =\n Pair<Int, Int>\n\npub type MyDatum {
|
|||
},
|
||||
"MyPair": {
|
||||
"title": "MyPair",
|
||||
"dataType": "#pair",
|
||||
"left": {
|
||||
"dataType": "list",
|
||||
"items": [
|
||||
{
|
||||
"$ref": "#/definitions/Int"
|
||||
},
|
||||
"right": {
|
||||
{
|
||||
"$ref": "#/definitions/Int"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Void": {
|
||||
"title": "Unit",
|
||||
|
|
|
@ -33,13 +33,15 @@ description: "Code:\n\npub type MyPair =\n Pair<Int, Int>\n\npub type MyDatum {
|
|||
},
|
||||
"MyPair": {
|
||||
"title": "MyPair",
|
||||
"dataType": "#pair",
|
||||
"left": {
|
||||
"dataType": "list",
|
||||
"items": [
|
||||
{
|
||||
"$ref": "#/definitions/Int"
|
||||
},
|
||||
"right": {
|
||||
{
|
||||
"$ref": "#/definitions/Int"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Void": {
|
||||
"title": "Unit",
|
||||
|
|
|
@ -78,13 +78,15 @@ description: "Code:\n\npub type Asset = (ByteArray, Int)\n\npub type POSIXTime =
|
|||
},
|
||||
"Pair$POSIXTime_Bool": {
|
||||
"title": "Pair",
|
||||
"dataType": "#pair",
|
||||
"left": {
|
||||
"dataType": "list",
|
||||
"items": [
|
||||
{
|
||||
"$ref": "#/definitions/POSIXTime"
|
||||
},
|
||||
"right": {
|
||||
{
|
||||
"$ref": "#/definitions/Bool"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Pairs$Asset_POSIXTime": {
|
||||
"title": "Pairs<a, POSIXTime>",
|
||||
|
|
|
@ -202,13 +202,15 @@ impl Validator {
|
|||
schema: Declaration::Inline(Box::new(Schema::Data(Data::Opaque))),
|
||||
}));
|
||||
|
||||
definitions.prune_orphan_pairs(
|
||||
definitions
|
||||
.prune_orphan_pairs(
|
||||
parameters
|
||||
.iter()
|
||||
.chain(redeemer.as_ref().map(|x| vec![x]).unwrap_or_default())
|
||||
.chain(datum.as_ref().map(|x| vec![x]).unwrap_or_default())
|
||||
.collect::<Vec<&Parameter>>(),
|
||||
);
|
||||
)
|
||||
.replace_pairs_with_data_lists();
|
||||
|
||||
Ok(Validator {
|
||||
title: format!("{}.{}.{}", &module.name, &def.name, &func.name,),
|
||||
|
@ -805,6 +807,22 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pair_of_lists() {
|
||||
assert_validator!(
|
||||
r#"
|
||||
pub type MyPair =
|
||||
Pair<List<Int>, Bool>
|
||||
|
||||
validator placeholder {
|
||||
spend(_datum: Option<Data>, _redeemer: MyPair, _utxo: Data, _self: Data,) {
|
||||
True
|
||||
}
|
||||
}
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn else_redeemer() {
|
||||
assert_validator!(
|
||||
|
|
Loading…
Reference in New Issue