16
16
package decls
17
17
18
18
import (
19
+ "context"
19
20
"fmt"
20
21
"strings"
21
22
@@ -242,23 +243,23 @@ func (f *FunctionDecl) Bindings() ([]*functions.Overload, error) {
242
243
// All of the defined overloads are wrapped into a top-level function which
243
244
// performs dynamic dispatch to the proper overload based on the argument types.
244
245
bindings := append ([]* functions.Overload {}, overloads ... )
245
- funcDispatch := func (args ... ref.Val ) ref.Val {
246
+ funcDispatch := func (ctx context. Context , args ... ref.Val ) ref.Val {
246
247
for _ , oID := range f .overloadOrdinals {
247
248
o := f .overloads [oID ]
248
249
// During dynamic dispatch over multiple functions, signature agreement checks
249
250
// are preserved in order to assist with the function resolution step.
250
251
switch len (args ) {
251
252
case 1 :
252
253
if o .unaryOp != nil && o .matchesRuntimeSignature ( /* disableTypeGuards=*/ false , args ... ) {
253
- return o .unaryOp (args [0 ])
254
+ return o .unaryOp (ctx , args [0 ])
254
255
}
255
256
case 2 :
256
257
if o .binaryOp != nil && o .matchesRuntimeSignature ( /* disableTypeGuards=*/ false , args ... ) {
257
- return o .binaryOp (args [0 ], args [1 ])
258
+ return o .binaryOp (ctx , args [0 ], args [1 ])
258
259
}
259
260
}
260
261
if o .functionOp != nil && o .matchesRuntimeSignature ( /* disableTypeGuards=*/ false , args ... ) {
261
- return o .functionOp (args ... )
262
+ return o .functionOp (ctx , args ... )
262
263
}
263
264
// eventually this will fall through to the noSuchOverload below.
264
265
}
@@ -333,8 +334,10 @@ func SingletonUnaryBinding(fn functions.UnaryOp, traits ...int) FunctionOpt {
333
334
return nil , fmt .Errorf ("function already has a singleton binding: %s" , f .Name ())
334
335
}
335
336
f .singleton = & functions.Overload {
336
- Operator : f .Name (),
337
- Unary : fn ,
337
+ Operator : f .Name (),
338
+ Unary : func (ctx context.Context , val ref.Val ) ref.Val {
339
+ return fn (val )
340
+ },
338
341
OperandTrait : trait ,
339
342
}
340
343
return f , nil
@@ -355,8 +358,10 @@ func SingletonBinaryBinding(fn functions.BinaryOp, traits ...int) FunctionOpt {
355
358
return nil , fmt .Errorf ("function already has a singleton binding: %s" , f .Name ())
356
359
}
357
360
f .singleton = & functions.Overload {
358
- Operator : f .Name (),
359
- Binary : fn ,
361
+ Operator : f .Name (),
362
+ Binary : func (ctx context.Context , lhs ref.Val , rhs ref.Val ) ref.Val {
363
+ return fn (lhs , rhs )
364
+ },
360
365
OperandTrait : trait ,
361
366
}
362
367
return f , nil
@@ -377,8 +382,10 @@ func SingletonFunctionBinding(fn functions.FunctionOp, traits ...int) FunctionOp
377
382
return nil , fmt .Errorf ("function already has a singleton binding: %s" , f .Name ())
378
383
}
379
384
f .singleton = & functions.Overload {
380
- Operator : f .Name (),
381
- Function : fn ,
385
+ Operator : f .Name (),
386
+ Function : func (ctx context.Context , values ... ref.Val ) ref.Val {
387
+ return fn (values ... )
388
+ },
382
389
OperandTrait : trait ,
383
390
}
384
391
return f , nil
@@ -460,11 +467,11 @@ type OverloadDecl struct {
460
467
461
468
// Function implementation options. Optional, but encouraged.
462
469
// unaryOp is a function binding that takes a single argument.
463
- unaryOp functions.UnaryOp
470
+ unaryOp functions.UnaryContextOp
464
471
// binaryOp is a function binding that takes two arguments.
465
- binaryOp functions.BinaryOp
472
+ binaryOp functions.BinaryContextOp
466
473
// functionOp is a catch-all for zero-arity and three-plus arity functions.
467
- functionOp functions.FunctionOp
474
+ functionOp functions.FunctionContextOp
468
475
}
469
476
470
477
// ID mirrors the overload signature and provides a unique id which may be referenced within the type-checker
@@ -580,41 +587,41 @@ func (o *OverloadDecl) hasBinding() bool {
580
587
}
581
588
582
589
// guardedUnaryOp creates an invocation guard around the provided unary operator, if one is defined.
583
- func (o * OverloadDecl ) guardedUnaryOp (funcName string , disableTypeGuards bool ) functions.UnaryOp {
590
+ func (o * OverloadDecl ) guardedUnaryOp (funcName string , disableTypeGuards bool ) functions.UnaryContextOp {
584
591
if o .unaryOp == nil {
585
592
return nil
586
593
}
587
- return func (arg ref.Val ) ref.Val {
594
+ return func (ctx context. Context , arg ref.Val ) ref.Val {
588
595
if ! o .matchesRuntimeUnarySignature (disableTypeGuards , arg ) {
589
596
return MaybeNoSuchOverload (funcName , arg )
590
597
}
591
- return o .unaryOp (arg )
598
+ return o .unaryOp (ctx , arg )
592
599
}
593
600
}
594
601
595
602
// guardedBinaryOp creates an invocation guard around the provided binary operator, if one is defined.
596
- func (o * OverloadDecl ) guardedBinaryOp (funcName string , disableTypeGuards bool ) functions.BinaryOp {
603
+ func (o * OverloadDecl ) guardedBinaryOp (funcName string , disableTypeGuards bool ) functions.BinaryContextOp {
597
604
if o .binaryOp == nil {
598
605
return nil
599
606
}
600
- return func (arg1 , arg2 ref.Val ) ref.Val {
607
+ return func (ctx context. Context , arg1 , arg2 ref.Val ) ref.Val {
601
608
if ! o .matchesRuntimeBinarySignature (disableTypeGuards , arg1 , arg2 ) {
602
609
return MaybeNoSuchOverload (funcName , arg1 , arg2 )
603
610
}
604
- return o .binaryOp (arg1 , arg2 )
611
+ return o .binaryOp (ctx , arg1 , arg2 )
605
612
}
606
613
}
607
614
608
615
// guardedFunctionOp creates an invocation guard around the provided variadic function binding, if one is provided.
609
- func (o * OverloadDecl ) guardedFunctionOp (funcName string , disableTypeGuards bool ) functions.FunctionOp {
616
+ func (o * OverloadDecl ) guardedFunctionOp (funcName string , disableTypeGuards bool ) functions.FunctionContextOp {
610
617
if o .functionOp == nil {
611
618
return nil
612
619
}
613
- return func (args ... ref.Val ) ref.Val {
620
+ return func (ctx context. Context , args ... ref.Val ) ref.Val {
614
621
if ! o .matchesRuntimeSignature (disableTypeGuards , args ... ) {
615
622
return MaybeNoSuchOverload (funcName , args ... )
616
623
}
617
- return o .functionOp (args ... )
624
+ return o .functionOp (ctx , args ... )
618
625
}
619
626
}
620
627
@@ -667,6 +674,30 @@ type OverloadOpt func(*OverloadDecl) (*OverloadDecl, error)
667
674
// UnaryBinding provides the implementation of a unary overload. The provided function is protected by a runtime
668
675
// type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
669
676
func UnaryBinding (binding functions.UnaryOp ) OverloadOpt {
677
+ return UnaryBindingContext (func (ctx context.Context , val ref.Val ) ref.Val {
678
+ return binding (val )
679
+ })
680
+ }
681
+
682
+ // BinaryBinding provides the implementation of a binary overload. The provided function is protected by a runtime
683
+ // type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
684
+ func BinaryBinding (binding functions.BinaryOp ) OverloadOpt {
685
+ return BinaryBindingContext (func (ctx context.Context , lhs ref.Val , rhs ref.Val ) ref.Val {
686
+ return binding (lhs , rhs )
687
+ })
688
+ }
689
+
690
+ // FunctionBinding provides the implementation of a variadic overload. The provided function is protected by a runtime
691
+ // type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
692
+ func FunctionBinding (binding functions.FunctionOp ) OverloadOpt {
693
+ return FunctionBindingContext (func (ctx context.Context , values ... ref.Val ) ref.Val {
694
+ return binding (values ... )
695
+ })
696
+ }
697
+
698
+ // UnaryBindingContext provides the implementation of a unary overload. The provided function is protected by a runtime
699
+ // type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
700
+ func UnaryBindingContext (binding functions.UnaryContextOp ) OverloadOpt {
670
701
return func (o * OverloadDecl ) (* OverloadDecl , error ) {
671
702
if o .hasBinding () {
672
703
return nil , fmt .Errorf ("overload already has a binding: %s" , o .ID ())
@@ -679,9 +710,9 @@ func UnaryBinding(binding functions.UnaryOp) OverloadOpt {
679
710
}
680
711
}
681
712
682
- // BinaryBinding provides the implementation of a binary overload. The provided function is protected by a runtime
713
+ // BinaryBindingContext provides the implementation of a binary overload. The provided function is protected by a runtime
683
714
// type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
684
- func BinaryBinding (binding functions.BinaryOp ) OverloadOpt {
715
+ func BinaryBindingContext (binding functions.BinaryContextOp ) OverloadOpt {
685
716
return func (o * OverloadDecl ) (* OverloadDecl , error ) {
686
717
if o .hasBinding () {
687
718
return nil , fmt .Errorf ("overload already has a binding: %s" , o .ID ())
@@ -694,9 +725,9 @@ func BinaryBinding(binding functions.BinaryOp) OverloadOpt {
694
725
}
695
726
}
696
727
697
- // FunctionBinding provides the implementation of a variadic overload. The provided function is protected by a runtime
728
+ // FunctionBindingContext provides the implementation of a variadic overload. The provided function is protected by a runtime
698
729
// type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
699
- func FunctionBinding (binding functions.FunctionOp ) OverloadOpt {
730
+ func FunctionBindingContext (binding functions.FunctionContextOp ) OverloadOpt {
700
731
return func (o * OverloadDecl ) (* OverloadDecl , error ) {
701
732
if o .hasBinding () {
702
733
return nil , fmt .Errorf ("overload already has a binding: %s" , o .ID ())
0 commit comments