440 likes | 558 Views
Join André van Delft at the University of Amsterdam's Department of Theory of Computer Science for a deep dive into event-driven and concurrent programming through the lens of ACP-based language extensions. This lecture covers the evolution of programming concepts, comparisons between ACP and Scriptic, and showcases practical examples, including document processing and lookup applications. Discover historical perspectives and syntactical differences in programming paradigms, and explore how these innovations impact modern computing.
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 ")"