From cda79cfc847a84c3cac158684530c8aabc462814 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 30 Apr 2018 21:59:01 +0200 Subject: [PATCH] Improve and test support for custom functions * NamesLocalVariablesFunction actually is a kernel operation, mark it as such * fix a crash caused by infinite recursion when trying to display a function which is not a `T_FUNCTION` * add tests for installing custom methods for NameFunction, NamesLocalVariablesFunction, and NumberArgumentsFunction --- lib/function.g | 2 +- lib/function.gi | 3 +++ tst/testinstall/callfunc.tst | 16 ++++++++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/function.g b/lib/function.g index fde53d9fb7..7604174d0d 100644 --- a/lib/function.g +++ b/lib/function.g @@ -243,7 +243,7 @@ DeclareOperationKernel( "NumberArgumentsFunction", [IS_OBJECT], NARG_FUNC ); ## ## <#/GAPDoc> ## -BIND_GLOBAL( "NamesLocalVariablesFunction", NAMS_FUNC ); +DeclareOperationKernel( "NamesLocalVariablesFunction", [IS_OBJECT], NAMS_FUNC ); ############################################################################# diff --git a/lib/function.gi b/lib/function.gi index d587e68c06..bb02952abd 100644 --- a/lib/function.gi +++ b/lib/function.gi @@ -63,6 +63,9 @@ end); InstallMethod(DisplayString, "for a function, using string stream", [IsFunction], function(fun) local s, stream; + if TNUM_OBJ(fun) <> T_FUNCTION then + TryNextMethod(); + fi; s := ""; stream := OutputTextString(s, true); PrintTo(stream, fun); diff --git a/tst/testinstall/callfunc.tst b/tst/testinstall/callfunc.tst index b833333578..0345f1b5cf 100644 --- a/tst/testinstall/callfunc.tst +++ b/tst/testinstall/callfunc.tst @@ -29,12 +29,20 @@ gap> ForAll([0..100], x -> CallFuncListWrap(swallow, List([1..x], y -> [y]) ) = true # test overloading CallFuncList -gap> fam := NewFamily("XYZsFamily");; -gap> cat := NewCategory("IsXYZ",IsObject);; +gap> fam := NewFamily("CustomFunctionFamily");; +gap> cat := NewCategory("IsCustomFunction", IsFunction);; gap> type := NewType(fam, cat and IsPositionalObjectRep);; gap> result := fail;; gap> InstallMethod(CallFuncList,[cat,IsList],function(func,args) result:=args; return args; end); -gap> o := Objectify(type,[]);; +gap> InstallMethod(NameFunction, [cat], f -> f![1]); +gap> InstallMethod(NamesLocalVariablesFunction, [cat], f -> ["arg"]); +gap> InstallMethod(NumberArgumentsFunction, [cat], f -> -1); + +# +gap> o := Objectify(type,["myName"]); +function( arg... ) ... end +gap> Display(o); + # test dispatch through interpreter / IntrFuncCallEnd gap> o(); @@ -109,7 +117,7 @@ gap> CallFuncList(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> cat2 := NewCategory("IsCustomFunction2",IsFunction);; gap> type2 := NewType(fam, cat2 and IsPositionalObjectRep);; gap> InstallMethod(CallFuncList,[cat2,IsList],function(func,args) result:=args; end); gap> o2 := Objectify(type2,[]);;