/// <summary> /// Use this block reference to derive a custom block based on the variable argument counts. /// </summary> /// <param name="?">original reference</param> /// <returns>derived description</returns> public AdvanceBlockDescription Derive(AdvanceBlockReference reference) { if (reference.Varargs.Count == 0) { return(this); } AdvanceBlockDescription result = new AdvanceBlockDescription(); result.Assign(this); result.Inputs = new Dictionary <string, AdvanceBlockParameterDescription>(); foreach (KeyValuePair <string, AdvanceBlockParameterDescription> e in this.Inputs) { int count; if (reference.Varargs.TryGetValue(e.Key, out count)) { for (int i = 1; i <= count; i++) { AdvanceBlockParameterDescription value = e.Value.Copy(); value.Type = e.Value.Type; // keep shared type value.Id = e.Key + i; value.Varargs = false; result.Inputs.Add(value.Id, value); } } else { result.Inputs.Add(e.Key, e.Value); } } return(result); }
/// <summary> /// Fill object data from xml node /// </summary> /// <param name="source"></param> protected override void LoadFromXmlNode(XmlNode source) { this.Id = GetAttribute(source, "id"); this.DisplayName = GetAttribute(source, "displayname", null); this.Documentation = GetUriAttribute(source, "documentation"); this.Tooltip = GetAttribute(source, "tooltip", null); this.Keywords = GetListAttribute(source, "keywords"); this.Category = GetAttribute(source, "category", null); List <AdvanceType> typeRefs = new List <AdvanceType>(); Dictionary <String, AdvanceType> sharedTypes = new Dictionary <string, AdvanceType>(); foreach (XmlNode tp in GetChildren(source, "type-variable")) { AdvanceTypeVariable bpd = CreateFromXml <AdvanceTypeVariable>(tp); if (this.TypeVariables.ContainsKey(bpd.Name)) { this.ThrowDuplicatedIdentifierException(tp, this.Id); } typeRefs.AddRange(bpd.Bounds); AdvanceType st = new AdvanceType(); st.TypeVariableName = bpd.Name; st.TypeVariable = bpd; sharedTypes.Add(bpd.Name, st); } // throw new MissingTypeVariableException(root.getXPath(), b.typeVariableName); while (typeRefs.Count > 0) { AdvanceType tvb = typeRefs[0]; typeRefs.RemoveAt(0); if (tvb.TypeVariableName != null) { if (!this.TypeVariables.TryGetValue(tvb.TypeVariableName, out tvb.TypeVariable)) { this.ThrowMissingTypeVariableException(source, tvb.TypeVariableName); } } else { typeRefs.AddRange(tvb.TypeArguments); } } List <AdvanceType> typeParams = new List <AdvanceType>(); this.HasVarargs = false; foreach (XmlNode inode in GetChildren(source, "input")) { AdvanceBlockParameterDescription bpd = CreateFromXml <AdvanceBlockParameterDescription>(inode); this.HasVarargs |= bpd.Varargs; if (this.Inputs.ContainsKey(bpd.Id)) { this.ThrowDuplicatedIdentifierException(inode, bpd.Id); } else { this.Inputs.Add(bpd.Id, bpd); } // use the shared type object instead of an individual type if (sharedTypes.ContainsKey(bpd.Type.TypeVariableName)) { bpd.Type = sharedTypes[bpd.Type.TypeVariableName]; } typeParams.Add(bpd.Type); } foreach (XmlNode onode in GetChildren(source, "output")) { AdvanceBlockParameterDescription bpd = CreateFromXml <AdvanceBlockParameterDescription>(onode); if (this.Outputs.ContainsKey(bpd.Id)) { this.ThrowDuplicatedIdentifierException(onode, bpd.Id); } else { this.Inputs.Add(bpd.Id, bpd); } // use the shared type object instead of an individual type if (sharedTypes.ContainsKey(bpd.Type.TypeVariableName)) { bpd.Type = sharedTypes[bpd.Type.TypeVariableName]; } typeParams.Add(bpd.Type); } while (typeParams.Count > 0) { AdvanceType at = typeParams[0]; typeParams.RemoveAt(0); if (at.Kind == TypeKind.VARIABLE_TYPE && at.TypeVariable == null) { this.TypeVariables.TryGetValue(at.TypeVariableName, out at.TypeVariable); } else if (at.Kind == TypeKind.PARAMETRIC_TYPE) { for (int i = 0; i < at.TypeArguments.Count; i++) { AdvanceType ta = at.TypeArguments[i]; if (ta.Kind == TypeKind.VARIABLE_TYPE) { AdvanceType sv; if (!sharedTypes.TryGetValue(ta.TypeVariableName, out sv)) { this.ThrowMissingTypeVariableException(source, ta.TypeVariableName); } at.TypeArguments[i] = sv; } } typeParams.AddRange(at.TypeArguments); } } }