// Return an expression that yields an appropriate StructureTemplate // instance of type bstruct from our current context. stmpl is an expression // that returns an instance of the structure that we are bound to. // Typical usage: // // UserType bstruct = BaseClass.ResolveUsedStructureType (trc, errors); // ... // ctor.BaseConstructorArgs.Add (ContextualStructRef (bstruct, stmpl)); // // If bstruct is null, CDH.Null is returned -- so in the above case, we // will pass null to the base constructor, which is appropriate since it // needs no structure. public CodeExpression ContextualStructRef(UserType bstruct, CodeExpression stmpl) { if (bstruct == null) { return(CDH.Null); } if (bstruct.Equals(NS.ParamsType)) { // Sweet! We are referring to ourselves. return(stmpl); } // We need some nontrivial different structure // type. Search our structure for a member that points to // a structure of that type. string foundparam = null; foreach (string param in Params.Parameters) { if (Params[param] != StructureParameterKind.Structure) { continue; } if (!bstruct.Equals(Params.StructParamType(param))) { continue; } // FIXME: better model that handles this. if (foundparam != null) { throw ExHelp.App("Ambiguous structure chain: structure {0} contains two parameters " + "of type {1}: {2} and {3}", Params, bstruct, foundparam, param); } foundparam = param; } if (foundparam == null) { throw ExHelp.App("Missing structure chain: structure {0} needs a parameter of type {1} " + "to allow chaining of type {2} to its base class {3}", Params, bstruct, this, BaseClass); } return(new CodeFieldReferenceExpression(stmpl, foundparam)); }
public UserType Resolve(string tname, bool errors) { if (tname.IndexOf('.') >= 0) { return(driver.LookupFQN(tname, !errors)); } // Not fully-qualified. Spelunk namespaces. UserType ut = null; //Console.WriteLine ("Trying to look up {0}", tname); foreach (string ns in AllUsings) { string full = ns + "." + tname; UserType hit = driver.LookupFQN(full, !errors); //Console.WriteLine (" {0} -> {1}", full, hit); if (hit == null) { continue; } if (errors && ut != null && !ut.Equals(hit)) { string s = String.Format("Ambiguous type name {0}: could be {1} " + "or {2}", tname, ut, hit); throw new Exception(s); } ut = hit; } if (errors && ut == null) { throw new Exception("Could not resolve the type name " + tname); } return(ut); }
// Return an expression that yields an appropriate StructureTemplate // instance of type bstruct from our current context. stmpl is an expression // that returns an instance of the structure that we are bound to. // Typical usage: // // UserType bstruct = BaseClass.ResolveUsedStructureType (trc, errors); // ... // ctor.BaseConstructorArgs.Add (ContextualStructRef (bstruct, stmpl)); // // If bstruct is null, CDH.Null is returned -- so in the above case, we // will pass null to the base constructor, which is appropriate since it // needs no structure. public CodeExpression ContextualStructRef (UserType bstruct, CodeExpression stmpl) { if (bstruct == null) return CDH.Null; if (bstruct.Equals (NS.ParamsType)) // Sweet! We are referring to ourselves. return stmpl; // We need some nontrivial different structure // type. Search our structure for a member that points to // a structure of that type. string foundparam = null; foreach (string param in Params.Parameters) { if (Params[param] != StructureParameterKind.Structure) continue; if (!bstruct.Equals (Params.StructParamType (param))) continue; // FIXME: better model that handles this. if (foundparam != null) throw ExHelp.App ("Ambiguous structure chain: structure {0} contains two parameters " + "of type {1}: {2} and {3}", Params, bstruct, foundparam, param); foundparam = param; } if (foundparam == null) throw ExHelp.App ("Missing structure chain: structure {0} needs a parameter of type {1} " + "to allow chaining of type {2} to its base class {3}", Params, bstruct, this, BaseClass); return new CodeFieldReferenceExpression (stmpl, foundparam); }
// Setup public bool Resolve(TypeResolveContext trc, bool errors) { // We need to resolve the rule as a template now, rather // than letting NameLookupContext do it, because NLC will // be operating with an undefined set of 'usings', and // probably won't be able to find the RTemplate associated // with the rule. if (Rule.ResolveExtension("RTemplate", trc, errors)) { return(true); } // Now we need to check that, if we have a template that // uses a structure, that our provider can access such // a structure, so that the template can actually be // instantiated. // // FIXME: This code is exactly parallel to // StructureBoundItem.ContextualStructRef. UserType ttmpl = Rule.ResolveUsedStructureType(trc, errors); if (ttmpl == null) { // Great, it's doesn't use anything, so whatever. return(false); } // XXX shouldn't apply anymore -- unbound providers are now impossible. // Would they have ever been useful? // //if (prov.Structure == null) { //if (errors) // Console.Error.WriteLine ("Target {0} in provider {1} references rule {2} that " + // "is bound to structure {3}, but the provider is not " + // "bound to a structure and so can provide no context", // this, prov, Rule, ttmpl); //return true; //} if (ttmpl.Equals(prov.NS.ParamsType)) { // It just depends on our containing structure. No problem. return(false); } foreach (string param in prov.Structure.Parameters) { if (prov.Structure[param] != StructureParameterKind.Structure) { continue; } if (ttmpl.Equals(prov.Structure.StructParamType(param))) { return(false); } } if (errors) { // WORST ERROR MESSAGE EVAR Console.Error.WriteLine("Target {0} in provider {1} references rule {2} that " + "is bound to structure {3}, but the provider's containing " + "structure {4} does not have an argument referencing that structure. " + "You probably need to add another parameter to the containing structure.", this, prov, Rule, ttmpl, prov.Structure); } return(true); }