Skip to content

Commit a2bd4d2

Browse files
committed
Prototype
finally some tests passing other passing tests fix edge cases fix edge cases cleaned up remove comment
1 parent 3f9c206 commit a2bd4d2

14 files changed

+1368
-135
lines changed

internal/analysis/check.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ const FnVarOriginBalance = "balance"
6161
const FnVarOriginOverdraft = "overdraft"
6262
const FnVarOriginGetAsset = "get_asset"
6363
const FnVarOriginGetAmount = "get_amount"
64+
const FnVarOriginVirtual = "virtual"
6465

6566
var Builtins = map[string]FnCallResolution{
6667
FnSetTxMeta: StatementFnCallResolution{
@@ -114,6 +115,18 @@ var Builtins = map[string]FnCallResolution{
114115
},
115116
},
116117
},
118+
FnVarOriginVirtual: VarOriginFnCallResolution{
119+
Params: []string{},
120+
Return: TypeAccount,
121+
Docs: "create a virtual account",
122+
VersionConstraints: []VersionClause{
123+
{
124+
// TODO flag
125+
Version: parser.NewVersionInterpreter(0, 0, 17),
126+
// FeatureFlag: flags.ExperimentalGetAmountFunctionFeatureFlag,
127+
},
128+
},
129+
},
117130
}
118131

119132
type Diagnostic struct {

internal/interpreter/args_parser_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func TestParseValid(t *testing.T) {
3636

3737
p := NewArgsParser([]Value{
3838
NewMonetaryInt(42),
39-
AccountAddress("user:001"),
39+
Account{Repr: AccountAddress("user:001")},
4040
})
4141
a1 := parseArg(p, parser.Range{}, expectNumber)
4242
a2 := parseArg(p, parser.Range{}, expectAccount)
@@ -47,16 +47,16 @@ func TestParseValid(t *testing.T) {
4747
require.NotNil(t, a1, "a1 should not be nil")
4848
require.NotNil(t, a2, "a2 should not be nil")
4949

50-
require.Equal(t, *a1, *big.NewInt(42))
51-
require.Equal(t, *a2, "user:001")
50+
require.Equal(t, *big.NewInt(42), *a1)
51+
require.Equal(t, Account{AccountAddress("user:001")}, *a2)
5252
}
5353

5454
func TestParseBadType(t *testing.T) {
5555
t.Parallel()
5656

5757
p := NewArgsParser([]Value{
5858
NewMonetaryInt(42),
59-
AccountAddress("user:001"),
59+
Account{Repr: AccountAddress("user:001")},
6060
})
6161
parseArg(p, parser.Range{}, expectMonetary)
6262
parseArg(p, parser.Range{}, expectAccount)

internal/interpreter/batch_balances_query.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ func (st *programState) findBalancesQueriesInStatement(statement parser.Statemen
3131
if err != nil {
3232
return err
3333
}
34-
st.batchQuery(*account, *asset, nil)
34+
35+
if account, ok := account.Repr.(AccountAddress); ok {
36+
st.batchQuery(string(account), *asset, nil)
37+
}
38+
3539
return nil
3640

3741
case *parser.SendStatement:
@@ -95,7 +99,10 @@ func (st *programState) findBalancesQueries(source parser.Source) InterpreterErr
9599
return err
96100
}
97101

98-
st.batchQuery(*account, st.CurrentAsset, color)
102+
if account, ok := account.Repr.(AccountAddress); ok {
103+
st.batchQuery(string(account), st.CurrentAsset, color)
104+
}
105+
99106
return nil
100107

101108
case *parser.SourceOverdraft:
@@ -113,7 +120,10 @@ func (st *programState) findBalancesQueries(source parser.Source) InterpreterErr
113120
return err
114121
}
115122

116-
st.batchQuery(*account, st.CurrentAsset, color)
123+
if account, ok := account.Repr.(AccountAddress); ok {
124+
st.batchQuery(string(account), st.CurrentAsset, color)
125+
}
126+
117127
return nil
118128

119129
case *parser.SourceInorder:

internal/interpreter/evaluate_expr.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ func (st *programState) divOp(rng parser.Range, left parser.ValueExpr, right par
216216

217217
func castToString(v Value, rng parser.Range) (string, InterpreterError) {
218218
switch v := v.(type) {
219-
case AccountAddress:
219+
case Account:
220220
return v.String(), nil
221221
case String:
222222
return v.String(), nil

internal/interpreter/function_exprs.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func overdraft(
1919

2020
// TODO more precise args range location
2121
p := NewArgsParser(args)
22-
account := parseArg(p, r, expectAccount)
22+
account := parseArg(p, r, expectAccountAddress) // TODO also handle virtual account
2323
asset := parseArg(p, r, expectAsset)
2424
err = p.parse()
2525
if err != nil {
@@ -53,7 +53,7 @@ func meta(
5353
) (string, InterpreterError) {
5454
// TODO more precise location
5555
p := NewArgsParser(args)
56-
account := parseArg(p, rng, expectAccount)
56+
account := parseArg(p, rng, expectAccountAddress)
5757
key := parseArg(p, rng, expectString)
5858
err := p.parse()
5959
if err != nil {
@@ -86,7 +86,7 @@ func balance(
8686
) (*Monetary, InterpreterError) {
8787
// TODO more precise args range location
8888
p := NewArgsParser(args)
89-
account := parseArg(p, r, expectAccount)
89+
account := parseArg(p, r, expectAccountAddress)
9090
asset := parseArg(p, r, expectAsset)
9191
err := p.parse()
9292
if err != nil {
@@ -102,7 +102,7 @@ func balance(
102102

103103
if balance.Cmp(big.NewInt(0)) == -1 {
104104
return nil, NegativeBalanceError{
105-
Account: *account,
105+
Account: Account{AccountAddress(*account)},
106106
Amount: *balance,
107107
}
108108
}
@@ -155,3 +155,7 @@ func getAmount(
155155

156156
return mon.Amount, nil
157157
}
158+
159+
func virtual() Value {
160+
return Account{Repr: NewVirtualAccount()}
161+
}

internal/interpreter/function_statements.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func setTxMeta(st *programState, r parser.Range, args []Value) InterpreterError
1717

1818
func setAccountMeta(st *programState, r parser.Range, args []Value) InterpreterError {
1919
p := NewArgsParser(args)
20-
account := parseArg(p, r, expectAccount)
20+
account := parseArg(p, r, expectAccountAddress)
2121
key := parseArg(p, r, expectString)
2222
meta := parseArg(p, r, expectAnything)
2323
err := p.parse()

internal/interpreter/funds_stack.go

Lines changed: 88 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import (
55
)
66

77
type Sender struct {
8-
Name string
9-
Amount *big.Int
10-
Color string
8+
Account AccountValue
9+
Amount *big.Int
10+
Color string
1111
}
1212

1313
type stack[T any] struct {
@@ -76,15 +76,15 @@ func (s *fundsStack) compactTop() {
7676
continue
7777
}
7878

79-
if first.Name != second.Name || first.Color != second.Color {
79+
if first.Account != second.Account || first.Color != second.Color {
8080
return
8181
}
8282

8383
s.senders = &stack[Sender]{
8484
Head: Sender{
85-
Name: first.Name,
86-
Color: first.Color,
87-
Amount: new(big.Int).Add(first.Amount, second.Amount),
85+
Account: first.Account,
86+
Color: first.Color,
87+
Amount: new(big.Int).Add(first.Amount, second.Amount),
8888
},
8989
Tail: s.senders.Tail.Tail,
9090
}
@@ -152,19 +152,19 @@ func (s *fundsStack) Pull(requiredAmount *big.Int, color *string) []Sender {
152152
case 1: // more than enough
153153
s.senders = &stack[Sender]{
154154
Head: Sender{
155-
Name: available.Name,
156-
Color: available.Color,
157-
Amount: new(big.Int).Sub(available.Amount, requiredAmount),
155+
Account: available.Account,
156+
Color: available.Color,
157+
Amount: new(big.Int).Sub(available.Amount, requiredAmount),
158158
},
159159
Tail: s.senders,
160160
}
161161
fallthrough
162162

163163
case 0: // exactly the same
164164
out = append(out, Sender{
165-
Name: available.Name,
166-
Color: available.Color,
167-
Amount: new(big.Int).Set(requiredAmount),
165+
Account: available.Account,
166+
Color: available.Color,
167+
Amount: new(big.Int).Set(requiredAmount),
168168
})
169169
return out
170170
}
@@ -186,3 +186,78 @@ func (s fundsStack) Clone() fundsStack {
186186

187187
return fs
188188
}
189+
190+
// Treat this stack as debts and filter out senders by "repaying" debts
191+
func (s *fundsStack) RepayWith(credits *fundsStack, asset string) []Posting {
192+
var postings []Posting
193+
194+
// for s.senders != nil {
195+
// // Peek head from debts and try to pull that much
196+
// hd := s.senders.Head
197+
198+
// senders := credits.Pull(hd.Amount, &hd.Color)
199+
// totalRepayed := big.NewInt(0)
200+
// for _, sender := range senders {
201+
// totalRepayed.Add(totalRepayed, sender.Amount)
202+
// postings = append(postings, Posting{
203+
// Source: sender.Account,
204+
// Destination: hd.Account,
205+
// Amount: sender.Amount,
206+
// Asset: coloredAsset(asset, &sender.Color),
207+
// })
208+
// }
209+
210+
// pulled := s.Pull(totalRepayed, &hd.Color)
211+
// if len(pulled) == 0 {
212+
// break
213+
// }
214+
215+
// // careful: infinite loops possible with different colors
216+
// // break
217+
// }
218+
219+
return postings
220+
}
221+
222+
// Treat this stack as debts and use the sender to repay debt.
223+
// Return the sender updated with the left amt (and the emitted postings)
224+
func (s *fundsStack) RepayWithSender(asset string, credit Sender) ([]Posting, Sender) {
225+
// clone the amount so that we can modify it
226+
credit.Amount = new(big.Int).Set(credit.Amount)
227+
228+
// Take away the debt that the credit allows for
229+
clearedDebt := s.PullColored(credit.Amount, credit.Color)
230+
231+
var postings []Posting
232+
233+
for _, receiver := range clearedDebt {
234+
switch creditAccount := credit.Account.(type) {
235+
case VirtualAccount:
236+
237+
// pulled := creditAccount.Pull(asset, nil, credit)
238+
// fmt.Printf("PULLED: %#v", credit)
239+
240+
panic("TODO handle vacc in credit scenario")
241+
242+
case AccountAddress:
243+
credit.Amount.Sub(credit.Amount, receiver.Amount)
244+
245+
switch receiverAccount := receiver.Account.(type) {
246+
case AccountAddress:
247+
postings = append(postings, Posting{
248+
Source: string(creditAccount),
249+
Destination: string(receiverAccount),
250+
Amount: receiver.Amount,
251+
Asset: coloredAsset(asset, &credit.Color),
252+
})
253+
254+
case VirtualAccount:
255+
panic("TODO repay vacc")
256+
}
257+
}
258+
259+
}
260+
261+
return postings, credit
262+
263+
}

0 commit comments

Comments
 (0)