# checks the follg.:
# 1. after a forward() subsequent forward()'s should act as send's
# 2. the statements following a 'return' in a op (that has forwarded control)
#    should not be executed
# 3. an op can refer formals after forwarding; var/res var.s are not affected
#    by assignments to them after a forward()
# 4. an op can forward to itself

resource fwd3()
    op initop(var int, string[*]) returns int # will fwd to fwd1() first
    op fwd1(var int, string[*]) returns int # will fwd to fwd2() first
    op fwd2(var int, string[*]) returns int # will self-fwd first
    op second_fwd(var int, string[*]) returns int # all the above procs, }ter
			#fwding once, will then do a forward to second_fwd()

    sem wait_for_secondfwd = 0

    #---------------------------------------------------------------------
    int initop_aft_fwd = 0   # a var that will be assigned to }ter fwding
    proc initop(i, s) returns result  {
	write("initop : ", s, i)
	write("forwarding to fwd1 ")
	i = 2
	s = "forwarded by initop"
	forward fwd1(i, s)

	forward second_fwd(i, s) #should act as a send

	reply # should have no effect on the caller

	# checks point 3 mentioned at the beginning of the prog.
	initop_aft_fwd = i*10  # should be 20

	result = i # but this should not be returned to the caller
	return
	write("initop : this should not have been printed")
    }

    #---------------------------------------------------------------------
    int fwd1_aft_fwd = 0 # a var that will be assigned to }ter fwding
    proc fwd1(j, s) returns result  {
	write("fwd1 : ", s, j)
	write("forwarding to fwd2 ")
	j = 3
	s = "forwarded by fwd1"
	forward fwd2(j, s)

	reply # should not have any effect on the caller

	forward second_fwd(j, s) #should act as a send

	# checks point 3 mentioned at the beginning of the prog.
	fwd1_aft_fwd = j*10  # should be 30

	result = j
	if (true) { return }
	write("initop : this should not have been printed")
    }

    #---------------------------------------------------------------------
    proc fwd2(k, s) returns result  {
	write("fwd2 : ", s, k)
							# self forward
	if (k > 0) { k = k - 1; s = "forwarded by fwd2"; forward fwd2( k, s)
	} else { k = 4; result = k
	}
	# the above "result" is the result that is to be
	# returned to the caller of initop(); also the 1st param is a
	# var param - so "4" is the last value that is to be copied out to
	# that.


	return

	s = "forwarded by fwd2"
	forward second_fwd(k, s) #shouldn't be forwarded
	write("initop : this should not have been printed")
    }

    #---------------------------------------------------------------------
    int   second_fwd_arr[2:3] =  ([2] 0)
    proc second_fwd(i, s) returns result  {
	second_fwd_arr[i] = i
	result = 5
	V(wait_for_secondfwd)
    }

    #---------------------------------------------------------------------
    int i = 1

    write(initop(i, "called from mainline")) # 4
    write(i) # 4
    write(initop_aft_fwd) # 20
    write(fwd1_aft_fwd) # 30

    # wait for the second_fwd_arr[] to get assigned values by second_fwd()
    P(wait_for_secondfwd); P(wait_for_secondfwd)
    for [ i= 2 to 3 ] { write(second_fwd_arr[i]) } # 2 3

end fwd3
