feature |
SR |
JR |
notes |
alternation |
if B1 -> S1
[] B2 -> S2
...
fi |
// native Java
if (C1) then {T1}
else if (C2) then {T2}
... |
SR's if is non-deterministic;
Java's is deterministic. Ci represents rewrite of Bi where Ci's
are now evaluated in order. Ti represents rewrite of Si into JR
code. |
indefinite iteration |
do B1 -> S1 od
do B1 -> S1
[] B2 -> S2
...
od
|
// native Java
while(C1) {T1}
// native Java
while(true) {
if (C1) then {T1}
else if (C2) then {T2}
...
else break;
}
|
see notes under alternation. |
definite iteration |
fa Q1, Q2, ... -> S af |
// native Java
for(R1) {
for(R2) {
...
T
}
} |
Qi represents an SR quantifier (e.g., i:=1 to 5 by 2); Ri
represents
its Java rewrite (e.g., int i=1; i <=5; i+=2). T represents
rewrite
of S into JR code. |
loop escape |
exit
next
|
// native Java
break
// native Java
continue |
As seen above, a fa loop with multiple quantifiers maps to
nested loops.
So, if exiting from such a loop, will need to give that loop a name, n,
and then `break n'. |
do nothing |
skip |
// native Java
// just omit from code |
|
stop program execution |
stop(expr) |
// JR extension
import edu.ucdavis.jr.JR;
...
JR.exit(expr) |
|
assignment |
x := e |
// native Java
x = f |
f represents possible rewrite of e into JR. |
swap |
x :=: y |
// native Java
{U tmp=x; x=y; y=tmp;} |
U represents type of x and y. (JR translation doesn't cover
the case
that swap appears as part of an expression, e.g., `if x:=:y -> ...
fi'.) |
output |
write(e1,e2,...)
writes(e1,e2,...) |
// native Java
System.out.println(
(f1)+" "+(f2)+...);
System.out.print(
(f1)+(f2)+...); |
fi represent possible rewrite of ei into JR. |
input |
read(v1,v2,...) |
// native Java
... |
Ugh. Too messy to show here! See Java text. |
input statement |
in op1(formals)
st b1 by e1 -> S1
[] ...
ni |
// JR extension
inni type1 op1(formals)
st c1 by f1 {T1}
[] type2 op2(formals)
st c2 by f2 {T2}
... |
type1 is op1's type.
SR formals are id; JR formals are ids and types.
So, JR's inni header is similar to that of Java's method header.
JR's inni (like SR's in) also supports quantifiers.
JR also supports additional flexibility in invocation
selection
(keywords: as, over, view, with).
|
receive statement |
receive op(v1,...) |
// JR extension
receive op(v1,...) |
|
send statement |
send op(e1,...) |
// JR extension
send op(f1,...) |
|
call statement |
call op(e1,...) |
// JR extension
call op(f1,...) |
|
concurrent invocation statement |
co ... oc |
CURRENTLY BEING DESIGNED
& IMPLEMENTED |
2004-10-06 beta version done! will be in next release.
|
semaphore |
sem ...
P ...
V ... |
// JR extension
sem ...
P ...
V... |
Arrays of semaphores are allowed and are similar to arrays of
void
operations.;
they are initialized similarly too. (See op declaration below.) |
proc |
proc ... |
// native Java method
... |
|
procedure |
procedure ... |
// native Java method
... |
|
process |
# simple
process p
...
end
# process family
process q(i:=1 to 4)
...
end
# 2D process family
# with st
process r(i:=1 to 4, j := 1 to 5 st i!=j)
...
end
|
//simple process
process p { ...}
// or
process p() {}
// process family
// note: extra ; and ()
// required
process q((int i=1;i<=4;i++;) ){ ....}
// 2D process family with st
process r((int i=1; i <=4; i++), (int j=1; j<=5; j++; i!=j) {
...}
|
non-static processes are created at the end of the
constructor, just
before it returns.
static processes are created as though they are created by
static initializers.
(Of course, processes are just an abbreviation. They can
be simulated
using an equivalent op decl, send(s), and a proc; with the
send(s)
in the class constructor or a static initializer.)
|
return statement |
return |
// native Java
// within void
return
// within non-void
return expression
|
|
reply statement |
reply |
// JR extension
// within void
reply
// within non-void
reply expression
|
(for consistency with Java's return statement.)
SR initial code corresponds to code within a constructor in a JR class;
reply is allowed in SR initial code, but not within JR's constructor
code. |
forward statement |
forward op(e1,...) |
// JR extension
forward op(f1,...) |
fi represents rewrite of ei. |
variable declaration |
var v1: t1, v2: t2, ...
var v1:t1:=e1, v2:t2:=e2,...
|
// native Java
private t1 v1;
private t2 v2;
...
// native Java
private t1 v1 = f1;
private t2 v2 = f2;
... |
fi represents rewrite of ei. |
arrays |
|
// native Java |
JR arrays are 0-based (unlike SR's 1-based default or
explicit lower
bound) and can be indexed only by integers. |
record type |
rec(field1, field2, ...) |
// native Java
public class
unique_name {
public type1 v1;
public type2 v2;
...
} |
fieldi is rewritten to typei vi.
qualified notation to access fields still used.
|
union type |
union(field1, field2, ...) |
// native Java
// rewrite same as
// for record type above |
Java doesn't have union types (to be safe), so simulate by a
record.
This wastes space (the current SR implementation uses that approach
anyway). |
enumeration type |
enum(id1, id2, ...) |
// native Java |
Java doesn't have enumeration types but they can be easily
simulated. |
pointers |
ptr, any, @, etc. |
// native Java
// no pointers! |
|
type declaration |
type t = type_definition |
// native Java
// replace occurrences
// of t by type_definition |
|
optype declaration |
optype t = operation_spec |
// no real equivalent
// just repeat equivalent
// prototype info as needed |
|
op declaration |
op n(params)
op n(params) returns t
#an array of ops, e.g.,
op n[0:9](params)returns int
|
// JR extension
// (can use private|public)
op void n(params)
op t n(params)
// an array of ops, e.g.,
cap int (params)n [] =
new cap int(params)[10];
for (int i=0;i<10;i++){
n[i] = new op int(params);
}
|
JR does not support operation restrictions (e.g., `{send}'.
(Arrays make sense if you think about it.)
|
op cap |
n: cap operation_spec |
// JR extension
cap prototype n |
|
(dynamic) op instantiation |
new (op operation_spec) |
// JR extension
new op prototype |
|
resource component |
resource n
imports
constant, type, or op decls
body n(params)
decls, stmts, procs
end |
// native Java
publicclass n {
constants
public n(params) {
// Constructor
}
} |
Be sure to make the main class public!
Be sure to make the constructor public!
(Not quite equivalent due to scoping.)
|
resource cap |
c: cap n |
remote n c |
(see note under resource instantiation) |
resource instantiation |
create n(args) |
// JR extension
new remote n(args)
// native Java
new n(args)
|
A remote object corresponds more closely to an SR
resource instance;
e.g., it can be located on a remote VM.
But sometimes just a plain Java object suffices.
|
global component |
global g
imports
decls
body g
decls, stmts, procs
end |
// native Java
// use class as in translation // of resource component but // with
variables and
// functions made static. |
|
global instantiation |
# implicit on executing first
# import g on each VM |
// native Java
// implicitly created
// on first use |
|
inheritance |
extend # as a very weak form |
// native Java
// use extends |
JR also allows inheritance of operations, which provides
additional flexibility for servicing invocations.
|
virtual machine cap |
n: cap vm |
// JR extension
cap vm n |
|
virtual machine creation |
create vm() |
// JR extension
new cap vm() |
JR also supports parameterized VMs.
|
capability constants |
null
noop |
// JR extension
null
noop |
noop currently implemented for only operation caps, not
remote
objects. |
destroying instances of resources and VMs |
destroy rcap
destroy vmcap |
NOT YET DESIGNED & IMPLEMENTED |
No simple equivalent (yet) in JR. The intent is that a
JRobject
will be garbage collected when no references to it exist (so set all
caps
to it to be null); however, the current RMI-based implementation keeps
some extra references to any JRobject.
We'll need to do something special to destroy VMs.
|
access to command line arguments |
numargs()
getarg(n,v) |
// native Java
// via arguments to main
// see example at bottom
// of page. |
Need to convert String argument to other type (as needed).
A simple trick to provide access to the command-line
arguments
is to store them in a public static variable in the "main" class.
|
make process sleep |
nap(m) |
// native Java
// if m > 0
Thread.sleep(m)
// if m = 0
Thread.yield()
|
My reading of Java documentation is that sleep(0) might not
cause a
yield. |
number of pending invocations |
?opname |
// JR extension
opname.length() |
|
predefined functions |
|
|
most SR predefined functions can be rewritten using Java
library functions. |
main resource |
resource n()
...
end |
// native Java
public class n {
...
public static void
main(String [] args) {...}
...
} |
|
exception handling
|
# none
|
// native Java
// plus extensions for
// handling exceptions
// that occur during
// asynchronous
// activities
|
|
automatic program termination |
SR detects when the program has no potential for activity
(e.g., all
processes terminated or blocked waiting for messages) and shutdown the
program automatically. |
JR does too. by default. That can be disabled by the
-explicit
command line option to jrrun.
JR also supports a "quiescence operation". The program
registers
such an operation; it is invoked implicitly when quiescence is detected.
|
|