Skip to content

Commit beac93b

Browse files
committed
Added events composition to the JS layer (towards #85)
1 parent 99aae35 commit beac93b

19 files changed

+386
-214
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ a link to this page somewhere in the documentation/system about section.
6161
* :bug: Fixed the bench marker.
6262
* :sparkles: BThread snapshots do not retain their entry point function after their first sync point. This results in lower memory footprint, and a more efficient de/serialization. These result in improved analysis performance and efficiency.
6363
* :sparkles: `BProgramSyncSnapshot`s are serialized using a single stream, and with the b-program's original scope as a top-level scope (([#126](https://github.com/bThink-BGU/BPjs/issues/126)).
64-
* :put_litter_in_its_place: Significant cleanup of the b-program io area.
65-
64+
* :put_litter_in_its_place: Significant cleanup of the b-program io area.
65+
* :sparkles: Event sets (and, by inheritance, events) are now composable. So you can write, e.g., `bp.Event("A").or(bp.Event("B")).negate()` to create an event set that contains all events except `A` and `B`.
66+
* :put_litter_in_its_place: Significant cleanup of the event set area. Some methods moved from `ComposableEventSet` to `EventSets`.
67+
* :sparkles: Another easy event set composition/creation added: `bp.eventSets` gives access to `EventSets`, with methods such as `bp.eventSets.anyOf(...)` and `bp.eventSets.not(...)`
6668

6769
[Earlier Changes](changelog-2020.md)
6870

bpLog.lang

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
2+
Description="BPjs_Log"
3+
4+
Categories = {"bpjs", "shell", "log"}
5+
6+
Identifiers=[[ [a-zA-Z_]\w*(?!\w*\/) ]]
7+
8+
Keywords={
9+
{ Id=1,
10+
List={"Added", "Done", "Starting", "Started", "Ended"},
11+
},
12+
{ Id=2,
13+
List={"BEvent"},
14+
}
15+
-- { Id=3,
16+
-- List={"ls", "cat", "tac", "rev", "cp", "mv", "rm", "rmdir", "chmod", "mkdir", "ls", "ll"},
17+
-- },
18+
19+
-- fixes issue with expressions like ${SHELL="${CONFIG_SHELL-/bin/sh}"}
20+
-- the [^\}]+ part fixes issue with "s#@PATH@#/opt/${pkgname}/bin/# ${pkgdir}/etc/profile.d/${pkgname}.sh"
21+
-- { Id=4,
22+
-- Regex=[[\$\{[^\}]+\$\{.+?\}.+?\}|\$\{.+?\}|\$\(.+?\) ]],
23+
-- },
24+
-- { Id=4,
25+
-- Regex=[[ \$[\w\#]+ ]],
26+
-- },
27+
-- { Id=2,
28+
-- Regex=[[ \-\-?[\w\-]+ ]],
29+
-- },
30+
31+
--see OnStateChange
32+
--{ Id=5,
33+
-- Regex=[[ \*\[.*?\]\* ]],
34+
--}
35+
}
36+
37+
-- hereDoc opening delimiter, see OnStateChange to handle end of string
38+
-- Strings={
39+
-- Delimiter=[[<<[\-]?\s*["']?\s*[A-Za-z_]+["']?|"|`|']],
40+
-- }
41+
42+
IgnoreCase=false
43+
44+
Comments={
45+
{ Block=false,
46+
Delimiter= { [[#]] },
47+
},
48+
}
49+
50+
-- Operators=[[\(|\)|\[|\]|\{|\}|\,|\;|\:|\&|<|>|\!|\=|\/|\*|\%|\+|\-|\|]]
51+
52+
function OnStateChange(oldState, newState, token, kwClass)
53+
54+
if oldState==HL_STRING and token==hereDoc then
55+
hereDoc = nil
56+
return HL_STRING_END
57+
end
58+
59+
if (string.sub(token,1,1) =="$" ) and oldState==HL_STRING and newState==HL_KEYWORD then
60+
return HL_INTERPOLATION
61+
end
62+
63+
-- fix of code like case $1 in *[\\\`\"\$]*)
64+
if kwClass==5 then
65+
return HL_OPERATOR
66+
end
67+
68+
if hereDoc~=nil then
69+
return HL_STRING
70+
end
71+
72+
--recognize hereDoc multine strings
73+
if oldState==HL_STANDARD and newState==HL_STRING then
74+
hereDoc = string.match(token, "<<%-?%s*%'?([%-%a%d_]+)" )
75+
end
76+
77+
return newState
78+
end

src/main/java/il/ac/bgu/cs/bp/bpjs/bprogramio/BPJSStubInputStream.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public BPJSStubInputStream(InputStream in, Scriptable scope, StubProvider aProvi
4545
protected Object resolveObject(Object obj) throws IOException {
4646
return ( obj instanceof StreamObjectStub )
4747
? stubProvider.get((StreamObjectStub) obj)
48-
: obj;
48+
: super.resolveObject(obj);
4949
}
5050

5151
@Override

src/main/java/il/ac/bgu/cs/bp/bpjs/bprogramio/BPJSStubOutputStream.java

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030

3131
import java.io.IOException;
3232
import java.io.OutputStream;
33-
import java.util.ArrayList;
34-
import java.util.List;
3533

3634
/**
3735
* Output stream for {@link BThreadSyncSnapshot} objects. Creates stubs for objects that can link back to the java
@@ -41,28 +39,19 @@
4139
*/
4240
public class BPJSStubOutputStream extends ScriptableOutputStream {
4341

44-
private final List<StreamObjectStub> stubs = new ArrayList<>();
45-
4642
@SuppressWarnings("OverridableMethodCallInConstructor")
4743
public BPJSStubOutputStream(OutputStream out, Scriptable scope) throws IOException {
4844
super(out, scope);
4945
}
5046

5147
@Override
5248
protected Object replaceObject(Object obj) throws IOException {
49+
if ( obj == null ) return null;
5350
if ( obj instanceof BProgramJsProxy ) {
54-
stubs.add(StreamObjectStub.BP_PROXY);
5551
return StreamObjectStub.BP_PROXY;
56-
} else if ( ! (obj instanceof java.io.Serializable) ) {
57-
System.err.println("Attempt to write a non-serializable object " + obj.toString());
58-
return "NOT SERIALIZABLE: " + obj.toString();
5952
} else {
60-
return obj;
53+
return super.replaceObject(obj);
6154
}
6255
}
63-
64-
public List<StreamObjectStub> getStubs() {
65-
return stubs;
66-
}
6756

6857
}

src/main/java/il/ac/bgu/cs/bp/bpjs/execution/jsproxy/BProgramJsProxy.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import il.ac.bgu.cs.bp.bpjs.model.BProgramSyncSnapshot;
1313
import il.ac.bgu.cs.bp.bpjs.model.SyncStatement;
1414
import il.ac.bgu.cs.bp.bpjs.model.ForkStatement;
15-
import il.ac.bgu.cs.bp.bpjs.model.eventsets.ComposableEventSet;
1615
import java.util.Map;
1716
import java.util.Objects;
1817
import java.util.concurrent.atomic.AtomicInteger;
@@ -96,10 +95,16 @@ public CapturedBThreadState(SyncStatement syncStmt, MapProxy modifications) {
9695

9796
public final BpLog log = new BpLog();
9897

98+
/** Deprecated - use eventSets.all */
99+
@Deprecated(forRemoval = true)
99100
public final EventSet all = EventSets.all;
100101

102+
/** Deprecated - use eventSets.none */
103+
@Deprecated(forRemoval = true)
101104
public final EventSet none = EventSets.none;
102105

106+
public final EventSetsJsProxy eventSets = new EventSetsJsProxy();
107+
103108
/**
104109
* Facility for creating random numbers. BPjs code should not use JavaScript's
105110
* random facility, as it won't play well with model checking.
@@ -142,7 +147,7 @@ public JsEventSet EventSet(String name, Object predicateObj) {
142147
}
143148

144149
public EventSet allExcept( EventSet es ) {
145-
return ComposableEventSet.not(es);
150+
return EventSets.not(es);
146151
}
147152

148153
/**
@@ -286,7 +291,7 @@ private EventSet convertToEventSet( Object jsObject ) {
286291

287292
if ( arr.getLength() == 1 ) return (EventSet)arr.get(0);
288293

289-
return ComposableEventSet.anyOf(
294+
return EventSets.anyOf(
290295
arr.getIndexIds().stream()
291296
.map( i ->(EventSet)arr.get(i) )
292297
.collect( toSet() ) );
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright 2021 michael.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
package il.ac.bgu.cs.bp.bpjs.execution.jsproxy;
25+
26+
import il.ac.bgu.cs.bp.bpjs.model.eventsets.ComposableEventSet;
27+
import il.ac.bgu.cs.bp.bpjs.model.eventsets.EventSet;
28+
import il.ac.bgu.cs.bp.bpjs.model.eventsets.EventSets;
29+
import java.util.Arrays;
30+
import java.util.HashSet;
31+
32+
/**
33+
* A proxy for the {@link EventSets} class, exposing its functionality at the
34+
* JavaScript level.
35+
*
36+
* @author michael
37+
*/
38+
public class EventSetsJsProxy {
39+
40+
public final EventSet all = EventSets.all;
41+
42+
public final EventSet none = EventSets.none;
43+
44+
public static EventSet not( final EventSet ifce ) {
45+
if ( ifce==null ) throw new IllegalArgumentException("eventset cannot be null");
46+
return ifce.negate();
47+
}
48+
49+
public static EventSet anyOf( final EventSet... ifces) {
50+
if ( ifces==null ) throw new IllegalArgumentException("eventset collection cannot be null");
51+
return new ComposableEventSet.AnyOf( new HashSet<>(Arrays.asList(ifces)) );
52+
}
53+
54+
public static EventSet allOf( final EventSet... ifces) {
55+
if ( ifces==null ) throw new IllegalArgumentException("eventset collection cannot be null");
56+
return new ComposableEventSet.AllOf(new HashSet<>(Arrays.asList(ifces)));
57+
}
58+
59+
}

src/main/java/il/ac/bgu/cs/bp/bpjs/model/BThreadSyncSnapshot.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import org.mozilla.javascript.Scriptable;
1313

1414
import java.util.Objects;
15-
import org.mozilla.javascript.ScriptRuntime;
1615

1716
/**
1817
* The state of a BThread at {@code bsync}.
@@ -194,6 +193,7 @@ public int hashCode() {
194193
int result = prime * Objects.hash(name, syncStatement);
195194
if (continuation != null) {
196195
result += getContinuationProgramState().hashCode(name);
196+
// result += continuation.hashCode();
197197
}
198198
result += ScriptableUtils.jsHashCode(data);
199199
return result;
@@ -227,6 +227,7 @@ public boolean equals(Object obj) {
227227
} else {
228228
// Check equality on the PC+stack+heap
229229
return getContinuationProgramState().equals(other.getContinuationProgramState());
230+
// return continuation.equals(other.getContinuation());
230231
}
231232
}
232233

src/main/java/il/ac/bgu/cs/bp/bpjs/model/eventselection/OrderedEventSelectionStrategy.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import il.ac.bgu.cs.bp.bpjs.model.SyncStatement;
2727
import il.ac.bgu.cs.bp.bpjs.model.BEvent;
2828
import il.ac.bgu.cs.bp.bpjs.model.BProgramSyncSnapshot;
29-
import il.ac.bgu.cs.bp.bpjs.model.eventsets.ComposableEventSet;
3029
import il.ac.bgu.cs.bp.bpjs.model.eventsets.EventSet;
3130
import il.ac.bgu.cs.bp.bpjs.model.eventsets.EventSets;
3231
import static java.util.Collections.emptySet;
@@ -60,7 +59,7 @@ public Set<BEvent> selectableEvents(BProgramSyncSnapshot bpss) {
6059
return externalEvents.isEmpty() ? emptySet() : singleton(externalEvents.get(0));
6160
}
6261

63-
EventSet blocked = ComposableEventSet.anyOf(statements.stream()
62+
EventSet blocked = EventSets.anyOf(statements.stream()
6463
.filter( stmt -> stmt!=null )
6564
.map(SyncStatement::getBlock )
6665
.filter(r -> r != EventSets.none )

src/main/java/il/ac/bgu/cs/bp/bpjs/model/eventselection/PrioritizedBSyncEventSelectionStrategy.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import il.ac.bgu.cs.bp.bpjs.model.SyncStatement;
2727
import il.ac.bgu.cs.bp.bpjs.model.BEvent;
2828
import il.ac.bgu.cs.bp.bpjs.model.BProgramSyncSnapshot;
29-
import il.ac.bgu.cs.bp.bpjs.model.eventsets.ComposableEventSet;
3029
import il.ac.bgu.cs.bp.bpjs.model.eventsets.EventSet;
3130
import il.ac.bgu.cs.bp.bpjs.model.eventsets.EventSets;
3231
import static java.util.Collections.emptySet;
@@ -63,7 +62,7 @@ public Set<BEvent> selectableEvents(BProgramSyncSnapshot bpss) {
6362
Set<SyncStatement> statements = bpss.getStatements();
6463
List<BEvent> externalEvents = bpss.getExternalEvents();
6564

66-
EventSet blocked = ComposableEventSet.anyOf(statements.stream()
65+
EventSet blocked = EventSets.anyOf(statements.stream()
6766
.filter( stmt -> stmt!=null )
6867
.map(SyncStatement::getBlock )
6968
.filter( r -> r != EventSets.none )

src/main/java/il/ac/bgu/cs/bp/bpjs/model/eventselection/PrioritizedBThreadsEventSelectionStrategy.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import il.ac.bgu.cs.bp.bpjs.model.SyncStatement;
1616
import il.ac.bgu.cs.bp.bpjs.model.BEvent;
1717
import il.ac.bgu.cs.bp.bpjs.model.BProgramSyncSnapshot;
18-
import il.ac.bgu.cs.bp.bpjs.model.eventsets.ComposableEventSet;
1918
import il.ac.bgu.cs.bp.bpjs.model.eventsets.EventSet;
2019
import il.ac.bgu.cs.bp.bpjs.model.eventsets.EventSets;
2120
import java.util.Collection;
@@ -55,7 +54,7 @@ public Set<BEvent> selectableEvents(BProgramSyncSnapshot bpss) {
5554
return externalEvents.isEmpty() ? emptySet() : singleton(externalEvents.get(0));
5655
}
5756

58-
final EventSet blocked = ComposableEventSet.anyOf(statements.stream()
57+
final EventSet blocked = EventSets.anyOf(statements.stream()
5958
.filter( stmt -> stmt!=null )
6059
.map(SyncStatement::getBlock )
6160
.filter( r -> r != EventSets.none )

0 commit comments

Comments
 (0)