private void CheckWellFormedness(BindModuleExpr bindExpr) { if (bindExpr.ModuleInfo != null) { return; } // checked already that the bindings is a function // check that receive set of interface is a subset of the receive set of machine foreach (var binding in bindExpr.Bindings) { if (!binding.Item1.ReceivableEvents.IsSubsetEqOf(binding.Item2.Receives)) { throw handler.InvalidBindExpr(bindExpr.SourceLocation, $"receive set of {binding.Item1.Name} is not a subset of receive set of {binding.Item2.Name}"); } if (!binding.Item2.PayloadType.IsAssignableFrom(binding.Item1.PayloadType)) { throw handler.InvalidBindExpr(bindExpr.SourceLocation, $"payload type of {binding.Item1.Name} is not a subtype of payload type of {binding.Item2.Name}"); } } //populate the attributes of the module bindExpr.ModuleInfo = new ModuleInfo(); var currentModuleInfo = bindExpr.ModuleInfo; // 1) Private events and private interfaces are empty // 2) Initialize Ip foreach (var binding in bindExpr.Bindings) { currentModuleInfo.InterfaceDef.Add(binding.Item1, binding.Item2); } // 3) Initialize Lp foreach (var binding in bindExpr.Bindings) { currentModuleInfo.LinkMap[binding.Item1] = new Dictionary <Interface, Interface>(); foreach (var interfaceCreated in binding.Item2.Creates.Interfaces) { currentModuleInfo.LinkMap[binding.Item1][interfaceCreated] = interfaceCreated; } } var boundMachines = bindExpr.Bindings.Select(b => b.Item2).ToList(); // 4) compute the sends currentModuleInfo.Sends.AddEvents(boundMachines.SelectMany(m => m.Sends.Events)); // 5) compute the receives currentModuleInfo.Receives.AddEvents(boundMachines.SelectMany(m => m.Receives.Events)); // 6) compute the creates foreach (var binding in bindExpr.Bindings) { foreach (var createdInterface in binding.Item2.Creates.Interfaces) { currentModuleInfo.Creates.AddInterface(currentModuleInfo.LinkMap[binding.Item1][createdInterface]); } } }