Skip to content

Commit d43d685

Browse files
committed
cache capability scope builtins for contract rebinding
1 parent 9a78523 commit d43d685

4 files changed

Lines changed: 31 additions & 8 deletions

File tree

vibes/capability_contracts_scanner.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ func (s *capabilityContractScanner) bindContracts(
5151
if _, skip := s.excluded[builtin]; skip {
5252
return
5353
}
54+
if scope != nil && scope.knownBuiltins != nil {
55+
scope.knownBuiltins[builtin] = struct{}{}
56+
}
5457
ownerScope, seen := scopes[builtin]
5558
if !seen {
5659
scopes[builtin] = scope

vibes/execution.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ type Execution struct {
5959
}
6060

6161
type capabilityContractScope struct {
62-
contracts map[string]CapabilityMethodContract
63-
roots []Value
62+
contracts map[string]CapabilityMethodContract
63+
roots []Value
64+
knownBuiltins map[*Builtin]struct{}
6465
}
6566

6667
type moduleContext struct {

vibes/execution_call_capabilities.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ func bindCapabilitiesForCall(exec *Execution, root *Env, rebinder *callFunctionR
2525
continue
2626
}
2727
scope := &capabilityContractScope{
28-
contracts: map[string]CapabilityMethodContract{},
28+
contracts: map[string]CapabilityMethodContract{},
29+
knownBuiltins: make(map[*Builtin]struct{}),
2930
}
3031
if provider, ok := adapter.(CapabilityContractProvider); ok {
3132
for methodName, contract := range provider.CapabilityContracts() {

vibes/execution_calls.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ import (
44
"errors"
55
)
66

7+
func valueCanContainBuiltins(val Value) bool {
8+
switch val.Kind() {
9+
case KindBuiltin, KindArray, KindHash, KindObject, KindClass, KindInstance:
10+
return true
11+
default:
12+
return false
13+
}
14+
}
15+
716
func (exec *Execution) autoInvokeIfNeeded(expr Expression, val Value, receiver Value) (Value, error) {
817
switch val.Kind() {
918
case KindFunction:
@@ -39,18 +48,21 @@ func (exec *Execution) invokeCallable(callee Value, receiver Value, args []Value
3948
scope := exec.capabilityContractScopes[builtin]
4049
var preCallKnownBuiltins map[*Builtin]struct{}
4150
if scope != nil && len(scope.contracts) > 0 {
42-
preCallKnownBuiltins = make(map[*Builtin]struct{})
51+
preCallKnownBuiltins = scope.knownBuiltins
4352
preCallScanner := newCapabilityContractScanner()
44-
if receiver.Kind() != KindNil {
53+
if valueCanContainBuiltins(receiver) {
4554
preCallScanner.collectBuiltins(receiver, preCallKnownBuiltins)
4655
}
47-
for _, root := range scope.roots {
48-
preCallScanner.collectBuiltins(root, preCallKnownBuiltins)
49-
}
5056
for _, arg := range args {
57+
if !valueCanContainBuiltins(arg) {
58+
continue
59+
}
5160
preCallScanner.collectBuiltins(arg, preCallKnownBuiltins)
5261
}
5362
for _, kwarg := range kwargs {
63+
if !valueCanContainBuiltins(kwarg) {
64+
continue
65+
}
5466
preCallScanner.collectBuiltins(kwarg, preCallKnownBuiltins)
5567
}
5668
}
@@ -94,9 +106,15 @@ func (exec *Execution) invokeCallable(callee Value, receiver Value, args []Value
94106
// Methods can also publish builtins by mutating positional or keyword
95107
// argument objects supplied by script code.
96108
for _, arg := range args {
109+
if !valueCanContainBuiltins(arg) {
110+
continue
111+
}
97112
postCallScanner.bindContracts(arg, scope, exec.capabilityContracts, exec.capabilityContractScopes)
98113
}
99114
for _, kwarg := range kwargs {
115+
if !valueCanContainBuiltins(kwarg) {
116+
continue
117+
}
100118
postCallScanner.bindContracts(kwarg, scope, exec.capabilityContracts, exec.capabilityContractScopes)
101119
}
102120
}

0 commit comments

Comments
 (0)