# -*- generated by 1.0.2 -*-
import da
PatternExpr_233 = da.pat.TuplePattern([da.pat.ConstantPattern('ack'), da.pat.FreePattern('c2'), da.pat.BoundPattern('_BoundPattern237_')])
PatternExpr_276 = da.pat.TuplePattern([da.pat.ConstantPattern('request'), da.pat.FreePattern('c2'), da.pat.FreePattern('p')])
PatternExpr_301 = da.pat.TuplePattern([da.pat.ConstantPattern('release'), da.pat.FreePattern(None), da.pat.FreePattern('p')])
PatternExpr_359 = da.pat.TuplePattern([da.pat.ConstantPattern('done')])
PatternExpr_364 = da.pat.BoundPattern('_BoundPattern366_')
PatternExpr_367 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.BoundPattern('_BoundPattern373_')]), da.pat.TuplePattern([da.pat.ConstantPattern('done')])])
PatternExpr_449 = da.pat.TuplePattern([da.pat.ConstantPattern('done'), da.pat.BoundPattern('_BoundPattern452_')])
PatternExpr_455 = da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.TuplePattern([da.pat.FreePattern(None), da.pat.FreePattern(None), da.pat.FreePattern(None)]), da.pat.TuplePattern([da.pat.ConstantPattern('done'), da.pat.BoundPattern('_BoundPattern465_')])])
_config_object = {'channel': 'fifo', 'clock': 'lamport'}
import sys

class P(da.DistProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._PReceivedEvent_0 = []
        self._PReceivedEvent_3 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_0', PatternExpr_233, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_1', PatternExpr_276, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_275]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_2', PatternExpr_301, sources=None, destinations=None, timestamps=None, record_history=None, handlers=[self._P_handler_300]), da.pat.EventPattern(da.pat.ReceivedEvent, '_PReceivedEvent_3', PatternExpr_359, sources=[PatternExpr_364], destinations=None, timestamps=None, record_history=True, handlers=[])])

    def setup(self, s, nrequests, **rest_470):
        super().setup(s=s, nrequests=nrequests, **rest_470)
        self._state.s = s
        self._state.nrequests = nrequests
        self._state.q = set()

    def run(self):

        def task():
            self.output('in cs')
        for i in range(self._state.nrequests):
            self.mutex(task)
        self.send(('done', self._id), self.parent())
        super()._label('_st_label_356', block=False)
        _st_label_356 = 0
        while (_st_label_356 == 0):
            _st_label_356 += 1
            if PatternExpr_367.match_iter(self._PReceivedEvent_3, _BoundPattern373_=self.parent(), SELF_ID=self._id):
                _st_label_356 += 1
            else:
                super()._label('_st_label_356', block=True)
                _st_label_356 -= 1
        self.output('terminating')

    def mutex(self, task):
        super()._label('request', block=False)
        c = self.logical_clock()
        self.send(('request', c, self._id), self._state.s)
        self._state.q.add(('request', c, self._id))
        super()._label('_st_label_198', block=False)
        c2 = p = None

        def UniversalOpExpr_200():
            nonlocal c2, p
            for (_ConstantPattern204_, c2, p) in self._state.q:
                if (_ConstantPattern204_ == 'request'):
                    if (not (((c2, p) == (c, self._id)) or ((c, self._id) < (c2, p)))):
                        return False
            return True
        c2 = p = None

        def UniversalOpExpr_226():
            nonlocal c2, p
            for p in self._state.s:

                def ExistentialOpExpr_231(p):
                    nonlocal c2
                    for (_, _, (_ConstantPattern248_, c2, _BoundPattern251_)) in self._PReceivedEvent_0:
                        if (_ConstantPattern248_ == 'ack'):
                            if (_BoundPattern251_ == p):
                                if (c2 > c):
                                    return True
                    return False
                if (not ExistentialOpExpr_231(p=p)):
                    return False
            return True
        _st_label_198 = 0
        while (_st_label_198 == 0):
            _st_label_198 += 1
            if (UniversalOpExpr_200() and UniversalOpExpr_226()):
                _st_label_198 += 1
            else:
                super()._label('_st_label_198', block=True)
                _st_label_198 -= 1
        super()._label('critical_section', block=False)
        task()
        super()._label('release', block=False)
        self._state.q.remove(('request', c, self._id))
        self.send(('release', self.logical_clock(), self._id), self._state.s)

    def _P_handler_275(self, c2, p):
        self._state.q.add(('request', c2, p))
        self.send(('ack', self.logical_clock(), self._id), p)
    _P_handler_275._labels = None
    _P_handler_275._notlabels = None

    def _P_handler_300(self, p):
        for x in {('request', c, p) for (_ConstantPattern317_, c, _BoundPattern320_) in self._state.q if (_ConstantPattern317_ == 'request') if (_BoundPattern320_ == p)}:
            self._state.q.remove(x)
            break
    _P_handler_300._labels = None
    _P_handler_300._notlabels = None

class Node_(da.NodeProcess):

    def __init__(self, procimpl, props):
        super().__init__(procimpl, props)
        self._Node_ReceivedEvent_0 = []
        self._events.extend([da.pat.EventPattern(da.pat.ReceivedEvent, '_Node_ReceivedEvent_0', PatternExpr_449, sources=None, destinations=None, timestamps=None, record_history=True, handlers=[])])

    def run(self):
        nprocs = (int(sys.argv[1]) if (len(sys.argv) > 1) else 10)
        nrequests = (int(sys.argv[2]) if (len(sys.argv) > 2) else 1)
        ps = self.new(P, num=nprocs)
        for p in ps:
            self._setup(p, ((ps - {p}), nrequests))
        self._start(ps)
        super()._label('_st_label_441', block=False)
        p = None

        def UniversalOpExpr_442():
            nonlocal p
            for p in ps:
                if (not PatternExpr_455.match_iter(self._Node_ReceivedEvent_0, _BoundPattern465_=p)):
                    return False
            return True
        _st_label_441 = 0
        while (_st_label_441 == 0):
            _st_label_441 += 1
            if UniversalOpExpr_442():
                _st_label_441 += 1
            else:
                super()._label('_st_label_441', block=True)
                _st_label_441 -= 1
        self.send(('done',), ps)
