Skip to content

Commit

Permalink
[runtime][expression] Add support for the entailment.
Browse files Browse the repository at this point in the history
  • Loading branch information
ptal committed Nov 10, 2018
1 parent 1545e39 commit f6f9289
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 56 deletions.
4 changes: 4 additions & 0 deletions runtime/src/main/java/bonsai/runtime/lattices/ES.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public ES(Kleene k) {
value = k;
}

public Kleene unwrap() {
return value;
}

public ES bottom() {
return new ES(Kleene.UNKNOWN);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,23 @@

public class Scheduler
{
private HashMap<Event, ArrayList<Schedulable>> waitingQueue;
private HashMap<Event, ArrayList<Schedulable>> waitingList;
private boolean scheduledProcess;

public Scheduler() {
waitingQueue = new HashMap();
waitingList = new HashMap();
scheduledProcess = false;
}

public void subscribe(Event event, Schedulable process) {
waitingQueue
waitingList
.computeIfAbsent(event, k -> new ArrayList<>())
.add(process);
}

// When `schedule` is called, the processes registered on this event are removed from the `waitingList`;
public void schedule(Event event) {
ArrayList<Schedulable> processes = waitingQueue.get(event);
ArrayList<Schedulable> processes = waitingList.get(event);
if (processes != null) {
for (Schedulable s: processes) {
s.schedule(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,27 @@
import java.util.*;
import bonsai.runtime.synchronous.interfaces.*;
import bonsai.runtime.synchronous.*;
import bonsai.runtime.synchronous.env.*;

public abstract class Access extends ASTNode implements Expression
{
protected String uid;
private boolean hasSubscribed;

public Access(String uid) {
this.uid = uid;
hasSubscribed = false;
}

public void prepareInstant(Layer layer) {
hasSubscribed = false;
}

protected void subscribe(Layer layer, int eventKind) {
if (!hasSubscribed) {
hasSubscribed = true;
Event event = new Event(uid, eventKind);
layer.subscribe(event, this);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2018 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package bonsai.runtime.synchronous.expressions;

import java.util.*;
import java.util.function.*;
import bonsai.runtime.core.*;
import bonsai.runtime.lattices.*;
import bonsai.runtime.synchronous.interfaces.*;
import bonsai.runtime.synchronous.*;
import bonsai.runtime.synchronous.env.*;
import bonsai.runtime.synchronous.variables.*;

// e |= e'
public class Entailment extends ASTNode implements Expression
{
// We have the variables appearing in the left and right side of the entailment.
// Note that constant are not represented in this class and directly compiled into the closure.
private List<FreeAccess> leftVars;
private List<FreeAccess> rightVars;
private Function<ArrayList<Object>, ES> eval;
private ExprResult result;

public Entailment(List<FreeAccess> leftVars, List<FreeAccess> rightVars,
Function<ArrayList<Object>, ES> eval) {
this.leftVars = leftVars;
this.rightVars = rightVars;
this.eval = eval;
this.result = new ExprResult();
}

private void prepareArgs(Layer layer, List<FreeAccess> accesses) {
for (FreeAccess access: accesses) {
access.prepareInstant(layer);
}
}

public void prepareInstant(Layer layer) {
this.result = new ExprResult();
prepareArgs(layer, leftVars);
prepareArgs(layer, rightVars);
}

private boolean evalArgs(Layer layer, List<FreeAccess> accesses,
ArrayList<Object> args)
{
boolean isReadOnly = true;
for (FreeAccess access : accesses) {
Variable var = access.executeFree(layer);
isReadOnly = isReadOnly && var.isReadable();
args.add(var.value());
}
return isReadOnly;
}

// We check if the result of the entailment cannot change anymore in the current instant.
// In this case, we promote unknown to false.
private Kleene promoteResult(Kleene r, boolean leftReadOnly, boolean rightReadOnly) {
Kleene promoted = null;
if (r == Kleene.UNKNOWN && leftReadOnly && rightReadOnly) {
promoted = Kleene.FALSE;
}
else if (r == Kleene.TRUE && rightReadOnly) {
promoted = Kleene.TRUE;
}
else if (r == Kleene.FALSE && leftReadOnly) {
promoted = Kleene.FALSE;
}
return promoted;
}

public ExprResult execute(Layer layer) {
if (result.isSuspended()) {
ArrayList<Object> args = new ArrayList();
boolean leftReadOnly = evalArgs(layer, leftVars, args);
boolean rightReadOnly = evalArgs(layer, rightVars, args);
Kleene r = eval.apply(args).unwrap();
Kleene promoted = promoteResult(r, leftReadOnly, rightReadOnly);
if (promoted != null) {
result = new ExprResult(new ES(promoted));
}
}
return result;
}

public CanResult canWriteOn(String uid, boolean inSurface) {
return new CanResult(true,false);
}

public void meetRWCounter(Layer layer) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2018 Pierre Talbot

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package bonsai.runtime.synchronous.expressions;

import java.util.*;
import bonsai.runtime.core.*;
import bonsai.runtime.synchronous.interfaces.*;
import bonsai.runtime.synchronous.*;
import bonsai.runtime.synchronous.env.*;
import bonsai.runtime.synchronous.variables.*;

public class FreeAccess extends Access
{
public FreeAccess(String uid) {
super(uid);
}

public ExprResult execute(Layer layer) {
throw new RuntimeException("BUG: Must call executeFree on FreeAccess.");
}

public Variable executeFree(Layer layer) {
subscribe(layer, Event.ANY);
return layer.lookUpVar(uid);
}

public CanResult canWriteOn(String uid, boolean inSurface) {
return new CanResult(true,false);
}

public void meetRWCounter(Layer layer) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,36 +30,29 @@ public ReadAccess(String uid) {
this.hasSubscribed = false;
}

public void prepareInstant(Layer env) {
Variable var = env.lookUpVar(uid);
var.joinRead(env);
public void prepareInstant(Layer layer) {
super.prepareInstant(layer);
Variable var = layer.lookUpVar(uid);
var.joinRead(layer);
}

public ExprResult execute(Layer env) {
Variable var = env.lookUpVar(uid);
public ExprResult execute(Layer layer) {
Variable var = layer.lookUpVar(uid);
if (var.isReadable()) {
return new ExprResult(var.value());
}
else {
subscribe(env, var);
subscribe(layer, Event.CAN_READ);
return new ExprResult();
}
}

void subscribe(Layer env, Variable var) {
if (!hasSubscribed) {
hasSubscribed = true;
Event event = new Event(var.uid(), Event.CAN_READ);
env.subscribe(event, this);
}
}

public CanResult canWriteOn(String uid, boolean inSurface) {
return new CanResult(true,false);
}

public void meetRWCounter(Layer env) {
Variable var = env.lookUpVar(uid);
var.meetRead(env);
public void meetRWCounter(Layer layer) {
Variable var = layer.lookUpVar(uid);
var.meetRead(layer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,43 +23,33 @@

public class ReadWriteAccess extends Access
{
private boolean hasSubscribed;

public ReadWriteAccess(String uid) {
super(uid);
this.hasSubscribed = false;
}

public void prepareInstant(Layer env) {
Variable var = env.lookUpVar(uid);
var.joinReadWrite(env);
public void prepareInstant(Layer layer) {
super.prepareInstant(layer);
Variable var = layer.lookUpVar(uid);
var.joinReadWrite(layer);
}

public ExprResult execute(Layer env) {
Variable var = env.lookUpVar(uid);
public ExprResult execute(Layer layer) {
Variable var = layer.lookUpVar(uid);
if (var.isReadWritable()) {
return new ExprResult(var.value());
}
else {
subscribe(env, var);
subscribe(layer, Event.CAN_READWRITE);
return new ExprResult();
}
}

private void subscribe(Layer env, Variable var) {
if (!hasSubscribed) {
hasSubscribed = true;
Event event = new Event(var.uid(), Event.CAN_READWRITE);
env.subscribe(event, this);
}
}

public CanResult canWriteOn(String uid, boolean inSurface) {
return new CanResult(true, uid == this.uid);
}

public void meetRWCounter(Layer env) {
Variable var = env.lookUpVar(uid);
var.meetReadWrite(env);
public void meetRWCounter(Layer layer) {
Variable var = layer.lookUpVar(uid);
var.meetReadWrite(layer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,24 @@ public WriteAccess(String uid) {
super(uid);
}

public void prepareInstant(Layer env) {
Variable var = env.lookUpVar(uid);
var.joinWrite(env);
public void prepareInstant(Layer layer) {
super.prepareInstant(layer);
Variable var = layer.lookUpVar(uid);
var.joinWrite(layer);
}

// A write access is always possible.
public ExprResult execute(Layer env) {
Variable var = env.lookUpVar(uid);
public ExprResult execute(Layer layer) {
Variable var = layer.lookUpVar(uid);
return new ExprResult(var.value());
}

public CanResult canWriteOn(String uid, boolean inSurface) {
return new CanResult(true, uid == this.uid);
}

public void meetRWCounter(Layer env) {
Variable var = env.lookUpVar(uid);
var.meetWrite(env);
public void meetRWCounter(Layer layer) {
Variable var = layer.lookUpVar(uid);
var.meetWrite(layer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,7 @@ public interface Schedulable
CanResult canWriteOn(String uid, boolean inSurface);
void meetRWCounter(Layer env);
void setParent(Schedulable parent);
// `schedule` can be called even if the current process is terminated.
// see Scheduler.schedule.
void schedule(Schedulable from);
}
14 changes: 7 additions & 7 deletions src/back/compiler/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ impl<'a> StatementCompiler<'a>
use ast::StmtKind::*;
match stmt.node {
Nothing => self.nothing(),
FnCall(java_call) => self.java_call(java_call),
// Seq(branches) => self.sequence(branches),
// OrPar(branches) => self.or_parallel(branches),
// AndPar(branches) => self.and_parallel(branches),
Expand All @@ -73,7 +74,6 @@ impl<'a> StatementCompiler<'a>
// Trap(name, body) => self.trap(name, body),
// Exit(name) => self.exit(name),
// Loop(body) => self.loop_stmt(body),
// FnCall(java_call) => self.java_call(java_call),
// ProcCall(process, args) => self.fun_call(process, args),
// ModuleCall(run_expr) => self.module_call(run_expr),
// Tell(var, expr) => self.tell(var, expr),
Expand All @@ -86,6 +86,12 @@ impl<'a> StatementCompiler<'a>
self.fmt.push("new Nothing()");
}

fn java_call(&mut self, java_call: Expr) {
self.fmt.push("new ClosureAtom(");
compile_closure(self.session, self.context, self.fmt, java_call, false);
self.fmt.push(")");
}

// fn nary_operator(&mut self, op_name: &str, mut branches: Vec<Stmt>)
// {
// if branches.len() == 1 {
Expand Down Expand Up @@ -277,12 +283,6 @@ impl<'a> StatementCompiler<'a>
// self.fmt.push(")");
// }

// fn java_call(&mut self, java_call: Expr) {
// self.fmt.push("new ClosureAtom(");
// compile_closure(self.session, self.context, self.fmt, java_call, false);
// self.fmt.push(")");
// }

// fn trap(&mut self, name: Ident, body: Box<Stmt>) {
// self.fmt.push_line(&format!("SC.until(\"{}\",", name));
// self.fmt.indent();
Expand Down

0 comments on commit f6f9289

Please sign in to comment.