diff --git a/doc/ref/create.xml b/doc/ref/create.xml index 8a82fb7e5f8..daee91fc762 100644 --- a/doc/ref/create.xml +++ b/doc/ref/create.xml @@ -1177,6 +1177,12 @@ avoid their being overwritten accidentally. See also Section . <#Include Label="DeclareCategory"> +<#Include Label="ClassOfOperation"> +<#Include Label="IsCategory"> +<#Include Label="IsRepresentation"> +<#Include Label="IsProperty"> +<#Include Label="IsAttribute"> +<#Include Label="CategoryByName"> <#Include Label="DeclareRepresentation"> <#Include Label="DeclareAttribute"> <#Include Label="DeclareProperty"> @@ -1188,6 +1194,7 @@ See also Section . <#Include Label="InstallValue"> <#Include Label="DeclareSynonym"> <#Include Label="FlushCaches"> +<#Include Label="FilterByName"> diff --git a/lib/filter.g b/lib/filter.g index de702e8a001..fdcc378ffe2 100644 --- a/lib/filter.g +++ b/lib/filter.g @@ -342,6 +342,86 @@ BIND_GLOBAL("NICE_FLAGS",QUO_INT(SUM_FLAGS,30)); BIND_GLOBAL( "CANONICAL_BASIS_FLAGS", QUO_INT(SUM_FLAGS,5) ); + +############################################################################# +## +#V IdOfFilter +## +## <#GAPDoc Label="IdOfFilter"> +## +## +## +## +## +## finds the id of the filter filter, or the id of the filter +## with name name respectively. +## The id of a filter is equal to the +## position of this filter in the global FILTERS list. +##

+## Note that not every filter for which IsFilter(filter) +## returns true has an ID, only elementary filters do. +## +## +## <#/GAPDoc> +## +## Note that the filter ID is stored in FLAG1_FILTER for most filters, +## testers have the ID stored in FLAG2_FILTER, so the code below is +## more efficient than just iterating over the FILTERS list. +## +## +BIND_GLOBAL( "IdOfFilter", +function(filter) + local fid; + fid := FLAG1_FILTER(filter); + if fid > 0 and FILTERS[fid] = filter then + return fid; + fi; + fid := FLAG2_FILTER(filter); + if fid > 0 and FILTERS[fid] = filter then + return fid; + fi; + return fail; +end); + +BIND_GLOBAL( "IdOfFilterByName", +function(name) + local fid; + for fid in [1..LEN_LIST(FILTERS)] do + if NAME_FUNC(FILTERS[fid]) = name then + return fid; + fi; + od; + return fail; +end); + + +############################################################################# +## +#V FilterByName +## +## <#GAPDoc Label="FilterByName"> +## +## +## +## +## finds the filter with name name in the global FILTERS list. This +## is useful to find filters that were created but not bound to a global +## variable. +## +## +## <#/GAPDoc> +## +BIND_GLOBAL( "FilterByName", +function(name) + local fid; + fid := IdOfFilterByName(name); + if fid <> fail then + return FILTERS[fid]; + else + return fail; + fi; +end); + ############################################################################# ## #E diff --git a/lib/function.g b/lib/function.g index 2a966650b47..d44f5701e06 100644 --- a/lib/function.g +++ b/lib/function.g @@ -636,79 +636,6 @@ InstallMethod( ViewObj, "for a function", true, [IsFunction], 0, Print(" ) ... end"); end); -BIND_GLOBAL( "VIEW_STRING_OPERATION", function ( op ) - local class, flags, types, catok, repok, propok, seenprop, - t, res; - class := "Operation"; - if IS_IDENTICAL_OBJ(op,IS_OBJECT) then - class := "Filter"; - elif IS_CONSTRUCTOR(op) then - class := "Constructor"; - elif IsFilter(op) then - class := "Filter"; - flags := FLAGS_FILTER(op); - if flags <> false then - flags := TRUES_FLAGS(flags); - else - flags := []; - fi; - types := INFO_FILTERS{flags}; - catok := true; - repok := true; - propok := true; - seenprop := false; - for t in types do - if not t in FNUM_REPS then - repok := false; - fi; - if not t in FNUM_CATS then - catok := false; - fi; - if not t in FNUM_PROS and not t in FNUM_TPRS then - propok := false; - fi; - if t in FNUM_PROS then - seenprop := true; - fi; - od; - if seenprop and propok then - class := "Property"; - elif catok then - class := "Category"; - elif repok then - class := "Representation"; - fi; - elif Tester(op) <> false then - # op is an attribute - class := "Attribute"; - fi; - - # Horrible. - res := "<"; - APPEND_LIST(res, class); - APPEND_LIST(res, " \""); - APPEND_LIST(res, NAME_FUNC(op)); - APPEND_LIST(res, "\">"); - return res; -end); - -BIND_GLOBAL( "PRINT_OPERATION", -function ( op ) - Print(VIEW_STRING_OPERATION(op)); -end); - -InstallMethod( ViewObj, - "for an operation", - [ IsOperation ], - PRINT_OPERATION ); - -InstallMethod( ViewString, - "for an operation", - [ IsOperation ], -function(op) - return VIEW_STRING_OPERATION(op); -end); - ############################################################################# ## #E diff --git a/lib/function.gi b/lib/function.gi index 5fe0b4c605e..7ee9cdcf481 100644 --- a/lib/function.gi +++ b/lib/function.gi @@ -60,25 +60,49 @@ function(func) return result; end); - -InstallMethod(DisplayString, "for a function, using string stream", [IsFunction], +InstallMethod(DisplayString, "for a function, using string stream", [IsFunction], function(fun) local s, stream; s := ""; stream := OutputTextString(s, true); PrintTo(stream, fun); CloseStream(stream); - Add(s, '\n'); + Add(s, '\n'); return MakeImmutable(s); end); -InstallMethod(String, "for a function, with whitespace reduced", [IsFunction], +InstallMethod(String, "for a function, with whitespace reduced", [IsFunction], function(fun) local s, str; s := ShallowCopy(DisplayString(fun)); - Remove(s); + Remove(s); NormalizeWhitespace(s); return MakeImmutable(s); end); - +BIND_GLOBAL( "VIEW_STRING_OPERATION", +function ( op ) + return STRINGIFY("<", ClassOfOperation(op), + " \"", NAME_FUNC(op), "\">"); +end); + +BIND_GLOBAL( "PRINT_OPERATION", +function ( op ) + Print(VIEW_STRING_OPERATION(op)); +end); + +InstallMethod( ViewObj, + "for an operation", + [ IsOperation ], + PRINT_OPERATION ); + +InstallMethod( ViewString, + "for an operation", + [ IsOperation ], +function(op) + return VIEW_STRING_OPERATION(op); +end); + +############################################################################# +## +#E diff --git a/lib/type.gd b/lib/type.gd index bf50fde282e..768bf8b92e0 100644 --- a/lib/type.gd +++ b/lib/type.gd @@ -36,3 +36,117 @@ ## DeclareOperation( "FiltersType", [ IsType ] ); DeclareOperation( "FiltersObj", [ IsObject ] ); + + +############################################################################# +## +#F ClassOfOperation( ) +## +## Determine the class of the operation op. +## +## <#GAPDoc Label="ClassOfOperation"> +## +## +## +## +## returns a string from the list [ "Attribute", "Operation", "Property", +## "Category", "Representation", "Filter"] reflecting which type of +## operation op is. +## +## +## <#/GAPDoc> +DeclareGlobalFunction( "ClassOfOperation" ); + + +############################################################################# +## +#F IsCategory( ) +## +## Determine whether the passed object is a category. +## +## <#GAPDoc Label="IsCategory"> +## +## +## +## +## returns true if object is a category, and false +## otherwise. +## +## +## <#/GAPDoc> +DeclareGlobalFunction( "IsCategory" ); + +############################################################################# +## +#F IsRepresentation( ) +## +## Determine whether the passed object is a representation. +## +## <#GAPDoc Label="IsRepresentation"> +## +## +## +## +## returns true if object is a representation, and +## false otherwise. +## +## +## <#/GAPDoc> +DeclareGlobalFunction( "IsRepresentation" ); + + +############################################################################# +## +#F IsAttribute( ) +## +## Determine whether the passed object is an attribute. +## +## <#GAPDoc Label="IsAttribute"> +## +## +## +## +## returns true if object is an attribute, and false +## otherwise. +## +## +## <#/GAPDoc> +DeclareGlobalFunction( "IsAttribute" ); + + +############################################################################# +## +#F IsProperty( ) +## +## Determine whether the passed object is a property. +## +## <#GAPDoc Label="IsProperty"> +## +## +## +## +## returns true if object is a property, and false +## otherwise. +## +## +## <#/GAPDoc> +DeclareGlobalFunction( "IsProperty" ); + + +############################################################################# +## +#F CategoryByName( ) +## +## Find a category given its name. +## +## <#GAPDoc Label="CategoryByName"> +## +## +## +## +## returns the category with name name if it is found, or fail otherwise. +## +## +## <#/GAPDoc> +DeclareGlobalFunction( "CategoryByName" ); + diff --git a/lib/type.gi b/lib/type.gi index 0265334a7de..433b76a9942 100644 --- a/lib/type.gi +++ b/lib/type.gi @@ -145,3 +145,84 @@ function ( type ) fi; return res; end); + +InstallGlobalFunction( ClassOfOperation, +function(op) + local class, flags, types, catok, repok, propok, seenprop, + t, flafs, res; + class := "Operation"; + if IS_IDENTICAL_OBJ(op,IS_OBJECT) then + class := "Filter"; + elif IS_CONSTRUCTOR(op) then + class := "Constructor"; + elif IsFilter(op) then + class := "Filter"; + flags := FLAGS_FILTER(op); + if flags <> false then + flags := TRUES_FLAGS(FLAGS_FILTER(op)); + types := INFO_FILTERS{flags}; + catok := true; + repok := true; + propok := true; + seenprop := false; + for t in types do + if not t in FNUM_REPS then + repok := false; + fi; + if not t in FNUM_CATS then + catok := false; + fi; + if not t in FNUM_PROS and not t in FNUM_TPRS then + propok := false; + fi; + if t in FNUM_PROS then + seenprop := true; + fi; + od; + if seenprop and propok then + class := "Property"; + elif catok then + class := "Category"; + elif repok then + class := "Representation"; + fi; + fi; + elif Tester(op) <> false then + # op is an attribute + class := "Attribute"; + fi; + return class; +end); + +InstallGlobalFunction( IsCategory, +function(object) + return IsOperation(object) and ClassOfOperation(object) = "Category"; +end); + +InstallGlobalFunction( IsRepresentation, +function(object) + return IsOperation(object) and ClassOfOperation(object) = "Representation"; +end); + +InstallGlobalFunction( IsAttribute, +function(object) + return IsOperation(object) and ClassOfOperation(object) = "Attribute"; +end); + +InstallGlobalFunction( IsProperty, +function(object) + return IsOperation(object) and ClassOfOperation(object) = "Property"; +end); + +InstallGlobalFunction( CategoryByName, +function(name) + local fid; + + for fid in CATS_AND_REPS do + if (INFO_FILTERS[fid] in FNUM_CATS) and + (NAME_FUNC(FILTERS[fid]) = name) then + return FILTERS[fid]; + fi; + od; + return fail; +end); diff --git a/tst/testinstall/type.tst b/tst/testinstall/type.tst new file mode 100644 index 00000000000..4eba37572d4 --- /dev/null +++ b/tst/testinstall/type.tst @@ -0,0 +1,38 @@ +# +gap> test := x -> List([IsFilter, IsCategory, IsRepresentation, IsAttribute, IsProperty, IsOperation], f -> f(x));; +gap> test(IsFinite); +[ true, false, false, false, true, true ] + +# +gap> test(IsMagma); +[ true, true, false, false, false, true ] + +# +gap> test(IsCommutative); +[ true, false, false, false, true, true ] + +# +gap> test(Size); +[ false, false, false, true, false, true ] + +# +gap> test(Group); +[ false, false, false, false, false, false ] + +# +gap> test((1,2,3)); +[ false, false, false, false, false, false ] + +# +gap> test("hello, world"); +[ false, false, false, false, false, false ] + +# +gap> FilterByName("IsCommutative"); + +gap> CategoryByName("IsMagma"); + + +# +gap> ForAll([1..Length(FILTERS)], id -> id = IdOfFilter(FILTERS[id])); +true