diff --git a/examples/acceptance_tests/035/aiken.lock b/examples/acceptance_tests/035/aiken.lock new file mode 100644 index 00000000..3a78b1e7 --- /dev/null +++ b/examples/acceptance_tests/035/aiken.lock @@ -0,0 +1,5 @@ +# This file was generated by Aiken +# You typically do not need to edit this file + +requirements = [] +packages = [] diff --git a/examples/acceptance_tests/035/aiken.toml b/examples/acceptance_tests/035/aiken.toml new file mode 100644 index 00000000..a9c17672 --- /dev/null +++ b/examples/acceptance_tests/035/aiken.toml @@ -0,0 +1,2 @@ +name = "aiken-lang/acceptance_test_035" +version = "0.0.0" diff --git a/examples/acceptance_tests/035/lib/aiken/dict.ak b/examples/acceptance_tests/035/lib/aiken/dict.ak new file mode 100644 index 00000000..f34d83bb --- /dev/null +++ b/examples/acceptance_tests/035/lib/aiken/dict.ak @@ -0,0 +1,60 @@ +/// An opaque `Dict`. The type is opaque because the module maintains some +/// invariant, namely: there's only one occurence of a given key in the dictionnary. +pub opaque type Dict { + inner: List<#(ByteArray, value)>, +} + +/// Create a new map +pub fn new() -> Dict { + Dict { inner: [] } +} + +pub fn insert( + self: Dict, + key k: ByteArray, + value v: value, +) -> Dict { + Dict { + inner: do_insert_with(self.inner, k, v, fn(_, left, _right) { Some(left) })} + +} + +pub fn union_with( + left: Dict, + right: Dict, + with: fn(ByteArray, value, value) -> Option, +) -> Dict { + Dict { inner: do_union_with(left.inner, right.inner, with) } +} + +fn do_union_with( + left: List<#(ByteArray, value)>, + right: List<#(ByteArray, value)>, + with: fn(ByteArray, value, value) -> Option, +) -> List<#(ByteArray, value)> { + when left is { + [] -> right + [#(k, v), ..rest] -> + do_union_with(rest, do_insert_with(right, k, v, with), with) + } +} + +fn do_insert_with( + self: List<#(ByteArray, value)>, + key k: ByteArray, + value v: value, + with: fn(ByteArray, value, value) -> Option, +) -> List<#(ByteArray, value)> { + when self is { + [] -> [#(k, v)] + [#(k2, v2), ..rest] -> + if k == k2 { + when with(k, v, v2) is { + Some(combined) -> [#(k, combined), ..rest] + None -> rest + } + } else { + [#(k2, v2), ..do_insert_with(rest, k, v, with)] + } + } +} diff --git a/examples/acceptance_tests/035/lib/tests.ak b/examples/acceptance_tests/035/lib/tests.ak new file mode 100644 index 00000000..597c6968 --- /dev/null +++ b/examples/acceptance_tests/035/lib/tests.ak @@ -0,0 +1,55 @@ +use aiken/dict.{Dict} + +pub type PolicyId = + ByteArray + +pub type AssetName = + ByteArray + +pub type Value = + Dict> + +pub fn from_asset( + policy_id: PolicyId, + asset_name: AssetName, + quantity: Int, +) -> Value { + let asset = + dict.new() + |> dict.insert(asset_name, quantity) + dict.new() + |> dict.insert(policy_id, asset) +} + +pub fn from_lovelace(quantity: Int) -> Value { + from_asset(#[], #[], quantity) +} + +pub fn add(left v0: Value, right v1: Value) -> Value { + dict.union_with( + v0, + v1, + fn(_, a0, a1) { + Some( + dict.union_with( + a0, + a1, + fn(_, q0, q1) { + let q = q0 + q1 + if q == 0 { + None + } else { + Some(q) + } + }, + )) + + }, + ) +} + +test add_1() { + let v1 = from_lovelace(1) + let v2 = from_lovelace(-1) + add(v1, v2) == dict.new() +}