440 likes | 552 Views
Event-driven and Concurrent Programming in 2 ACP Based Language Extensions. Lecture at University of Amsterdam Department Theory of Computer Science 18 April 2011 André van Delft, Rijswijk a ndre.vandelft (a) gmail.com http://code.google.com/p/scriptic/
E N D
Event-driven and Concurrent Programming in 2 ACP Based Language Extensions Lecture at University of Amsterdam Department Theory of Computer Science 18 April 2011 André van Delft, Rijswijk andre.vandelft (a) gmail.com http://code.google.com/p/scriptic/ http://code.google.com/p/subscript/
Overview Scriptic • History • ACP vsScriptic • Examples • Case study: Document Processing • Implementation Subscript • Scala based • Differenceswith Scriptic • Examples • Syntax
History • 1956 Kleene: formal automata>> a*b, regular expressions. • 1960 Backus Naur Form • 1960 Compiler-compiler >> Yacc • 1962 Simula: OO, parallelism, simulation time • 1971 Hans Bekič “an algebra of processes” • 1973 Campbell and Haberman: path expressions • 1978 Van den Bos: Input Tool Model (ITM) • 1979 Campbell, Kolstad: Path Pascal • 1978 Hoare: Communicating Sequential Processes (CSP) • 1980 Milner: Calculus of Communicating Systems (CCS) • 1982 Bergstra, Klop Algebra of Communicating Processes (ACP • 1987 Van Delft: ITM >> Scriptic-Pascal, Modula-2, C, C++, Java
Example: Hello World Java public class HelloWorldApp { public static void main (String args[]) { System.out.println("Hello World!"); } Scriptic public class HelloWorldApp { public static scripts main (String args[]) = {System.out.println( "Hello World!")} }
Hello World, continued show(String s) = {System.out.print(s)} hello = show("Hello ") world = show("World!") test1 = hello ; world test2 = hello + world test3 = hello & world
Interleaving and Iterations show(String s) = int i: for(i=0; i<s.length(); i++); {System.out.print(s.charAt(i))} test3 = hello & world // World! Hello show(String s) = int i: for(i=0; i<s.length(); i++) & private: {System.out.print(s.charAt(i))}
Optionality and Iterations (- + x); y // optionally x; then y (..; x); y // zero or more x; then y (x; ..); y // onceor more x; then y x; ..; y // oneor more x, separatedby y parameterList = r("(");(-+parameters);r(")") parameters = parameter; .. ;r(", ") parameterList = "(" (.parameters) ")" parameters = parameter..","
Example: a Queue Simulation (1) live = days(5) || servers(10) waitTime(double d) = {duration=d:} hours (int i) = waitTime(i*HOUR) times (int i) = while(pass<i) Servers (int n) = times(n) & server(pass+1) server (int i) = ...; serveCustomer(i) Days (int n) = times(n); day(pass) day (int i) = workingDay(i) && hours(24); theDayEnds(i) workingDay (int i) = hours (9); createCustomers || hours(17); theShopCloses createCustomers = ...;waitTime(randomNegExp(3*MINUTE)); <customer(pass)>
Example: a Queue Simulation (2) customer(int c) = double d=FromJava.elapsedTime(): customerEnters(c); getServed(c); customerLeaves(c, d) serveCustomer(int s), getServed(int c) = {duration=randomNegExp(30*MINUTE): trace(" customer "+c+" is served by "+s)} theShopCloses = {:trace("the shop closes"); report():} theDayEnds(inti) = {:trace("day "+i+" ends "); report():} customerEnters(inti) = {:trace("customer "+i+" enters“):} customerLeaves(inti) = {:trace("customer "+i+" leaves“):}
Example: a Lookup Applicaton (1) private void searchButton_actionPerformed() { showSearchingText();new Thread() {public void run() { searchInDatabase(); SwingUtilities.invokeLater(new Runnable() {public void run() { showSearchResults(); } } ); } }.start();}
Example: a Lookup Applicaton (2) searchSequence = searchCommand; showSearchingText;searchInDatabase;showSearchResults searchCommand = action(searchButton) showSearchingText = @swing: {showSearchingText()}showSearchResults = @swing: {showSearchResults()} searchInDatabase = {* searchInDatabase() *}
Example: a Lookup Applicaton (3) searchCommand = action(searchButton) + vkey(searchTF, KeyEvent.VK_ENTER!) cancelCommand= action(cancelButton) + vkey(searchTF, KeyEvent.VK_ESCAPE!)exitCommand= action(exitButton) + windowClosing(this)
Example: a Lookup Applicaton (4) exit = exitCommand; @swing: while(!confirmExit()) cancelSearch = cancelCommand; @swing: {showCanceledText()} live = searchSequences || exit searchSequences= ...; searchSequence searchSequence= searchCommand; (searchAction / cancelSearch)searchAction = showSearchingText;searchInDatabase;showSearchResults
Event-handling scripts (1) public classKeyEventHolder { publicKeyEvent event; } public class AnchorKeyListenerimplementsKeyListener { publicKeyEventHolder pressed = newKeyEventHolder(); publicKeyEventHolder released = newKeyEventHolder(); publicKeyEventHolder typed = newKeyEventHolder(); public void keyPressed(KeyEvent e) { pressed.event=e; FromJava.doCodeAtAnchor(pressed); } ... } key(Component comp, char k) = ( AnchorKeyListener a = newAnchorKeyListener() : @swing: {comp.addKeyListener(a)} < @a.pressed: {. k=a.pressed.event.getKeyChar(); k!!?? .} > @swing: {comp.removeKeyListener(a)} )
Event-handling scripts (2) action(JButton button) = ( AnchorActionListener a = new AnchorActionListener() : @swing: {button.addActionListener(a); button.setEnabled(true)} < @a: {. .} > @swing: {button.removeActionListener(a); if (button.getActionListeners().length==0) {button.setEnabled(false);}} )
@swing: public class SwingCodeInvoker implements CodeInvokerSynchronous, CodeInvokerAsynchronous { public void invokeSynchronously(Runnable r) throws Exception { SwingUtilities.invokeAndWait(r); } public void invokeAsynchronously(Runnable r) throws Exception { SwingUtilities.invokeLater(r); } } public class Scripts { public static SwingCodeInvoker swing = new SwingCodeInvoker(); … }
Example: Game of Life (1) live = canvasOperations || mouseInput || speedChanges || exit
Example: Game of Life (2) randomizeCmd = action(randomizeButton) + key('r' !) clearCmd = action( clearButton) + key('c' !) stepCmd = action( stepButton) + key(' ' !) multiStepStartCmd = action( startButton) + key('\n'!) multiStepStopCmd = action( stopButton) + key('\n'!) exitCmd = action( exitButton) + key('x' !) + windowClosing(this) exit = exitCmd; booleandoExit: @swing: {doExit = confirmExit()}; while (! doExit) key(char c) = key(this, c?!)
Example: Game of Life (3) canvasOperations = ...; ( (..;singleStep); multiStep || clear || randomize) do1Step = {*canvas.calculateGeneration()*}; @swing: {:canvas.repaint():} randomize = randomizeCmd; @swing: {:canvas.doRandomize():} clear = clearCmd; @swing: {:canvas.doClear():} singleStep = stepCmd; do1Step multiStep = multiStepStartCmd; ( ...; do1Step; {*sleep()*} / multiStepStopCmd )
Example: Game of Life (4) speedChanges = ...; speedChange speedChange = speedKeyInput + speedButtonInput + speedSliderInput speedKeyInput = char c: ( for(c='0'; c<='9'; c++) + private c: key(c!); setSpeed(numKey2Speed(c)) ) speedButtonInput = if (speed()>minSpeed()) speedDecButton + if (speed()<maxSpeed()) speedIncButton speedDecButton = action(minSpeedButton); setSpeed(minSpeed()) + action( slowerButton); setSpeed(speed()-1) speedIncButton = action(maxSpeedButton); setSpeed(maxSpeed()) + action( fasterButton); setSpeed(speed()+1) speedSliderInput = stateChange(speedSlider); setSpeed(speedSlider.getValue()) setSpeed(int s) = @swing: {:setSpeed(s):}
Example: Game of Life (5) mouseInput = mousePressInput & mouseDragInput mousePressInput = ( ...; MouseEvent me: mousePress(canvas, me?); {:canvas.mouseDownToggle(me):} ) mouseDragInput = ( ...; MouseEvent me: mouseDrag (canvas, me?); {:canvas.mouseDragToggle(me):} ) Whencritical to catch all events: mousePressInput = ( AnchorMouseListener a = newAnchorMouseListener(): @swing : { canvas.addMouseListener(a)} < @a.pressed: {...canvas.mouseDownToggle(a.pressed.event)...} > @swing : { canvas.removeMouseListener(a)} ) mouseDragInput = …
Case study: Document Processing (1) • 25 communication protocols, multiple editions • 106 pages documentation: MS Word • Store as XML; from there create HTML+Java • Many tables • Structure consistent, but… • Typo’s
Case study: Document Processing (2) • Old flow: .doc .txt patched.txt sh+Perl+Java.xml • New flow: .doc .odt patched.odt Scriptic.xml
Case study: Document Processing (3) error(String s) = {:error(s):} fail(String s) = error(s); () nonEmptyLine= anyText; endOfLine emptyLine= endOfLine someEmptyLines= ..; endOfLine someLines= ..; anyLine someLinesAndTables= ..; anyLineOrTable someTables= ..; anyTable someTableRows= ..; anyTableRow someTableCells= ..; anyTableCell anyLineOrTable= anyLine + anyTable anyTable= startOfTable; someTableRows; endOfTable anyTableRow= startOfTableRow; someTableCells; endOfTableRow anyTableCell= startOfTableCell; someLinesAndTables; endOfTableCell
Case study: Document Processing (4) // parse a table row with exactly the given strings in the cells tableRow(String[] rowTexts) = startOfTableRow; ( while (pass<rowTexts.length); tableCell_text(rowTexts[pass])); endOfTableRow // parse a table cell; in case the cellText is an output parameter, it may be built // from multiple lines these lines then are concatenated with a space as separator tableCell_text(String cellText) = startOfTableCell; line(cellText?!); if (cellText?) ( String s: ( ..; line(s?); {:cellText = concatenateTrimmed(cellText,s):}) ); endOfTableCell // parse a table cell containing a number; tableCell_number(int n) = startOfTableCell; number(n?!); endOfLine; endOfTableCell text_oneOf(String[] allowedStrings, String s) = int i: for (i=0; i<allowedStrings.length; i++) + String ls = allowedStrings[i]: text(ls); {:s=ls:}
Case study: Document Processing (5) text_YesOrNo(booleanisYes) = if ( isYes || isYes?) (text("Yes"); {:isYes= true:}) + if (!isYes || isYes?) (text("No" ); {:isYes=false:}) footnote(intn, String s) = footnoteDeclarationPrefix(n?!); line(s?); (..; String s1: line(s1?); {:s=concatenateTrimmed(s,s1.trim()):}) footnoteReference(intn) = in( "(",n?!,")" ) // Parse a Yes/No table cell with an optional footnote tableCell_YesOrNo(booleanb, intfn) = startOfTableCell; text_YesOrNo(b?!); (- + footnoteReference(fn?)); endOfLine; endOfTableCell
Case study: Document Processing (6) wordSequencesForPointsLinesAndAreasTable = startOfTable; tableRow(wordSequencesForPointsLinesAndAreasTableHeaderRowTitles); ( startOfTableRow; ( tableCell_text(typeOfPointLineArea?); wordSequenceTableCell; tableCell_text(applicableTransmitTable?); messageUseTableCell || tableCell_text(""); startOfTableCell; text("followed by additional"); delimitedStrings(msgs?, "/", "sequences"); line("sequences"); endOfTableCell; tableCell_text(""); messageUseTableCell ); endOfTableRow; .. ); endOfTable
Case study: Document Processing (7) [prio 1](line=13) <text>, ws, endsline, value = “TNumber, Objective" [prio 0](line=13) <END_OF_TABLE_CELL>, ws [prio 0](line=12) <START_OF_TABLE_CELL>, ws [prio 3](line=13) <text>, ws, value = "M" 5-4-J22.0-1 J22.0I WORD: Unexpected input at line 13, position: 1 M for P2 JU; T for nonP2 JU ^ Expected: [prio 11] <regexp>, ws, value = "\Q-\E[ \t]*" <> "(\s*\Q-\E[ \t]*).*" [prio 11] <regexp>, ws, value = "\QDefault =\E[ \t]*" <> "(\s*\QDefault =\E[ \t]*).*" [prio 11] <regexp>, ws, value = "\Q(Default =\E[ \t]*" <> "(\s*\Q(Default =\E[ \t]*).*" [prio 10] <regexp>, ws, value = "\Q(\E[ \t]*(.+?)\Q)\E" <> "(\s*\Q(\E[ \t]*(.+?)\Q)\E).*" >> ? [prio 10] <regexp>, ws, value = "\Q(\E[ \t]*(\d+)\Q)\E[ \t]*" <> "(\s*)\E[ \t]*).*" >> ? [prio 5] <number>, ws [prio 3] <text>, ws, endsline, value = "" [prio 3] <text>, ws, value = "For" [prio 3] <text>, ws, value = "if" [prio 3] <text>, ws, value = "Otherwise" [prio 3] <text>, ws, value = "." [prio 3] <text>, ws, value = "M" [prio 3] <text>, ws, value = "M*" [prio 3] <text>, ws, value = "T" [prio 3] <text>, ws, value = "T*" [prio 0] <END_OF_TABLE_CELL>, ws
Case study: Document Processing (8) Conclusions • Fastparserdevelopment • Input now as easy as output • 50% of time spentoncorrectingtypos in input docs • More input structurerecognized • Clearerrormessages • Fastoperation • Goodintegrationwith ODF, Java, JAXB, Antetc • A few compiler problems • No run-timeproblems • Disambiguationneedsattention
Implementation - Compiler main(String args[]) = {System.out.print ("Hello ")}; {System.out.println("world!")} public static void main(String args[]) { FromJava.mainscript().startScript(null, main_template(), new Object[] {args }); } private static NodeTemplate main_template() { if(main_template != null) {return main_template;} else { main_template = NodeTemplate.makeNodeTemplate( "", "T", "main", "([Ljava/lang/String;)", "T__main_code", 9, (short)0, (short)1, new Object[][] { new Object[] {new int[] { 12, 0, 10, 7, 10, 26}, new int[] {10,7,4}}, new Object[] {new int[] { 59, 0, 10, 29, 11, 59}, new int[] {10, 59}}, new Object[] {new int[] {123, 1, 10, 29, 10, 59} }, new Object[] {new int[] {123, 1, 11, 29, 11, 59} }, } }); return main_template; } } public static void T__main_code(Node node, int i) { switch(i) { case 0: System.out.print("Hello "); return; case 1: System.out.println("world!"); break;} }
Implementation - Notes • Based on ITM implementation, 1982 • Compiler: complicated • VM: 100k, fast • VM: Just Java • VM: No extra threads • VM: Could be bugfree…
Subscript on Scala • Available on JVM+DotNet • Functional programming • Multiple Inheritance-like • No more “static” items • Syntactic sugar: less semicolons, parentheses • Gaining momentum • Extendible compiler
Subscript vs Scriptic • simplified syntax for old functionality • simplified semantics for process communication • simplified support for 'forcing' parameters • removed language features for discrete event simulations • allow for plug-in support for discrete event simulations, parallel execution etc • syntactic sugar for very concise specifications • support for more flavours of parallelism + other concepts • unambiguous language definition
Sieve of Eratosthenes objectEratosthenes{ public scripts main(args: Array[String]) = generator(2, 1000000) ==> (..==>sieve) ==[toPrint,]==> printer generator(start,end:Int) = for(i<-start to end) <=i printer = ..=>i:Int? println,i sieve = =>p:Int? toPrint<=p; ..=>i:Int? if(i%p!=0) <=i <==>i:Int = ηtoPrint<=,=>i:Int = η}
Example: a LookupApplicaton(5) searchCommand = searchButton + KeyEvent.VK_ENTER , searchTFcancelCommand = cancelButton + KeyEvent.VK_ESCAPE, searchTFexitCommand = exitButton + windowClosing exit = exitCommand@swing: while (!confirmExit cancelSearch = cancelCommand @swing: showCanceledText live = searchSequences || exit searchSequences= ...searchSequence searchSequence= searchCommand; searchAction / cancelSearch searchAction = showSearchingTextsearchInDBshowSearchResults 38
Syntax (1) subScriptCode = "scripts" operatorModifiers; ..scriptDefinition scriptDefinition = scriptDefinitionLHS; ";" + ("+="+"=") scriptExpression scriptDefinitionLHS = scriptHeader + "===" (scriptHeader..) scriptHeader = scriptName; (."..") optionalParameters.."," scriptName + doubleArrowoptionalParameters scriptName = identifier + "_" optionalParameters = . "(" formalParameters ")" formalParameters = .; formalParameter .. "," formalParameter = identifier ":" type .formalOutputMarker formalOutputMarker = "?" + "??" scriptExpression = operatorModifiersscriptExpression(10)
Syntax (2) scriptExpression(i:Int) = if (i>=0) (scriptExpression(i-1) .. operator(i)) else scriptTerm operator(i:Int) =+ i matches ( case 10 ==> if newLineSignificant newLine else δ case 9 ==> ";" case 8 ==> "||" "|" "||·" "|·" "|+" "|;" "|/" "||+" "||;" "||/" "|+|" "|;|" "|/|" case 7 ==> "&&" "&" "&&·" "&·" case 6 ==> "==" "<==" "==>" "<==>“ "==·" "<==·" "==>·" "<==>·“ case 5 ==> "+" case 4 ==> "/" "%" "/#" "%#" "/#/" "%#%" case 3 ==> "#“ case 2 ==> "‖" "╙“ case 1 ==> "·" case 0 ==> if commasOmittable δ else ε )
Syntax (3) scriptTerm =;+variableDeclaration privateDeclaration ternary "try" simpleTerm (catchClause %# finallyClause) "if" valueExpressionsimpleTerm ."else" simpleTerm ternary = unary . "?" ternary . ":" ternary unary = ..(directive+unaryOperator); simpleTerm directive = "@" (directivePart ..",") ":“ directivePart = . "†"; . "#"; scalaCode unaryOperator =+ "!" "-" "~" "*" "**“ simpleTerm =;+ simpleValueLedTerm codeFragment throwTerm whileTerm forTerm specialTerm "(" scriptExpression ")" arrow . actualParameters
Syntax (4) doubleArrow =+ "<-->" "<==>" arrow =+ "<-“ "->" "<-*" "*->“ "?->" "<=" "=>" "<=*“ "*=>“ "?=>“ actualParameters = simpleActualParameters + classicActualParameters ."??" valueExpression simpleActualParameters = simpleActualParameter..parameterSeparator classicActualParameters = "(" ( .; actualParameter.."," ) ")“ parameterSeparator = "," + ifcommasOmittableε simpleActualParameter = simpleValueExpression . actualOutputMarker actualParameter = valueExpression . actualOutputMarker actualOutputMarker = . ":" type; "?" + "??" valueExpression specialTerm =+ "δ" "ε" "η" "μ" "ν" "τ" "." ".." "..." "break“ identifiers = identifier..",“ variableDeclaration = "val" identifiers "=" simpleValueExpression + "var" identifiers (":" type %# "=" simpleValueExpression)
Syntax (5) privateDeclaration = "private"; identifier..",“ simpleValueLedTerm = simpleValueExpression; (.actualOutputMarker) ..parameterSeparatorsimpleValueExpression + arrow . actualParameters + "match" "(" scriptCaseClauses ")" simpleValueExpression = "_“ + literal + "{=" scalaExpression "=}“ + "new" (classTemplate + templateBody) + ( "here" + currentInstanceExpression + identifier ."." currentInstanceExpression) (.. "." identifier) (. classicActualParameters) currentInstanceExpression = "this" + "super" "." identifier
Syntax (6) codeFragment = ;+ "{" scalaCode "}“ "{*" scalaCode "*}“ "{?" scalaCode "?}“ "{!" scalaCode "!}“ "{." scalaCode ".}“ "{.." scalaCode "..}“ "{..." scalaCode ; "...}" + "..}" whileTerm = "while" valueExpression throwTerm = "throw" valueExpression forTerm = "for"; "(" enumerators ")" + "{" enumerators "}“ catchClause = "catch" "(" (scriptCaseClause..) ")“ scriptCaseClause =;; "case" pattern . "if" valueExpression ("=>" + "*=>") scriptExpression finallyClause = "finally" "{" scalaCode "}“ valueExpression = parenthesizedExpression + simpleValueExpression parenthesizedExpression = "(" scalaExpression ")"