/// <summary> /// Evaluate an argument list within the context of the enclosing /// template but store the values in the context of self, the /// new embedded template. For example, bold(item=item) means /// that bold.item should get the value of enclosing.item. /// </summary> protected internal virtual void evaluateArguments(StringTemplate self) { StringTemplateAST argumentsAST = self.getArgumentsAST(); if (argumentsAST == null || argumentsAST.getFirstChild() == null) { // return immediately if missing tree or no actual args return ; } // Evaluate args in the context of the enclosing template, but we // need the predefined args like 'it', 'attr', and 'i' to be // available as well so we put a dummy ST between the enclosing // context and the embedded context. The dummy has the predefined // context as does the embedded. StringTemplate enclosing = self.getEnclosingInstance(); StringTemplate argContextST = new StringTemplate(self.getGroup(), ""); argContextST.setName("<invoke "+self.getName()+" arg context>"); argContextST.setEnclosingInstance(enclosing); argContextST.setArgumentContext(self.getArgumentContext()); ActionEvaluator eval = new ActionEvaluator(argContextST, this, null); try { // using any initial argument context (such as when obj is set), // evaluate the arg list like bold(item=obj). Since we pass // in any existing arg context, that context gets filled with // new values. With bold(item=obj), context becomes: // {[obj=...],[item=...]}. IDictionary ac = eval.argList(argumentsAST, self, self.getArgumentContext()); self.setArgumentContext(ac); } catch (RecognitionException re) { self.error("can't evaluate tree: " + argumentsAST.ToStringList(), re); } }
protected internal virtual void evaluateArguments(StringTemplate self) { StringTemplateAST argumentsAST = self.getArgumentsAST(); if (argumentsAST == null || argumentsAST.getFirstChild() == null) { // return immediately if missing tree or no actual args return ; } ActionEvaluator eval = new ActionEvaluator(self, this, null); try { // using any initial argument context (such as when obj is set), // evaluate the arg list like bold(item=obj). Since we pass // in any existing arg context, that context gets filled with // new values. With bold(item=obj), context becomes: // {[obj=...],[item=...]}. IDictionary ac = eval.argList(argumentsAST, self.getArgumentContext()); self.setArgumentContext(ac); } catch (RecognitionException re) { self.error("can't evaluate tree: " + argumentsAST.ToStringList(), re); } }
/// <summary>Resolve an attribute reference. It can be in three possible places: /// /// 1. the attribute list for the current template /// 2. if self is an embedded template, somebody invoked us possibly /// with arguments--check the argument context /// 3. if self is an embedded template, the attribute list for the enclosing /// instance (recursively up the enclosing instance chain) /// /// Attribute references are checked for validity. If an attribute has /// a value, its validity was checked before template rendering. /// If the attribute has no value, then we must check to ensure it is a /// valid reference. Somebody could reference any random value like $xyz$; /// formal arg checks before rendering cannot detect this--only the ref /// can initiate a validity check. So, if no value, walk up the enclosed /// template tree again, this time checking formal parameters not /// attributes Map. The formal definition must exist even if no value. /// /// To avoid infinite recursion in toString(), we have another condition /// to check regarding attribute values. If your template has a formal /// argument, foo, then foo will hide any value available from "above" /// in order to prevent infinite recursion. /// /// This method is not static so people can overrided functionality. /// </summary> public virtual Object get(StringTemplate self, String attribute) { //System.out.println("get("+self.getName()+", "+attribute+")"); if (self == null) { return null; } if (lintMode) { self.trackAttributeReference(attribute); } // is it here? Object o = null; if (self.attributes != null) { o = self.attributes[attribute]; } // nope, check argument context in case embedded if (o == null) { IDictionary argContext = self.getArgumentContext(); if (argContext != null) { o = argContext[attribute]; } } if (o == null && self.getFormalArgument(attribute) != null) { // if you've defined attribute as formal arg for this // template and it has no value, do not look up the // enclosing dynamic scopes. This avoids potential infinite // recursion. return null; } // not locally defined, check enclosingInstance if embedded if (o == null && self.enclosingInstance != null) { /* System.out.println("looking for "+getName()+"."+attribute+" in super="+ enclosingInstance.getName()); */ Object valueFromEnclosing = get(self.enclosingInstance, attribute); if (valueFromEnclosing == null) { checkNullAttributeAgainstFormalArguments(self, attribute); } o = valueFromEnclosing; } return o; }