CLASSPATH:=/net/aioli/contrib/:/net/aioli/classes:$CLASSPATH
formalism of lambda is VAR ::= var; TOP ::= true false app VAR abs; true -> ; false -> ; app -> TOP TOP ; abs -> VAR TOP ; var -> implemented as STRING ; end
java aioli.metal.Compile lambda.metal
It creates a file formalism.java that we can compile as a standard java file:
javac formalism.java
We get as lambdaected the corresponding class file formalism.class. If you have any problem in completing the previous two steps, either you are using an old version of java (<1.1) or your CLASSPATH is not properly set.
prettyprinter std of lambda is *x!0 -> "..."; app(*x, *y) -> [<h 0> "(" [<h 1> *x *y ] ")"]; abs(*x, *y) -> [<h 0> "(" [<h 1> "lambda" [<h 0> in class = var : *x "."] *y] ")"]; var *x -> identitypp(*x); true() -> in class = kw : "True"; false() -> in class = kw : "False"; end prettyprinter
java aioli.ppml.Compile lambda-std.ppml
We get two java files BBstd.java et PPstd.java. We then simply need to compile the latter:
javac PPstd.java
Cette fois on a deux fichiers base_std.java et pp_std.java. Il suffit de compiler le second pour compiler aussi le premier:
javac pp_std.java
Vtp implements a very simple protocol to transfer tree structures. So eventhough we don't have yet a parser for lambda we can already build applications that manipulates lambda term. Our first example is a program that visualizes lambda terms. It is described in the file test.java:
package lambda; import java.io.*; import java.awt.Frame; import java.awt.Container; import aioli.vtp.*; import aioli.variable.*; import aioli.gfxobj.*; public final class test extends Frame { public static void main(String[] theArgs) { new test(theArgs[0]); } public test(String file) { try { Tree tree = Proto.readTree(new FileInputStream(file)); Variable var = new Variable(tree); System.out.println(tree.toString()); Ctedit ct = new Ctedit(var,"std"); add(ct.getComponent()); setSize(600,400); setTitle("Lambda"); setVisible(true); ct.setStyle("DEFAULT","times-17","black","white"); ct.setStyle("kw","times-17-i",null,null); ct.setStyle("var",null,"blue",null); ct.redraw(120,20); } catch (FileNotFoundException e) {} } }
javac test.java
To run an example, we just need to create a file proto.txt that contains valid construction using the protocol, so for example:
a lambda$var x n lambda$true 0 n lambda$abs 2 eNow the command
java lambda.test proto.txt
creates a window:
expression : ident | "True" | "False" | "(" ( "lambda" ident "." expression | expression expression ) ")" ; ident: ("a".."z"|"A".."Z"|"_"|"$") ("a".."z"|"A".."Z"|"_"|"0".."9"|"$")*For the moment there is no mechanism to retrieve parser, parser can belong to arbitrary packages. So we arbitrary decide to write the parser in the lambda subdirectory in the file lambda.g. Adding a header and vtp actions to the previous definition gives:
header {package lambda;} { import java.io.*; import aioli.vtp.*;} class LambdaParser extends Parser; options { tokenVocabulary=Lambda; vtpLanguage = "lambda"; } { //class Main { public static Tree parse(InputStream ds) throws Exception { try { LambdaLexer lexer = new LambdaLexer(ds); LambdaParser parser = new LambdaParser(lexer); return parser.expression(); } catch(Exception e) { System.err.println("exception: "+e); throw e; // so we can get stack trace } } //} } expression returns [Tree tr] << tr1 == *;tr2 == *;tr = *;>> : id1:IDENT <<tr = var *id1^;>> | "True" <<tr= true();>> | "False" <<tr= false();>> | LPAREN ( "lambda" id2:IDENT DOT tr1=expression <<tr=abs(var *id2^, *tr1);>> | tr1=expression tr2=expression <<tr=app(*tr1,*tr2);>> ) RPAREN ; class LambdaLexer extends Lexer; options {tokenVocabulary=Lambda;} LPAREN : '(' ; RPAREN : ')' ; DOT : '.'; // MISC STUFF WS : (' ' | '\t' | '\n' { newline(); } | '\r') { _ttype = Token.SKIP; } ; IDENT options { testLiterals=true;} : ('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')* ;
java antlr.Tool lambda.gIt produces several java files. The main file we need to compile is the LambdaParser:
javac LambdaParser.java
package lambda; import java.io.*; import java.awt.Frame; import java.awt.Component; import aioli.vtp.*; import aioli.variable.*; import aioli.gfxobj.*; public final class test1 extends Frame { public static void main(String[] theArgs) { new test1(theArgs[0]); } public test1(String file) { try { Tree tree = LambdaParser.parse(new FileInputStream(file)); Variable var = new Variable(tree); Ctedit ct = new Ctedit(var,"std"); add(ct.getComponent()); setSize(600,400); setTitle("Lambda"); setVisible(true); ct.setStyle("DEFAULT","times-17","black","white"); ct.setStyle("kw","times-17-i",null,null); ct.setStyle("var",null,"blue",null); ct.redraw(120,20); } catch (FileNotFoundException e) {} catch (java.lang.Exception e) {} } }
javac test1.java
To run an example, we just need to create a file ex.lambda that contains a valid lambda expression:
(lambda x . True)Now the command
java lambda.test1 ex.lambda
produces the same result than the example without parser:
We can refine this example by adding a button that shows where is the binder of a variable. The idea is to select a variable in the window and click on a button "Binder", the selection is then automatically moved to the binder of this variable. We first define in the class Binding a method that wlaks through the tree to find the binder
package lambda; import aioli.vtp.*; public class Binding { public static Tree find(Tree tree) { // First check if it is a variable we are finding if (tree == null) return null; if ("lambda".equals(tree.formalism().name()) && "var".equals(tree.operatorName())) { String nameVar = tree.atomValue().string(); while (tree != null) { if ("abs".equals(tree.operatorName()) && "var".equals(tree.down(1).operatorName()) && nameVar.equals(tree.down(1).atomValue().string())) return tree.down(1); tree = tree.up(1); } } return null; } }
package lambda; import java.awt.*; import java.awt.event.*; import aioli.variable.Variable; import aioli.vtp.Tree; class BinderListener implements ActionListener { Variable _var; Tree _tree; Tree _old ; BinderListener(Variable var) { _var=var; _tree=null; _old =null; } public void actionPerformed(ActionEvent ae) { String str=((Button)(ae.getSource())).getLabel(); Tree tree = _var.getCurrentTree(); Tree res = Binding.find(tree); if (res != null) _var.updateCurrentSelection(res); } } public class BinderBut extends Panel { protected void makebutton(String name, GridBagLayout gridbag, GridBagConstraints c, BinderListener el) { Button button = new Button(name); gridbag.setConstraints(button, c); button.addActionListener(el); add(button); } public BinderBut(Variable var) { GridBagLayout g = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); BinderListener el = new BinderListener(var); setLayout(g); c.fill = GridBagConstraints.BOTH; setLayout(g); c.weighty = 0.0; //reset to the default c.gridwidth = GridBagConstraints.REMAINDER; //end row c.gridheight = 1; //reset to the default makebutton("Binder",g,c,el); c.weighty = 1.0; //reset to the default java.awt.Canvas cv = new java.awt.Canvas(); g.setConstraints(cv, c); add(cv); } }
package lambda; import java.io.*; import java.awt.Frame; import java.awt.Component; import aioli.vtp.*; import aioli.variable.*; import aioli.gfxobj.*; public final class test2 extends Frame { public static void main(String[] theArgs) { new test2(theArgs[0]); } public test2(String file) { try { Tree tree = LambdaParser.parse(new FileInputStream(file)); Variable var = new Variable(tree); Ctedit ct = new Ctedit(var,"std"); add(ct.getComponent()); add("West",new BinderBut(var)); setSize(600,400); setTitle("Lambda"); setVisible(true); ct.setStyle("DEFAULT","times-17","black","white"); ct.setStyle("kw","times-17-i",null,null); ct.setStyle("var",null,"blue",null); ct.redraw(120,20); } catch (FileNotFoundException e) {} catch (java.lang.Exception e) {} } }
javac test2.javaand we run it with the file ex1.lambda that contains a lambda term with some variables:
(lambda x . (lambda y . (y x)))Running the command:
java lambda.test2 ex1.lambdaselecting the second occurrence of x and clicking on the button Binder gives the expected result: