public Circuit construct() { Dictionary <int, Circuit.Element> result = new Dictionary <int, Circuit.Element>(); Dictionary <Element, object> elmResult = new Dictionary <Element, object>(); foreach (KeyValuePair <int, Element> here in contents) { Element elm = here.Value; if (elm.availObjects.Count != 1) { throw new ApplicationException("expecting all elements to have exactly one solution"); } signals.ICircuitConnectible avail = elm.availObjects[0]; signals.ICircuitElement newOb = null; switch (elm.type) { case ElementType.Module: { signals.IBlockDriver drv = avail as signals.IBlockDriver; if (drv != null) { newOb = drv.Create(); } else { newOb = (signals.IBlock)avail; } break; } case ElementType.Function: case ElementType.FunctionOnIn: case ElementType.FunctionOnOut: newOb = ((signals.IFunctionSpec)avail).Create(); break; } result.Add(elm.circuitId, new Circuit.Element(new ElemKey(elm), elm.circuitId, newOb)); elmResult.Add(elm, newOb); } foreach (KeyValuePair <EndpointKey, EndpointKey> conn in connections) { EndpointKey from = conn.Key; EndpointKey to = conn.Value; object fromObj = elmResult[from.elem]; object toObj = elmResult[to.elem]; switch (from.elem.type) { case ElementType.Module: { signals.IOutEndpoint outEP = from.OutputEP((signals.IBlock)fromObj); switch (to.elem.type) { case ElementType.Module: { signals.IEPBuffer buff = outEP.CreateBuffer(); signals.IInEndpoint inEP = to.InputEP((signals.IBlock)toObj); outEP.Connect(buff); inEP.Connect(buff); break; } case ElementType.Function: case ElementType.FunctionOnIn: { signals.IEPBuffer buff = outEP.CreateBuffer(); signals.IInEndpoint inEP = ((signals.IFunction)toObj).Input; outEP.Connect(buff); inEP.Connect(buff); break; } case ElementType.FunctionOnOut: { signals.IEPSendTo inEP = ((signals.IFunction)toObj).Output; outEP.Connect(inEP); break; } } break; } case ElementType.Function: case ElementType.FunctionOnIn: { signals.IInputFunction func = ((signals.IFunction)fromObj).Input; switch (to.elem.type) { case ElementType.Module: { signals.IInEndpoint inEP = to.InputEP((signals.IBlock)toObj); inEP.Connect(func); break; } case ElementType.Function: case ElementType.FunctionOnIn: { signals.IInEndpoint inEP = ((signals.IFunction)toObj).Input; inEP.Connect(func); break; } case ElementType.FunctionOnOut: throw new ApplicationException("incompatible connection types"); } break; } case ElementType.FunctionOnOut: { signals.IOutputFunction func = ((signals.IFunction)fromObj).Output; switch (to.elem.type) { case ElementType.Module: { signals.IEPBuffer buff = func.CreateBuffer(); signals.IInEndpoint inEP = to.InputEP((signals.IBlock)toObj); func.Connect(buff); inEP.Connect(buff); break; } case ElementType.Function: case ElementType.FunctionOnIn: { signals.IEPBuffer buff = func.CreateBuffer(); signals.IInEndpoint inEP = ((signals.IFunction)toObj).Input; func.Connect(buff); inEP.Connect(buff); break; } case ElementType.FunctionOnOut: { signals.IOutEndpoint outEP = ((signals.IFunction)toObj).Output; outEP.Connect(func); break; } } break; } } } return(new Circuit(result)); }
public signals.EType OutputType(signals.ICircuitConnectible conn) { return(OutputType(conn.Fingerprint)); }
private void resolveNeighbors(sharptest.ModLibrary library, Element elm) { if (elm.availObjects.Count != 1) { throw new ApplicationException("elm should contain a single availObject by this point"); } signals.ICircuitConnectible avail = elm.availObjects[0]; Dictionary <Element, bool> recurseList = new Dictionary <Element, bool>(); List <KeyValuePair <EndpointKey, EndpointKey> > tempCollect = new List <KeyValuePair <EndpointKey, EndpointKey> >(); tempCollect.AddRange(connections); foreach (KeyValuePair <EndpointKey, EndpointKey> entry in tempCollect) { EndpointKey key = entry.Key; EndpointKey value = entry.Value; if (key.elem == elm) { Element otherElm = value.elem; signals.EType ourType = key.OutputType(avail); bool changed = false; if (otherElm.availObjects.Count > 1) { // if we have more than one option here, just look for possible compatibility List <signals.ICircuitConnectible> newAvail = new List <signals.ICircuitConnectible>(); foreach (signals.ICircuitConnectible otherAvail in otherElm.availObjects) { signals.EType otherType = value.InputType(otherAvail); if (ourType != otherType && findImplicitConversion(library, ourType, otherType) == null) { changed = true; } else { newAvail.Add(otherAvail); } } otherElm.availObjects = newAvail; } if (otherElm.availObjects.Count == 1) { // if we're on one-to-one terms, we might add compat connections signals.ICircuitConnectible otherAvail = otherElm.availObjects[0]; signals.EType otherType = value.InputType(otherAvail); if (ourType != otherType) { signals.IFunctionSpec func = findImplicitConversion(library, ourType, otherType); if (func == null) { // only option isn't type-compatible? Looks like we broke a connection throw new LinkTypeFailure(entry.Key, ourType, entry.Value, otherType); } else { AddImplicitConversion(key, value, func); } } } else if (otherElm.availObjects.Count == 0) { // ran out of possible connections? Looks like we broke a connection throw new CannotResolveElement(otherElm); } if (changed) { recurseList.Add(value.elem, true); } } if (value.elem == elm) { Element otherElm = key.elem; signals.EType ourType = value.InputType(avail); bool changed = false; if (otherElm.availObjects.Count > 1) { // if we have more than one option here, just look for possible compatibility List <signals.ICircuitConnectible> newAvail = new List <signals.ICircuitConnectible>(); foreach (signals.ICircuitConnectible otherAvail in otherElm.availObjects) { signals.EType otherType = key.OutputType(otherAvail); if (ourType != otherType && findImplicitConversion(library, otherType, ourType) == null) { changed = true; } else { newAvail.Add(otherAvail); } } otherElm.availObjects = newAvail; } if (otherElm.availObjects.Count == 1) { // if we're on one-to-one terms, we might add compat connections signals.ICircuitConnectible otherAvail = otherElm.availObjects[0]; signals.EType otherType = key.OutputType(otherAvail); if (ourType != otherType) { signals.IFunctionSpec func = findImplicitConversion(library, otherType, ourType); if (func == null) { // only option isn't type-compatible? Looks like we broke a connection throw new LinkTypeFailure(entry.Key, otherType, entry.Value, ourType); } else { AddImplicitConversion(key, value, func); } } } else if (otherElm.availObjects.Count == 0) { // ran out of possible connections? Looks like we broke a connection throw new CannotResolveElement(otherElm); } if (changed) { recurseList.Add(value.elem, true); } } } foreach (KeyValuePair <Element, bool> entry in recurseList) { if (entry.Key.availObjects.Count == 1) { resolveNeighbors(library, entry.Key); } } }