@@ -871,9 +871,45 @@ func (vm *Vm) NotImplemented(name string, arg int32) {
871
871
fmt .Printf ("%s %d NOT IMPLEMENTED\n " , name , arg )
872
872
}
873
873
874
+ // setupCall sets function fnObj up for calling with args and kwargs
875
+ //
876
+ // if fnObj is Go code then it calls it and returns result, nil, nil
877
+ //
878
+ // if fnObj requires evaluation in the vm then it returns nil, locals, globals
879
+ //
880
+ // kwargs should be nil if not required
881
+ //
882
+ // fnObj must be a callable type such as *py.Method or *py.Function
883
+ //
884
+ // The result is returned
885
+ func setupCall (fnObj py.Object , args py.Tuple , kwargs py.StringDict ) (result py.Object , locals py.StringDict , pyfn * py.Function ) {
886
+ // fmt.Printf("setupCall %T %v with args = %v, kwargs = %v\n", fnObj, fnObj, args, kwargs)
887
+ switch fn := fnObj .(type ) {
888
+ case * py.Method :
889
+ self := py .None // FIXME should be the module
890
+ if kwargs != nil {
891
+ result = fn .CallWithKeywords (self , args , kwargs )
892
+ } else {
893
+ result = fn .Call (self , args )
894
+ }
895
+ case * py.Function :
896
+ pyfn = fn
897
+ if kwargs != nil {
898
+ locals = fn .LocalsForCallWithKeywords (args , kwargs )
899
+ } else {
900
+ locals = fn .LocalsForCall (args )
901
+ }
902
+ default :
903
+ // FIXME should be TypeError
904
+ panic (fmt .Sprintf ("TypeError: '%s' object is not callable" , fnObj .Type ().Name ))
905
+ }
906
+ return
907
+ }
908
+
874
909
// Calls function fn with args and kwargs
875
910
//
876
- // fn can be a string in which case it will be looked up or another callable type
911
+ // fn can be a string in which case it will be looked up or another
912
+ // callable type such as *py.Method or *py.Function
877
913
//
878
914
// kwargs is a sequence of name, value pairs
879
915
//
@@ -891,29 +927,19 @@ func (vm *Vm) Call(fnObj py.Object, args []py.Object, kwargs []py.Object) {
891
927
kwargsd [string (kwargs [i ].(py.String ))] = kwargs [i + 1 ]
892
928
}
893
929
}
894
- try_again:
895
- switch fn := fnObj .( type ) {
896
- case py.String :
930
+
931
+ // Lookup if string
932
+ if fn , ok := fnObj .( py.String ); ok {
897
933
fnObj = vm .frame .Lookup (string (fn ))
898
- goto try_again
899
- case * py.Method :
900
- self := py .None // FIXME should be the module
901
- if kwargsd != nil {
902
- vm .PUSH (fn .CallWithKeywords (self , args , kwargsd ))
903
- } else {
904
- vm .PUSH (fn .Call (self , args ))
905
- }
906
- case * py.Function :
907
- var locals py.StringDict
908
- if kwargsd != nil {
909
- locals = fn .LocalsForCallWithKeywords (args , kwargsd )
910
- } else {
911
- locals = fn .LocalsForCall (args )
912
- }
913
- vm .PushFrame (vm .frame .Globals , locals , fn .Code )
914
- default :
915
- // FIXME should be TypeError
916
- panic (fmt .Sprintf ("TypeError: '%s' object is not callable" , fnObj .Type ().Name ))
934
+ }
935
+
936
+ // Call or setup for the call
937
+ result , locals , fn := setupCall (fnObj , args , kwargsd )
938
+ // fmt.Printf("setupCall returned %v, %v, %v\n", result, locals, fn)
939
+ if fn == nil {
940
+ vm .PUSH (result )
941
+ } else {
942
+ vm .PushFrame (fn .Globals , locals , fn .Code )
917
943
}
918
944
}
919
945
@@ -944,7 +970,9 @@ func (vm *Vm) PopFrame() {
944
970
// FIXME figure out how we are going to signal exceptions!
945
971
//
946
972
// Any parameters are expected to have been decoded into locals
947
- func Run (globals , locals py.StringDict , code * py.Code ) (err error ) {
973
+ //
974
+ // Returns an Object and an error
975
+ func Run (globals , locals py.StringDict , code * py.Code ) (res py.Object , err error ) {
948
976
vm := NewVm ()
949
977
defer func () {
950
978
if r := recover (); r != nil {
@@ -988,6 +1016,26 @@ func Run(globals, locals py.StringDict, code *py.Code) (err error) {
988
1016
fmt .Printf ("vmstack = %#v\n " , vm .stack )
989
1017
panic ("vm stack should only have 1 entry on at this point" )
990
1018
}
991
- // return vm.POP()
992
- return nil
1019
+ return vm .POP (), nil
1020
+ }
1021
+
1022
+ // Calls function fnObj with args and kwargs in a new vm (or directly
1023
+ // if Go code)
1024
+ //
1025
+ // kwargs should be nil if not required
1026
+ //
1027
+ // fnObj must be a callable type such as *py.Method or *py.Function
1028
+ //
1029
+ // The result is returned
1030
+ func Call (fnObj py.Object , args py.Tuple , kwargs py.StringDict ) py.Object {
1031
+ result , locals , fn := setupCall (fnObj , args , kwargs )
1032
+ if result == nil {
1033
+ var err error
1034
+ result , err = Run (fn .Globals , locals , fn .Code )
1035
+ if err != nil {
1036
+ // FIXME - do what exactly!
1037
+ panic (err )
1038
+ }
1039
+ }
1040
+ return result
993
1041
}
0 commit comments