Chapter 8: The Styles of Generated Programs

Summary

The design of handcrafted programs and generated programs follow different paths. Handcrafted programs should be easy to understand and change. In a program-generation system, the need for understanding and change occurs at the specification level, not the program level. This results in greater flexibility in the design of generated programs. Three styles of generated programs are presented in this chapter. The OO-approach favors highly structured OO techniques. The code-driven approach favors straightforward code with embedded data. The table-driven approach puts data in a separate data section that is used by the code section. A typical program generator will use some combination of these three techniques.



Chapter 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13

Example 8-3: OO-Driven Style JackAndJill Program
Example 8-4: Code-Driven JackAndJill Program
Example 8-5: Table-Driven JackAndJill Program

Example 8-3: OO-Driven Style JackAndJill Program

package com.craigc.progen;
import java.awt.*;
import java.awt.event.*;

public class JackAndJillPlay1 extends Frame {
    
    /** base class for all button props */
    class ButtonProp extends Button {
        ButtonProp(String label, ActionListener script) {
            super(label);
            addActionListener(script);
        }
    }
    
    /* The Props for JackAndJillPlay ******************/
    
    ButtonProp upProp = new ButtonProp("Go up the hill",
        new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                fetchProp.setLabel("Fetch a pail of water");
                enterNewScene(topScene);
            }
        });
    ButtonProp fetchProp = new ButtonProp("Fetch a pail of water",
        new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                fetchProp.setLabel("Fetch another pail");
            }
        });
    ButtonProp fallProp = new ButtonProp("Fall down, break crown",
        new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                fallProp.setLabel("Break crown");
                tumbleProp.setLabel("Tumble after");
                enterNewScene(bottomScene);
            }
        });
    ButtonProp tumbleProp = new ButtonProp("Tumble down",
        new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                enterNewScene(bottomScene);
            }
        });
    
    /* The Scenes for JackAndJillPlay ******************/
    
    /** base class for all scenes */
    class Scene extends Panel {
        void setup() {};    // used to setup a scene on entry
    };
    
    class BottomScene extends Scene {
        void setup() {
            removeAll();    // remove any old props
            setLayout(new FlowLayout());
            add(upProp);
            add(fallProp);
            setBackground(Color.decode("#8888aa"));
        }
    }
            
    class TopScene extends Scene {
        void setup() {
            removeAll();    // remove any old props
            setLayout(new FlowLayout());
            add(fetchProp);
            add(fallProp);
            add(tumbleProp);
            setBackground(Color.decode("#dddddd"));
        }
    }
            
    BottomScene bottomScene = new BottomScene();
    TopScene topScene = new TopScene();
        
    /* Creating and starting up the JackAndJillPlay **/
    
    Scene currentScene;
    
    public JackAndJillPlay1() {
        super("Jack and Jill #1");
        setSize(300, 120);
        
        // start scene
        enterNewScene(bottomScene);
    }
    
    public void enterNewScene(Scene scene) {
        removeAll();  // remove previous scene if any
        currentScene = scene;
        scene.setup();
        add(scene);
        show();
    }
    
    public static void main(String[] args) {
        new JackAndJillPlay1();
    }
}

Example 8-4: Code-Driven JackAndJill Program

package com.craigc.progen;
import java.awt.*;
import java.awt.event.*;

class JackAndJillPlay2 extends Frame {
    
    /* The Props for JackAndJill ****************/
    
    Button upProp = new Button("Go up the hill");
    Button fetchProp = new Button("Fetch a pail of water");
    Button fallProp = new Button("Fall down, break crown");
    Button tumbleProp = new Button("Tumble down");

    /* The Events in the JackAndJill ***************/

    class PropEvent implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
            Object prop = evt.getSource();
            if (prop==upProp) {
                fetchProp.setLabel("Fetch a pail of water");
                enterNewScene("top");
            } else if (prop==fetchProp) {
                fetchProp.setLabel("Fetch another pail");
            } else if (prop==fallProp) {
                fallProp.setLabel("Break crown");
                tumbleProp.setLabel("Tumble after");
                enterNewScene("bottom");
            } else if (prop==tumbleProp) {
                enterNewScene("bottom");
            } else {
                System.out.println("Invalid prop");
            }
        }
    }
    
    /* Creating and starting up the JackAndJill ****/
    
    String currentScene;
    
    public JackAndJillPlay2() {
        super("Jack and Jill");
        setSize(200, 120);
        setLayout(new FlowLayout());
        
        // initialize props
        PropEvent a = new PropEvent();
        upProp.addActionListener(a);
        fetchProp.addActionListener(a);
        fallProp.addActionListener(a);
        tumbleProp.addActionListener(a);

        // start scene
        enterNewScene("bottom");
    }

    public void enterNewScene(String scene) {
        removeAll();  // remove previous scene
        currentScene = scene;
        if (scene.equals("bottom")) {
            add(upProp);
            add(fallProp);
            setBackground(Color.decode("#8888aa"));
        } else if (scene.equals("top")) {
            add(fetchProp);
            add(fallProp);
            add(tumbleProp);
            setBackground(Color.decode("#dddddd"));
        } else {
            System.out.println("Invalid scene: "+scene);
        }
        show();
    }

    public static void main(String[] args) {
        new JackAndJillPlay2();
    }

}

Example 8-5: Table-Driven JackAndJill Program

package com.craigc.progen;
import java.awt.*;
import java.awt.event.*;

class JackAndJillPlay3 extends Frame {
    
    /* The Prop and Scene tables *******************/
    
    final static String title = "Jack and Jill #3";
    final int width = 300;
    final int height = 120;
    final int startScene = 0; // bottom
    
    // String[] propNames = { "up", "fetch", "fall", "down" };
    
    // initial labels
    final String[] propLabels = {
        "Go up the hill",
        "Fetch a pail of water",
        "Fall down, break crown",
        "Tumble down",
    };
    
    // map props to actions after each prop's action event
    final int[][][] propActions = {
        { { 1, 0 } },  // fetch "Fetch a pail of water"
        { { 1, 1 } },  // fetch "Fetch another pail"
        { { 2, 2 },    // fall "Break crown"
          { 3, 3 }, }, // tumble "Tumble after"
        {},
    };
    
    // map props to next scene
    final int[] nextScene = {
        1,  // top
        -1, // none
        0,  // bottom
        0,  // bottom
    };
    
    // String[] sceneNames = { "bottom", "top" };
    
    // map scenes to list of props to add for that scene
    final int[][] sceneProps = {
        { 0, 2 },    // up fall
        { 1, 2, 3 }, // fetch fall tumble
    };
    
    final String[] sceneColors = {
        "#8888aa",
        null,
    };

    final String[] traitValues = {
        "Fetch a pail of water",
        "Fetch another pail",
        "Break crown",
        "Tumble after",
    };
    
    /* The Events in the JackAndJillPlay *******************/
    
    class PropEvent implements ActionListener {
        int propnum;    // what prop this listener listens for
        
        public PropEvent(int j) {
            propnum = j;
        }
        
        public void actionPerformed(ActionEvent evt) {
            for (int j=0; j<propActions[propnum].length; ++j) {
                props[propActions[propnum][j][0]].setLabel(
                    traitValues[propActions[propnum][j][1]]);
            }
            
            if (nextScene[propnum] >= 0) {
                enterNewScene(nextScene[propnum]);
            }
        }
    }
    
    /* Creating and starting up the JackAndJillPlay *********/
    
    int currentScene;
    Button[] props; // the props
    
    public JackAndJillPlay3() {
        super(title);
        setSize(width, height);
        setLayout(new FlowLayout());
        
        // initialize props
        props = new Button[propLabels.length];
        for (int j=0; j<propLabels.length; ++j) {
            props[j] = new Button();
            props[j].setLabel(propLabels[j]);
            props[j].addActionListener(new PropEvent(j));
        }
  
        // start scene
        enterNewScene(startScene);
    }
    
    public void enterNewScene(int scene) {
        removeAll();  // remove previous scene if any
        currentScene = scene;
        for (int j=0; j<sceneProps[scene].length; ++j) {
            add(props[sceneProps[scene][j]]);
        }
        String bg = sceneColors[scene];
        setBackground(Color.decode(bg==null?"#dddddd":bg));
        show();
    }
    
    public static void main(String[] args) {
        new JackAndJillPlay3();
    }
}