package smallstep.test; import java.awt.BorderLayout; import java.awt.Component; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTree; import javax.swing.tree.DefaultTreeCellRenderer; import smallstep.SmallStepProofModel; import smallstep.SmallStepProofModelFactory; import smallstep.SmallStepProofNode; import common.ProofNode; /** * Test class for the small step interpreter. * * @author Benedikt Meurer * @version $Id$ */ @SuppressWarnings("serial") public class SmallStepTreeView extends JFrame { /** * Simple test expression. */ //private static final String SIMPLE = "not ((+) 1 ( (/) 10 (9 + ~- (8 + 1))))"; //private static final String SIMPLE = "let f = ref (lambda x.x) in let fact = lambda x.if x = 0 then 1 else x * (!f (x - 1)) in (f := fact, !f 3)"; private static final String SIMPLE = "let rec f = lambda x.if x = 0 then 1 else x * (f (x - 1)) in f 3"; //private static final String SIMPLE = "(1 + 2, 5 * 8, let x = 9 in (8,(+) 9 x), y)"; //private static final String SIMPLE = "let (x, y, z) = (~- 8, not true, 1) in x > z || y"; //private static final String SIMPLE = "let rev l = let rec rev_helper s t = if is_empty s then t else rev_helper (tl s) ((hd s) :: t) in rev_helper l [] in rev [1+5,2+5,3+5]"; //private static final String SIMPLE = "let rec f s t = s + t in f [] [1,2,3]"; //private static final String SIMPLE = "let x = 1 in x"; // // Renderer // /** * The tree renderer. */ class Renderer extends DefaultTreeCellRenderer { /** * {@inheritDoc} * * @see javax.swing.tree.DefaultTreeCellRenderer#getTreeCellRendererComponent(javax.swing.JTree, java.lang.Object, boolean, boolean, boolean, int, boolean) */ @Override public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus) { super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus); SmallStepProofNode node = (SmallStepProofNode)value; StringBuilder builder = new StringBuilder(); builder.append('['); for (int n = 0; n < node.getSteps().length; ++n) { if (n > 0) builder.append(", "); builder.append(node.getSteps()[n].getRule().getName()); } builder.append("] -> "); if (node.getExpression().containsReferences()) { builder.append('('); } builder.append(node.getExpression()); if (node.getExpression().containsReferences()) { builder.append(", "); builder.append(node.getStore()); builder.append(')'); } setText(builder.toString()); return this; } } // // Constructor // /** * Default constructor. */ public SmallStepTreeView(final SmallStepProofModel model) { // setup the frame setLayout(new BorderLayout()); setSize(630, 580); setTitle("BigStepTreeView test"); // setup the tree panel JPanel treePanel = new JPanel(new BorderLayout()); treePanel.setBorder(BorderFactory.createEtchedBorder()); add(treePanel, BorderLayout.CENTER); // setup the tree final JTree tree = new JTree(model); tree.setCellRenderer(new Renderer()); treePanel.add(tree, BorderLayout.CENTER); // setup the button panel JPanel buttons = new JPanel(new FlowLayout()); add(buttons, BorderLayout.SOUTH); // setup the guess button JButton guessButton = new JButton("Guess"); guessButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { try { // guess the last node ProofNode node = model.getRoot().getLastLeaf(); model.guess(node); // expand to the last node tree.expandRow(tree.getRowCount() - 1); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(SmallStepTreeView.this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } }); buttons.add(guessButton); // setup the undo button final JButton undoButton = new JButton("Undo"); undoButton.setEnabled(false); undoButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { try { // undo the last change model.undo(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(SmallStepTreeView.this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } }); model.addPropertyChangeListener("undoable", new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { undoButton.setEnabled(model.isUndoable()); } }); buttons.add(undoButton); // setup the redo button final JButton redoButton = new JButton("Redo"); redoButton.setEnabled(false); redoButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { try { // redo the last undone change model.redo(); // expand to the last node tree.expandRow(tree.getRowCount() - 1); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(SmallStepTreeView.this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } }); model.addPropertyChangeListener("redoable", new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent event) { redoButton.setEnabled(model.isRedoable()); } }); buttons.add(redoButton); // setup the translate button JButton translateButton = new JButton("Translate"); translateButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { try { // translate the last node ProofNode node = model.getRoot().getLastLeaf(); model.translateToCoreSyntax(node); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog(SmallStepTreeView.this, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); } } }); buttons.add(translateButton); // setup the close button JButton closeButton = new JButton("Close"); closeButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { System.exit(0); } }); buttons.add(closeButton); } // // Program entry point // /** * Runs the small step interpreter test. * * @param args the command line arguments. */ public static void main(String[] args) { try { // parse the program SmallStepProofModelFactory factory = SmallStepProofModelFactory.newInstance(); SmallStepProofModel model = factory.newProofModel(SIMPLE); // evaluate the resulting small step expression SmallStepTreeView tv = new SmallStepTreeView(model); tv.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); tv.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }