Files @ fc987660fdee
Branch filter:

Location: CSY/reowolf/testdata/parser/positive/tarry.pdl

MH
WIP on compiler rearchitecting
#version 100

/*
Example distributed algorithm: Tarry's algorithm.

A token passes around the network, starting at some initiator. The initiator
starts the algorithm, and when the algorithm ends the token is back again at
the initiator. The non-initiators are signaled when they receive the token
for the first time; when the token is handled traversal continues.

The network topology is defined by applications: they create an initiator or
non-initiator component, and establish bidirectional channels in between.
In this example, the whole network is created statically for simulation
purposes: there are 4 processes and some channels in between.

Ports: initiator start, initiator end, three pairs of signals.
*/

import std.reo;

composite main(in start, out end, out s1o, in s1i, out s2o, in s2i, out s3o, in s3i) {
	// Processes: p, q, r, s
	// Channels: pq, pr, qr, rs
	channel p_pq -> pq_q;
	channel q_pq -> pq_p;
	channel p_pr -> pr_r;
	channel r_pr -> pr_p;
	channel q_qr -> qr_r;
	channel r_qr -> qr_q;
	channel r_rs -> rs_s;
	channel s_rs -> rs_r;
	
	new initiator(start, end, {pq_p, pr_p}, {p_pq, p_pr});
	new noninitiator(s1o, s1i, {pq_q, qr_q}, {q_pq, q_qr});
	new noninitiator(s2o, s2i, {pr_r, rs_r}, {r_pr, r_rs});
	new noninitiator(s3o, s3i, {rs_s}, {s_rs});
}
primitive initiator(in start, out end, in[] peeri, out[] peero) {
	msg token = null;
	in[] neighbori = {};
	out[] neighboro = {};
	assert peeri.length == peero.length;
	while (true) {
		// Step 1. Initiator waits for token
		while (token == null) {
			synchronous {
				if (fires(start)) {
					token = get(start);
				}
			}
		}
		// Reset neighbors
		neighbori = peeri;
		peeri = {};
		neighboro = peero;
		peero = {};
		// Step 2. Keep sending token to processes
		while (neighbori.length > 0) {
			int idx = 0;
			// Select first channel that accepts our token
			while (token != null) {
				synchronous {
					int i = 0;
					while (i < neighboro.length) {
						if (fires(neighboro[i])) {
							put(neighboro[i], token);
							idx = i;
							token = null;
							break;
						} else i++;
					}
				}
			}
			// Eliminate from neighbor set
			peeri = {neighbori[idx]} @ peeri;
			peero = {neighboro[idx]} @ peero;
			neighbori = neighbori[0:idx] @ neighbori[idx:neighbori.length];
			neighboro = neighboro[0:idx] @ neighboro[idx:neighboro.length];
			// Step 3. Await return of token
			while (token == null) {
				synchronous {
					int i = 0;
					while (i < peeri.length + neighbori.length) {
						if (fires(peeri@neighbori[i])) {
							token = get(peeri@neighbori[i]);
							break;
						} else i++;
					}
				}
			}
		}
		// Step 4. Token is back and all neighbors visited
		while (token != null) {
			synchronous {
				if (fires(end)) {
					put(end, token);
					token = null;
				}
			}
		}
	}
}
primitive noninitiator(out start, in end, in[] peeri, out[] peero) {
	msg token = null;
	in[] neighbori = {};
	out[] neighboro = {};
	in[] parenti = {};
	out[] parento = {};
	assert peeri.length == peero.length;
	while (true) {
		int idx = 0;
		// Step 1. Await token for first time
		while (token == null) {
			synchronous {
				int i = 0;
				while (i < peeri.length) {
					if (fires(peeri[i])) {
						token = get(peeri[i]);
						idx = i;
						break;
					} else i++;
				}
			}
		}
		// Reset neighbors
		neighbori = peeri[0:idx] @ peeri[idx:peeri.length];
		neighboro = peero[0:idx] @ peero[idx:peero.length];
		parenti = {peeri[idx]};
		parento = {peero[idx]};
		peeri = {};
		peero = {};
		// Step 2. Non-initiator signals
		while (token != null) {
			synchronous {
				if (fires(end)) {
					put(end, token);
					token = null;
				}
			}
		}
		while (token == null) {
			synchronous {
				if (fires(start)) {
					token = get(start);
				}
			}
		}
		// Step 3. Keep sending token to processes
		while (neighbori.length > 0) {
			idx = 0;
			// Select first channel that accepts our token
			while (token != null) {
				synchronous {
					int i = 0;
					while (i < neighboro.length) {
						if (fires(neighboro[i])) {
							put(neighboro[i], token);
							idx = i;
							token = null;
							break;
						} else i++;
					}
				}
			}
			// Eliminate from neighbor set
			peeri = {neighbori[idx]} @ peeri;
			peero = {neighboro[idx]} @ peero;
			neighbori = neighbori[0:idx] @ neighbori[idx:neighbori.length];
			neighboro = neighboro[0:idx] @ neighboro[idx:neighboro.length];
			// Step 4. Await return of token
			while (token == null) {
				synchronous {
					int i = 0;
					while (i < peeri.length + neighbori.length) {
						if (fires(peeri@neighbori[i])) {
							token = get(peeri@neighbori[i]);
							break;
						} else i++;
					}
				}
			}
		}
		// Step 5. Token is back, pass to parent
		while (token != null) {
			synchronous {
				if (fires(parento[0])) {
					put(parento[0], token);
					token = null;
				}
			}
		}
		peeri = {parenti[0]} @ peeri;
		peero = {parento[0]} @ peero;
		parenti = {};
		parento = {};
	}
}