Merge branch 'aiken-watch'
This commit is contained in:
commit
c2725abcea
16
CHANGELOG.md
16
CHANGELOG.md
|
@ -1,6 +1,20 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## v1.0.20-alpha - 10/25/2023
|
## v1.0.21-alpha - unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- **aiken**: `--watch` flag on the `build`, `check` and `docs` commands to automatically watch and re-execute the command on file changes.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
N/A
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
N/A
|
||||||
|
|
||||||
|
## v1.0.20-alpha - 2023-10-25
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,7 @@ dependencies = [
|
||||||
"itertools",
|
"itertools",
|
||||||
"miette",
|
"miette",
|
||||||
"minicbor",
|
"minicbor",
|
||||||
|
"notify",
|
||||||
"owo-colors",
|
"owo-colors",
|
||||||
"pallas",
|
"pallas",
|
||||||
"pallas-traverse",
|
"pallas-traverse",
|
||||||
|
@ -360,6 +361,12 @@ version = "1.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
|
@ -505,7 +512,7 @@ checksum = "223163f58c9a40c3b0a43e1c4b50a9ce09f007ea2cb1ec258a687945b4b7929f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"clap_lex",
|
"clap_lex",
|
||||||
"strsim",
|
"strsim",
|
||||||
"terminal_size 0.2.6",
|
"terminal_size 0.2.6",
|
||||||
|
@ -662,7 +669,7 @@ version = "0.25.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
|
checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"crossterm_winapi",
|
"crossterm_winapi",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
|
@ -866,6 +873,18 @@ dependencies = [
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filetime"
|
||||||
|
version = "0.2.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall 0.3.5",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fixedbitset"
|
name = "fixedbitset"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
@ -921,6 +940,15 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fsevent-sys"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fslock"
|
name = "fslock"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -1054,7 +1082,7 @@ version = "0.17.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b989d6a7ca95a362cf2cfc5ad688b3a467be1f87e480b8dad07fee8c79b0044"
|
checksum = "7b989d6a7ca95a362cf2cfc5ad688b3a467be1f87e480b8dad07fee8c79b0044"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"libc",
|
"libc",
|
||||||
"libgit2-sys",
|
"libgit2-sys",
|
||||||
"log",
|
"log",
|
||||||
|
@ -1293,13 +1321,33 @@ version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f2cb48b81b1dc9f39676bf99f5499babfec7cd8fe14307f7b3d747208fb5690"
|
checksum = "9f2cb48b81b1dc9f39676bf99f5499babfec7cd8fe14307f7b3d747208fb5690"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"inotify-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify-sys"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "inquire"
|
name = "inquire"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c33e7c1ddeb15c9abcbfef6029d8e29f69b52b6d6c891031b88ed91b5065803b"
|
checksum = "c33e7c1ddeb15c9abcbfef6029d8e29f69b52b6d6c891031b88ed91b5065803b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"dyn-clone",
|
"dyn-clone",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -1414,6 +1462,26 @@ dependencies = [
|
||||||
"signature",
|
"signature",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kqueue"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c"
|
||||||
|
dependencies = [
|
||||||
|
"kqueue-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kqueue-sys"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
@ -1505,7 +1573,7 @@ version = "0.94.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237"
|
checksum = "0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
|
@ -1660,6 +1728,25 @@ dependencies = [
|
||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "notify"
|
||||||
|
version = "6.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.1",
|
||||||
|
"crossbeam-channel",
|
||||||
|
"filetime",
|
||||||
|
"fsevent-sys",
|
||||||
|
"inotify",
|
||||||
|
"kqueue",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"mio",
|
||||||
|
"walkdir",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-bigint"
|
name = "num-bigint"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
@ -1728,7 +1815,7 @@ version = "0.10.55"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d"
|
checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"foreign-types",
|
"foreign-types",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -2069,7 +2156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65"
|
checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit-set",
|
"bit-set",
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
@ -2097,7 +2184,7 @@ version = "0.9.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63"
|
checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"memchr",
|
"memchr",
|
||||||
"unicase",
|
"unicase",
|
||||||
]
|
]
|
||||||
|
@ -2184,7 +2271,7 @@ version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2193,7 +2280,7 @@ version = "0.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2283,7 +2370,7 @@ version = "0.37.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77"
|
checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"errno",
|
"errno",
|
||||||
"io-lifetimes",
|
"io-lifetimes",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -2377,7 +2464,7 @@ version = "2.8.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
|
checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"core-foundation",
|
"core-foundation",
|
||||||
"core-foundation-sys",
|
"core-foundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
|
@ -516,7 +516,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
.group();
|
.group();
|
||||||
|
|
||||||
// Format body
|
// Format body
|
||||||
let body = self.expr(body);
|
let body = self.expr(body, true);
|
||||||
|
|
||||||
// Add any trailing comments
|
// Add any trailing comments
|
||||||
let body = match printed_comments(self.pop_comments(end_location), false) {
|
let body = match printed_comments(self.pop_comments(end_location), false) {
|
||||||
|
@ -609,8 +609,10 @@ impl<'comments> Formatter<'comments> {
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
let args = wrap_args(args.iter().map(|e| (self.fn_arg(e), false))).group();
|
let args = wrap_args(args.iter().map(|e| (self.fn_arg(e), false))).group();
|
||||||
let body = match body {
|
let body = match body {
|
||||||
UntypedExpr::Trace { .. } | UntypedExpr::When { .. } => self.expr(body).force_break(),
|
UntypedExpr::Trace { .. } | UntypedExpr::When { .. } => {
|
||||||
_ => self.expr(body),
|
self.expr(body, true).force_break()
|
||||||
|
}
|
||||||
|
_ => self.expr(body, true),
|
||||||
};
|
};
|
||||||
|
|
||||||
let header = "fn".to_doc().append(args);
|
let header = "fn".to_doc().append(args);
|
||||||
|
@ -634,15 +636,19 @@ impl<'comments> Formatter<'comments> {
|
||||||
fn sequence<'a>(&mut self, expressions: &'a [UntypedExpr]) -> Document<'a> {
|
fn sequence<'a>(&mut self, expressions: &'a [UntypedExpr]) -> Document<'a> {
|
||||||
let count = expressions.len();
|
let count = expressions.len();
|
||||||
let mut documents = Vec::with_capacity(count * 2);
|
let mut documents = Vec::with_capacity(count * 2);
|
||||||
|
|
||||||
for (i, expression) in expressions.iter().enumerate() {
|
for (i, expression) in expressions.iter().enumerate() {
|
||||||
let preceding_newline = self.pop_empty_lines(expression.start_byte_index());
|
let preceding_newline = self.pop_empty_lines(expression.start_byte_index());
|
||||||
|
|
||||||
if i != 0 && preceding_newline {
|
if i != 0 && preceding_newline {
|
||||||
documents.push(lines(2));
|
documents.push(lines(2));
|
||||||
} else if i != 0 {
|
} else if i != 0 {
|
||||||
documents.push(lines(1));
|
documents.push(lines(1));
|
||||||
}
|
}
|
||||||
documents.push(self.expr(expression).group());
|
|
||||||
|
documents.push(self.expr(expression, false).group());
|
||||||
}
|
}
|
||||||
|
|
||||||
documents.to_doc().force_break()
|
documents.to_doc().force_break()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -653,8 +659,6 @@ impl<'comments> Formatter<'comments> {
|
||||||
kind: AssignmentKind,
|
kind: AssignmentKind,
|
||||||
annotation: &'a Option<Annotation>,
|
annotation: &'a Option<Annotation>,
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
self.pop_empty_lines(pattern.location().end);
|
|
||||||
|
|
||||||
let keyword = match kind {
|
let keyword = match kind {
|
||||||
AssignmentKind::Let => "let",
|
AssignmentKind::Let => "let",
|
||||||
AssignmentKind::Expect => "expect",
|
AssignmentKind::Expect => "expect",
|
||||||
|
@ -667,6 +671,8 @@ impl<'comments> Formatter<'comments> {
|
||||||
keyword.to_doc().append(self.case_clause_value(value))
|
keyword.to_doc().append(self.case_clause_value(value))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
self.pop_empty_lines(pattern.location().end);
|
||||||
|
|
||||||
let pattern = self.pattern(pattern);
|
let pattern = self.pattern(pattern);
|
||||||
|
|
||||||
let annotation = annotation
|
let annotation = annotation
|
||||||
|
@ -782,7 +788,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expr<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
pub fn expr<'a>(&mut self, expr: &'a UntypedExpr, is_top_level: bool) -> Document<'a> {
|
||||||
let comments = self.pop_comments(expr.start_byte_index());
|
let comments = self.pop_comments(expr.start_byte_index());
|
||||||
|
|
||||||
let document = match expr {
|
let document = match expr {
|
||||||
|
@ -821,7 +827,18 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
UntypedExpr::String { value, .. } => self.string(value),
|
UntypedExpr::String { value, .. } => self.string(value),
|
||||||
|
|
||||||
UntypedExpr::Sequence { expressions, .. } => self.sequence(expressions),
|
UntypedExpr::Sequence { expressions, .. } => {
|
||||||
|
let sequence = self.sequence(expressions);
|
||||||
|
|
||||||
|
if is_top_level {
|
||||||
|
sequence
|
||||||
|
} else {
|
||||||
|
"{".to_doc()
|
||||||
|
.append(line().append(sequence).nest(INDENT).group())
|
||||||
|
.append(line())
|
||||||
|
.append("}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UntypedExpr::Var { name, .. } if name.contains(CAPTURE_VARIABLE) => "_".to_doc(),
|
UntypedExpr::Var { name, .. } if name.contains(CAPTURE_VARIABLE) => "_".to_doc(),
|
||||||
|
|
||||||
|
@ -878,7 +895,10 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
UntypedExpr::FieldAccess {
|
UntypedExpr::FieldAccess {
|
||||||
label, container, ..
|
label, container, ..
|
||||||
} => self.expr(container).append(".").append(label.as_str()),
|
} => self
|
||||||
|
.expr(container, false)
|
||||||
|
.append(".")
|
||||||
|
.append(label.as_str()),
|
||||||
|
|
||||||
UntypedExpr::RecordUpdate {
|
UntypedExpr::RecordUpdate {
|
||||||
constructor,
|
constructor,
|
||||||
|
@ -893,7 +913,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
UntypedExpr::TupleIndex { index, tuple, .. } => {
|
UntypedExpr::TupleIndex { index, tuple, .. } => {
|
||||||
let suffix = Ordinal(*index + 1).suffix().to_doc();
|
let suffix = Ordinal(*index + 1).suffix().to_doc();
|
||||||
self.expr(tuple)
|
self.expr(tuple, false)
|
||||||
.append(".".to_doc())
|
.append(".".to_doc())
|
||||||
.append((index + 1).to_doc())
|
.append((index + 1).to_doc())
|
||||||
.append(suffix)
|
.append(suffix)
|
||||||
|
@ -953,7 +973,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
} else {
|
} else {
|
||||||
line()
|
line()
|
||||||
})
|
})
|
||||||
.append(self.expr(then)),
|
.append(self.expr(then, false)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1027,7 +1047,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
self.expr(fun)
|
self.expr(fun, false)
|
||||||
.append(wrap_args(
|
.append(wrap_args(
|
||||||
args.iter()
|
args.iter()
|
||||||
.map(|a| (self.call_arg(a, needs_curly), needs_curly)),
|
.map(|a| (self.call_arg(a, needs_curly), needs_curly)),
|
||||||
|
@ -1051,7 +1071,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
let else_begin = line().append("} else {");
|
let else_begin = line().append("} else {");
|
||||||
|
|
||||||
let else_body = line().append(self.expr(final_else)).nest(INDENT);
|
let else_body = line().append(self.expr(final_else, true)).nest(INDENT);
|
||||||
|
|
||||||
let else_end = line().append("}");
|
let else_end = line().append("}");
|
||||||
|
|
||||||
|
@ -1072,7 +1092,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
.append(break_("{", " {"))
|
.append(break_("{", " {"))
|
||||||
.group();
|
.group();
|
||||||
|
|
||||||
let if_body = line().append(self.expr(&branch.body)).nest(INDENT);
|
let if_body = line().append(self.expr(&branch.body, true)).nest(INDENT);
|
||||||
|
|
||||||
if_begin.append(if_body)
|
if_begin.append(if_body)
|
||||||
}
|
}
|
||||||
|
@ -1110,8 +1130,8 @@ impl<'comments> Formatter<'comments> {
|
||||||
args: &'a [UntypedRecordUpdateArg],
|
args: &'a [UntypedRecordUpdateArg],
|
||||||
) -> Document<'a> {
|
) -> Document<'a> {
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
let constructor_doc = self.expr(constructor);
|
let constructor_doc = self.expr(constructor, false);
|
||||||
let spread_doc = "..".to_doc().append(self.expr(&spread.base));
|
let spread_doc = "..".to_doc().append(self.expr(&spread.base, false));
|
||||||
let arg_docs = args.iter().map(|a| (self.record_update_arg(a), true));
|
let arg_docs = args.iter().map(|a| (self.record_update_arg(a), true));
|
||||||
let all_arg_docs = once((spread_doc, true)).chain(arg_docs);
|
let all_arg_docs = once((spread_doc, true)).chain(arg_docs);
|
||||||
constructor_doc.append(wrap_args(all_arg_docs)).group()
|
constructor_doc.append(wrap_args(all_arg_docs)).group()
|
||||||
|
@ -1128,14 +1148,14 @@ impl<'comments> Formatter<'comments> {
|
||||||
let left_precedence = left.binop_precedence();
|
let left_precedence = left.binop_precedence();
|
||||||
let right_precedence = right.binop_precedence();
|
let right_precedence = right.binop_precedence();
|
||||||
|
|
||||||
let left = self.expr(left);
|
let left = self.expr(left, false);
|
||||||
let right = self.expr(right);
|
let right = self.expr(right, false);
|
||||||
|
|
||||||
self.operator_side(left, precedence, left_precedence)
|
self.operator_side(left, precedence, left_precedence)
|
||||||
.append(" ")
|
.append(" ")
|
||||||
.append(name)
|
.append(name)
|
||||||
.append(" ")
|
.append(" ")
|
||||||
.append(self.operator_side(right, precedence, right_precedence - 1))
|
.append(self.operator_side(right, precedence, right_precedence.saturating_sub(1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn operator_side<'a>(&mut self, doc: Document<'a>, op: u8, side: u8) -> Document<'a> {
|
pub fn operator_side<'a>(&mut self, doc: Document<'a>, op: u8, side: u8) -> Document<'a> {
|
||||||
|
@ -1161,7 +1181,9 @@ impl<'comments> Formatter<'comments> {
|
||||||
.append(
|
.append(
|
||||||
line()
|
line()
|
||||||
.append(join(
|
.append(join(
|
||||||
expressions.iter().map(|expression| self.expr(expression)),
|
expressions
|
||||||
|
.iter()
|
||||||
|
.map(|expression| self.expr(expression, false)),
|
||||||
",".to_doc().append(line()),
|
",".to_doc().append(line()),
|
||||||
))
|
))
|
||||||
.nest(INDENT)
|
.nest(INDENT)
|
||||||
|
@ -1241,10 +1263,10 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
if hole_in_first_position && args.len() == 1 {
|
if hole_in_first_position && args.len() == 1 {
|
||||||
// x |> fun(_)
|
// x |> fun(_)
|
||||||
self.expr(fun)
|
self.expr(fun, false)
|
||||||
} else if hole_in_first_position {
|
} else if hole_in_first_position {
|
||||||
// x |> fun(_, 2, 3)
|
// x |> fun(_, 2, 3)
|
||||||
self.expr(fun).append(
|
self.expr(fun, false).append(
|
||||||
wrap_args(
|
wrap_args(
|
||||||
args.iter()
|
args.iter()
|
||||||
.skip(1)
|
.skip(1)
|
||||||
|
@ -1254,7 +1276,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// x |> fun(1, _, 3)
|
// x |> fun(1, _, 3)
|
||||||
self.expr(fun)
|
self.expr(fun, false)
|
||||||
.append(wrap_args(args.iter().map(|a| (self.call_arg(a, false), false))).group())
|
.append(wrap_args(args.iter().map(|a| (self.call_arg(a, false), false))).group())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1267,14 +1289,14 @@ impl<'comments> Formatter<'comments> {
|
||||||
..
|
..
|
||||||
} => match args.as_slice() {
|
} => match args.as_slice() {
|
||||||
[first, second] if is_breakable_expr(&second.value) && first.is_capture_hole() => {
|
[first, second] if is_breakable_expr(&second.value) && first.is_capture_hole() => {
|
||||||
self.expr(fun)
|
self.expr(fun, false)
|
||||||
.append("(_, ")
|
.append("(_, ")
|
||||||
.append(self.call_arg(second, false))
|
.append(self.call_arg(second, false))
|
||||||
.append(")")
|
.append(")")
|
||||||
.group()
|
.group()
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => self.expr(fun).append(
|
_ => self.expr(fun, false).append(
|
||||||
wrap_args(args.iter().map(|a| (self.call_arg(a, false), false))).group(),
|
wrap_args(args.iter().map(|a| (self.call_arg(a, false), false))).group(),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -1556,12 +1578,12 @@ impl<'comments> Formatter<'comments> {
|
||||||
| UntypedExpr::Sequence { .. }
|
| UntypedExpr::Sequence { .. }
|
||||||
| UntypedExpr::Assignment { .. } => "{"
|
| UntypedExpr::Assignment { .. } => "{"
|
||||||
.to_doc()
|
.to_doc()
|
||||||
.append(line().append(self.expr(expr)).nest(INDENT))
|
.append(line().append(self.expr(expr, true)).nest(INDENT))
|
||||||
.append(line())
|
.append(line())
|
||||||
.append("}")
|
.append("}")
|
||||||
.force_break(),
|
.force_break(),
|
||||||
|
|
||||||
_ => self.expr(expr),
|
_ => self.expr(expr, false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1598,18 +1620,21 @@ impl<'comments> Formatter<'comments> {
|
||||||
| UntypedExpr::Sequence { .. }
|
| UntypedExpr::Sequence { .. }
|
||||||
| UntypedExpr::Assignment { .. } => " {"
|
| UntypedExpr::Assignment { .. } => " {"
|
||||||
.to_doc()
|
.to_doc()
|
||||||
.append(line().append(self.expr(expr)).nest(INDENT).group())
|
.append(line().append(self.expr(expr, true)).nest(INDENT).group())
|
||||||
.append(line())
|
.append(line())
|
||||||
.append("}")
|
.append("}")
|
||||||
.force_break(),
|
.force_break(),
|
||||||
|
|
||||||
UntypedExpr::Fn { .. } | UntypedExpr::List { .. } => {
|
UntypedExpr::Fn { .. } | UntypedExpr::List { .. } => {
|
||||||
line().append(self.expr(expr)).nest(INDENT).group()
|
line().append(self.expr(expr, false)).nest(INDENT).group()
|
||||||
}
|
}
|
||||||
|
|
||||||
UntypedExpr::When { .. } => line().append(self.expr(expr)).nest(INDENT).group(),
|
UntypedExpr::When { .. } => line().append(self.expr(expr, false)).nest(INDENT).group(),
|
||||||
|
|
||||||
_ => break_("", " ").append(self.expr(expr)).nest(INDENT).group(),
|
_ => break_("", " ")
|
||||||
|
.append(self.expr(expr, false))
|
||||||
|
.nest(INDENT)
|
||||||
|
.group(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1647,7 +1672,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
|| break_(",", ", ")
|
|| break_(",", ", ")
|
||||||
};
|
};
|
||||||
let elements_document = join(elements.iter().map(|e| self.wrap_expr(e)), comma());
|
let elements_document = join(elements.iter().map(|e| self.wrap_expr(e)), comma());
|
||||||
let tail = tail.map(|e| self.expr(e));
|
let tail = tail.map(|e| self.expr(e, false));
|
||||||
list(elements_document, elements.len(), tail)
|
list(elements_document, elements.len(), tail)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1720,7 +1745,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
let right = self.clause_guard(right);
|
let right = self.clause_guard(right);
|
||||||
self.operator_side(left, name_precedence, left_precedence)
|
self.operator_side(left, name_precedence, left_precedence)
|
||||||
.append(name)
|
.append(name)
|
||||||
.append(self.operator_side(right, name_precedence, right_precedence - 1))
|
.append(self.operator_side(right, name_precedence, right_precedence.saturating_sub(1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clause_guard<'a>(&mut self, clause_guard: &'a UntypedClauseGuard) -> Document<'a> {
|
fn clause_guard<'a>(&mut self, clause_guard: &'a UntypedClauseGuard) -> Document<'a> {
|
||||||
|
@ -1771,7 +1796,7 @@ impl<'comments> Formatter<'comments> {
|
||||||
|
|
||||||
fn wrap_unary_op<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
fn wrap_unary_op<'a>(&mut self, expr: &'a UntypedExpr) -> Document<'a> {
|
||||||
match expr {
|
match expr {
|
||||||
UntypedExpr::BinOp { .. } => "(".to_doc().append(self.expr(expr)).append(")"),
|
UntypedExpr::BinOp { .. } => "(".to_doc().append(self.expr(expr, false)).append(")"),
|
||||||
_ => self.wrap_expr(expr),
|
_ => self.wrap_expr(expr),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4049,6 +4049,12 @@ impl<'a> CodeGenerator<'a> {
|
||||||
Term::equals_string()
|
Term::equals_string()
|
||||||
} else if tipo.is_bytearray() {
|
} else if tipo.is_bytearray() {
|
||||||
Term::equals_bytestring()
|
Term::equals_bytestring()
|
||||||
|
} else if tipo.is_bls381_12_g1() {
|
||||||
|
Term::bls12_381_g1_equal()
|
||||||
|
} else if tipo.is_bls381_12_g2() {
|
||||||
|
Term::bls12_381_g2_equal()
|
||||||
|
} else if tipo.is_ml_result() {
|
||||||
|
panic!("ML Result equality is not supported")
|
||||||
} else {
|
} else {
|
||||||
Term::equals_data()
|
Term::equals_data()
|
||||||
};
|
};
|
||||||
|
|
|
@ -579,6 +579,12 @@ pub fn get_variant_name(t: &Rc<Type>) -> String {
|
||||||
"_bool".to_string()
|
"_bool".to_string()
|
||||||
} else if t.is_bytearray() {
|
} else if t.is_bytearray() {
|
||||||
"_bytearray".to_string()
|
"_bytearray".to_string()
|
||||||
|
} else if t.is_bls381_12_g1() {
|
||||||
|
"_bls381_12_g1".to_string()
|
||||||
|
} else if t.is_bls381_12_g2() {
|
||||||
|
"_bls381_12_g2".to_string()
|
||||||
|
} else if t.is_ml_result() {
|
||||||
|
"_ml_result".to_string()
|
||||||
} else if t.is_map() {
|
} else if t.is_map() {
|
||||||
let mut full_type = vec!["_map".to_string()];
|
let mut full_type = vec!["_map".to_string()];
|
||||||
let pair_type = &t.get_inner_types()[0];
|
let pair_type = &t.get_inner_types()[0];
|
||||||
|
@ -1305,7 +1311,7 @@ pub fn convert_constants_to_data(constants: Vec<Rc<UplcConstant>>) -> Vec<UplcCo
|
||||||
UplcConstant::Bls12_381G2Element(b) => UplcConstant::Data(PlutusData::BoundedBytes(
|
UplcConstant::Bls12_381G2Element(b) => UplcConstant::Data(PlutusData::BoundedBytes(
|
||||||
b.deref().clone().compress().into(),
|
b.deref().clone().compress().into(),
|
||||||
)),
|
)),
|
||||||
UplcConstant::Bls12_381MlResult(_) => unreachable!("Bls12_381MlResult not supported"),
|
UplcConstant::Bls12_381MlResult(_) => panic!("Bls12_381MlResult not supported"),
|
||||||
};
|
};
|
||||||
new_constants.push(constant);
|
new_constants.push(constant);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,25 @@ fn validator_illegal_return_type() {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn validator_useless_pub() {
|
||||||
|
let source_code = r#"
|
||||||
|
type Datum {
|
||||||
|
thing: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
validator {
|
||||||
|
pub fn foo(_d: Datum, _r, _c) {
|
||||||
|
True
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
|
||||||
|
let (warnings, _) = check_validator(parse(source_code)).unwrap();
|
||||||
|
|
||||||
|
assert!(matches!(warnings[0], Warning::PubInValidatorModule { .. }))
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn validator_illegal_arity() {
|
fn validator_illegal_arity() {
|
||||||
let source_code = r#"
|
let source_code = r#"
|
||||||
|
|
|
@ -62,6 +62,77 @@ fn format_if() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_logic_op_with_code_block() {
|
||||||
|
assert_format!(
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
True || {
|
||||||
|
let bar = 1
|
||||||
|
bar == bar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_grouped_expression() {
|
||||||
|
assert_format!(
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
y == { x |> f }
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_grouped_expression_2() {
|
||||||
|
assert_format!(
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
( y == x ) |> f
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_grouped_expression_3() {
|
||||||
|
assert_format!(
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
{ x |> f } == y
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_grouped_expression_4() {
|
||||||
|
assert_format!(
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
x |> { f == y }
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn format_preserve_newline_after_bool_expect() {
|
||||||
|
assert_format!(
|
||||||
|
r#"
|
||||||
|
fn foo() {
|
||||||
|
expect 1 == 1
|
||||||
|
|
||||||
|
False
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn format_validator() {
|
fn format_validator() {
|
||||||
assert_format!(
|
assert_format!(
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: crates/aiken-lang/src/tests/format.rs
|
||||||
|
description: "Code:\n\nfn foo() {\n y == { x |> f }\n}\n"
|
||||||
|
---
|
||||||
|
fn foo() {
|
||||||
|
y == ( x |> f )
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: crates/aiken-lang/src/tests/format.rs
|
||||||
|
description: "Code:\n\nfn foo() {\n ( y == x ) |> f\n}\n"
|
||||||
|
---
|
||||||
|
fn foo() {
|
||||||
|
( y == x ) |> f
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: crates/aiken-lang/src/tests/format.rs
|
||||||
|
description: "Code:\n\nfn foo() {\n { x |> f } == y\n}\n"
|
||||||
|
---
|
||||||
|
fn foo() {
|
||||||
|
( x |> f ) == y
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
source: crates/aiken-lang/src/tests/format.rs
|
||||||
|
description: "Code:\n\nfn foo() {\n x |> { f == y }\n}\n"
|
||||||
|
---
|
||||||
|
fn foo() {
|
||||||
|
x |> f == y
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
---
|
||||||
|
source: crates/aiken-lang/src/tests/format.rs
|
||||||
|
description: "Code:\n\nfn foo() {\n True || {\n let bar = 1\n bar == bar\n }\n}\n"
|
||||||
|
---
|
||||||
|
fn foo() {
|
||||||
|
True || {
|
||||||
|
let bar = 1
|
||||||
|
bar == bar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
source: crates/aiken-lang/src/tests/format.rs
|
||||||
|
description: "Code:\n\nfn foo() {\n expect 1 == 1\n\n False\n}\n"
|
||||||
|
---
|
||||||
|
fn foo() {
|
||||||
|
expect 1 == 1
|
||||||
|
|
||||||
|
False
|
||||||
|
}
|
||||||
|
|
|
@ -1131,15 +1131,15 @@ fn suggest_constructor_pattern(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn suggest_unify(
|
fn suggest_unify(
|
||||||
expected: &Rc<Type>,
|
expected: &Type,
|
||||||
given: &Rc<Type>,
|
given: &Type,
|
||||||
situation: &Option<UnifyErrorSituation>,
|
situation: &Option<UnifyErrorSituation>,
|
||||||
rigid_type_names: &HashMap<u64, String>,
|
rigid_type_names: &HashMap<u64, String>,
|
||||||
) -> String {
|
) -> String {
|
||||||
let expected_str = expected.to_pretty_with_names(rigid_type_names.clone(), 0);
|
let expected_str = expected.to_pretty_with_names(rigid_type_names.clone(), 0);
|
||||||
let given_str = given.to_pretty_with_names(rigid_type_names.clone(), 0);
|
let given_str = given.to_pretty_with_names(rigid_type_names.clone(), 0);
|
||||||
|
|
||||||
let (expected, given) = match (expected.as_ref(), given.as_ref()) {
|
let (expected, given) = match (expected, given) {
|
||||||
(
|
(
|
||||||
Type::App {
|
Type::App {
|
||||||
module: expected_module,
|
module: expected_module,
|
||||||
|
@ -1630,7 +1630,7 @@ pub enum UnknownRecordFieldSituation {
|
||||||
|
|
||||||
fn format_suggestion(sample: &UntypedExpr) -> String {
|
fn format_suggestion(sample: &UntypedExpr) -> String {
|
||||||
Formatter::new()
|
Formatter::new()
|
||||||
.expr(sample)
|
.expr(sample, false)
|
||||||
.to_pretty_string(70)
|
.to_pretty_string(70)
|
||||||
.lines()
|
.lines()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
|
|
|
@ -426,7 +426,9 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
tipo: string(),
|
tipo: string(),
|
||||||
value: format!(
|
value: format!(
|
||||||
"{} ? False",
|
"{} ? False",
|
||||||
format::Formatter::new().expr(&value).to_pretty_string(999)
|
format::Formatter::new()
|
||||||
|
.expr(&value, false)
|
||||||
|
.to_pretty_string(999)
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -150,9 +150,9 @@ impl FieldMap {
|
||||||
|
|
||||||
self.fields
|
self.fields
|
||||||
.keys()
|
.keys()
|
||||||
.cloned()
|
|
||||||
.filter(|f| !given.contains(f))
|
.filter(|f| !given.contains(f))
|
||||||
.sorted()
|
.sorted()
|
||||||
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ indexmap = "1.9.2"
|
||||||
itertools = "0.10.5"
|
itertools = "0.10.5"
|
||||||
miette = { version = "5.9.0", features = ["fancy"] }
|
miette = { version = "5.9.0", features = ["fancy"] }
|
||||||
minicbor = "0.19.1"
|
minicbor = "0.19.1"
|
||||||
|
notify = "6.1.1"
|
||||||
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
|
||||||
pallas = "0.18.0"
|
pallas = "0.18.0"
|
||||||
pallas-traverse = "0.18.0"
|
pallas-traverse = "0.18.0"
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
use crate::{
|
use crate::{blueprint::error as blueprint, deps::manifest::Package, package_name::PackageName};
|
||||||
blueprint::error as blueprint, deps::manifest::Package, package_name::PackageName, pretty,
|
|
||||||
script::EvalHint,
|
|
||||||
};
|
|
||||||
use aiken_lang::{
|
use aiken_lang::{
|
||||||
ast::{self, BinOp, Span},
|
ast::{self, Span},
|
||||||
error::ExtraData,
|
error::ExtraData,
|
||||||
parser::error::ParseError,
|
parser::error::ParseError,
|
||||||
tipo,
|
tipo,
|
||||||
|
@ -18,7 +15,6 @@ use std::{
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
use uplc::machine::cost_model::ExBudget;
|
|
||||||
use zip::result::ZipError;
|
use zip::result::ZipError;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -97,7 +93,7 @@ pub enum Error {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
verbose: bool,
|
verbose: bool,
|
||||||
src: String,
|
src: String,
|
||||||
evaluation_hint: Option<EvalHint>,
|
evaluation_hint: Option<String>,
|
||||||
},
|
},
|
||||||
|
|
||||||
#[error(
|
#[error(
|
||||||
|
@ -266,31 +262,45 @@ impl Diagnostic for Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||||
|
fn boxed<'a>(s: Box<dyn Display + 'a>) -> Box<dyn Display + 'a> {
|
||||||
|
Box::new(format!(
|
||||||
|
" {} {}",
|
||||||
|
"Error"
|
||||||
|
.if_supports_color(Stdout, |s| s.red())
|
||||||
|
.if_supports_color(Stdout, |s| s.bold()),
|
||||||
|
format!("{s}").if_supports_color(Stdout, |s| s.red())
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Error::DuplicateModule { .. } => Some(Box::new("aiken::module::duplicate")),
|
Error::DuplicateModule { .. } => Some(boxed(Box::new("aiken::module::duplicate"))),
|
||||||
Error::FileIo { .. } => None,
|
Error::FileIo { .. } => None,
|
||||||
Error::Blueprint(e) => e.code(),
|
Error::Blueprint(e) => e.code().map(boxed),
|
||||||
Error::ImportCycle { .. } => Some(Box::new("aiken::module::cyclical")),
|
Error::ImportCycle { .. } => Some(boxed(Box::new("aiken::module::cyclical"))),
|
||||||
Error::Parse { .. } => Some(Box::new("aiken::parser")),
|
Error::Parse { .. } => Some(boxed(Box::new("aiken::parser"))),
|
||||||
Error::Type { error, .. } => Some(Box::new(format!(
|
Error::Type { error, .. } => Some(boxed(Box::new(format!(
|
||||||
"aiken::check{}",
|
"aiken::check{}",
|
||||||
error.code().map(|s| format!("::{s}")).unwrap_or_default()
|
error.code().map(|s| format!("::{s}")).unwrap_or_default()
|
||||||
))),
|
)))),
|
||||||
Error::StandardIo(_) => None,
|
Error::StandardIo(_) => None,
|
||||||
Error::MissingManifest { .. } => None,
|
Error::MissingManifest { .. } => None,
|
||||||
Error::TomlLoading { .. } => Some(Box::new("aiken::loading::toml")),
|
Error::TomlLoading { .. } => Some(boxed(Box::new("aiken::loading::toml"))),
|
||||||
Error::Format { .. } => None,
|
Error::Format { .. } => None,
|
||||||
Error::TestFailure { path, .. } => Some(Box::new(path.to_str().unwrap_or(""))),
|
Error::TestFailure { path, .. } => Some(boxed(Box::new(path.to_str().unwrap_or("")))),
|
||||||
Error::Http(_) => Some(Box::new("aiken::packages::download")),
|
Error::Http(_) => Some(Box::new("aiken::packages::download")),
|
||||||
Error::ZipExtract(_) => None,
|
Error::ZipExtract(_) => None,
|
||||||
Error::JoinError(_) => None,
|
Error::JoinError(_) => None,
|
||||||
Error::UnknownPackageVersion { .. } => Some(Box::new("aiken::packages::resolve")),
|
Error::UnknownPackageVersion { .. } => {
|
||||||
Error::UnableToResolvePackage { .. } => Some(Box::new("aiken::package::download")),
|
Some(boxed(Box::new("aiken::packages::resolve")))
|
||||||
|
}
|
||||||
|
Error::UnableToResolvePackage { .. } => {
|
||||||
|
Some(boxed(Box::new("aiken::package::download")))
|
||||||
|
}
|
||||||
Error::Json { .. } => None,
|
Error::Json { .. } => None,
|
||||||
Error::MalformedStakeAddress { .. } => None,
|
Error::MalformedStakeAddress { .. } => None,
|
||||||
Error::NoValidatorNotFound { .. } => None,
|
Error::NoValidatorNotFound { .. } => None,
|
||||||
Error::MoreThanOneValidatorFound { .. } => None,
|
Error::MoreThanOneValidatorFound { .. } => None,
|
||||||
Error::Module(e) => e.code(),
|
Error::Module(e) => e.code().map(boxed),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,33 +323,9 @@ impl Diagnostic for Error {
|
||||||
Error::MissingManifest { .. } => Some(Box::new("Try running `aiken new <REPOSITORY/PROJECT>` to initialise a project with an example manifest.")),
|
Error::MissingManifest { .. } => Some(Box::new("Try running `aiken new <REPOSITORY/PROJECT>` to initialise a project with an example manifest.")),
|
||||||
Error::TomlLoading { .. } => None,
|
Error::TomlLoading { .. } => None,
|
||||||
Error::Format { .. } => None,
|
Error::Format { .. } => None,
|
||||||
Error::TestFailure { evaluation_hint, .. } =>{
|
Error::TestFailure { evaluation_hint, .. } => match evaluation_hint {
|
||||||
match evaluation_hint {
|
None => None,
|
||||||
None => None,
|
Some(hint) => Some(Box::new(hint.to_string()))
|
||||||
Some(hint) => {
|
|
||||||
let budget = ExBudget { mem: i64::MAX, cpu: i64::MAX, };
|
|
||||||
let left = pretty::boxed("left", &match hint.left.clone().eval(budget).result() {
|
|
||||||
Ok(term) => format!("{term}"),
|
|
||||||
Err(err) => format!("{err}"),
|
|
||||||
});
|
|
||||||
let right = pretty::boxed("right", &match hint.right.clone().eval(budget).result() {
|
|
||||||
Ok(term) => format!("{term}"),
|
|
||||||
Err(err) => format!("{err}"),
|
|
||||||
});
|
|
||||||
let msg = match hint.bin_op {
|
|
||||||
BinOp::And => Some(format!("{left}\n\nand\n\n{right}\n\nshould both be true.")),
|
|
||||||
BinOp::Or => Some(format!("{left}\n\nor\n\n{right}\n\nshould be true.")),
|
|
||||||
BinOp::Eq => Some(format!("{left}\n\nshould be equal to\n\n{right}")),
|
|
||||||
BinOp::NotEq => Some(format!("{left}\n\nshould not be equal to\n\n{right}")),
|
|
||||||
BinOp::LtInt => Some(format!("{left}\n\nshould be lower than\n\n{right}")),
|
|
||||||
BinOp::LtEqInt => Some(format!("{left}\n\nshould be lower than or equal to\n\n{right}")),
|
|
||||||
BinOp::GtEqInt => Some(format!("{left}\n\nshould be greater than\n\n{right}")),
|
|
||||||
BinOp::GtInt => Some(format!("{left}\n\nshould be greater than or equal to\n\n{right}")),
|
|
||||||
_ => None
|
|
||||||
}?;
|
|
||||||
Some(Box::new(msg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Error::Http(_) => None,
|
Error::Http(_) => None,
|
||||||
Error::ZipExtract(_) => None,
|
Error::ZipExtract(_) => None,
|
||||||
|
@ -560,14 +546,24 @@ impl Diagnostic for Warning {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
|
||||||
|
fn boxed<'a>(s: Box<dyn Display + 'a>) -> Box<dyn Display + 'a> {
|
||||||
|
Box::new(format!(
|
||||||
|
" {} {}",
|
||||||
|
"Warning"
|
||||||
|
.if_supports_color(Stdout, |s| s.yellow())
|
||||||
|
.if_supports_color(Stdout, |s| s.bold()),
|
||||||
|
format!("{s}").if_supports_color(Stdout, |s| s.yellow())
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Warning::Type { warning, .. } => Some(Box::new(format!(
|
Warning::Type { warning, .. } => Some(boxed(Box::new(format!(
|
||||||
"aiken::check{}",
|
"aiken::check{}",
|
||||||
warning.code().map(|s| format!("::{s}")).unwrap_or_default()
|
warning.code().map(|s| format!("::{s}")).unwrap_or_default()
|
||||||
))),
|
)))),
|
||||||
Warning::NoValidators => Some(Box::new("aiken::check")),
|
Warning::NoValidators => Some(boxed(Box::new("aiken::check"))),
|
||||||
Warning::DependencyAlreadyExists { .. } => {
|
Warning::DependencyAlreadyExists { .. } => {
|
||||||
Some(Box::new("aiken::packages::already_exists"))
|
Some(boxed(Box::new("aiken::packages::already_exists")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ pub mod script;
|
||||||
pub mod telemetry;
|
pub mod telemetry;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
pub mod watch;
|
||||||
|
|
||||||
use crate::blueprint::{
|
use crate::blueprint::{
|
||||||
definitions::Definitions,
|
definitions::Definitions,
|
||||||
|
@ -328,7 +329,11 @@ where
|
||||||
Some(Error::TestFailure {
|
Some(Error::TestFailure {
|
||||||
name: e.script.name.clone(),
|
name: e.script.name.clone(),
|
||||||
path: e.script.input_path.clone(),
|
path: e.script.input_path.clone(),
|
||||||
evaluation_hint: e.script.evaluation_hint.clone(),
|
evaluation_hint: e
|
||||||
|
.script
|
||||||
|
.evaluation_hint
|
||||||
|
.as_ref()
|
||||||
|
.map(|hint| hint.to_string()),
|
||||||
src: e.script.program.to_pretty(),
|
src: e.script.program.to_pretty(),
|
||||||
verbose,
|
verbose,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use crate::{ExBudget, Term};
|
use crate::{pretty, ExBudget, Term};
|
||||||
use aiken_lang::ast::BinOp;
|
use aiken_lang::ast::BinOp;
|
||||||
use std::path::PathBuf;
|
use std::{
|
||||||
|
fmt::{self, Display},
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
use uplc::ast::{NamedDeBruijn, Program};
|
use uplc::ast::{NamedDeBruijn, Program};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -42,6 +45,48 @@ pub struct EvalHint {
|
||||||
pub right: Program<NamedDeBruijn>,
|
pub right: Program<NamedDeBruijn>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for EvalHint {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let unlimited_budget = ExBudget {
|
||||||
|
mem: i64::MAX,
|
||||||
|
cpu: i64::MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
let left = pretty::boxed(
|
||||||
|
"left",
|
||||||
|
&match self.left.clone().eval(unlimited_budget).result() {
|
||||||
|
Ok(term) => format!("{term}"),
|
||||||
|
Err(err) => format!("{err}"),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let right = pretty::boxed(
|
||||||
|
"right",
|
||||||
|
&match self.right.clone().eval(unlimited_budget).result() {
|
||||||
|
Ok(term) => format!("{term}"),
|
||||||
|
Err(err) => format!("{err}"),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
let msg = match self.bin_op {
|
||||||
|
BinOp::And => Some(format!("{left}\n\nand\n\n{right}\n\nshould both be true.")),
|
||||||
|
BinOp::Or => Some(format!("{left}\n\nor\n\n{right}\n\nshould be true.")),
|
||||||
|
BinOp::Eq => Some(format!("{left}\n\nshould be equal to\n\n{right}")),
|
||||||
|
BinOp::NotEq => Some(format!("{left}\n\nshould not be equal to\n\n{right}")),
|
||||||
|
BinOp::LtInt => Some(format!("{left}\n\nshould be lower than\n\n{right}")),
|
||||||
|
BinOp::LtEqInt => Some(format!(
|
||||||
|
"{left}\n\nshould be lower than or equal to\n\n{right}"
|
||||||
|
)),
|
||||||
|
BinOp::GtEqInt => Some(format!("{left}\n\nshould be greater than\n\n{right}")),
|
||||||
|
BinOp::GtInt => Some(format!(
|
||||||
|
"{left}\n\nshould be greater than or equal to\n\n{right}"
|
||||||
|
)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
.ok_or(fmt::Error)?;
|
||||||
|
|
||||||
|
f.write_str(&msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EvalInfo {
|
pub struct EvalInfo {
|
||||||
pub success: bool,
|
pub success: bool,
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
|
use crate::pretty;
|
||||||
use crate::script::EvalInfo;
|
use crate::script::EvalInfo;
|
||||||
use std::{fmt::Display, path::PathBuf};
|
use owo_colors::{
|
||||||
|
OwoColorize,
|
||||||
|
Stream::{self, Stderr},
|
||||||
|
};
|
||||||
|
use std::{collections::BTreeMap, fmt::Display, path::PathBuf};
|
||||||
|
use uplc::machine::cost_model::ExBudget;
|
||||||
|
|
||||||
pub trait EventListener {
|
pub trait EventListener {
|
||||||
fn handle_event(&self, _event: Event) {}
|
fn handle_event(&self, _event: Event) {}
|
||||||
|
@ -64,3 +70,339 @@ impl Display for DownloadSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
|
pub struct Terminal;
|
||||||
|
|
||||||
|
impl EventListener for Terminal {
|
||||||
|
fn handle_event(&self, event: Event) {
|
||||||
|
match event {
|
||||||
|
Event::StartingCompilation {
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
root,
|
||||||
|
} => {
|
||||||
|
eprintln!(
|
||||||
|
"{} {} {} ({})",
|
||||||
|
" Compiling"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
name.if_supports_color(Stderr, |s| s.bold()),
|
||||||
|
version,
|
||||||
|
root.display()
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Event::BuildingDocumentation {
|
||||||
|
name,
|
||||||
|
version,
|
||||||
|
root,
|
||||||
|
} => {
|
||||||
|
eprintln!(
|
||||||
|
"{} {} {} ({})",
|
||||||
|
" Generating documentation"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
name.if_supports_color(Stderr, |s| s.bold()),
|
||||||
|
version,
|
||||||
|
root.to_str()
|
||||||
|
.unwrap_or("")
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Event::WaitingForBuildDirLock => {
|
||||||
|
eprintln!(
|
||||||
|
"{}",
|
||||||
|
"Waiting for build directory lock ..."
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Event::DumpingUPLC { path } => {
|
||||||
|
eprintln!(
|
||||||
|
"{} {} ({})",
|
||||||
|
" Exporting"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
"UPLC".if_supports_color(Stderr, |s| s.bold()),
|
||||||
|
path.display()
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Event::GeneratingBlueprint { path } => {
|
||||||
|
eprintln!(
|
||||||
|
"{} {} ({})",
|
||||||
|
" Generating"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
"project's blueprint".if_supports_color(Stderr, |s| s.bold()),
|
||||||
|
path.display()
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Event::GeneratingDocFiles { output_path } => {
|
||||||
|
eprintln!(
|
||||||
|
"{} in {}",
|
||||||
|
" Generating documentation files"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
output_path
|
||||||
|
.to_str()
|
||||||
|
.unwrap_or("")
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Event::GeneratingUPLCFor { name, path } => {
|
||||||
|
eprintln!(
|
||||||
|
"{} {}.{{{}}}",
|
||||||
|
" Generating UPLC for"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
path.to_str()
|
||||||
|
.unwrap_or("")
|
||||||
|
.if_supports_color(Stderr, |s| s.blue()),
|
||||||
|
name.if_supports_color(Stderr, |s| s.bright_blue()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Event::EvaluatingFunction { results } => {
|
||||||
|
eprintln!(
|
||||||
|
"{}\n",
|
||||||
|
" Evaluating function ..."
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple())
|
||||||
|
);
|
||||||
|
|
||||||
|
let (max_mem, max_cpu) = find_max_execution_units(&results);
|
||||||
|
|
||||||
|
for eval_info in &results {
|
||||||
|
println!(" {}", fmt_eval(eval_info, max_mem, max_cpu, Stderr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::RunningTests => {
|
||||||
|
eprintln!(
|
||||||
|
"{} {}\n",
|
||||||
|
" Testing"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
"...".if_supports_color(Stderr, |s| s.bold())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Event::FinishedTests { tests } => {
|
||||||
|
let (max_mem, max_cpu) = find_max_execution_units(&tests);
|
||||||
|
|
||||||
|
for (module, infos) in &group_by_module(&tests) {
|
||||||
|
let title = module
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.blue())
|
||||||
|
.to_string();
|
||||||
|
|
||||||
|
let tests = infos
|
||||||
|
.iter()
|
||||||
|
.map(|eval_info| fmt_test(eval_info, max_mem, max_cpu, true))
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
let summary = fmt_test_summary(infos, true);
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"{}\n",
|
||||||
|
pretty::indent(
|
||||||
|
&pretty::open_box(&title, &tests, &summary, |border| border
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_black())
|
||||||
|
.to_string()),
|
||||||
|
4
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::ResolvingPackages { name } => {
|
||||||
|
eprintln!(
|
||||||
|
"{} {}",
|
||||||
|
" Resolving"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
name.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Event::PackageResolveFallback { name } => {
|
||||||
|
eprintln!(
|
||||||
|
"{} {}\n ↳ You're seeing this message because the package version is unpinned and the network is not accessible.",
|
||||||
|
" Using"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.yellow()),
|
||||||
|
format!("uncertain local version for {name}")
|
||||||
|
.if_supports_color(Stderr, |s| s.yellow())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Event::PackagesDownloaded {
|
||||||
|
start,
|
||||||
|
count,
|
||||||
|
source,
|
||||||
|
} => {
|
||||||
|
let elapsed = format!("{:.2}s", start.elapsed().as_millis() as f32 / 1000.);
|
||||||
|
|
||||||
|
let msg = match count {
|
||||||
|
1 => format!("1 package in {elapsed}"),
|
||||||
|
_ => format!("{count} packages in {elapsed}"),
|
||||||
|
};
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"{} {} from {source}",
|
||||||
|
match source {
|
||||||
|
DownloadSource::Network => " Downloaded",
|
||||||
|
DownloadSource::Cache => " Fetched",
|
||||||
|
}
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
msg.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Event::ResolvingVersions => {
|
||||||
|
eprintln!(
|
||||||
|
"{}",
|
||||||
|
" Resolving dependencies"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fmt_test(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize, styled: bool) -> String {
|
||||||
|
let EvalInfo {
|
||||||
|
success,
|
||||||
|
script,
|
||||||
|
spent_budget,
|
||||||
|
logs,
|
||||||
|
..
|
||||||
|
} = eval_info;
|
||||||
|
|
||||||
|
let ExBudget { mem, cpu } = spent_budget;
|
||||||
|
let mem_pad = pretty::pad_left(mem.to_string(), max_mem, " ");
|
||||||
|
let cpu_pad = pretty::pad_left(cpu.to_string(), max_cpu, " ");
|
||||||
|
|
||||||
|
let test = format!(
|
||||||
|
"{status} [mem: {mem_unit}, cpu: {cpu_unit}] {module}",
|
||||||
|
status = if *success {
|
||||||
|
pretty::style_if(styled, "PASS".to_string(), |s| {
|
||||||
|
s.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.green())
|
||||||
|
.to_string()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
pretty::style_if(styled, "FAIL".to_string(), |s| {
|
||||||
|
s.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.red())
|
||||||
|
.to_string()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
mem_unit = pretty::style_if(styled, mem_pad, |s| s
|
||||||
|
.if_supports_color(Stderr, |s| s.cyan())
|
||||||
|
.to_string()),
|
||||||
|
cpu_unit = pretty::style_if(styled, cpu_pad, |s| s
|
||||||
|
.if_supports_color(Stderr, |s| s.cyan())
|
||||||
|
.to_string()),
|
||||||
|
module = pretty::style_if(styled, script.name.clone(), |s| s
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_blue())
|
||||||
|
.to_string()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let logs = if logs.is_empty() {
|
||||||
|
String::new()
|
||||||
|
} else {
|
||||||
|
logs.iter()
|
||||||
|
.map(|line| {
|
||||||
|
format!(
|
||||||
|
"{arrow} {styled_line}",
|
||||||
|
arrow = "↳".if_supports_color(Stderr, |s| s.bright_yellow()),
|
||||||
|
styled_line = line.if_supports_color(Stderr, |s| s.bright_black())
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
};
|
||||||
|
|
||||||
|
if logs.is_empty() {
|
||||||
|
test
|
||||||
|
} else {
|
||||||
|
[test, logs].join("\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fmt_test_summary(tests: &Vec<&EvalInfo>, styled: bool) -> String {
|
||||||
|
let (n_passed, n_failed) = tests
|
||||||
|
.iter()
|
||||||
|
.fold((0, 0), |(n_passed, n_failed), test_info| {
|
||||||
|
if test_info.success {
|
||||||
|
(n_passed + 1, n_failed)
|
||||||
|
} else {
|
||||||
|
(n_passed, n_failed + 1)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
format!(
|
||||||
|
"{} | {} | {}",
|
||||||
|
pretty::style_if(styled, format!("{} tests", tests.len()), |s| s
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.to_string()),
|
||||||
|
pretty::style_if(styled, format!("{n_passed} passed"), |s| s
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_green())
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.to_string()),
|
||||||
|
pretty::style_if(styled, format!("{n_failed} failed"), |s| s
|
||||||
|
.if_supports_color(Stderr, |s| s.bright_red())
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.to_string()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fmt_eval(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize, stream: Stream) -> String {
|
||||||
|
let EvalInfo {
|
||||||
|
output,
|
||||||
|
script,
|
||||||
|
spent_budget,
|
||||||
|
..
|
||||||
|
} = eval_info;
|
||||||
|
|
||||||
|
let ExBudget { mem, cpu } = spent_budget;
|
||||||
|
|
||||||
|
format!(
|
||||||
|
" {}::{} [mem: {}, cpu: {}]\n │\n ╰─▶ {}",
|
||||||
|
script.module.if_supports_color(stream, |s| s.blue()),
|
||||||
|
script.name.if_supports_color(stream, |s| s.bright_blue()),
|
||||||
|
pretty::pad_left(mem.to_string(), max_mem, " "),
|
||||||
|
pretty::pad_left(cpu.to_string(), max_cpu, " "),
|
||||||
|
output
|
||||||
|
.as_ref()
|
||||||
|
.map(|x| format!("{x}"))
|
||||||
|
.unwrap_or_else(|| "Error.".to_string()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn group_by_module(infos: &Vec<EvalInfo>) -> BTreeMap<String, Vec<&EvalInfo>> {
|
||||||
|
let mut modules = BTreeMap::new();
|
||||||
|
for eval_info in infos {
|
||||||
|
let xs: &mut Vec<&EvalInfo> = modules.entry(eval_info.script.module.clone()).or_default();
|
||||||
|
xs.push(eval_info);
|
||||||
|
}
|
||||||
|
modules
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_max_execution_units(xs: &[EvalInfo]) -> (usize, usize) {
|
||||||
|
let (max_mem, max_cpu) = xs.iter().fold(
|
||||||
|
(0, 0),
|
||||||
|
|(max_mem, max_cpu), EvalInfo { spent_budget, .. }| {
|
||||||
|
if spent_budget.mem >= max_mem && spent_budget.cpu >= max_cpu {
|
||||||
|
(spent_budget.mem, spent_budget.cpu)
|
||||||
|
} else if spent_budget.mem > max_mem {
|
||||||
|
(spent_budget.mem, max_cpu)
|
||||||
|
} else if spent_budget.cpu > max_cpu {
|
||||||
|
(max_mem, spent_budget.cpu)
|
||||||
|
} else {
|
||||||
|
(max_mem, max_cpu)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
(max_mem.to_string().len(), max_cpu.to_string().len())
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,225 @@
|
||||||
|
use crate::{telemetry::Terminal, Project};
|
||||||
|
use miette::{Diagnostic, IntoDiagnostic};
|
||||||
|
use notify::{Event, RecursiveMode, Watcher};
|
||||||
|
use owo_colors::{OwoColorize, Stream::Stderr};
|
||||||
|
use std::{
|
||||||
|
collections::VecDeque,
|
||||||
|
env,
|
||||||
|
ffi::OsStr,
|
||||||
|
fmt::{self, Display},
|
||||||
|
path::Path,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Diagnostic, thiserror::Error)]
|
||||||
|
enum ExitFailure {
|
||||||
|
#[error("")]
|
||||||
|
ExitFailure,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExitFailure {
|
||||||
|
fn into_report() -> miette::Report {
|
||||||
|
ExitFailure::ExitFailure.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Summary {
|
||||||
|
warning_count: usize,
|
||||||
|
error_count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Summary {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.write_str(&format!(
|
||||||
|
" {} {} {}, {} {}",
|
||||||
|
"Summary"
|
||||||
|
.if_supports_color(Stderr, |s| s.purple())
|
||||||
|
.if_supports_color(Stderr, |s| s.bold()),
|
||||||
|
self.error_count,
|
||||||
|
if self.error_count == 1 {
|
||||||
|
"error"
|
||||||
|
} else {
|
||||||
|
"errors"
|
||||||
|
}
|
||||||
|
.if_supports_color(Stderr, |s| s.red())
|
||||||
|
.if_supports_color(Stderr, |s| s.bold()),
|
||||||
|
self.warning_count,
|
||||||
|
if self.warning_count == 1 {
|
||||||
|
"warning"
|
||||||
|
} else {
|
||||||
|
"warnings"
|
||||||
|
}
|
||||||
|
.if_supports_color(Stderr, |s| s.yellow())
|
||||||
|
.if_supports_color(Stderr, |s| s.bold()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A default filter for file events that catches the most relevant "source" changes
|
||||||
|
pub fn default_filter(evt: &Event) -> bool {
|
||||||
|
// Only watch for changes to .ak and aiken.toml files, and ignore the build directory
|
||||||
|
let source_file = evt
|
||||||
|
.paths
|
||||||
|
.iter()
|
||||||
|
.any(|p| p.extension() == Some(OsStr::new("ak")) || p.ends_with("aiken.toml"));
|
||||||
|
let build_dir = evt
|
||||||
|
.paths
|
||||||
|
.iter()
|
||||||
|
.all(|p| p.ancestors().any(|a| a.ends_with("build")));
|
||||||
|
match evt.kind {
|
||||||
|
notify::EventKind::Any => true,
|
||||||
|
notify::EventKind::Create(_)
|
||||||
|
| notify::EventKind::Modify(_)
|
||||||
|
| notify::EventKind::Remove(_) => source_file && !build_dir,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_project<A>(directory: Option<&Path>, deny: bool, mut action: A) -> miette::Result<()>
|
||||||
|
where
|
||||||
|
A: FnMut(&mut Project<Terminal>) -> Result<(), Vec<crate::error::Error>>,
|
||||||
|
{
|
||||||
|
let project_path = if let Some(d) = directory {
|
||||||
|
d.to_path_buf()
|
||||||
|
} else {
|
||||||
|
env::current_dir().into_diagnostic()?
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut project = match Project::new(project_path, Terminal) {
|
||||||
|
Ok(p) => Ok(p),
|
||||||
|
Err(e) => {
|
||||||
|
e.report();
|
||||||
|
Err(ExitFailure::into_report())
|
||||||
|
}
|
||||||
|
}?;
|
||||||
|
|
||||||
|
let build_result = action(&mut project);
|
||||||
|
|
||||||
|
let warnings = project.warnings();
|
||||||
|
|
||||||
|
let warning_count = warnings.len();
|
||||||
|
|
||||||
|
for warning in &warnings {
|
||||||
|
warning.report()
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(errs) = build_result {
|
||||||
|
for err in &errs {
|
||||||
|
err.report()
|
||||||
|
}
|
||||||
|
|
||||||
|
eprintln!(
|
||||||
|
"{}",
|
||||||
|
Summary {
|
||||||
|
warning_count,
|
||||||
|
error_count: errs.len(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return Err(ExitFailure::into_report());
|
||||||
|
} else {
|
||||||
|
eprintln!(
|
||||||
|
"{}",
|
||||||
|
Summary {
|
||||||
|
error_count: 0,
|
||||||
|
warning_count
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if warning_count > 0 && deny {
|
||||||
|
Err(ExitFailure::into_report())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run a function each time a file in the project changes
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// // Note: doctest disabled, because aiken_project doesn't have an implementation of EventListener I can use
|
||||||
|
/// use aiken_project::watch::{watch_project, default_filter};
|
||||||
|
/// use aiken_project::{Project};
|
||||||
|
/// watch_project(None, Terminal, default_filter, 500, |project| {
|
||||||
|
/// println!("Project changed!");
|
||||||
|
/// Ok(())
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
pub fn watch_project<F, A>(
|
||||||
|
directory: Option<&Path>,
|
||||||
|
filter: F,
|
||||||
|
debounce: u32,
|
||||||
|
mut action: A,
|
||||||
|
) -> miette::Result<()>
|
||||||
|
where
|
||||||
|
F: Fn(&Event) -> bool,
|
||||||
|
A: FnMut(&mut Project<Terminal>) -> Result<(), Vec<crate::error::Error>>,
|
||||||
|
{
|
||||||
|
let project_path = directory
|
||||||
|
.map(|p| p.to_path_buf())
|
||||||
|
.unwrap_or(env::current_dir().into_diagnostic()?);
|
||||||
|
|
||||||
|
// Set up a queue for events, primarily so we can debounce on related events
|
||||||
|
let queue = Arc::new(Mutex::new(VecDeque::new()));
|
||||||
|
|
||||||
|
// Run the action once, to start
|
||||||
|
queue
|
||||||
|
.lock()
|
||||||
|
.expect("lock queue")
|
||||||
|
.push_back(Event::default());
|
||||||
|
|
||||||
|
// Spawn a file-watcher that will put each change event on the queue
|
||||||
|
let queue_write = queue.clone();
|
||||||
|
let mut watcher = notify::recommended_watcher(move |res: notify::Result<Event>| {
|
||||||
|
match res {
|
||||||
|
Ok(event) => queue_write
|
||||||
|
.lock()
|
||||||
|
.expect("lock queue")
|
||||||
|
.push_back(event.clone()),
|
||||||
|
Err(e) => {
|
||||||
|
// TODO: miette diagnostic?
|
||||||
|
println!(
|
||||||
|
"Encountered an error while monitoring for file changes: {:?}",
|
||||||
|
e
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.into_diagnostic()?;
|
||||||
|
|
||||||
|
// Start watching for any changes in the project directory
|
||||||
|
let _ = watcher.watch(project_path.as_path(), RecursiveMode::Recursive);
|
||||||
|
|
||||||
|
// And then start reading from the queue
|
||||||
|
let queue_read = queue.clone();
|
||||||
|
loop {
|
||||||
|
// We sleep for the debounce interval, because notify will dump 12 related events into the queue all at once
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(debounce.into()));
|
||||||
|
|
||||||
|
// Grab the lock, and pop all events except the last one off the queue
|
||||||
|
let mut queue = queue_read.lock().expect("lock queue");
|
||||||
|
let mut latest = None;
|
||||||
|
// debounce the events, and ignore build/lock changes, because they come in in large batches
|
||||||
|
while let Some(evt) = queue.pop_back() {
|
||||||
|
// check if this event is meaningful to the caller
|
||||||
|
if !filter(&evt) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
latest = Some(evt);
|
||||||
|
}
|
||||||
|
// release the lock here, in case other events come in
|
||||||
|
drop(queue);
|
||||||
|
|
||||||
|
// If we have an event that survived the filter, then we can construct the project and invoke the action
|
||||||
|
if latest.is_some() {
|
||||||
|
print!("{esc}c", esc = 27 as char);
|
||||||
|
println!(
|
||||||
|
"{} ...",
|
||||||
|
" Watching"
|
||||||
|
.if_supports_color(Stderr, |s| s.bold())
|
||||||
|
.if_supports_color(Stderr, |s| s.purple()),
|
||||||
|
);
|
||||||
|
with_project(directory, false, &mut action).unwrap_or(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::with_project;
|
|
||||||
use aiken_lang::ast::Tracing;
|
use aiken_lang::ast::Tracing;
|
||||||
|
use aiken_project::watch::with_project;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
/// Compute a validator's address.
|
/// Compute a validator's address.
|
||||||
|
@ -34,7 +34,7 @@ pub fn exec(
|
||||||
rebuild,
|
rebuild,
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
with_project(directory, false, |p| {
|
with_project(directory.as_deref(), false, |p| {
|
||||||
if rebuild {
|
if rebuild {
|
||||||
p.build(false, Tracing::NoTraces)?;
|
p.build(false, Tracing::NoTraces)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use crate::with_project;
|
|
||||||
use aiken_project::{
|
use aiken_project::{
|
||||||
blueprint::{
|
blueprint::{
|
||||||
self,
|
self,
|
||||||
|
@ -7,6 +6,7 @@ use aiken_project::{
|
||||||
},
|
},
|
||||||
error::Error,
|
error::Error,
|
||||||
pretty::multiline,
|
pretty::multiline,
|
||||||
|
watch::with_project,
|
||||||
};
|
};
|
||||||
use inquire;
|
use inquire;
|
||||||
use num_bigint::BigInt;
|
use num_bigint::BigInt;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::with_project;
|
|
||||||
use aiken_lang::ast::Tracing;
|
use aiken_lang::ast::Tracing;
|
||||||
|
use aiken_project::watch::with_project;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
/// Compute a validator's hash
|
/// Compute a validator's hash
|
||||||
|
@ -29,7 +29,7 @@ pub fn exec(
|
||||||
rebuild,
|
rebuild,
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
with_project(directory, false, |p| {
|
with_project(directory.as_deref(), false, |p| {
|
||||||
if rebuild {
|
if rebuild {
|
||||||
p.build(false, Tracing::NoTraces)?;
|
p.build(false, Tracing::NoTraces)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::with_project;
|
|
||||||
use aiken_lang::ast::Tracing;
|
use aiken_lang::ast::Tracing;
|
||||||
|
use aiken_project::watch::with_project;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
/// Compute a minting scripts Policy ID
|
/// Compute a minting scripts Policy ID
|
||||||
|
@ -29,7 +29,7 @@ pub fn exec(
|
||||||
rebuild,
|
rebuild,
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
with_project(directory, false, |p| {
|
with_project(directory.as_deref(), false, |p| {
|
||||||
if rebuild {
|
if rebuild {
|
||||||
p.build(false, Tracing::NoTraces)?;
|
p.build(false, Tracing::NoTraces)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use aiken_project::watch::{self, watch_project, with_project};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
#[derive(clap::Args)]
|
||||||
|
@ -10,6 +11,10 @@ pub struct Args {
|
||||||
#[clap(short = 'D', long)]
|
#[clap(short = 'D', long)]
|
||||||
deny: bool,
|
deny: bool,
|
||||||
|
|
||||||
|
/// When enabled, re-run the command on file changes instead of exiting
|
||||||
|
#[clap(short, long)]
|
||||||
|
watch: bool,
|
||||||
|
|
||||||
/// Also dump textual uplc
|
/// Also dump textual uplc
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
uplc: bool,
|
uplc: bool,
|
||||||
|
@ -23,9 +28,18 @@ pub fn exec(
|
||||||
Args {
|
Args {
|
||||||
directory,
|
directory,
|
||||||
deny,
|
deny,
|
||||||
|
watch,
|
||||||
uplc,
|
uplc,
|
||||||
keep_traces,
|
keep_traces,
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
crate::with_project(directory, deny, |p| p.build(uplc, keep_traces.into()))
|
if watch {
|
||||||
|
watch_project(directory.as_deref(), watch::default_filter, 500, |p| {
|
||||||
|
p.build(uplc, keep_traces.into())
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
with_project(directory.as_deref(), deny, |p| {
|
||||||
|
p.build(uplc, keep_traces.into())
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use aiken_project::watch::{self, watch_project, with_project};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
#[derive(clap::Args)]
|
||||||
|
@ -18,6 +19,10 @@ pub struct Args {
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
debug: bool,
|
debug: bool,
|
||||||
|
|
||||||
|
/// When enabled, re-run the command on file changes instead of exiting
|
||||||
|
#[clap(long)]
|
||||||
|
watch: bool,
|
||||||
|
|
||||||
/// Only run tests if they match any of these strings.
|
/// Only run tests if they match any of these strings.
|
||||||
/// You can match a module with `-m aiken/list` or `-m list`.
|
/// You can match a module with `-m aiken/list` or `-m list`.
|
||||||
/// You can match a test with `-m "aiken/list.{map}"` or `-m "aiken/option.{flatten_1}"`
|
/// You can match a test with `-m "aiken/list.{map}"` or `-m "aiken/option.{flatten_1}"`
|
||||||
|
@ -43,15 +48,29 @@ pub fn exec(
|
||||||
match_tests,
|
match_tests,
|
||||||
exact_match,
|
exact_match,
|
||||||
no_traces,
|
no_traces,
|
||||||
|
watch,
|
||||||
|
..
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
crate::with_project(directory, deny, |p| {
|
if watch {
|
||||||
p.check(
|
watch_project(directory.as_deref(), watch::default_filter, 500, |p| {
|
||||||
skip_tests,
|
p.check(
|
||||||
match_tests.clone(),
|
skip_tests,
|
||||||
debug,
|
match_tests.clone(),
|
||||||
exact_match,
|
debug,
|
||||||
(!no_traces).into(),
|
exact_match,
|
||||||
)
|
(!no_traces).into(),
|
||||||
})
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
with_project(directory.as_deref(), deny, |p| {
|
||||||
|
p.check(
|
||||||
|
skip_tests,
|
||||||
|
match_tests.clone(),
|
||||||
|
debug,
|
||||||
|
exact_match,
|
||||||
|
(!no_traces).into(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use aiken_project::watch::{self, watch_project, with_project};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
#[derive(clap::Args)]
|
||||||
|
@ -10,6 +11,10 @@ pub struct Args {
|
||||||
#[clap(short = 'D', long)]
|
#[clap(short = 'D', long)]
|
||||||
deny: bool,
|
deny: bool,
|
||||||
|
|
||||||
|
/// When enabled, re-run the command on file changes instead of exiting
|
||||||
|
#[clap(short, long)]
|
||||||
|
watch: bool,
|
||||||
|
|
||||||
/// Output directory for the documentation
|
/// Output directory for the documentation
|
||||||
#[clap(short = 'o', long)]
|
#[clap(short = 'o', long)]
|
||||||
destination: Option<PathBuf>,
|
destination: Option<PathBuf>,
|
||||||
|
@ -19,8 +24,15 @@ pub fn exec(
|
||||||
Args {
|
Args {
|
||||||
directory,
|
directory,
|
||||||
deny,
|
deny,
|
||||||
|
watch,
|
||||||
destination,
|
destination,
|
||||||
}: Args,
|
}: Args,
|
||||||
) -> miette::Result<()> {
|
) -> miette::Result<()> {
|
||||||
crate::with_project(directory, deny, |p| p.docs(destination.clone()))
|
if watch {
|
||||||
|
watch_project(directory.as_deref(), watch::default_filter, 500, |p| {
|
||||||
|
p.docs(destination.clone())
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
with_project(directory.as_deref(), deny, |p| p.docs(destination.clone()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,431 +0,0 @@
|
||||||
use aiken_project::{
|
|
||||||
pretty,
|
|
||||||
script::EvalInfo,
|
|
||||||
telemetry::{self, DownloadSource},
|
|
||||||
Project,
|
|
||||||
};
|
|
||||||
use miette::IntoDiagnostic;
|
|
||||||
use owo_colors::{
|
|
||||||
OwoColorize,
|
|
||||||
Stream::{self, Stderr},
|
|
||||||
};
|
|
||||||
use std::{collections::BTreeMap, env, path::PathBuf, process};
|
|
||||||
use uplc::machine::cost_model::ExBudget;
|
|
||||||
|
|
||||||
pub mod cmd;
|
|
||||||
|
|
||||||
pub fn with_project<A>(directory: Option<PathBuf>, deny: bool, mut action: A) -> miette::Result<()>
|
|
||||||
where
|
|
||||||
A: FnMut(&mut Project<Terminal>) -> Result<(), Vec<aiken_project::error::Error>>,
|
|
||||||
{
|
|
||||||
let project_path = if let Some(d) = directory {
|
|
||||||
d
|
|
||||||
} else {
|
|
||||||
env::current_dir().into_diagnostic()?
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut project = match Project::new(project_path, Terminal) {
|
|
||||||
Ok(p) => p,
|
|
||||||
Err(e) => {
|
|
||||||
e.report();
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let build_result = action(&mut project);
|
|
||||||
|
|
||||||
let warnings = project.warnings();
|
|
||||||
|
|
||||||
let warning_count = warnings.len();
|
|
||||||
|
|
||||||
for warning in &warnings {
|
|
||||||
warning.report()
|
|
||||||
}
|
|
||||||
|
|
||||||
let plural = if warning_count == 1 { "" } else { "s" };
|
|
||||||
|
|
||||||
if let Err(errs) = build_result {
|
|
||||||
for err in &errs {
|
|
||||||
err.report()
|
|
||||||
}
|
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"\n{}",
|
|
||||||
"Summary"
|
|
||||||
.if_supports_color(Stderr, |s| s.purple())
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
);
|
|
||||||
|
|
||||||
let warning_text = format!("{warning_count} warning{plural}");
|
|
||||||
|
|
||||||
let plural = if errs.len() == 1 { "" } else { "s" };
|
|
||||||
|
|
||||||
let error_text = format!("{} error{}", errs.len(), plural);
|
|
||||||
|
|
||||||
let full_summary = format!(
|
|
||||||
" {}, {}",
|
|
||||||
error_text.if_supports_color(Stderr, |s| s.red()),
|
|
||||||
warning_text.if_supports_color(Stderr, |s| s.yellow())
|
|
||||||
);
|
|
||||||
|
|
||||||
eprintln!("{full_summary}");
|
|
||||||
|
|
||||||
process::exit(1);
|
|
||||||
} else {
|
|
||||||
eprintln!(
|
|
||||||
"\n{}",
|
|
||||||
"Summary"
|
|
||||||
.if_supports_color(Stderr, |s| s.purple())
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
);
|
|
||||||
|
|
||||||
let warning_text = format!("{warning_count} warning{plural}");
|
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
" 0 errors, {}",
|
|
||||||
warning_text.if_supports_color(Stderr, |s| s.yellow()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if warning_count > 0 && deny {
|
|
||||||
process::exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy)]
|
|
||||||
pub struct Terminal;
|
|
||||||
|
|
||||||
impl telemetry::EventListener for Terminal {
|
|
||||||
fn handle_event(&self, event: telemetry::Event) {
|
|
||||||
match event {
|
|
||||||
telemetry::Event::StartingCompilation {
|
|
||||||
name,
|
|
||||||
version,
|
|
||||||
root,
|
|
||||||
} => {
|
|
||||||
eprintln!(
|
|
||||||
"{} {} {} ({})",
|
|
||||||
" Compiling"
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple()),
|
|
||||||
name.if_supports_color(Stderr, |s| s.bold()),
|
|
||||||
version,
|
|
||||||
root.display()
|
|
||||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
telemetry::Event::BuildingDocumentation {
|
|
||||||
name,
|
|
||||||
version,
|
|
||||||
root,
|
|
||||||
} => {
|
|
||||||
eprintln!(
|
|
||||||
"{} {} {} ({})",
|
|
||||||
" Generating documentation"
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple()),
|
|
||||||
name.if_supports_color(Stderr, |s| s.bold()),
|
|
||||||
version,
|
|
||||||
root.to_str()
|
|
||||||
.unwrap_or("")
|
|
||||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
telemetry::Event::WaitingForBuildDirLock => {
|
|
||||||
eprintln!(
|
|
||||||
"{}",
|
|
||||||
"Waiting for build directory lock ..."
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
telemetry::Event::DumpingUPLC { path } => {
|
|
||||||
eprintln!(
|
|
||||||
"{} {} ({})",
|
|
||||||
" Exporting"
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple()),
|
|
||||||
"UPLC".if_supports_color(Stderr, |s| s.bold()),
|
|
||||||
path.display()
|
|
||||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
telemetry::Event::GeneratingBlueprint { path } => {
|
|
||||||
eprintln!(
|
|
||||||
"{} {} ({})",
|
|
||||||
" Generating"
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple()),
|
|
||||||
"project's blueprint".if_supports_color(Stderr, |s| s.bold()),
|
|
||||||
path.display()
|
|
||||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
telemetry::Event::GeneratingDocFiles { output_path } => {
|
|
||||||
eprintln!(
|
|
||||||
"{} in {}",
|
|
||||||
" Generating documentation files"
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple()),
|
|
||||||
output_path
|
|
||||||
.to_str()
|
|
||||||
.unwrap_or("")
|
|
||||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
telemetry::Event::GeneratingUPLCFor { name, path } => {
|
|
||||||
eprintln!(
|
|
||||||
"{} {}.{{{}}}",
|
|
||||||
" Generating UPLC for"
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple()),
|
|
||||||
path.to_str()
|
|
||||||
.unwrap_or("")
|
|
||||||
.if_supports_color(Stderr, |s| s.blue()),
|
|
||||||
name.if_supports_color(Stderr, |s| s.bright_blue()),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
telemetry::Event::EvaluatingFunction { results } => {
|
|
||||||
eprintln!(
|
|
||||||
"{}\n",
|
|
||||||
" Evaluating function ..."
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple())
|
|
||||||
);
|
|
||||||
|
|
||||||
let (max_mem, max_cpu) = find_max_execution_units(&results);
|
|
||||||
|
|
||||||
for eval_info in &results {
|
|
||||||
println!(" {}", fmt_eval(eval_info, max_mem, max_cpu, Stderr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
telemetry::Event::RunningTests => {
|
|
||||||
eprintln!(
|
|
||||||
"{} {}\n",
|
|
||||||
" Testing"
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple()),
|
|
||||||
"...".if_supports_color(Stderr, |s| s.bold())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
telemetry::Event::FinishedTests { tests } => {
|
|
||||||
let (max_mem, max_cpu) = find_max_execution_units(&tests);
|
|
||||||
|
|
||||||
for (module, infos) in &group_by_module(&tests) {
|
|
||||||
let title = module
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.blue())
|
|
||||||
.to_string();
|
|
||||||
|
|
||||||
let tests = infos
|
|
||||||
.iter()
|
|
||||||
.map(|eval_info| fmt_test(eval_info, max_mem, max_cpu, true))
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.join("\n");
|
|
||||||
|
|
||||||
let summary = fmt_test_summary(infos, true);
|
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"{}\n",
|
|
||||||
pretty::indent(
|
|
||||||
&pretty::open_box(&title, &tests, &summary, |border| border
|
|
||||||
.if_supports_color(Stderr, |s| s.bright_black())
|
|
||||||
.to_string()),
|
|
||||||
4
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
telemetry::Event::ResolvingPackages { name } => {
|
|
||||||
eprintln!(
|
|
||||||
"{} {}",
|
|
||||||
" Resolving"
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple()),
|
|
||||||
name.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
telemetry::Event::PackageResolveFallback { name } => {
|
|
||||||
eprintln!(
|
|
||||||
"{} {}\n ↳ You're seeing this message because the package version is unpinned and the network is not accessible.",
|
|
||||||
" Using"
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.yellow()),
|
|
||||||
format!("uncertain local version for {name}")
|
|
||||||
.if_supports_color(Stderr, |s| s.yellow())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
telemetry::Event::PackagesDownloaded {
|
|
||||||
start,
|
|
||||||
count,
|
|
||||||
source,
|
|
||||||
} => {
|
|
||||||
let elapsed = format!("{:.2}s", start.elapsed().as_millis() as f32 / 1000.);
|
|
||||||
|
|
||||||
let msg = match count {
|
|
||||||
1 => format!("1 package in {elapsed}"),
|
|
||||||
_ => format!("{count} packages in {elapsed}"),
|
|
||||||
};
|
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"{} {} from {source}",
|
|
||||||
match source {
|
|
||||||
DownloadSource::Network => " Downloaded",
|
|
||||||
DownloadSource::Cache => " Fetched",
|
|
||||||
}
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple()),
|
|
||||||
msg.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
telemetry::Event::ResolvingVersions => {
|
|
||||||
eprintln!(
|
|
||||||
"{}",
|
|
||||||
" Resolving dependencies"
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.purple()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fmt_test(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize, styled: bool) -> String {
|
|
||||||
let EvalInfo {
|
|
||||||
success,
|
|
||||||
script,
|
|
||||||
spent_budget,
|
|
||||||
logs,
|
|
||||||
..
|
|
||||||
} = eval_info;
|
|
||||||
|
|
||||||
let ExBudget { mem, cpu } = spent_budget;
|
|
||||||
let mem_pad = pretty::pad_left(mem.to_string(), max_mem, " ");
|
|
||||||
let cpu_pad = pretty::pad_left(cpu.to_string(), max_cpu, " ");
|
|
||||||
|
|
||||||
let test = format!(
|
|
||||||
"{status} [mem: {mem_unit}, cpu: {cpu_unit}] {module}",
|
|
||||||
status = if *success {
|
|
||||||
pretty::style_if(styled, "PASS".to_string(), |s| {
|
|
||||||
s.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.green())
|
|
||||||
.to_string()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
pretty::style_if(styled, "FAIL".to_string(), |s| {
|
|
||||||
s.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.if_supports_color(Stderr, |s| s.red())
|
|
||||||
.to_string()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
mem_unit = pretty::style_if(styled, mem_pad, |s| s
|
|
||||||
.if_supports_color(Stderr, |s| s.cyan())
|
|
||||||
.to_string()),
|
|
||||||
cpu_unit = pretty::style_if(styled, cpu_pad, |s| s
|
|
||||||
.if_supports_color(Stderr, |s| s.cyan())
|
|
||||||
.to_string()),
|
|
||||||
module = pretty::style_if(styled, script.name.clone(), |s| s
|
|
||||||
.if_supports_color(Stderr, |s| s.bright_blue())
|
|
||||||
.to_string()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let logs = if logs.is_empty() {
|
|
||||||
String::new()
|
|
||||||
} else {
|
|
||||||
logs.iter()
|
|
||||||
.map(|line| {
|
|
||||||
format!(
|
|
||||||
"{arrow} {styled_line}",
|
|
||||||
arrow = "↳".if_supports_color(Stderr, |s| s.bright_yellow()),
|
|
||||||
styled_line = line.if_supports_color(Stderr, |s| s.bright_black())
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
.join("\n")
|
|
||||||
};
|
|
||||||
|
|
||||||
if logs.is_empty() {
|
|
||||||
test
|
|
||||||
} else {
|
|
||||||
[test, logs].join("\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fmt_test_summary(tests: &Vec<&EvalInfo>, styled: bool) -> String {
|
|
||||||
let (n_passed, n_failed) = tests
|
|
||||||
.iter()
|
|
||||||
.fold((0, 0), |(n_passed, n_failed), test_info| {
|
|
||||||
if test_info.success {
|
|
||||||
(n_passed + 1, n_failed)
|
|
||||||
} else {
|
|
||||||
(n_passed, n_failed + 1)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
format!(
|
|
||||||
"{} | {} | {}",
|
|
||||||
pretty::style_if(styled, format!("{} tests", tests.len()), |s| s
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.to_string()),
|
|
||||||
pretty::style_if(styled, format!("{n_passed} passed"), |s| s
|
|
||||||
.if_supports_color(Stderr, |s| s.bright_green())
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.to_string()),
|
|
||||||
pretty::style_if(styled, format!("{n_failed} failed"), |s| s
|
|
||||||
.if_supports_color(Stderr, |s| s.bright_red())
|
|
||||||
.if_supports_color(Stderr, |s| s.bold())
|
|
||||||
.to_string()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fmt_eval(eval_info: &EvalInfo, max_mem: usize, max_cpu: usize, stream: Stream) -> String {
|
|
||||||
let EvalInfo {
|
|
||||||
output,
|
|
||||||
script,
|
|
||||||
spent_budget,
|
|
||||||
..
|
|
||||||
} = eval_info;
|
|
||||||
|
|
||||||
let ExBudget { mem, cpu } = spent_budget;
|
|
||||||
|
|
||||||
format!(
|
|
||||||
" {}::{} [mem: {}, cpu: {}]\n │\n ╰─▶ {}",
|
|
||||||
script.module.if_supports_color(stream, |s| s.blue()),
|
|
||||||
script.name.if_supports_color(stream, |s| s.bright_blue()),
|
|
||||||
pretty::pad_left(mem.to_string(), max_mem, " "),
|
|
||||||
pretty::pad_left(cpu.to_string(), max_cpu, " "),
|
|
||||||
output
|
|
||||||
.as_ref()
|
|
||||||
.map(|x| format!("{x}"))
|
|
||||||
.unwrap_or_else(|| "Error.".to_string()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn group_by_module(infos: &Vec<EvalInfo>) -> BTreeMap<String, Vec<&EvalInfo>> {
|
|
||||||
let mut modules = BTreeMap::new();
|
|
||||||
for eval_info in infos {
|
|
||||||
let xs: &mut Vec<&EvalInfo> = modules.entry(eval_info.script.module.clone()).or_default();
|
|
||||||
xs.push(eval_info);
|
|
||||||
}
|
|
||||||
modules
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_max_execution_units(xs: &[EvalInfo]) -> (usize, usize) {
|
|
||||||
let (max_mem, max_cpu) = xs.iter().fold(
|
|
||||||
(0, 0),
|
|
||||||
|(max_mem, max_cpu), EvalInfo { spent_budget, .. }| {
|
|
||||||
if spent_budget.mem >= max_mem && spent_budget.cpu >= max_cpu {
|
|
||||||
(spent_budget.mem, spent_budget.cpu)
|
|
||||||
} else if spent_budget.mem > max_mem {
|
|
||||||
(spent_budget.mem, max_cpu)
|
|
||||||
} else if spent_budget.cpu > max_cpu {
|
|
||||||
(max_mem, spent_budget.cpu)
|
|
||||||
} else {
|
|
||||||
(max_mem, max_cpu)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
(max_mem.to_string().len(), max_cpu.to_string().len())
|
|
||||||
}
|
|
|
@ -1,17 +1,19 @@
|
||||||
use aiken::cmd::{
|
use aiken_project::{config, pretty};
|
||||||
|
use cmd::{
|
||||||
blueprint::{self, address},
|
blueprint::{self, address},
|
||||||
build, check, completion, docs, fmt, lsp, new,
|
build, check, completion, docs, fmt, lsp, new,
|
||||||
packages::{self, add},
|
packages::{self, add},
|
||||||
tx, uplc, Cmd,
|
tx, uplc, Cmd,
|
||||||
};
|
};
|
||||||
use aiken_project::{config, pretty};
|
|
||||||
|
|
||||||
use owo_colors::OwoColorize;
|
use owo_colors::OwoColorize;
|
||||||
|
use std::process;
|
||||||
|
|
||||||
fn main() -> miette::Result<()> {
|
mod cmd;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
panic_handler();
|
panic_handler();
|
||||||
|
|
||||||
match Cmd::default() {
|
let result = match Cmd::default() {
|
||||||
Cmd::New(args) => new::exec(args),
|
Cmd::New(args) => new::exec(args),
|
||||||
Cmd::Fmt(args) => fmt::exec(args),
|
Cmd::Fmt(args) => fmt::exec(args),
|
||||||
Cmd::Build(args) => build::exec(args),
|
Cmd::Build(args) => build::exec(args),
|
||||||
|
@ -25,6 +27,11 @@ fn main() -> miette::Result<()> {
|
||||||
Cmd::Tx(sub_cmd) => tx::exec(sub_cmd),
|
Cmd::Tx(sub_cmd) => tx::exec(sub_cmd),
|
||||||
Cmd::Uplc(sub_cmd) => uplc::exec(sub_cmd),
|
Cmd::Uplc(sub_cmd) => uplc::exec(sub_cmd),
|
||||||
Cmd::Completion(sub_cmd) => completion::exec(sub_cmd),
|
Cmd::Completion(sub_cmd) => completion::exec(sub_cmd),
|
||||||
|
};
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(()) => (),
|
||||||
|
Err(_) => process::exit(1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,9 +240,12 @@ impl Machine {
|
||||||
env,
|
env,
|
||||||
t.clone(),
|
t.clone(),
|
||||||
)),
|
)),
|
||||||
None => todo!(),
|
None => Err(Error::MissingCaseBranch(
|
||||||
|
branches,
|
||||||
|
Value::Constr { tag, fields },
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
_ => todo!("return a proper evaluation error"),
|
v => Err(Error::NonConstrScrutinized(v)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,12 +186,12 @@ impl Default for MachineCosts {
|
||||||
},
|
},
|
||||||
// Placeholder values
|
// Placeholder values
|
||||||
constr: ExBudget {
|
constr: ExBudget {
|
||||||
mem: 30000000000,
|
mem: 100,
|
||||||
cpu: 30000000000,
|
cpu: 23000,
|
||||||
},
|
},
|
||||||
case: ExBudget {
|
case: ExBudget {
|
||||||
mem: 30000000000,
|
mem: 100,
|
||||||
cpu: 30000000000,
|
cpu: 23000,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,10 @@ pub enum Error {
|
||||||
NonPolymorphicInstantiation(Value),
|
NonPolymorphicInstantiation(Value),
|
||||||
#[error("Attempted to apply a non-function:\n\n{0:#?} to argument:\n\n{1:#?}")]
|
#[error("Attempted to apply a non-function:\n\n{0:#?} to argument:\n\n{1:#?}")]
|
||||||
NonFunctionalApplication(Value, Value),
|
NonFunctionalApplication(Value, Value),
|
||||||
|
#[error("Attempted to case a non-const:\n\n{0:#?}")]
|
||||||
|
NonConstrScrutinized(Value),
|
||||||
|
#[error("Cases: {0:#?}\n\n are missing branch for constr:\n\n{1:#?}")]
|
||||||
|
MissingCaseBranch(Vec<Term<NamedDeBruijn>>, Value),
|
||||||
#[error("Type mismatch expected '{0}' got '{1}'")]
|
#[error("Type mismatch expected '{0}' got '{1}'")]
|
||||||
TypeMismatch(Type, Type),
|
TypeMismatch(Type, Type),
|
||||||
#[error("Type mismatch expected '(list a)' got '{0}'")]
|
#[error("Type mismatch expected '(list a)' got '{0}'")]
|
||||||
|
@ -36,6 +40,7 @@ pub enum Error {
|
||||||
NotAConstant(Value),
|
NotAConstant(Value),
|
||||||
#[error("The evaluation never reached a final state")]
|
#[error("The evaluation never reached a final state")]
|
||||||
MachineNeverReachedDone,
|
MachineNeverReachedDone,
|
||||||
|
|
||||||
#[error("Decoding utf8")]
|
#[error("Decoding utf8")]
|
||||||
Utf8(#[from] FromUtf8Error),
|
Utf8(#[from] FromUtf8Error),
|
||||||
#[error("Out of Bounds\n\nindex: {}\nbytestring: {}\npossible: 0 - {}", .0, hex::encode(.1), .1.len() - 1)]
|
#[error("Out of Bounds\n\nindex: {}\nbytestring: {}\npossible: 0 - {}", .0, hex::encode(.1), .1.len() - 1)]
|
||||||
|
|
|
@ -89,8 +89,6 @@ impl BuiltinRuntime {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, arg: Value) -> Result<(), Error> {
|
pub fn push(&mut self, arg: Value) -> Result<(), Error> {
|
||||||
self.fun.check_type(&arg, &self.args)?;
|
|
||||||
|
|
||||||
self.args.push(arg);
|
self.args.push(arg);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -264,171 +262,6 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_type(&self, arg: &Value, args: &[Value]) -> Result<(), Error> {
|
|
||||||
match self {
|
|
||||||
DefaultFunction::AddInteger => arg.expect_type(Type::Integer),
|
|
||||||
DefaultFunction::SubtractInteger => arg.expect_type(Type::Integer),
|
|
||||||
DefaultFunction::MultiplyInteger => arg.expect_type(Type::Integer),
|
|
||||||
DefaultFunction::DivideInteger => arg.expect_type(Type::Integer),
|
|
||||||
DefaultFunction::QuotientInteger => arg.expect_type(Type::Integer),
|
|
||||||
DefaultFunction::RemainderInteger => arg.expect_type(Type::Integer),
|
|
||||||
DefaultFunction::ModInteger => arg.expect_type(Type::Integer),
|
|
||||||
DefaultFunction::EqualsInteger => arg.expect_type(Type::Integer),
|
|
||||||
DefaultFunction::LessThanInteger => arg.expect_type(Type::Integer),
|
|
||||||
DefaultFunction::LessThanEqualsInteger => arg.expect_type(Type::Integer),
|
|
||||||
DefaultFunction::AppendByteString => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::ConsByteString => {
|
|
||||||
if args.is_empty() {
|
|
||||||
arg.expect_type(Type::Integer)
|
|
||||||
} else {
|
|
||||||
arg.expect_type(Type::ByteString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::SliceByteString => {
|
|
||||||
if args.len() < 2 {
|
|
||||||
arg.expect_type(Type::Integer)
|
|
||||||
} else {
|
|
||||||
arg.expect_type(Type::ByteString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::LengthOfByteString => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::IndexByteString => {
|
|
||||||
if args.is_empty() {
|
|
||||||
arg.expect_type(Type::ByteString)
|
|
||||||
} else {
|
|
||||||
arg.expect_type(Type::Integer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::EqualsByteString => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::LessThanByteString => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::LessThanEqualsByteString => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::Sha2_256 => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::Sha3_256 => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::Blake2b_224 => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::Blake2b_256 => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::Keccak_256 => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::VerifyEd25519Signature => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::VerifyEcdsaSecp256k1Signature => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::VerifySchnorrSecp256k1Signature => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::AppendString => arg.expect_type(Type::String),
|
|
||||||
DefaultFunction::EqualsString => arg.expect_type(Type::String),
|
|
||||||
DefaultFunction::EncodeUtf8 => arg.expect_type(Type::String),
|
|
||||||
DefaultFunction::DecodeUtf8 => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::IfThenElse => {
|
|
||||||
if args.is_empty() {
|
|
||||||
arg.expect_type(Type::Bool)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::ChooseUnit => {
|
|
||||||
if args.is_empty() {
|
|
||||||
arg.expect_type(Type::Unit)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::Trace => {
|
|
||||||
if args.is_empty() {
|
|
||||||
arg.expect_type(Type::String)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::FstPair => arg.expect_pair(),
|
|
||||||
DefaultFunction::SndPair => arg.expect_pair(),
|
|
||||||
DefaultFunction::ChooseList => {
|
|
||||||
if args.is_empty() {
|
|
||||||
arg.expect_list()
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::MkCons => {
|
|
||||||
if args.is_empty() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
let first = &args[0];
|
|
||||||
|
|
||||||
arg.expect_type(Type::List(Rc::new(first.try_into()?)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::HeadList => arg.expect_list(),
|
|
||||||
DefaultFunction::TailList => arg.expect_list(),
|
|
||||||
DefaultFunction::NullList => arg.expect_list(),
|
|
||||||
DefaultFunction::ChooseData => {
|
|
||||||
if args.is_empty() {
|
|
||||||
arg.expect_type(Type::Data)
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::ConstrData => {
|
|
||||||
if args.is_empty() {
|
|
||||||
arg.expect_type(Type::Integer)
|
|
||||||
} else {
|
|
||||||
arg.expect_type(Type::List(Rc::new(Type::Data)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::MapData => arg.expect_type(Type::List(Rc::new(Type::Pair(
|
|
||||||
Rc::new(Type::Data),
|
|
||||||
Rc::new(Type::Data),
|
|
||||||
)))),
|
|
||||||
DefaultFunction::ListData => arg.expect_type(Type::List(Rc::new(Type::Data))),
|
|
||||||
DefaultFunction::IData => arg.expect_type(Type::Integer),
|
|
||||||
DefaultFunction::BData => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::UnConstrData => arg.expect_type(Type::Data),
|
|
||||||
DefaultFunction::UnMapData => arg.expect_type(Type::Data),
|
|
||||||
DefaultFunction::UnListData => arg.expect_type(Type::Data),
|
|
||||||
DefaultFunction::UnIData => arg.expect_type(Type::Data),
|
|
||||||
DefaultFunction::UnBData => arg.expect_type(Type::Data),
|
|
||||||
DefaultFunction::EqualsData => arg.expect_type(Type::Data),
|
|
||||||
DefaultFunction::SerialiseData => arg.expect_type(Type::Data),
|
|
||||||
DefaultFunction::MkPairData => arg.expect_type(Type::Data),
|
|
||||||
DefaultFunction::MkNilData => arg.expect_type(Type::Unit),
|
|
||||||
DefaultFunction::MkNilPairData => arg.expect_type(Type::Unit),
|
|
||||||
|
|
||||||
DefaultFunction::Bls12_381_G1_Add => arg.expect_type(Type::Bls12_381G1Element),
|
|
||||||
DefaultFunction::Bls12_381_G1_Neg => arg.expect_type(Type::Bls12_381G1Element),
|
|
||||||
DefaultFunction::Bls12_381_G1_ScalarMul => {
|
|
||||||
if args.is_empty() {
|
|
||||||
arg.expect_type(Type::Integer)
|
|
||||||
} else {
|
|
||||||
arg.expect_type(Type::Bls12_381G1Element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::Bls12_381_G1_Equal => arg.expect_type(Type::Bls12_381G1Element),
|
|
||||||
DefaultFunction::Bls12_381_G1_Compress => arg.expect_type(Type::Bls12_381G1Element),
|
|
||||||
DefaultFunction::Bls12_381_G1_Uncompress => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::Bls12_381_G1_HashToGroup => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::Bls12_381_G2_Add => arg.expect_type(Type::Bls12_381G2Element),
|
|
||||||
DefaultFunction::Bls12_381_G2_Neg => arg.expect_type(Type::Bls12_381G2Element),
|
|
||||||
DefaultFunction::Bls12_381_G2_ScalarMul => {
|
|
||||||
if args.is_empty() {
|
|
||||||
arg.expect_type(Type::Integer)
|
|
||||||
} else {
|
|
||||||
arg.expect_type(Type::Bls12_381G2Element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::Bls12_381_G2_Equal => arg.expect_type(Type::Bls12_381G2Element),
|
|
||||||
DefaultFunction::Bls12_381_G2_Compress => arg.expect_type(Type::Bls12_381G2Element),
|
|
||||||
DefaultFunction::Bls12_381_G2_Uncompress => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::Bls12_381_G2_HashToGroup => arg.expect_type(Type::ByteString),
|
|
||||||
DefaultFunction::Bls12_381_MillerLoop => {
|
|
||||||
if args.is_empty() {
|
|
||||||
arg.expect_type(Type::Bls12_381G1Element)
|
|
||||||
} else {
|
|
||||||
arg.expect_type(Type::Bls12_381G2Element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DefaultFunction::Bls12_381_MulMlResult => arg.expect_type(Type::Bls12_381MlResult),
|
|
||||||
DefaultFunction::Bls12_381_FinalVerify => arg.expect_type(Type::Bls12_381MlResult),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This should be safe because we've already checked
|
|
||||||
// the types of the args as they were pushed. Although
|
|
||||||
// the unreachables look ugly, it's the reality of the situation.
|
|
||||||
pub fn call(
|
pub fn call(
|
||||||
&self,
|
&self,
|
||||||
semantics: BuiltinSemantics,
|
semantics: BuiltinSemantics,
|
||||||
|
@ -437,8 +270,8 @@ impl DefaultFunction {
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
match self {
|
match self {
|
||||||
DefaultFunction::AddInteger => {
|
DefaultFunction::AddInteger => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
|
|
||||||
let result = arg1 + arg2;
|
let result = arg1 + arg2;
|
||||||
|
|
||||||
|
@ -447,8 +280,8 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::SubtractInteger => {
|
DefaultFunction::SubtractInteger => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
|
|
||||||
let result = arg1 - arg2;
|
let result = arg1 - arg2;
|
||||||
|
|
||||||
|
@ -457,8 +290,8 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::MultiplyInteger => {
|
DefaultFunction::MultiplyInteger => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
|
|
||||||
let result = arg1 * arg2;
|
let result = arg1 * arg2;
|
||||||
|
|
||||||
|
@ -467,8 +300,8 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::DivideInteger => {
|
DefaultFunction::DivideInteger => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
|
|
||||||
if *arg2 != 0.into() {
|
if *arg2 != 0.into() {
|
||||||
let (result, _) = arg1.div_mod_floor(arg2);
|
let (result, _) = arg1.div_mod_floor(arg2);
|
||||||
|
@ -481,8 +314,8 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultFunction::QuotientInteger => {
|
DefaultFunction::QuotientInteger => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
|
|
||||||
if *arg2 != 0.into() {
|
if *arg2 != 0.into() {
|
||||||
let (result, _) = arg1.div_rem(arg2);
|
let (result, _) = arg1.div_rem(arg2);
|
||||||
|
@ -495,8 +328,8 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultFunction::RemainderInteger => {
|
DefaultFunction::RemainderInteger => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
|
|
||||||
if *arg2 != 0.into() {
|
if *arg2 != 0.into() {
|
||||||
let (_, result) = arg1.div_rem(arg2);
|
let (_, result) = arg1.div_rem(arg2);
|
||||||
|
@ -509,8 +342,8 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultFunction::ModInteger => {
|
DefaultFunction::ModInteger => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
|
|
||||||
if *arg2 != 0.into() {
|
if *arg2 != 0.into() {
|
||||||
let (_, result) = arg1.div_mod_floor(arg2);
|
let (_, result) = arg1.div_mod_floor(arg2);
|
||||||
|
@ -523,32 +356,32 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultFunction::EqualsInteger => {
|
DefaultFunction::EqualsInteger => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
|
|
||||||
let value = Value::bool(arg1 == arg2);
|
let value = Value::bool(arg1 == arg2);
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::LessThanInteger => {
|
DefaultFunction::LessThanInteger => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
|
|
||||||
let value = Value::bool(arg1 < arg2);
|
let value = Value::bool(arg1 < arg2);
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::LessThanEqualsInteger => {
|
DefaultFunction::LessThanEqualsInteger => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
|
|
||||||
let value = Value::bool(arg1 <= arg2);
|
let value = Value::bool(arg1 <= arg2);
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::AppendByteString => {
|
DefaultFunction::AppendByteString => {
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
let arg2 = args[1].unwrap_byte_string();
|
let arg2 = args[1].unwrap_byte_string()?;
|
||||||
|
|
||||||
let result = arg1.iter().copied().chain(arg2.iter().copied()).collect();
|
let result = arg1.iter().copied().chain(arg2.iter().copied()).collect();
|
||||||
|
|
||||||
|
@ -557,8 +390,8 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::ConsByteString => {
|
DefaultFunction::ConsByteString => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_byte_string();
|
let arg2 = args[1].unwrap_byte_string()?;
|
||||||
|
|
||||||
let byte: u8 = match semantics {
|
let byte: u8 = match semantics {
|
||||||
BuiltinSemantics::V1 => {
|
BuiltinSemantics::V1 => {
|
||||||
|
@ -584,9 +417,9 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::SliceByteString => {
|
DefaultFunction::SliceByteString => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
let arg3 = args[2].unwrap_byte_string();
|
let arg3 = args[2].unwrap_byte_string()?;
|
||||||
|
|
||||||
let skip: usize = if arg1.lt(&0.into()) {
|
let skip: usize = if arg1.lt(&0.into()) {
|
||||||
0
|
0
|
||||||
|
@ -606,15 +439,15 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::LengthOfByteString => {
|
DefaultFunction::LengthOfByteString => {
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
|
|
||||||
let value = Value::integer(arg1.len().into());
|
let value = Value::integer(arg1.len().into());
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::IndexByteString => {
|
DefaultFunction::IndexByteString => {
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
let arg2 = args[1].unwrap_integer();
|
let arg2 = args[1].unwrap_integer()?;
|
||||||
|
|
||||||
let index: i128 = arg2.try_into().unwrap();
|
let index: i128 = arg2.try_into().unwrap();
|
||||||
|
|
||||||
|
@ -629,24 +462,24 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultFunction::EqualsByteString => {
|
DefaultFunction::EqualsByteString => {
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
let arg2 = args[1].unwrap_byte_string();
|
let arg2 = args[1].unwrap_byte_string()?;
|
||||||
|
|
||||||
let value = Value::bool(arg1 == arg2);
|
let value = Value::bool(arg1 == arg2);
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::LessThanByteString => {
|
DefaultFunction::LessThanByteString => {
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
let arg2 = args[1].unwrap_byte_string();
|
let arg2 = args[1].unwrap_byte_string()?;
|
||||||
|
|
||||||
let value = Value::bool(arg1 < arg2);
|
let value = Value::bool(arg1 < arg2);
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::LessThanEqualsByteString => {
|
DefaultFunction::LessThanEqualsByteString => {
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
let arg2 = args[1].unwrap_byte_string();
|
let arg2 = args[1].unwrap_byte_string()?;
|
||||||
|
|
||||||
let value = Value::bool(arg1 <= arg2);
|
let value = Value::bool(arg1 <= arg2);
|
||||||
|
|
||||||
|
@ -655,7 +488,7 @@ impl DefaultFunction {
|
||||||
DefaultFunction::Sha2_256 => {
|
DefaultFunction::Sha2_256 => {
|
||||||
use cryptoxide::{digest::Digest, sha2::Sha256};
|
use cryptoxide::{digest::Digest, sha2::Sha256};
|
||||||
|
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
|
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
|
|
||||||
|
@ -672,7 +505,7 @@ impl DefaultFunction {
|
||||||
DefaultFunction::Sha3_256 => {
|
DefaultFunction::Sha3_256 => {
|
||||||
use cryptoxide::{digest::Digest, sha3::Sha3_256};
|
use cryptoxide::{digest::Digest, sha3::Sha3_256};
|
||||||
|
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
|
|
||||||
let mut hasher = Sha3_256::new();
|
let mut hasher = Sha3_256::new();
|
||||||
|
|
||||||
|
@ -690,7 +523,7 @@ impl DefaultFunction {
|
||||||
DefaultFunction::Blake2b_224 => {
|
DefaultFunction::Blake2b_224 => {
|
||||||
use cryptoxide::{blake2b::Blake2b, digest::Digest};
|
use cryptoxide::{blake2b::Blake2b, digest::Digest};
|
||||||
|
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
|
|
||||||
let mut digest = [0u8; 28];
|
let mut digest = [0u8; 28];
|
||||||
let mut context = Blake2b::new(28);
|
let mut context = Blake2b::new(28);
|
||||||
|
@ -705,7 +538,7 @@ impl DefaultFunction {
|
||||||
DefaultFunction::Blake2b_256 => {
|
DefaultFunction::Blake2b_256 => {
|
||||||
use cryptoxide::{blake2b::Blake2b, digest::Digest};
|
use cryptoxide::{blake2b::Blake2b, digest::Digest};
|
||||||
|
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
|
|
||||||
let mut digest = [0u8; 32];
|
let mut digest = [0u8; 32];
|
||||||
let mut context = Blake2b::new(32);
|
let mut context = Blake2b::new(32);
|
||||||
|
@ -720,7 +553,7 @@ impl DefaultFunction {
|
||||||
DefaultFunction::Keccak_256 => {
|
DefaultFunction::Keccak_256 => {
|
||||||
use cryptoxide::{digest::Digest, sha3::Keccak256};
|
use cryptoxide::{digest::Digest, sha3::Keccak256};
|
||||||
|
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
|
|
||||||
let mut hasher = Keccak256::new();
|
let mut hasher = Keccak256::new();
|
||||||
|
|
||||||
|
@ -737,9 +570,9 @@ impl DefaultFunction {
|
||||||
DefaultFunction::VerifyEd25519Signature => {
|
DefaultFunction::VerifyEd25519Signature => {
|
||||||
use cryptoxide::ed25519;
|
use cryptoxide::ed25519;
|
||||||
|
|
||||||
let public_key = args[0].unwrap_byte_string();
|
let public_key = args[0].unwrap_byte_string()?;
|
||||||
let message = args[1].unwrap_byte_string();
|
let message = args[1].unwrap_byte_string()?;
|
||||||
let signature = args[2].unwrap_byte_string();
|
let signature = args[2].unwrap_byte_string()?;
|
||||||
|
|
||||||
let public_key: [u8; 32] = public_key
|
let public_key: [u8; 32] = public_key
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -758,37 +591,37 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::VerifyEcdsaSecp256k1Signature => {
|
DefaultFunction::VerifyEcdsaSecp256k1Signature => {
|
||||||
let public_key = args[0].unwrap_byte_string();
|
let public_key = args[0].unwrap_byte_string()?;
|
||||||
let message = args[1].unwrap_byte_string();
|
let message = args[1].unwrap_byte_string()?;
|
||||||
let signature = args[2].unwrap_byte_string();
|
let signature = args[2].unwrap_byte_string()?;
|
||||||
|
|
||||||
verify_ecdsa(public_key, message, signature)
|
verify_ecdsa(public_key, message, signature)
|
||||||
}
|
}
|
||||||
DefaultFunction::VerifySchnorrSecp256k1Signature => {
|
DefaultFunction::VerifySchnorrSecp256k1Signature => {
|
||||||
let public_key = args[0].unwrap_byte_string();
|
let public_key = args[0].unwrap_byte_string()?;
|
||||||
let message = args[1].unwrap_byte_string();
|
let message = args[1].unwrap_byte_string()?;
|
||||||
let signature = args[2].unwrap_byte_string();
|
let signature = args[2].unwrap_byte_string()?;
|
||||||
|
|
||||||
verify_schnorr(public_key, message, signature)
|
verify_schnorr(public_key, message, signature)
|
||||||
}
|
}
|
||||||
DefaultFunction::AppendString => {
|
DefaultFunction::AppendString => {
|
||||||
let arg1 = args[0].unwrap_string();
|
let arg1 = args[0].unwrap_string()?;
|
||||||
let arg2 = args[1].unwrap_string();
|
let arg2 = args[1].unwrap_string()?;
|
||||||
|
|
||||||
let value = Value::string(format!("{arg1}{arg2}"));
|
let value = Value::string(format!("{arg1}{arg2}"));
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::EqualsString => {
|
DefaultFunction::EqualsString => {
|
||||||
let arg1 = args[0].unwrap_string();
|
let arg1 = args[0].unwrap_string()?;
|
||||||
let arg2 = args[1].unwrap_string();
|
let arg2 = args[1].unwrap_string()?;
|
||||||
|
|
||||||
let value = Value::bool(arg1 == arg2);
|
let value = Value::bool(arg1 == arg2);
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::EncodeUtf8 => {
|
DefaultFunction::EncodeUtf8 => {
|
||||||
let arg1 = args[0].unwrap_string();
|
let arg1 = args[0].unwrap_string()?;
|
||||||
|
|
||||||
let bytes = arg1.as_bytes().to_vec();
|
let bytes = arg1.as_bytes().to_vec();
|
||||||
|
|
||||||
|
@ -797,7 +630,7 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::DecodeUtf8 => {
|
DefaultFunction::DecodeUtf8 => {
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
|
|
||||||
let string = String::from_utf8(arg1.clone())?;
|
let string = String::from_utf8(arg1.clone())?;
|
||||||
|
|
||||||
|
@ -806,7 +639,7 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::IfThenElse => {
|
DefaultFunction::IfThenElse => {
|
||||||
let condition = args[0].unwrap_bool();
|
let condition = args[0].unwrap_bool()?;
|
||||||
|
|
||||||
if *condition {
|
if *condition {
|
||||||
Ok(args[1].clone())
|
Ok(args[1].clone())
|
||||||
|
@ -815,35 +648,33 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultFunction::ChooseUnit => {
|
DefaultFunction::ChooseUnit => {
|
||||||
// We don't need to check it here because this is already done in
|
args[0].unwrap_unit()?;
|
||||||
// expect_type
|
|
||||||
// let Value::Con(Constant::Unit) = args[0] else {unreachable!()};
|
|
||||||
|
|
||||||
Ok(args[1].clone())
|
Ok(args[1].clone())
|
||||||
}
|
}
|
||||||
DefaultFunction::Trace => {
|
DefaultFunction::Trace => {
|
||||||
let arg1 = args[0].unwrap_string();
|
let arg1 = args[0].unwrap_string()?;
|
||||||
|
|
||||||
logs.push(arg1.clone());
|
logs.push(arg1.clone());
|
||||||
|
|
||||||
Ok(args[1].clone())
|
Ok(args[1].clone())
|
||||||
}
|
}
|
||||||
DefaultFunction::FstPair => {
|
DefaultFunction::FstPair => {
|
||||||
let (_, _, first, _) = args[0].unwrap_pair();
|
let (_, _, first, _) = args[0].unwrap_pair()?;
|
||||||
|
|
||||||
let value = Value::Con(first.clone());
|
let value = Value::Con(first.clone());
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::SndPair => {
|
DefaultFunction::SndPair => {
|
||||||
let (_, _, _, second) = args[0].unwrap_pair();
|
let (_, _, _, second) = args[0].unwrap_pair()?;
|
||||||
|
|
||||||
let value = Value::Con(second.clone());
|
let value = Value::Con(second.clone());
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::ChooseList => {
|
DefaultFunction::ChooseList => {
|
||||||
let (_, list) = args[0].unwrap_list();
|
let (_, list) = args[0].unwrap_list()?;
|
||||||
|
|
||||||
if list.is_empty() {
|
if list.is_empty() {
|
||||||
Ok(args[1].clone())
|
Ok(args[1].clone())
|
||||||
|
@ -852,8 +683,12 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultFunction::MkCons => {
|
DefaultFunction::MkCons => {
|
||||||
let item = args[0].unwrap_constant();
|
let item = args[0].unwrap_constant()?;
|
||||||
let (r#type, list) = args[1].unwrap_list();
|
let (r#type, list) = args[1].unwrap_list()?;
|
||||||
|
|
||||||
|
if *r#type != Type::from(item) {
|
||||||
|
return Err(Error::TypeMismatch(Type::from(item), r#type.clone()));
|
||||||
|
}
|
||||||
|
|
||||||
let mut ret = vec![item.clone()];
|
let mut ret = vec![item.clone()];
|
||||||
|
|
||||||
|
@ -864,15 +699,10 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::HeadList => {
|
DefaultFunction::HeadList => {
|
||||||
let c @ Value::Con(inner) = &args[0] else {
|
let (_, list) = args[0].unwrap_list()?;
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
let Constant::ProtoList(_, list) = inner.as_ref() else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
if list.is_empty() {
|
if list.is_empty() {
|
||||||
Err(Error::EmptyList(c.clone()))
|
Err(Error::EmptyList(args[0].clone()))
|
||||||
} else {
|
} else {
|
||||||
let value = Value::Con(list[0].clone().into());
|
let value = Value::Con(list[0].clone().into());
|
||||||
|
|
||||||
|
@ -880,15 +710,10 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultFunction::TailList => {
|
DefaultFunction::TailList => {
|
||||||
let c @ Value::Con(inner) = &args[0] else {
|
let (r#type, list) = args[0].unwrap_list()?;
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
let Constant::ProtoList(r#type, list) = inner.as_ref() else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
if list.is_empty() {
|
if list.is_empty() {
|
||||||
Err(Error::EmptyList(c.clone()))
|
Err(Error::EmptyList(args[0].clone()))
|
||||||
} else {
|
} else {
|
||||||
let value = Value::list(r#type.clone(), list[1..].to_vec());
|
let value = Value::list(r#type.clone(), list[1..].to_vec());
|
||||||
|
|
||||||
|
@ -896,27 +721,26 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultFunction::NullList => {
|
DefaultFunction::NullList => {
|
||||||
let (_, list) = args[0].unwrap_list();
|
let (_, list) = args[0].unwrap_list()?;
|
||||||
|
|
||||||
let value = Value::bool(list.is_empty());
|
let value = Value::bool(list.is_empty());
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::ChooseData => {
|
DefaultFunction::ChooseData => {
|
||||||
let con = args[0].unwrap_constant();
|
let con = args[0].unwrap_data()?;
|
||||||
|
|
||||||
match con {
|
match con {
|
||||||
Constant::Data(PlutusData::Constr(_)) => Ok(args[1].clone()),
|
PlutusData::Constr(_) => Ok(args[1].clone()),
|
||||||
Constant::Data(PlutusData::Map(_)) => Ok(args[2].clone()),
|
PlutusData::Map(_) => Ok(args[2].clone()),
|
||||||
Constant::Data(PlutusData::Array(_)) => Ok(args[3].clone()),
|
PlutusData::Array(_) => Ok(args[3].clone()),
|
||||||
Constant::Data(PlutusData::BigInt(_)) => Ok(args[4].clone()),
|
PlutusData::BigInt(_) => Ok(args[4].clone()),
|
||||||
Constant::Data(PlutusData::BoundedBytes(_)) => Ok(args[5].clone()),
|
PlutusData::BoundedBytes(_) => Ok(args[5].clone()),
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DefaultFunction::ConstrData => {
|
DefaultFunction::ConstrData => {
|
||||||
let i = args[0].unwrap_integer();
|
let i = args[0].unwrap_integer()?;
|
||||||
let l = args[1].unwrap_data_list();
|
let l = args[1].unwrap_data_list()?;
|
||||||
|
|
||||||
let data_list: Vec<PlutusData> = l
|
let data_list: Vec<PlutusData> = l
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -939,7 +763,17 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::MapData => {
|
DefaultFunction::MapData => {
|
||||||
let (_, list) = args[0].unwrap_list();
|
let (r#type, list) = args[0].unwrap_list()?;
|
||||||
|
|
||||||
|
if *r#type != Type::Pair(Rc::new(Type::Data), Rc::new(Type::Data)) {
|
||||||
|
return Err(Error::TypeMismatch(
|
||||||
|
Type::List(Rc::new(Type::Pair(
|
||||||
|
Rc::new(Type::Data),
|
||||||
|
Rc::new(Type::Data),
|
||||||
|
))),
|
||||||
|
r#type.clone(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let mut map = Vec::new();
|
let mut map = Vec::new();
|
||||||
|
|
||||||
|
@ -948,12 +782,13 @@ impl DefaultFunction {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
|
||||||
match (left.as_ref(), right.as_ref()) {
|
let (Constant::Data(key), Constant::Data(value)) =
|
||||||
(Constant::Data(key), Constant::Data(value)) => {
|
(left.as_ref(), right.as_ref())
|
||||||
map.push((key.clone(), value.clone()));
|
else {
|
||||||
}
|
unreachable!()
|
||||||
_ => unreachable!(),
|
};
|
||||||
}
|
|
||||||
|
map.push((key.clone(), value.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let value = Value::data(PlutusData::Map(map.into()));
|
let value = Value::data(PlutusData::Map(map.into()));
|
||||||
|
@ -961,7 +796,7 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::ListData => {
|
DefaultFunction::ListData => {
|
||||||
let (_, list) = args[0].unwrap_list();
|
let list = args[0].unwrap_data_list()?;
|
||||||
|
|
||||||
let data_list: Vec<PlutusData> = list
|
let data_list: Vec<PlutusData> = list
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -976,14 +811,14 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::IData => {
|
DefaultFunction::IData => {
|
||||||
let i = args[0].unwrap_integer();
|
let i = args[0].unwrap_integer()?;
|
||||||
|
|
||||||
let value = Value::data(PlutusData::BigInt(to_pallas_bigint(i)));
|
let value = Value::data(PlutusData::BigInt(to_pallas_bigint(i)));
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::BData => {
|
DefaultFunction::BData => {
|
||||||
let b = args[0].unwrap_byte_string();
|
let b = args[0].unwrap_byte_string()?;
|
||||||
|
|
||||||
let value = Value::data(PlutusData::BoundedBytes(b.clone().try_into().unwrap()));
|
let value = Value::data(PlutusData::BoundedBytes(b.clone().try_into().unwrap()));
|
||||||
|
|
||||||
|
@ -1022,10 +857,7 @@ impl DefaultFunction {
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
v => Err(Error::DeserialisationError(
|
v => Err(Error::NotAConstant(v.clone())),
|
||||||
"UnConstrData".to_string(),
|
|
||||||
v.clone(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
DefaultFunction::UnMapData => match &args[0] {
|
DefaultFunction::UnMapData => match &args[0] {
|
||||||
v @ Value::Con(inner) => {
|
v @ Value::Con(inner) => {
|
||||||
|
@ -1055,10 +887,7 @@ impl DefaultFunction {
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
v => Err(Error::DeserialisationError(
|
v => Err(Error::NotAConstant(v.clone())),
|
||||||
"UnMapData".to_string(),
|
|
||||||
v.clone(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
DefaultFunction::UnListData => match &args[0] {
|
DefaultFunction::UnListData => match &args[0] {
|
||||||
v @ Value::Con(inner) => {
|
v @ Value::Con(inner) => {
|
||||||
|
@ -1079,10 +908,7 @@ impl DefaultFunction {
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
v => Err(Error::DeserialisationError(
|
v => Err(Error::NotAConstant(v.clone())),
|
||||||
"UnListData".to_string(),
|
|
||||||
v.clone(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
DefaultFunction::UnIData => match &args[0] {
|
DefaultFunction::UnIData => match &args[0] {
|
||||||
v @ Value::Con(inner) => {
|
v @ Value::Con(inner) => {
|
||||||
|
@ -1097,10 +923,7 @@ impl DefaultFunction {
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
v => Err(Error::DeserialisationError(
|
v => Err(Error::NotAConstant(v.clone())),
|
||||||
"UnIData".to_string(),
|
|
||||||
v.clone(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
DefaultFunction::UnBData => match &args[0] {
|
DefaultFunction::UnBData => match &args[0] {
|
||||||
v @ Value::Con(inner) => {
|
v @ Value::Con(inner) => {
|
||||||
|
@ -1115,34 +938,18 @@ impl DefaultFunction {
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
v => Err(Error::DeserialisationError(
|
v => Err(Error::NotAConstant(v.clone())),
|
||||||
"UnBData".to_string(),
|
|
||||||
v.clone(),
|
|
||||||
)),
|
|
||||||
},
|
},
|
||||||
DefaultFunction::EqualsData => {
|
DefaultFunction::EqualsData => {
|
||||||
let (Value::Con(inner1), Value::Con(inner2)) = (&args[0], &args[1]) else {
|
let d1 = args[0].unwrap_data()?;
|
||||||
unreachable!()
|
let d2 = args[1].unwrap_data()?;
|
||||||
};
|
|
||||||
|
|
||||||
let Constant::Data(d1) = inner1.as_ref() else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
let Constant::Data(d2) = inner2.as_ref() else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
let value = Value::bool(d1.eq(d2));
|
let value = Value::bool(d1.eq(d2));
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::SerialiseData => {
|
DefaultFunction::SerialiseData => {
|
||||||
let Value::Con(inner) = &args[0] else {
|
let d = args[0].unwrap_data()?;
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
let Constant::Data(d) = inner.as_ref() else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
let serialized_data = plutus_data_to_bytes(d).unwrap();
|
let serialized_data = plutus_data_to_bytes(d).unwrap();
|
||||||
|
|
||||||
|
@ -1151,16 +958,8 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::MkPairData => {
|
DefaultFunction::MkPairData => {
|
||||||
let (Value::Con(inner1), Value::Con(inner2)) = (&args[0], &args[1]) else {
|
let d1 = args[0].unwrap_data()?;
|
||||||
unreachable!()
|
let d2 = args[1].unwrap_data()?;
|
||||||
};
|
|
||||||
|
|
||||||
let Constant::Data(d1) = inner1.as_ref() else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
let Constant::Data(d2) = inner2.as_ref() else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
let constant = Constant::ProtoPair(
|
let constant = Constant::ProtoPair(
|
||||||
Type::Data,
|
Type::Data,
|
||||||
|
@ -1174,11 +973,15 @@ impl DefaultFunction {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::MkNilData => {
|
DefaultFunction::MkNilData => {
|
||||||
|
args[0].unwrap_unit()?;
|
||||||
|
|
||||||
let value = Value::list(Type::Data, vec![]);
|
let value = Value::list(Type::Data, vec![]);
|
||||||
|
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
DefaultFunction::MkNilPairData => {
|
DefaultFunction::MkNilPairData => {
|
||||||
|
args[0].unwrap_unit()?;
|
||||||
|
|
||||||
let constant = Constant::ProtoList(
|
let constant = Constant::ProtoList(
|
||||||
Type::Pair(Rc::new(Type::Data), Rc::new(Type::Data)),
|
Type::Pair(Rc::new(Type::Data), Rc::new(Type::Data)),
|
||||||
vec![],
|
vec![],
|
||||||
|
@ -1190,8 +993,8 @@ impl DefaultFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultFunction::Bls12_381_G1_Add => {
|
DefaultFunction::Bls12_381_G1_Add => {
|
||||||
let arg1 = args[0].unwrap_bls12_381_g1_element();
|
let arg1 = args[0].unwrap_bls12_381_g1_element()?;
|
||||||
let arg2 = args[1].unwrap_bls12_381_g1_element();
|
let arg2 = args[1].unwrap_bls12_381_g1_element()?;
|
||||||
|
|
||||||
let mut out = blst::blst_p1::default();
|
let mut out = blst::blst_p1::default();
|
||||||
|
|
||||||
|
@ -1208,7 +1011,7 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G1_Neg => {
|
DefaultFunction::Bls12_381_G1_Neg => {
|
||||||
let arg1 = args[0].unwrap_bls12_381_g1_element();
|
let arg1 = args[0].unwrap_bls12_381_g1_element()?;
|
||||||
|
|
||||||
let mut out = *arg1;
|
let mut out = *arg1;
|
||||||
|
|
||||||
|
@ -1225,8 +1028,8 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G1_ScalarMul => {
|
DefaultFunction::Bls12_381_G1_ScalarMul => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_bls12_381_g1_element();
|
let arg2 = args[1].unwrap_bls12_381_g1_element()?;
|
||||||
|
|
||||||
let size_scalar = size_of::<blst::blst_scalar>();
|
let size_scalar = size_of::<blst::blst_scalar>();
|
||||||
|
|
||||||
|
@ -1266,8 +1069,8 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G1_Equal => {
|
DefaultFunction::Bls12_381_G1_Equal => {
|
||||||
let arg1 = args[0].unwrap_bls12_381_g1_element();
|
let arg1 = args[0].unwrap_bls12_381_g1_element()?;
|
||||||
let arg2 = args[1].unwrap_bls12_381_g1_element();
|
let arg2 = args[1].unwrap_bls12_381_g1_element()?;
|
||||||
|
|
||||||
let is_equal = unsafe { blst::blst_p1_is_equal(arg1, arg2) };
|
let is_equal = unsafe { blst::blst_p1_is_equal(arg1, arg2) };
|
||||||
|
|
||||||
|
@ -1276,7 +1079,7 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G1_Compress => {
|
DefaultFunction::Bls12_381_G1_Compress => {
|
||||||
let arg1 = args[0].unwrap_bls12_381_g1_element();
|
let arg1 = args[0].unwrap_bls12_381_g1_element()?;
|
||||||
|
|
||||||
let out = arg1.compress();
|
let out = arg1.compress();
|
||||||
|
|
||||||
|
@ -1285,7 +1088,7 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G1_Uncompress => {
|
DefaultFunction::Bls12_381_G1_Uncompress => {
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
|
|
||||||
let out = blst::blst_p1::uncompress(arg1)?;
|
let out = blst::blst_p1::uncompress(arg1)?;
|
||||||
|
|
||||||
|
@ -1294,8 +1097,8 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G1_HashToGroup => {
|
DefaultFunction::Bls12_381_G1_HashToGroup => {
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
let arg2 = args[1].unwrap_byte_string();
|
let arg2 = args[1].unwrap_byte_string()?;
|
||||||
|
|
||||||
if arg2.len() > 255 {
|
if arg2.len() > 255 {
|
||||||
return Err(Error::HashToCurveDstTooBig);
|
return Err(Error::HashToCurveDstTooBig);
|
||||||
|
@ -1321,8 +1124,8 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G2_Add => {
|
DefaultFunction::Bls12_381_G2_Add => {
|
||||||
let arg1 = args[0].unwrap_bls12_381_g2_element();
|
let arg1 = args[0].unwrap_bls12_381_g2_element()?;
|
||||||
let arg2 = args[1].unwrap_bls12_381_g2_element();
|
let arg2 = args[1].unwrap_bls12_381_g2_element()?;
|
||||||
|
|
||||||
let mut out = blst::blst_p2::default();
|
let mut out = blst::blst_p2::default();
|
||||||
|
|
||||||
|
@ -1339,7 +1142,7 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G2_Neg => {
|
DefaultFunction::Bls12_381_G2_Neg => {
|
||||||
let arg1 = args[0].unwrap_bls12_381_g2_element();
|
let arg1 = args[0].unwrap_bls12_381_g2_element()?;
|
||||||
|
|
||||||
let mut out = *arg1;
|
let mut out = *arg1;
|
||||||
|
|
||||||
|
@ -1356,8 +1159,8 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G2_ScalarMul => {
|
DefaultFunction::Bls12_381_G2_ScalarMul => {
|
||||||
let arg1 = args[0].unwrap_integer();
|
let arg1 = args[0].unwrap_integer()?;
|
||||||
let arg2 = args[1].unwrap_bls12_381_g2_element();
|
let arg2 = args[1].unwrap_bls12_381_g2_element()?;
|
||||||
|
|
||||||
let size_scalar = size_of::<blst::blst_scalar>();
|
let size_scalar = size_of::<blst::blst_scalar>();
|
||||||
|
|
||||||
|
@ -1397,8 +1200,8 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G2_Equal => {
|
DefaultFunction::Bls12_381_G2_Equal => {
|
||||||
let arg1 = args[0].unwrap_bls12_381_g2_element();
|
let arg1 = args[0].unwrap_bls12_381_g2_element()?;
|
||||||
let arg2 = args[1].unwrap_bls12_381_g2_element();
|
let arg2 = args[1].unwrap_bls12_381_g2_element()?;
|
||||||
|
|
||||||
let is_equal = unsafe { blst::blst_p2_is_equal(arg1, arg2) };
|
let is_equal = unsafe { blst::blst_p2_is_equal(arg1, arg2) };
|
||||||
|
|
||||||
|
@ -1407,7 +1210,7 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G2_Compress => {
|
DefaultFunction::Bls12_381_G2_Compress => {
|
||||||
let arg1 = args[0].unwrap_bls12_381_g2_element();
|
let arg1 = args[0].unwrap_bls12_381_g2_element()?;
|
||||||
|
|
||||||
let out = arg1.compress();
|
let out = arg1.compress();
|
||||||
|
|
||||||
|
@ -1416,7 +1219,7 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G2_Uncompress => {
|
DefaultFunction::Bls12_381_G2_Uncompress => {
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
|
|
||||||
let out = blst::blst_p2::uncompress(arg1)?;
|
let out = blst::blst_p2::uncompress(arg1)?;
|
||||||
|
|
||||||
|
@ -1425,8 +1228,8 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_G2_HashToGroup => {
|
DefaultFunction::Bls12_381_G2_HashToGroup => {
|
||||||
let arg1 = args[0].unwrap_byte_string();
|
let arg1 = args[0].unwrap_byte_string()?;
|
||||||
let arg2 = args[1].unwrap_byte_string();
|
let arg2 = args[1].unwrap_byte_string()?;
|
||||||
|
|
||||||
if arg2.len() > 255 {
|
if arg2.len() > 255 {
|
||||||
return Err(Error::HashToCurveDstTooBig);
|
return Err(Error::HashToCurveDstTooBig);
|
||||||
|
@ -1452,8 +1255,8 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_MillerLoop => {
|
DefaultFunction::Bls12_381_MillerLoop => {
|
||||||
let arg1 = args[0].unwrap_bls12_381_g1_element();
|
let arg1 = args[0].unwrap_bls12_381_g1_element()?;
|
||||||
let arg2 = args[1].unwrap_bls12_381_g2_element();
|
let arg2 = args[1].unwrap_bls12_381_g2_element()?;
|
||||||
|
|
||||||
let mut out = blst::blst_fp12::default();
|
let mut out = blst::blst_fp12::default();
|
||||||
|
|
||||||
|
@ -1472,8 +1275,8 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_MulMlResult => {
|
DefaultFunction::Bls12_381_MulMlResult => {
|
||||||
let arg1 = args[0].unwrap_bls12_381_ml_result();
|
let arg1 = args[0].unwrap_bls12_381_ml_result()?;
|
||||||
let arg2 = args[1].unwrap_bls12_381_ml_result();
|
let arg2 = args[1].unwrap_bls12_381_ml_result()?;
|
||||||
|
|
||||||
let mut out = blst::blst_fp12::default();
|
let mut out = blst::blst_fp12::default();
|
||||||
|
|
||||||
|
@ -1486,8 +1289,8 @@ impl DefaultFunction {
|
||||||
Ok(Value::Con(constant.into()))
|
Ok(Value::Con(constant.into()))
|
||||||
}
|
}
|
||||||
DefaultFunction::Bls12_381_FinalVerify => {
|
DefaultFunction::Bls12_381_FinalVerify => {
|
||||||
let arg1 = args[0].unwrap_bls12_381_ml_result();
|
let arg1 = args[0].unwrap_bls12_381_ml_result()?;
|
||||||
let arg2 = args[1].unwrap_bls12_381_ml_result();
|
let arg2 = args[1].unwrap_bls12_381_ml_result()?;
|
||||||
|
|
||||||
let verified = unsafe { blst::blst_fp12_finalverify(arg1, arg2) };
|
let verified = unsafe { blst::blst_fp12_finalverify(arg1, arg2) };
|
||||||
|
|
||||||
|
|
|
@ -69,125 +69,138 @@ impl Value {
|
||||||
Value::Con(constant.into())
|
Value::Con(constant.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwrap_integer(&self) -> &BigInt {
|
pub(super) fn unwrap_integer(&self) -> Result<&BigInt, Error> {
|
||||||
let Value::Con(inner) = self else {
|
let inner = self.unwrap_constant()?;
|
||||||
unreachable!()
|
|
||||||
};
|
let Constant::Integer(integer) = inner else {
|
||||||
let Constant::Integer(integer) = inner.as_ref() else {
|
return Err(Error::TypeMismatch(Type::Integer, inner.into()));
|
||||||
unreachable!()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
integer
|
Ok(integer)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwrap_byte_string(&self) -> &Vec<u8> {
|
pub(super) fn unwrap_byte_string(&self) -> Result<&Vec<u8>, Error> {
|
||||||
let Value::Con(inner) = self else {
|
let inner = self.unwrap_constant()?;
|
||||||
unreachable!()
|
|
||||||
};
|
let Constant::ByteString(byte_string) = inner else {
|
||||||
let Constant::ByteString(byte_string) = inner.as_ref() else {
|
return Err(Error::TypeMismatch(Type::ByteString, inner.into()));
|
||||||
unreachable!()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
byte_string
|
Ok(byte_string)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwrap_string(&self) -> &String {
|
pub(super) fn unwrap_string(&self) -> Result<&String, Error> {
|
||||||
let Value::Con(inner) = self else {
|
let inner = self.unwrap_constant()?;
|
||||||
unreachable!()
|
|
||||||
};
|
let Constant::String(string) = inner else {
|
||||||
let Constant::String(string) = inner.as_ref() else {
|
return Err(Error::TypeMismatch(Type::String, inner.into()));
|
||||||
unreachable!()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
string
|
Ok(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwrap_bool(&self) -> &bool {
|
pub(super) fn unwrap_bool(&self) -> Result<&bool, Error> {
|
||||||
let Value::Con(inner) = self else {
|
let inner = self.unwrap_constant()?;
|
||||||
unreachable!()
|
|
||||||
};
|
let Constant::Bool(condition) = inner else {
|
||||||
let Constant::Bool(condition) = inner.as_ref() else {
|
return Err(Error::TypeMismatch(Type::Bool, inner.into()));
|
||||||
unreachable!()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
condition
|
Ok(condition)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwrap_pair(&self) -> (&Type, &Type, &Rc<Constant>, &Rc<Constant>) {
|
#[allow(clippy::type_complexity)]
|
||||||
let Value::Con(inner) = self else {
|
pub(super) fn unwrap_pair(
|
||||||
unreachable!()
|
&self,
|
||||||
};
|
) -> Result<(&Type, &Type, &Rc<Constant>, &Rc<Constant>), Error> {
|
||||||
let Constant::ProtoPair(t1, t2, first, second) = inner.as_ref() else {
|
let inner = self.unwrap_constant()?;
|
||||||
unreachable!()
|
|
||||||
|
let Constant::ProtoPair(t1, t2, first, second) = inner else {
|
||||||
|
return Err(Error::PairTypeMismatch(inner.into()));
|
||||||
};
|
};
|
||||||
|
|
||||||
(t1, t2, first, second)
|
Ok((t1, t2, first, second))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwrap_list(&self) -> (&Type, &Vec<Constant>) {
|
pub(super) fn unwrap_list(&self) -> Result<(&Type, &Vec<Constant>), Error> {
|
||||||
let Value::Con(inner) = self else {
|
let inner = self.unwrap_constant()?;
|
||||||
unreachable!()
|
|
||||||
};
|
let Constant::ProtoList(t, list) = inner else {
|
||||||
let Constant::ProtoList(t, list) = inner.as_ref() else {
|
return Err(Error::ListTypeMismatch(inner.into()));
|
||||||
unreachable!()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
(t, list)
|
Ok((t, list))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwrap_constant(&self) -> &Constant {
|
pub(super) fn unwrap_data(&self) -> Result<&PlutusData, Error> {
|
||||||
|
let inner = self.unwrap_constant()?;
|
||||||
|
|
||||||
|
let Constant::Data(data) = inner else {
|
||||||
|
return Err(Error::TypeMismatch(Type::Data, inner.into()));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn unwrap_unit(&self) -> Result<(), Error> {
|
||||||
|
let inner = self.unwrap_constant()?;
|
||||||
|
|
||||||
|
let Constant::Unit = inner else {
|
||||||
|
return Err(Error::TypeMismatch(Type::Unit, inner.into()));
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) fn unwrap_constant(&self) -> Result<&Constant, Error> {
|
||||||
let Value::Con(item) = self else {
|
let Value::Con(item) = self else {
|
||||||
unreachable!()
|
return Err(Error::NotAConstant(self.clone()));
|
||||||
};
|
};
|
||||||
|
|
||||||
item.as_ref()
|
Ok(item.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwrap_data_list(&self) -> &Vec<Constant> {
|
pub(super) fn unwrap_data_list(&self) -> Result<&Vec<Constant>, Error> {
|
||||||
let Value::Con(inner) = self else {
|
let inner = self.unwrap_constant()?;
|
||||||
unreachable!()
|
|
||||||
};
|
let Constant::ProtoList(Type::Data, list) = inner else {
|
||||||
let Constant::ProtoList(Type::Data, list) = inner.as_ref() else {
|
return Err(Error::TypeMismatch(
|
||||||
unreachable!()
|
Type::List(Type::Data.into()),
|
||||||
|
inner.into(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
list
|
Ok(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwrap_bls12_381_g1_element(&self) -> &blst::blst_p1 {
|
pub(super) fn unwrap_bls12_381_g1_element(&self) -> Result<&blst::blst_p1, Error> {
|
||||||
let Value::Con(inner) = self else {
|
let inner = self.unwrap_constant()?;
|
||||||
unreachable!()
|
|
||||||
|
let Constant::Bls12_381G1Element(element) = inner else {
|
||||||
|
return Err(Error::TypeMismatch(Type::Bls12_381G1Element, inner.into()));
|
||||||
};
|
};
|
||||||
|
|
||||||
let Constant::Bls12_381G1Element(element) = inner.as_ref() else {
|
Ok(element)
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
element
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwrap_bls12_381_g2_element(&self) -> &blst::blst_p2 {
|
pub(super) fn unwrap_bls12_381_g2_element(&self) -> Result<&blst::blst_p2, Error> {
|
||||||
let Value::Con(inner) = self else {
|
let inner = self.unwrap_constant()?;
|
||||||
unreachable!()
|
|
||||||
|
let Constant::Bls12_381G2Element(element) = inner else {
|
||||||
|
return Err(Error::TypeMismatch(Type::Bls12_381G2Element, inner.into()));
|
||||||
};
|
};
|
||||||
|
|
||||||
let Constant::Bls12_381G2Element(element) = inner.as_ref() else {
|
Ok(element)
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
element
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unwrap_bls12_381_ml_result(&self) -> &blst::blst_fp12 {
|
pub(super) fn unwrap_bls12_381_ml_result(&self) -> Result<&blst::blst_fp12, Error> {
|
||||||
let Value::Con(inner) = self else {
|
let inner = self.unwrap_constant()?;
|
||||||
unreachable!()
|
|
||||||
|
let Constant::Bls12_381MlResult(element) = inner else {
|
||||||
|
return Err(Error::TypeMismatch(Type::Bls12_381MlResult, inner.into()));
|
||||||
};
|
};
|
||||||
|
|
||||||
let Constant::Bls12_381MlResult(element) = inner.as_ref() else {
|
Ok(element)
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
element
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_integer(&self) -> bool {
|
pub fn is_integer(&self) -> bool {
|
||||||
|
|
|
@ -145,7 +145,7 @@ peg::parser! {
|
||||||
}
|
}
|
||||||
|
|
||||||
rule case(interner: &mut Interner) -> Term<Name>
|
rule case(interner: &mut Interner) -> Term<Name>
|
||||||
= "(" _* "case" _+ constr:term(interner) _* branches:(t:term(interner) _* { t })+ _* ")" {
|
= "(" _* "case" _+ constr:term(interner) _* branches:(t:term(interner) _* { t })* _* ")" {
|
||||||
Term::Case { constr: constr.into(), branches }
|
Term::Case { constr: constr.into(), branches }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
(program
|
||||||
|
1.0.0
|
||||||
|
[
|
||||||
|
[ (force (builtin ifThenElse)) (con string "11 <= 22") ]
|
||||||
|
(con string "\172(11 <= 22)")
|
||||||
|
]
|
||||||
|
)
|
|
@ -0,0 +1,4 @@
|
||||||
|
(program 1.0.0 [
|
||||||
|
[ (force (builtin ifThenElse)) (con string "11 <= 22") ]
|
||||||
|
(con string "\172(11 <= 22)")
|
||||||
|
])
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- select first branch
|
||||||
|
(program 1.1.0
|
||||||
|
(case (constr 0 (con integer 0)) (lam x (con integer 1)) (lam x (con integer 2)))
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
(program 1.1.0 (con integer 1))
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- select second branch
|
||||||
|
(program 1.1.0
|
||||||
|
(case (constr 1 (con integer 0)) (lam x (con integer 1)) (lam x (con integer 2)))
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
(program 1.1.0 (con integer 2))
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- select first branch and do computation with the args
|
||||||
|
(program 1.1.0
|
||||||
|
(case (constr 0 (con integer 3) (con integer 2)) (lam x (lam y [(builtin addInteger) x y])) (lam x (lam y [(builtin subtractInteger) x y])))
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
(program 1.1.0 (con integer 5))
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- select second branch and do computation with the args
|
||||||
|
(program 1.1.0
|
||||||
|
(case (constr 1 (con integer 3) (con integer 2)) (lam x (lam y [(builtin addInteger) x y])) (lam x (lam y [(builtin subtractInteger) x y])))
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
(program 1.1.0 (con integer 1))
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- case of non-constr
|
||||||
|
(program 1.1.0
|
||||||
|
(case (con integer 1) (lam x x) (lam x x))
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
evaluation failure
|
|
@ -1,4 +0,0 @@
|
||||||
-- case can't be used before 1.1.0
|
|
||||||
(program 1.0.0
|
|
||||||
(case (con integer 1))
|
|
||||||
)
|
|
|
@ -1 +0,0 @@
|
||||||
parse error
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- nullary case
|
||||||
|
(program 1.1.0
|
||||||
|
(case (constr 0) (con integer 1) (con integer 2))
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
(program 1.1.0 (con integer 1))
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- empty case, aka -XEmptyCase
|
||||||
|
(program 1.1.0
|
||||||
|
(case (constr 0))
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
evaluation failure
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- empty constr
|
||||||
|
(program 1.1.0
|
||||||
|
(constr 0 )
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
(program 1.1.0 (constr 0))
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- constr with an argument
|
||||||
|
(program 1.1.0
|
||||||
|
(constr 0 (con integer 1))
|
||||||
|
)
|
|
@ -0,0 +1 @@
|
||||||
|
(program 1.1.0 (constr 0 (con integer 1)))
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- ill-typed but does not fail at runtime because the builtin application is not saturated.
|
||||||
|
(program 1.0.0 [(builtin addInteger) (con unit ())])
|
|
@ -0,0 +1 @@
|
||||||
|
(program 1.0.0 [ (builtin addInteger) (con unit ()) ])
|
|
@ -119,12 +119,13 @@ fn check_mint_and_outputs(
|
||||||
when minted_assets is {
|
when minted_assets is {
|
||||||
[] -> True
|
[] -> True
|
||||||
[(minted_asset_name, quantity), ..rest_assets] -> {
|
[(minted_asset_name, quantity), ..rest_assets] -> {
|
||||||
expect True =
|
expect
|
||||||
list.any(
|
list.any(
|
||||||
expected_assets,
|
expected_assets,
|
||||||
fn(expected_asset) { expected_asset == minted_asset_name },
|
fn(expected_asset) { expected_asset == minted_asset_name },
|
||||||
)
|
)
|
||||||
expect True =
|
|
||||||
|
expect
|
||||||
list.any(
|
list.any(
|
||||||
outputs,
|
outputs,
|
||||||
fn(output) {
|
fn(output) {
|
||||||
|
@ -132,6 +133,7 @@ fn check_mint_and_outputs(
|
||||||
datum == InlineDatum(minted_asset_name) && address.payment_credential == validator_cred
|
datum == InlineDatum(minted_asset_name) && address.payment_credential == validator_cred
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
quantity == 1 && check_mint_and_outputs(
|
quantity == 1 && check_mint_and_outputs(
|
||||||
rest_assets,
|
rest_assets,
|
||||||
outputs,
|
outputs,
|
||||||
|
|
Loading…
Reference in New Issue