Examples Using Macros
The examples in the following sections show how you can use macros in rules:
Adding a New Required Argument to a Function
You can write a rule like the following to trap problems associated with a function (such as ggTestData) requiring one or more new arguments with a new release of code and notifying the user:
SK_RULE( ggTestData
length(SK_ARGS()) == 2
SK_WARNING( GGTESTDATA
strcat( "This function will require 3 arguments in the next release: %L\n"
"The extra argument will specify the width of the widget.\n") SK_FORM())
)
SK_REGISTER( GGTESTDATA )
Replacing One Function with Another
You can write a rule like the following to replace a standard function called setof with another function called realSetof. The standard setof function is not a true setof because it does not remove repeated elements; instead, it is more of a bagof function. The replacement realSetof function removes repeated elements and allows many statements in the body of the function call (whereas setof allows only one). The rule needs to handle the fact that the first argument is a loop variable.
SK_RULE( realSetof
t
let( ((args SK_ARGS()))
when(symbolp(car(args))
SK_PUSH_VAR(car(args))
)
map(‘SK_CHECK_FORM cdr(args))
when(symbolp(car(args))
SK_POP_VAR(car(args))
)
)
)
The rule above uses let to declare a local variable args to save calling SK_ARGS many times. You can define a second rule as follows to check that the loop variable is given as a symbol:
SK_RULE( realSetof
!symbolp(car(SK_ARGS()))
SK_ERROR( REALSETOF1 “First argument must be a symbol: %L\n” SK_FORM())
)
SK_REGISTER( REALSETOF1 )
Promoting Standard Format Messages
You can write a rule as follows to check that the format string for three new functions matches the given number of arguments. The three new functions (ggInfo, ggWarn and ggError) take the same arguments as printf and usually work the same, except that they change the format a little and also copy the messages to various log files. The SK_ALIAS macro lets you alias the three new functions to printf so that you can apply the same rule.
SK_ALIAS( (ggInfo ggWarn ggError) printf )
Preventing Heavily Nested Calls to Boolean Operators
You can write a rule that promotes nicer looking code by preventing too many nested calls to boolean operators (null, or, and and).
Consider the following example, which is difficult to understand:
!a && ((b || !c) && (!d || !b)
To improve code readability, it would be better to split this expression into several statements and add associated comments.
The following rule counts boolean operators and warns you when there are “too many”:
SK_RULE( (null and or)
ggCountBools(SK_FORM()) > 5
SK_HINT( BOOLS “Lots of boolean calls found : %L\n” SK_FORM())
)
SK_REGISTER( BOOLS )
You might write the ggCountBools function as follows:
procedure( ggCountBools(args)
let( ((i 0))
foreach(arg args
when(listp(arg) && memq(car(arg) ‘(null or and))
i = i + 1 + ggCountBools(cdr(arg))
)
)
i
)
)
In case of deeply nested booleans, you can improve the rule by looking at the function call higher in the call stack and, if that call is a boolean function itself, not checking the current call (because it is unnecessary):
SK_RULE( (null and or)
!memq(car(SK_FORM(1)) ‘(null and or)) && ggCountBools(SK_FORM()) > 5
SK_HINT( BOOLS “Lots of boolean calls found : %L\n” SK_FORM())
)
Related Topics
Rule Structure - SK_RULE Macro
Return to top