diff --git a/src/funcs.c b/src/funcs.c index bd1831065a..bb480bec55 100644 --- a/src/funcs.c +++ b/src/funcs.c @@ -98,7 +98,9 @@ UInt ExecProccallOpts( ** ** 'ExecProccallargs' executes a procedure call to the function ** 'FUNC_CALL()' with the arguments 'ARGI_CALL(,1)' to -** 'ARGI_CALL(,)'. It returns the value returned by the function. +** 'ARGI_CALL(,)'. It discards the value returned by the function +** and returns the statement execution status (as per EXEC_STAT, q.v.) +** resulting from the procedure call, which in fact is always 0. */ static Obj DispatchFuncCall( Obj func, Int nargs, Obj arg1, Obj arg2, Obj arg3, Obj arg4, Obj arg5, Obj arg6) @@ -168,10 +170,10 @@ UInt ExecProccall1args ( arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) ); /* call the function */ + SET_BRK_CALL_TO( call ); if (TNUM_OBJ(func) != T_FUNCTION) DispatchFuncCall(func, 1, (Obj) arg1, (Obj) 0L, (Obj) 0L, (Obj) 0L, (Obj) 0L, (Obj) 0L); else { - SET_BRK_CALL_TO( call ); CALL_1ARGS( func, arg1 ); } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called @@ -198,10 +200,10 @@ UInt ExecProccall2args ( arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) ); /* call the function */ + SET_BRK_CALL_TO( call ); if (TNUM_OBJ(func) != T_FUNCTION) DispatchFuncCall(func, 2, (Obj) arg1, (Obj) arg2, (Obj) 0L, (Obj) 0L, (Obj) 0L, (Obj) 0L); else { - SET_BRK_CALL_TO( call ); CALL_2ARGS( func, arg1, arg2 ); } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called @@ -230,10 +232,10 @@ UInt ExecProccall3args ( arg3 = EVAL_EXPR( ARGI_CALL( call, 3 ) ); /* call the function */ + SET_BRK_CALL_TO( call ); if (TNUM_OBJ(func) != T_FUNCTION) DispatchFuncCall(func, 3, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) 0L, (Obj) 0L, (Obj) 0L); else { - SET_BRK_CALL_TO( call ); CALL_3ARGS( func, arg1, arg2, arg3 ); } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called @@ -264,10 +266,10 @@ UInt ExecProccall4args ( arg4 = EVAL_EXPR( ARGI_CALL( call, 4 ) ); /* call the function */ + SET_BRK_CALL_TO( call ); if (TNUM_OBJ(func) != T_FUNCTION) DispatchFuncCall(func, 4, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) 0, (Obj) 0); else { - SET_BRK_CALL_TO( call ); CALL_4ARGS( func, arg1, arg2, arg3, arg4 ); } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called @@ -300,10 +302,10 @@ UInt ExecProccall5args ( arg5 = EVAL_EXPR( ARGI_CALL( call, 5 ) ); /* call the function */ + SET_BRK_CALL_TO( call ); if (TNUM_OBJ(func) != T_FUNCTION) DispatchFuncCall(func, 5, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) arg5, (Obj) 0L); else { - SET_BRK_CALL_TO( call ); CALL_5ARGS( func, arg1, arg2, arg3, arg4, arg5 ); } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called @@ -338,10 +340,10 @@ UInt ExecProccall6args ( arg6 = EVAL_EXPR( ARGI_CALL( call, 6 ) ); /* call the function */ + SET_BRK_CALL_TO( call ); if (TNUM_OBJ(func) != T_FUNCTION) DispatchFuncCall(func, 6, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) arg5, (Obj) arg6); else { - SET_BRK_CALL_TO( call ); CALL_6ARGS( func, arg1, arg2, arg3, arg4, arg5, arg6 ); } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called @@ -375,10 +377,10 @@ UInt ExecProccallXargs ( } /* call the function */ + SET_BRK_CALL_TO( call ); if (TNUM_OBJ(func) != T_FUNCTION) { DoOperation2Args(CallFuncListOper, func, args); } else { - SET_BRK_CALL_TO( call ); CALL_XARGS( func, args ); } @@ -441,13 +443,13 @@ Obj EvalFunccall0args ( /* evaluate the function */ func = EVAL_EXPR( FUNC_CALL( call ) ); - if (TNUM_OBJ(func) != T_FUNCTION) { - return DispatchFuncCall(func, 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 ); - } - /* call the function and return the result */ SET_BRK_CALL_TO( call ); - result = CALL_0ARGS( func ); + if (TNUM_OBJ(func) != T_FUNCTION) { + result = DispatchFuncCall(func, 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 ); + } else { + result = CALL_0ARGS( func ); + } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called READ() and the user quit from a break loop inside it */ @@ -473,13 +475,13 @@ Obj EvalFunccall1args ( /* evaluate the arguments */ arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) ); - if (TNUM_OBJ(func) != T_FUNCTION) { - return DispatchFuncCall(func, 1, (Obj) arg1, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 ); - } - /* call the function and return the result */ SET_BRK_CALL_TO( call ); - result = CALL_1ARGS( func, arg1 ); + if (TNUM_OBJ(func) != T_FUNCTION) { + result = DispatchFuncCall(func, 1, (Obj) arg1, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 ); + } else { + result = CALL_1ARGS( func, arg1 ); + } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called READ() and the user quit from a break loop inside it */ @@ -508,13 +510,13 @@ Obj EvalFunccall2args ( arg1 = EVAL_EXPR( ARGI_CALL( call, 1 ) ); arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) ); - if (TNUM_OBJ(func) != T_FUNCTION) { - return DispatchFuncCall(func, 2, (Obj) arg1, (Obj) arg2, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 ); - } - /* call the function and return the result */ SET_BRK_CALL_TO( call ); - result = CALL_2ARGS( func, arg1, arg2 ); + if (TNUM_OBJ(func) != T_FUNCTION) { + result = DispatchFuncCall(func, 2, (Obj) arg1, (Obj) arg2, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 ); + } else { + result = CALL_2ARGS( func, arg1, arg2 ); + } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called READ() and the user quit from a break loop inside it */ @@ -545,13 +547,13 @@ Obj EvalFunccall3args ( arg2 = EVAL_EXPR( ARGI_CALL( call, 2 ) ); arg3 = EVAL_EXPR( ARGI_CALL( call, 3 ) ); - if (TNUM_OBJ(func) != T_FUNCTION) { - return DispatchFuncCall(func, 3, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) 0, (Obj) 0, (Obj) 0 ); - } - /* call the function and return the result */ SET_BRK_CALL_TO( call ); - result = CALL_3ARGS( func, arg1, arg2, arg3 ); + if (TNUM_OBJ(func) != T_FUNCTION) { + result = DispatchFuncCall(func, 3, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) 0, (Obj) 0, (Obj) 0 ); + } else { + result = CALL_3ARGS( func, arg1, arg2, arg3 ); + } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called READ() and the user quit from a break loop inside it */ @@ -583,13 +585,13 @@ Obj EvalFunccall4args ( arg3 = EVAL_EXPR( ARGI_CALL( call, 3 ) ); arg4 = EVAL_EXPR( ARGI_CALL( call, 4 ) ); - if (TNUM_OBJ(func) != T_FUNCTION) { - return DispatchFuncCall(func, 4, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) 0, (Obj) 0 ); - } - /* call the function and return the result */ SET_BRK_CALL_TO( call ); - result = CALL_4ARGS( func, arg1, arg2, arg3, arg4 ); + if (TNUM_OBJ(func) != T_FUNCTION) { + result = DispatchFuncCall(func, 4, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) 0, (Obj) 0 ); + } else { + result = CALL_4ARGS( func, arg1, arg2, arg3, arg4 ); + } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called READ() and the user quit from a break loop inside it */ @@ -624,13 +626,13 @@ Obj EvalFunccall5args ( arg4 = EVAL_EXPR( ARGI_CALL( call, 4 ) ); arg5 = EVAL_EXPR( ARGI_CALL( call, 5 ) ); - if (TNUM_OBJ(func) != T_FUNCTION) { - return DispatchFuncCall(func, 5, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) arg5, (Obj) 0 ); - } - /* call the function and return the result */ SET_BRK_CALL_TO( call ); - result = CALL_5ARGS( func, arg1, arg2, arg3, arg4, arg5 ); + if (TNUM_OBJ(func) != T_FUNCTION) { + result = DispatchFuncCall(func, 5, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) arg5, (Obj) 0 ); + } else { + result = CALL_5ARGS( func, arg1, arg2, arg3, arg4, arg5 ); + } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called READ() and the user quit from a break loop inside it */ @@ -667,13 +669,13 @@ Obj EvalFunccall6args ( arg5 = EVAL_EXPR( ARGI_CALL( call, 5 ) ); arg6 = EVAL_EXPR( ARGI_CALL( call, 6 ) ); - if (TNUM_OBJ(func) != T_FUNCTION) { - return DispatchFuncCall(func, 6, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) arg5, (Obj) arg6 ); - } - /* call the function and return the result */ SET_BRK_CALL_TO( call ); - result = CALL_6ARGS( func, arg1, arg2, arg3, arg4, arg5, arg6 ); + if (TNUM_OBJ(func) != T_FUNCTION) { + result = DispatchFuncCall(func, 6, (Obj) arg1, (Obj) arg2, (Obj) arg3, (Obj) arg4, (Obj) arg5, (Obj) arg6 ); + } else { + result = CALL_6ARGS( func, arg1, arg2, arg3, arg4, arg5, arg6 ); + } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called READ() and the user quit from a break loop inside it */ @@ -708,13 +710,13 @@ Obj EvalFunccallXargs ( CHANGED_BAG( args ); } - if (TNUM_OBJ(func) != T_FUNCTION) { - return DispatchFuncCall(func, -1, (Obj) args, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 ); - } - /* call the function and return the result */ SET_BRK_CALL_TO( call ); - result = CALL_XARGS( func, args ); + if (TNUM_OBJ(func) != T_FUNCTION) { + result = DispatchFuncCall(func, -1, (Obj) args, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0, (Obj) 0 ); + } else { + result = CALL_XARGS( func, args ); + } if (STATE(UserHasQuit) || STATE(UserHasQUIT)) /* the procedure must have called READ() and the user quit from a break loop inside it */ diff --git a/tst/test-error/func-and-proc-call-trace.g b/tst/test-error/func-and-proc-call-trace.g new file mode 100644 index 0000000000..6680b6d063 --- /dev/null +++ b/tst/test-error/func-and-proc-call-trace.g @@ -0,0 +1,112 @@ +informproc0 := function(l) +Add(l,1); +l(); +end;; +informproc0([]); +quit; +Print("\n\n"); +informproc1 := function(l) +Add(l,1); +l(1); +end;; +informproc1([]); +quit; +Print("\n\n"); +informproc2 := function(l) +Add(l,1); +l(1,2); +end;; +informproc2([]); +quit; +Print("\n\n"); +informproc3 := function(l) +Add(l,1); +l(1,2,3); +end;; +informproc3([]); +quit; +Print("\n\n"); +informproc4 := function(l) +Add(l,1); +l(1,2,3,4); +end;; +informproc4([]); +quit; +Print("\n\n"); +informproc5 := function(l) +Add(l,1); +l(1,2,3,4,5); +end;; +informproc5([]); +quit; +Print("\n\n"); +informproc6 := function(l) +Add(l,1); +l(1,2,3,4,5,6); +end;; +informproc6([]); +quit; +Print("\n\n"); +informprocmore := function(l) +Add(l,1); +l(1,2,3,4,5,6,7); +end;; +informprocmore([]); +quit; +Print("\n\n"); +informfunc0 := function(l) +Add(l,1); +Print(l()); +end;; +informfunc0([]); +quit; +Print("\n\n"); +informfunc1 := function(l) +Add(l,1); +Print(l(1)); +end;; +informfunc1([]); +quit; +Print("\n\n"); +informfunc2 := function(l) +Add(l,1); +Print(l(1,2)); +end;; +informfunc2([]); +quit; +Print("\n\n"); +informfunc3 := function(l) +Add(l,1); +Print(l(1,2,3)); +end;; +informfunc3([]); +quit; +Print("\n\n"); +informfunc4 := function(l) +Add(l,1); +Print(l(1,2,3,4)); +end;; +informfunc4([]); +quit; +Print("\n\n"); +informfunc5 := function(l) +Add(l,1); +Print(l(1,2,3,4,5)); +end;; +informfunc5([]); +quit; +Print("\n\n"); +informfunc6 := function(l) +Add(l,1); +Print(l(1,2,3,4,5,6)); +end;; +informfunc6([]); +quit; +Print("\n\n"); +informfuncmore := function(l) +Add(l,1); +Print(l(1,2,3,4,5,6,7)); +end;; +informfuncmore([]); +quit; +Print("\n\n"); diff --git a/tst/test-error/func-and-proc-call-trace.g.out b/tst/test-error/func-and-proc-call-trace.g.out new file mode 100644 index 0000000000..42cc4006b9 --- /dev/null +++ b/tst/test-error/func-and-proc-call-trace.g.out @@ -0,0 +1,144 @@ +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( ); at *stdin*:3 called from +( ) + called from read-eval loop at *stdin*:5 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1 ); at *stdin*:8 called from +( ) + called from read-eval loop at *stdin*:10 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2 ); at *stdin*:13 called from +( ) + called from read-eval loop at *stdin*:15 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2, 3 ); at *stdin*:18 called from +( ) + called from read-eval loop at *stdin*:20 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2, 3, 4 ); at *stdin*:23 called from +( ) + called from read-eval loop at *stdin*:25 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2, 3, 4, 5 ); at *stdin*:28 called from +( ) + called from read-eval loop at *stdin*:30 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2, 3, 4, 5, 6 ); at *stdin*:33 called from +( ) + called from read-eval loop at *stdin*:35 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2, 3, 4, 5, 6, 7 ); at *stdin*:38 called from +( ) + called from read-eval loop at *stdin*:40 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( ) at *stdin*:43 called from +( ) + called from read-eval loop at *stdin*:45 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1 ) at *stdin*:48 called from +( ) + called from read-eval loop at *stdin*:50 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2 ) at *stdin*:53 called from +( ) + called from read-eval loop at *stdin*:55 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2, 3 ) at *stdin*:58 called from +( ) + called from read-eval loop at *stdin*:60 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2, 3, 4 ) at *stdin*:63 called from +( ) + called from read-eval loop at *stdin*:65 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2, 3, 4, 5 ) at *stdin*:68 called from +( ) + called from read-eval loop at *stdin*:70 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2, 3, 4, 5, 6 ) at *stdin*:73 called from +( ) + called from read-eval loop at *stdin*:75 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + +Error, no method found! For debugging hints type ?Recovery from NoMethodFound +Error, no 1st choice method found for `CallFuncList' on 2 arguments at GAPROOT/lib/methsel2.g:241 called from +l( 1, 2, 3, 4, 5, 6, 7 ) at *stdin*:78 called from +( ) + called from read-eval loop at *stdin*:80 +you can 'quit;' to quit to outer loop, or +you can 'return;' to continue +brk> + diff --git a/tst/testinstall/callfunc.tst b/tst/testinstall/callfunc.tst index 37e0a79f9a..4fdae55b19 100644 --- a/tst/testinstall/callfunc.tst +++ b/tst/testinstall/callfunc.tst @@ -102,5 +102,27 @@ gap> CALL_FUNC_LIST(o, [1,2,3,4,5,6]); gap> CALL_FUNC_LIST(o, [1,2,3,4,5,6,7]); [ 1, 2, 3, 4, 5, 6, 7 ] -# +# test overloading CallFuncList with a procedure call +gap> cat2 := NewCategory("IsXYZ2",IsObject);; +gap> type2 := NewType(fam, cat2 and IsPositionalObjectRep);; +gap> InstallMethod(CallFuncList,[cat2,IsList],function(func,args) result:=args; end); +gap> o2 := Objectify(type2,[]);; + +# test edge case: expecting a func call, but doing a proc call +gap> f := function() return o2(); end;; f(); +Error, Function Calls: must return a value +gap> f := function() return o2(1); end;; f(); +Error, Function Calls: must return a value +gap> f := function() return o2(1,2); end;; f(); +Error, Function Calls: must return a value +gap> f := function() return o2(1,2,3); end;; f(); +Error, Function Calls: must return a value +gap> f := function() return o2(1,2,3,4); end;; f(); +Error, Function Calls: must return a value +gap> f := function() return o2(1,2,3,4,5); end;; f(); +Error, Function Calls: must return a value +gap> f := function() return o2(1,2,3,4,6,7); end;; f(); +Error, Function Calls: must return a value +gap> f := function() return o2(1,2,3,4,5,6,7); end;; f(); +Error, Function Calls: must return a value gap> STOP_TEST( "callfunc.tst", 1);