Feature comparison: SR vs. JR
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.



Example of command line argument processing.

    public static void main(String [] args) {

        if (args.length != 2) {
            System.err.println("need 2 command line arguments: machine_name and number_of_iterations");
             try {
                JR.exit(1);
             }
             catch (Exception oops){
                 System.err.println("Exception...\n");
                oops.printStackTrace();
             }
        }

        int N = Integer.parseInt(args[1]); // convert 2nd arg to an int
        ...
    }