1616package decls
1717
1818import (
19+ "context"
1920 "fmt"
2021 "strings"
2122
@@ -242,23 +243,23 @@ func (f *FunctionDecl) Bindings() ([]*functions.Overload, error) {
242243 // All of the defined overloads are wrapped into a top-level function which
243244 // performs dynamic dispatch to the proper overload based on the argument types.
244245 bindings := append ([]* functions.Overload {}, overloads ... )
245- funcDispatch := func (args ... ref.Val ) ref.Val {
246+ funcDispatch := func (ctx context. Context , args ... ref.Val ) ref.Val {
246247 for _ , oID := range f .overloadOrdinals {
247248 o := f .overloads [oID ]
248249 // During dynamic dispatch over multiple functions, signature agreement checks
249250 // are preserved in order to assist with the function resolution step.
250251 switch len (args ) {
251252 case 1 :
252253 if o .unaryOp != nil && o .matchesRuntimeSignature ( /* disableTypeGuards=*/ false , args ... ) {
253- return o .unaryOp (args [0 ])
254+ return o .unaryOp (ctx , args [0 ])
254255 }
255256 case 2 :
256257 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 ])
258259 }
259260 }
260261 if o .functionOp != nil && o .matchesRuntimeSignature ( /* disableTypeGuards=*/ false , args ... ) {
261- return o .functionOp (args ... )
262+ return o .functionOp (ctx , args ... )
262263 }
263264 // eventually this will fall through to the noSuchOverload below.
264265 }
@@ -333,8 +334,10 @@ func SingletonUnaryBinding(fn functions.UnaryOp, traits ...int) FunctionOpt {
333334 return nil , fmt .Errorf ("function already has a singleton binding: %s" , f .Name ())
334335 }
335336 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+ },
338341 OperandTrait : trait ,
339342 }
340343 return f , nil
@@ -355,8 +358,10 @@ func SingletonBinaryBinding(fn functions.BinaryOp, traits ...int) FunctionOpt {
355358 return nil , fmt .Errorf ("function already has a singleton binding: %s" , f .Name ())
356359 }
357360 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+ },
360365 OperandTrait : trait ,
361366 }
362367 return f , nil
@@ -377,8 +382,10 @@ func SingletonFunctionBinding(fn functions.FunctionOp, traits ...int) FunctionOp
377382 return nil , fmt .Errorf ("function already has a singleton binding: %s" , f .Name ())
378383 }
379384 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+ },
382389 OperandTrait : trait ,
383390 }
384391 return f , nil
@@ -460,11 +467,11 @@ type OverloadDecl struct {
460467
461468 // Function implementation options. Optional, but encouraged.
462469 // unaryOp is a function binding that takes a single argument.
463- unaryOp functions.UnaryOp
470+ unaryOp functions.UnaryContextOp
464471 // binaryOp is a function binding that takes two arguments.
465- binaryOp functions.BinaryOp
472+ binaryOp functions.BinaryContextOp
466473 // functionOp is a catch-all for zero-arity and three-plus arity functions.
467- functionOp functions.FunctionOp
474+ functionOp functions.FunctionContextOp
468475}
469476
470477// 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 {
580587}
581588
582589// 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 {
584591 if o .unaryOp == nil {
585592 return nil
586593 }
587- return func (arg ref.Val ) ref.Val {
594+ return func (ctx context. Context , arg ref.Val ) ref.Val {
588595 if ! o .matchesRuntimeUnarySignature (disableTypeGuards , arg ) {
589596 return MaybeNoSuchOverload (funcName , arg )
590597 }
591- return o .unaryOp (arg )
598+ return o .unaryOp (ctx , arg )
592599 }
593600}
594601
595602// 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 {
597604 if o .binaryOp == nil {
598605 return nil
599606 }
600- return func (arg1 , arg2 ref.Val ) ref.Val {
607+ return func (ctx context. Context , arg1 , arg2 ref.Val ) ref.Val {
601608 if ! o .matchesRuntimeBinarySignature (disableTypeGuards , arg1 , arg2 ) {
602609 return MaybeNoSuchOverload (funcName , arg1 , arg2 )
603610 }
604- return o .binaryOp (arg1 , arg2 )
611+ return o .binaryOp (ctx , arg1 , arg2 )
605612 }
606613}
607614
608615// 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 {
610617 if o .functionOp == nil {
611618 return nil
612619 }
613- return func (args ... ref.Val ) ref.Val {
620+ return func (ctx context. Context , args ... ref.Val ) ref.Val {
614621 if ! o .matchesRuntimeSignature (disableTypeGuards , args ... ) {
615622 return MaybeNoSuchOverload (funcName , args ... )
616623 }
617- return o .functionOp (args ... )
624+ return o .functionOp (ctx , args ... )
618625 }
619626}
620627
@@ -667,6 +674,30 @@ type OverloadOpt func(*OverloadDecl) (*OverloadDecl, error)
667674// UnaryBinding provides the implementation of a unary overload. The provided function is protected by a runtime
668675// type-guard which ensures runtime type agreement between the overload signature and runtime argument types.
669676func 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 {
670701 return func (o * OverloadDecl ) (* OverloadDecl , error ) {
671702 if o .hasBinding () {
672703 return nil , fmt .Errorf ("overload already has a binding: %s" , o .ID ())
@@ -679,9 +710,9 @@ func UnaryBinding(binding functions.UnaryOp) OverloadOpt {
679710 }
680711}
681712
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
683714// 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 {
685716 return func (o * OverloadDecl ) (* OverloadDecl , error ) {
686717 if o .hasBinding () {
687718 return nil , fmt .Errorf ("overload already has a binding: %s" , o .ID ())
@@ -694,9 +725,9 @@ func BinaryBinding(binding functions.BinaryOp) OverloadOpt {
694725 }
695726}
696727
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
698729// 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 {
700731 return func (o * OverloadDecl ) (* OverloadDecl , error ) {
701732 if o .hasBinding () {
702733 return nil , fmt .Errorf ("overload already has a binding: %s" , o .ID ())
0 commit comments