mirror of
https://github.com/ton-blockchain/ton
synced 2025-02-13 03:32:22 +00:00
This is a very big change. If FunC has `.methods()` and `~methods()`, Tolk has only dot, one and only way to call a `.method()`. A method may mutate an object, or may not. It's a behavioral and semantic difference from FunC. - `cs.loadInt(32)` modifies a slice and returns an integer - `b.storeInt(x, 32)` modifies a builder - `b = b.storeInt()` also works, since it not only modifies, but returns - chained methods also work, they return `self` - everything works exactly as expected, similar to JS - no runtime overhead, exactly same Fift instructions - custom methods are created with ease - tilda `~` does not exist in Tolk at all
213 lines
4.9 KiB
Text
213 lines
4.9 KiB
Text
fun incChained(mutate self: int): self {
|
|
self = self + 1;
|
|
return self;
|
|
}
|
|
|
|
fun incChained2(mutate self: int): self {
|
|
return self.incChained();
|
|
}
|
|
|
|
fun incChained3(mutate self: int): self {
|
|
incChained(mutate self);
|
|
return self;
|
|
}
|
|
|
|
fun incChained4(mutate self: int): self {
|
|
self.incChained();
|
|
return self;
|
|
}
|
|
|
|
@method_id(101)
|
|
fun testIncChainedCodegen(x: int) {
|
|
return x.incChained().incChained2().incChained3().incChained4();
|
|
}
|
|
|
|
@method_id(102)
|
|
fun testIncChained() {
|
|
var x: int = 10;
|
|
incChained(mutate x);
|
|
x.incChained();
|
|
x.incChained2();
|
|
x.incChained2().incChained();
|
|
x = x.incChained();
|
|
x = x.incChained2().incChained().incChained2();
|
|
return x.incChained();
|
|
}
|
|
|
|
fun incChainedWithMiddleReturn(mutate self: int, maxValue: int): self {
|
|
if (self >= maxValue) {
|
|
return self;
|
|
}
|
|
self += 1;
|
|
return self;
|
|
}
|
|
|
|
@method_id(103)
|
|
fun testIncChainedWithMiddleReturn(x: int) {
|
|
x.incChainedWithMiddleReturn(10).incChainedWithMiddleReturn(10);
|
|
x = x.incChainedWithMiddleReturn(10).incChainedWithMiddleReturn(10);
|
|
return x.incChainedWithMiddleReturn(10).incChainedWithMiddleReturn(999);
|
|
}
|
|
|
|
fun incChainedMutatingBoth(mutate self: int, mutate y: int): self {
|
|
self += 1;
|
|
y += 1;
|
|
return self;
|
|
}
|
|
|
|
global c104: int;
|
|
|
|
@method_id(104)
|
|
fun testIncChainedMutatingBoth() {
|
|
var (x, y) = (0, 0);
|
|
c104 = 0;
|
|
x.incChainedMutatingBoth(mutate y).incChainedMutatingBoth(mutate y);
|
|
incChainedMutatingBoth(mutate x, mutate y);
|
|
x = x.incChainedMutatingBoth(mutate c104).incChainedMutatingBoth(mutate c104).incChainedMutatingBoth(mutate y);
|
|
return (x, y, c104);
|
|
}
|
|
|
|
fun incTensorChained(mutate self: (int, int)): self {
|
|
val (f, s) = self;
|
|
self = (f + 1, s + 1);
|
|
return self;
|
|
}
|
|
|
|
@method_id(105)
|
|
fun testIncTensorChained(f: int, s: int) {
|
|
var tens = (f, s);
|
|
tens.incTensorChained().incTensorChained();
|
|
return tens.incTensorChained().incTensorChained();
|
|
}
|
|
|
|
fun incConditionalChainable(mutate self: int, mutate another: int, ifLessThan: int): self {
|
|
another += 1;
|
|
return self.incChained() < ifLessThan ? self.incChained().incChained() : self;
|
|
}
|
|
|
|
@method_id(106)
|
|
fun testIncConditionalChainable(x: int) {
|
|
var y = 0;
|
|
x.incConditionalChainable(mutate y, 5).incConditionalChainable(mutate y, 5);
|
|
x = x.incConditionalChainable(mutate y, 5).incConditionalChainable(mutate y, 5);
|
|
return (x.incConditionalChainable(mutate y, 5), y);
|
|
}
|
|
|
|
fun checkNotEq(self: int, throwIfEq: int): void {
|
|
if (self == throwIfEq) {
|
|
throw 100 + throwIfEq;
|
|
}
|
|
}
|
|
|
|
@method_id(107)
|
|
fun testNotMutatingSelf(arg: int) {
|
|
try {
|
|
arg.checkNotEq(100);
|
|
arg.checkNotEq(101);
|
|
arg.checkNotEq(102);
|
|
return 0;
|
|
} catch (code) {
|
|
return code;
|
|
}
|
|
}
|
|
|
|
global c108: int;
|
|
|
|
fun checkNotEqChainable(self: int, throwIfEq: int): self {
|
|
c108 += 1;
|
|
if (self != throwIfEq) {
|
|
return self;
|
|
}
|
|
throw 100 + throwIfEq;
|
|
return self;
|
|
}
|
|
|
|
@method_id(108)
|
|
fun testNotMutatingChainableSelf(arg: int) {
|
|
c108 = 0;
|
|
try {
|
|
arg.checkNotEqChainable(100).checkNotEqChainable(101).checkNotEqChainable(102);
|
|
arg = arg.checkNotEqChainable(100).checkNotEqChainable(101).checkNotEqChainable(102);
|
|
return (arg, c108);
|
|
} catch (code) {
|
|
return (code, c108);
|
|
}
|
|
}
|
|
|
|
global onceFailed109: int;
|
|
|
|
fun checkNotEqChainableMutateAnother(self: int, throwIfEq: int, mutate toInc: int): self {
|
|
if (onceFailed109) { return self; }
|
|
toInc += 1;
|
|
try { return self.checkNotEqChainable(throwIfEq); }
|
|
catch { onceFailed109 = 1; return self; }
|
|
}
|
|
|
|
global c109: int;
|
|
|
|
@method_id(109)
|
|
fun testNotMutatingChainableSelfMutateAnother(initial: int) {
|
|
val arg = initial;
|
|
var x = 0;
|
|
c108 = 0;
|
|
c109 = 0;
|
|
onceFailed109 = 0;
|
|
arg.checkNotEqChainableMutateAnother(100, mutate x)
|
|
.checkNotEqChainableMutateAnother(101, mutate c109)
|
|
.checkNotEqChainableMutateAnother(102, mutate x);
|
|
return (arg, c108, c109, x);
|
|
}
|
|
|
|
|
|
fun main() { }
|
|
|
|
/**
|
|
@testcase | 101 | 5 | 9
|
|
@testcase | 102 | | 20
|
|
@testcase | 103 | 1 | 7
|
|
@testcase | 103 | 100 | 101
|
|
@testcase | 103 | 8 | 11
|
|
@testcase | 104 | | 6 4 2
|
|
@testcase | 105 | 1 2 | 5 6
|
|
@testcase | 106 | -20 | -5 5
|
|
@testcase | 106 | -1 | 8 5
|
|
@testcase | 106 | 7 | 12 5
|
|
@testcase | 107 | 200 | 0
|
|
@testcase | 107 | 102 | 202
|
|
@testcase | 108 | 200 | 200 6
|
|
@testcase | 108 | 101 | 201 0
|
|
@testcase | 109 | 200 | 200 3 1 2
|
|
@testcase | 109 | 100 | 100 0 0 1
|
|
@testcase | 109 | 102 | 102 2 1 2
|
|
|
|
@fif_codegen
|
|
"""
|
|
incChained PROC:<{
|
|
// self
|
|
INC // self
|
|
}>
|
|
incChained2 PROC:<{
|
|
// self
|
|
incChained CALLDICT // self
|
|
}>
|
|
incChained3 PROC:<{
|
|
// self
|
|
incChained CALLDICT // self
|
|
}>
|
|
incChained4 PROC:<{
|
|
// self
|
|
incChained CALLDICT // self
|
|
}>
|
|
"""
|
|
|
|
@fif_codegen
|
|
"""
|
|
testIncChainedCodegen PROC:<{
|
|
// x
|
|
incChained CALLDICT // x
|
|
incChained2 CALLDICT // x
|
|
incChained3 CALLDICT // x
|
|
incChained4 CALLDICT // x
|
|
}>
|
|
"""
|
|
*/
|