Skip to content

Commit

Permalink
Improve and test support for custom functions
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
fingolfin committed May 1, 2018
1 parent 86996fc commit d23d2eb
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 20 deletions.
21 changes: 8 additions & 13 deletions lib/function.g
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,10 @@ DeclareOperationKernel("NameFunction", [IS_OBJECT], NAME_FUNC);

#############################################################################
##
#F SetNameFunction( <func>, <name> ) . . . . . . . .set name of a function
#O SetNameFunction( <func>, <name> ) . . . . . . . .set name of a function
##
## <ManSection>
## <Func Name="SetNameFunction" Arg='func, name'/>
## <Oper Name="SetNameFunction" Arg='func, name'/>
##
## <Description>
## changes the name of a function. This only changes the name stored in
Expand All @@ -174,15 +174,12 @@ DeclareOperationKernel("NameFunction", [IS_OBJECT], NAME_FUNC);
## </Description>
## </ManSection>
##
#T If objects simulate functions this must become an operation, or an attribute
#T with the above
##
DeclareOperationKernel( "SetNameFunction", [IS_OBJECT, IS_STRING], SET_NAME_FUNC );


#############################################################################
##
#F NumberArgumentsFunction( <func> )
#O NumberArgumentsFunction( <func> )
##
## <#GAPDoc Label="NumberArgumentsFunction">
## <ManSection>
Expand Down Expand Up @@ -216,7 +213,7 @@ DeclareOperationKernel( "NumberArgumentsFunction", [IS_OBJECT], NARG_FUNC );

#############################################################################
##
#F NamesLocalVariablesFunction( <func> )
#O NamesLocalVariablesFunction( <func> )
##
## <#GAPDoc Label="NamesLocalVariablesFunction">
## <ManSection>
Expand All @@ -229,7 +226,7 @@ DeclareOperationKernel( "NumberArgumentsFunction", [IS_OBJECT], NARG_FUNC );
## <A>func</A>, and the remaining ones are the local variables as given in
## the <K>local</K> statement in <A>func</A>.
## (The number of arguments can be computed with
## <Ref Func="NumberArgumentsFunction"/>.)
## <Ref Oper="NumberArgumentsFunction"/>.)
## <P/>
## <Example><![CDATA[
## gap> NamesLocalVariablesFunction(function( a, b ) local c; return 1; end);
Expand All @@ -243,7 +240,7 @@ DeclareOperationKernel( "NumberArgumentsFunction", [IS_OBJECT], NARG_FUNC );
## </ManSection>
## <#/GAPDoc>
##
BIND_GLOBAL( "NamesLocalVariablesFunction", NAMS_FUNC );
DeclareOperationKernel( "NamesLocalVariablesFunction", [IS_OBJECT], NAMS_FUNC );


#############################################################################
Expand Down Expand Up @@ -368,7 +365,7 @@ end);

#############################################################################
##
#F CallFuncList( <func>, <args> ) . . . . . . . . . . . . . call a function
#O CallFuncList( <func>, <args> ) . . . . . . . . . . . . . call a function
##
## <#GAPDoc Label="CallFuncList">
## <ManSection>
Expand All @@ -389,7 +386,7 @@ end);
## 13
## ]]></Example>
## <P/>
## A more useful application of <Ref Func="CallFuncList"/> is for a function
## A more useful application of <Ref Oper="CallFuncList"/> is for a function
## <C>g</C> that is called in the body of a function <C>f</C> with
## (a sublist of) the arguments of <C>f</C>, where <C>f</C> has been defined
## with a single formal argument <C>arg</C>
Expand Down Expand Up @@ -441,8 +438,6 @@ end);
## </ManSection>
## <#/GAPDoc>
##
#T If objects simulate functions this must become an operation.
##
UNBIND_GLOBAL("CallFuncList"); # was declared 2b defined
DeclareOperationKernel( "CallFuncList", [IS_OBJECT, IS_LIST], CALL_FUNC_LIST );
DeclareOperationKernel( "CallFuncListWrap", [IS_OBJECT, IS_LIST], CALL_FUNC_LIST_WRAP );
Expand Down
6 changes: 3 additions & 3 deletions lib/function.gi
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
## that they need to be in function.g
##

InstallMethod( ViewString, "for a function", true, [IsFunction], 0,
InstallMethod( ViewString, "for a function", [IsFunction and IsInternalRep],
function(func)
local locks, nams, narg, i, isvarg, result;
result := "";
Expand Down Expand Up @@ -60,7 +60,7 @@ function(func)
return result;
end);

InstallMethod(DisplayString, "for a function, using string stream", [IsFunction],
InstallMethod(DisplayString, "for a function, using string stream", [IsFunction and IsInternalRep],
function(fun)
local s, stream;
s := "";
Expand All @@ -71,7 +71,7 @@ function(fun)
return MakeImmutable(s);
end);

InstallMethod(String, "for a function, with whitespace reduced", [IsFunction],
InstallMethod(String, "for a function, with whitespace reduced", [IsFunction and IsInternalRep],
function(fun)
local s, str;
s := ShallowCopy(DisplayString(fun));
Expand Down
21 changes: 17 additions & 4 deletions tst/testinstall/callfunc.tst
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,25 @@ 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"]);;
gap> Display(o);
<object>
gap> NameFunction(o);
"myName"
gap> NamesLocalVariablesFunction(o);
[ "arg" ]
gap> NumberArgumentsFunction(o);
-1

# test dispatch through interpreter / IntrFuncCallEnd
gap> o();
Expand Down Expand Up @@ -109,7 +122,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,[]);;
Expand Down

0 comments on commit d23d2eb

Please sign in to comment.