private void VisitFunction(Function function) { Debug.Assert(function.OutParams.Count == 1); List <CommutativityHint> hints = new List <CommutativityHint>(); // First we collect all {:commutativity "first_action", "second_action"} attributes for (QKeyValue kv = function.Attributes; kv != null; kv = kv.Next) { if (kv.Key != CivlAttributes.COMMUTATIVITY) { continue; } if (kv.Params.Count == 2 && kv.Params[0] is string firstActionName && kv.Params[1] is string secondActionName) { firstAction = ctc.FindAtomicActionOrAbstraction(firstActionName); secondAction = ctc.FindAtomicActionOrAbstraction(secondActionName); if (firstAction == null) { ctc.Error(kv, $"Could not find atomic action {firstActionName}"); } if (secondAction == null) { ctc.Error(kv, $"Could not find atomic action {secondActionName}"); } if (firstAction != null && secondAction != null) { CheckInParams(function.InParams); } hints.Add(new CommutativityHint(function, firstAction, secondAction, args)); }