From 452d1cbb4709b190226eb4b08e1e74cffd1d9beb Mon Sep 17 00:00:00 2001 From: ascandone Date: Tue, 21 Jan 2025 00:53:49 +0100 Subject: [PATCH] implemented oneof in destination --- internal/interpreter/interpreter.go | 21 +++++++ internal/interpreter/interpreter_test.go | 77 ++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/internal/interpreter/interpreter.go b/internal/interpreter/interpreter.go index 5ef54d2..d2afd2e 100644 --- a/internal/interpreter/interpreter.go +++ b/internal/interpreter/interpreter.go @@ -715,6 +715,27 @@ func (s *programState) receiveFrom(destination parser.Destination, amount *big.I // passing "remainingAmount" directly breaks the code return handler(destination.Remaining, remainingAmountCopy) + case *parser.DestinationOneof: + err := s.checkFeatureFlag(ExperimentalOneofFeatureFlag) + if err != nil { + return err + } + for _, destinationClause := range destination.Clauses { + cap, err := evaluateExprAs(s, destinationClause.Cap, expectMonetaryOfAsset(s.CurrentAsset)) + if err != nil { + return err + } + + // if the clause cap is >= the amount we're trying to receive, only go through this branch + switch cap.Cmp(amount) { + case 0, 1: + return s.receiveFromKeptOrDest(destinationClause.To, amount) + } + + // otherwise try next clause (keep looping) + } + return s.receiveFromKeptOrDest(destination.Remaining, amount) + default: utils.NonExhaustiveMatchPanic[any](destination) return nil diff --git a/internal/interpreter/interpreter_test.go b/internal/interpreter/interpreter_test.go index a3a88ed..4988b22 100644 --- a/internal/interpreter/interpreter_test.go +++ b/internal/interpreter/interpreter_test.go @@ -3666,3 +3666,80 @@ func TestOneofSingleton(t *testing.T) { } testWithFeatureFlag(t, tc, machine.ExperimentalOneofFeatureFlag) } + +func TestOneofDestinationFirstClause(t *testing.T) { + tc := NewTestCase() + tc.compile(t, ` + send [GEM 10] ( + source = @world + destination = oneof { + max [GEM 99999] to @a + remaining to @b + } + ) + `) + tc.expected = CaseResult{ + Postings: []Posting{ + { + Asset: "GEM", + Amount: big.NewInt(10), + Source: "world", + Destination: "a", + }, + }, + Error: nil, + } + testWithFeatureFlag(t, tc, machine.ExperimentalOneofFeatureFlag) +} + +func TestOneofDestinationSecondClause(t *testing.T) { + tc := NewTestCase() + tc.compile(t, ` + send [GEM 10] ( + source = @world + destination = oneof { + max [GEM 9] to @a + max [GEM 10] to @b + remaining to @rem + } + ) + `) + tc.expected = CaseResult{ + Postings: []Posting{ + { + Asset: "GEM", + Amount: big.NewInt(10), + Source: "world", + Destination: "b", + }, + }, + Error: nil, + } + testWithFeatureFlag(t, tc, machine.ExperimentalOneofFeatureFlag) +} + +func TestOneofDestinationRemainingClause(t *testing.T) { + tc := NewTestCase() + tc.compile(t, ` + send [GEM 100] ( + source = @world + destination = oneof { + max [GEM 9] to @a + max [GEM 10] to @b + remaining to @rem + } + ) + `) + tc.expected = CaseResult{ + Postings: []Posting{ + { + Asset: "GEM", + Amount: big.NewInt(100), + Source: "world", + Destination: "rem", + }, + }, + Error: nil, + } + testWithFeatureFlag(t, tc, machine.ExperimentalOneofFeatureFlag) +}