Programs often contain code that work or is useful only in some cases, for instance debug code. In C, the preprocessor #ifdef directive is used to select code conditionally. Other languages such as Java don't have an equivalent feature.
One problem with #ifdef is that it applies on code text, not on code concepts. Therefore, if you want to remove debug code from your program, you need to have #ifdef directives all over the place. Also, #ifdef directives can work on fractions of code elements, fracturing the represented concept itself. At the worst, you end up with code that potentially looks like:
#ifdef CONFIG_A
int
#endif
#ifdef CONFIG_B
void *
#endif
foo(
#ifndef CONFIG_A
void *ptr,
#endif
#ifdef CONFIG_C
int *
#else
short *
#endif
data_ptr) { ... }
The strip plug-in illustrates how a thin-tool can conditionally remove (or modify) arbitrary concepts, while leaving them whole and consistent.
Conditional Code in Java
The +strip option of Moka invokes the strip thin tool. The plug-in takes an argument used to identify names of entities to be removed. On the command line, this argument follows a colon. The following command would be used to remove all entities and references to entities that begin with debug.
% moka tests/debug.java +strip:debug -out
Before strip
Before applying "strip", the original code contains a lot of debug code. This code is unnecessary and undesirable in production, so we want to remove it. This is exactly what the "strip" plug-in will do.
class debugInfo
{
public static boolean debugEnable = true;
}
class Point
{
int x, y;
private void debugSelf(String text)
{
System.out.println (text);
}
Point()
{
debugSelf ("default ctor");
}
Point(int x, int y)
{
debugSelf ("ctor(x,y)");
this .x = x;
this .y = y;
}
// A Point instance is explicitly created at class initialization time:
static Point origin = new Point (0, 0);
// A String can be implicitly created by a + operator:
public String toString()
{
return "(" + x + "," + y + ")";
}
}
class debugTest
{
public static void main(String[] args)
{
// A Point is explicitly created using newInstance:
Point p = null;
try
{
p = (Point) Class.forName ("Point") .newInstance ();
}
catch(Exception e)
{
System.out.println (e);
}
// An array is implicitly created by an array constructor:
Point[] a = {
new Point (0, 0), new Point (1, 1)
};
// Strings are implicitly created by + operators:
System.out.println ("p: " + p);
System.out.println ("a: { " + a[0] + ", " + a[1] + " }");
// An array is explicitly created by an array creation expression:
String[] sa = new String[2];
sa[0] = "he";
sa[1] = "llo";
System.out.println (sa[0] + sa[1]);
}
}
After strip
After applying the "strip" plug-in, all declarations where the name begins with "debug" have been removed. Notice that the complete declaration is removed, not just the line containing it.
// class debugInfo removed : /* Nop */;
class Point
{
int x, y;
// debugSelf removed : /* Nop */;
Point()
{
// Call to debugSelf removed : /* Nop */;
}
Point(int x, int y)
{
// Call to debugSelf removed : /* Nop */;
this .x = x;
this .y = y;
}
// A Point instance is explicitly created at class initialization time:
static Point origin = new Point (0, 0);
// A String can be implicitly created by a + operator:
public String toString()
{
return "(" + x + "," + y + ")";
}
}
// class debugTest removed : /* Nop */;
|