@@ -25,6 +25,15 @@ module 0x42.CoinInterface {
2525 label b0:
2626 return *&move(self).T<T>::merge;
2727 }
28+
29+ public value<T>(self: &Self.T<T>, coin: &T): u64 {
30+ let value: |&T| (u64);
31+ let ret: u64;
32+ label b0:
33+ value = *&move(self).T<T>::value;
34+ ret = call_function_pointer<|&T| (u64)>(move(coin), move(value));
35+ return move(ret);
36+ }
2837}
2938
3039//# publish
@@ -80,6 +89,59 @@ module 0x42.BasicCoin1 {
8089 }
8190}
8291
92+
93+ //# publish
94+ module 0x42.BasicCoin2 {
95+ import 0x42.CoinInterface;
96+
97+ struct Coin has store, drop { value: u64 }
98+
99+ public zero(): Self.Coin {
100+ label b0:
101+ return Coin { value: 0 };
102+ }
103+
104+ public mint(value: u64): Self.Coin {
105+ label b0:
106+ return Coin { value: move(value) };
107+ }
108+
109+ public value(c: &Self.Coin): u64 {
110+ label b0:
111+ return *&move(c).Coin::value;
112+ }
113+
114+ public merge(c: &mut Self.Coin, other: Self.Coin) {
115+ let value: u64;
116+ label b0:
117+ Coin { value } = move(other);
118+ *&mut move(c).Coin::value = (*©(c).Coin::value) + 1;
119+ return;
120+ }
121+
122+
123+ public split(c: &mut Self.Coin, value: u64): Self.Coin {
124+ let coin_value: u64;
125+ label b0:
126+ coin_value = *©(c).Coin::value;
127+ assert(copy(coin_value) >= copy(value), 0);
128+ *&mut copy(c).Coin::value = move(coin_value) - copy(value);
129+ return Coin { value: move(value) };
130+ }
131+
132+ public coin_interface(): CoinInterface.T<Self.Coin> {
133+ let value: |&Self.Coin| (u64);
134+ let split: |&mut Self.Coin, u64| (Self.Coin);
135+ let merge: |&mut Self.Coin, Self.Coin| ();
136+ let interface: CoinInterface.T<Self.Coin>;
137+ label b0:
138+ value = get_function_pointer(Self.value);
139+ split = get_function_pointer(Self.split);
140+ merge = get_function_pointer(Self.merge);
141+ interface = CoinInterface.new_interface<Self.Coin>(move(value), move(split), move(merge));
142+ return move(interface);
143+ }
144+ }
83145//# publish
84146module 0x42.CoinType {
85147 struct Foo has drop {
@@ -91,13 +153,11 @@ module 0x42.CoinType {
91153module 0x42.GenericAdder {
92154 import 0x42.CoinInterface;
93155 public add_coins<T>(interface: &CoinInterface.T<T>, coin1: &T, coin2: &T): u64 {
94- let value: |&T| (u64);
95156 let v1: u64;
96157 let v2: u64;
97158 label b0:
98- value = CoinInterface.value_func<T>(move(interface));
99- v1 = call_function_pointer<|&T| (u64)>(move(coin1), copy(value));
100- v2 = call_function_pointer<|&T| (u64)>(move(coin2), copy(value));
159+ v1 = CoinInterface.value<T>(copy(interface), move(coin1));
160+ v2 = CoinInterface.value<T>(move(interface), move(coin2));
101161 return move(v1) + move(v2);
102162 }
103163}
@@ -123,3 +183,23 @@ label b0:
123183 return;
124184}
125185
186+ //# run
187+ import 0x42.CoinInterface;
188+ import 0x42.BasicCoin2;
189+ import 0x42.GenericAdder;
190+
191+ main() {
192+ let interface: CoinInterface.T<BasicCoin2.Coin>;
193+ let coin1: BasicCoin2.Coin;
194+ let coin2: BasicCoin2.Coin;
195+ let v: u64;
196+ label b0:
197+ coin1 = BasicCoin2.mint(10);
198+ coin2 = BasicCoin2.mint(20);
199+ interface = BasicCoin2.coin_interface();
200+
201+ v = GenericAdder.add_coins<BasicCoin2.Coin>(&interface, &coin1, &coin2);
202+ assert(move(v) == 30, 0);
203+ return;
204+ }
205+
0 commit comments