Revision: 4532 http://sourceforge.net/p/vexi/code/4532 Author: mkpg2 Date: 2013-06-20 17:03:57 +0000 (Thu, 20 Jun 2013) Log Message: ----------- Change. Make $vars accessible from child/sibling scopes. - More convenient when setting up action listeners for buttons for example. - The 'down side' is that outer ids will be null when inner templates are being instantiated. Fix. Line numbering when using sub templates.
Modified Paths: -------------- branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/VML.java branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/VMLBuilder.java branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/TestGUT.java branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/evaltemplate.t branches/vexi3/org.vexi-core.main/src/test/java/test/core/template/TestTemplate.java Added Paths: ----------- branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/evaltemplate2.t branches/vexi3/org.vexi-core.main/src/test/java/test/core/template/lang_subtemplate_ids.t Modified: branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/VML.java =================================================================== --- branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/VML.java 2013-06-01 18:35:31 UTC (rev 4531) +++ branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/VML.java 2013-06-20 17:03:57 UTC (rev 4532) @@ -2,7 +2,10 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import org.ibex.js.Backtraceable; import org.ibex.js.JS; @@ -11,21 +14,26 @@ import org.ibex.js.parse.Function; import org.ibex.util.Tree; import org.vexi.core.VML.Static.Template; +import org.vexi.core.VML.Static.Template.PerInstantiationScope; public class VML implements Constants { static public class SubBlessing extends JS.Obj { + final PerInstantiationScope idContextParent; final JS property; final Template template; - SubBlessing(String property, Template template){ - this.property = JSU.S(property); + SubBlessing(PerInstantiationScope idContextParent, JS property, Template template){ + this.idContextParent = idContextParent; + this.property = property; this.template = template; } @Override public JS new_(JS[] args) throws JSExn { return apply(null,args); } @Override public JS apply(JS this_, JS[] args) throws JSExn { - return template.apply(this_,args); + JS[] thisHolder = new JS[]{this_}; + template.apply(thisHolder,args, idContextParent, null); + return thisHolder[0]; } @Override public String coerceToString() { return "SubString$"+Integer.toHexString(hashCode()); @@ -40,7 +48,9 @@ Template template; public Static(JS vexi, JS constructor, String sourceName) { - super(null); + // UGLY in fact it doesn't matter what the elementStart, it is only + // used for skipping lines, but we are never inside another code block. + super(null, -1); this.vexi = vexi; this.constructor = constructor; this.sourceName = sourceName; @@ -111,7 +121,7 @@ Object script = null; ///< the script on this node List children = null; ///< during XML parsing, this holds the list of currently-parsed children; null otherwise - List subtemplates = null; ///< sub templates to be assigned to properties, not applied on creation + Map subtemplates = null; ///< sub templates to be assigned to properties, not applied on creation Object preapply = null; ///< Pre-applied template (~linked list) in root node only (unless lang:apply) Object principal = null; ///< Template to be applied @@ -130,10 +140,9 @@ // Static data/methods /////////////////////////////////////////////////////////////////// // FOOTNOTE:1 - Template(CodeBlock parent, Template preapply, int startLine) { - super(parent); + Template(CodeBlock parent, int elementStart, Template preapply) { + super(parent, elementStart); this.preapply = preapply; - this.startLine = startLine; } void addChild(Template template) { @@ -142,8 +151,8 @@ } void addSubTemplate(String property, Template template) { - if(subtemplates==null) subtemplates = new ArrayList(); - subtemplates.add(new SubBlessing(property, template)); + if(subtemplates==null) subtemplates = new LinkedHashMap(); + subtemplates.put(JSU.S(property), template); } // Methods to apply templates //////////////////////////////////////////////////////// @@ -157,7 +166,7 @@ // @param ptemplates a vector of the fileNames to recieve private references on the pboxes public JS apply(JS this_, JS[] args) throws JSExn { JS[] thisHolder = new JS[] { this_ }; - apply(thisHolder, args, null); + apply(thisHolder, args, null, null); return thisHolder[0]; } @@ -182,12 +191,12 @@ t = ((Blessing)Vexi.resolveString(vexi,t.getStatic().sourceName)).getTemplate(); } } - t.apply(thisHolder, args, null); + t.apply(thisHolder, args, null, null); return (Template)t; } - private void apply(JS[] thisHolder, JS[] args, PerInstantiationScope parentPis) throws JSExn { + void apply(JS[] thisHolder, JS[] args, PerInstantiationScope idContextParent, PerInstantiationScope idContext) throws JSExn { Main.SCHEDULER.findCurrentInterpreter().enterNonJSCall(this); try { // REMARK - the preapplies may not have been resolved yet, @@ -208,24 +217,28 @@ } // FIXME this dollar stuff is all wrong - if (id!=null && parentPis!=null) { - parentPis.putDollar(id, this_); - } + // FEATURE only if necessary (i.e. if there is JS code) - PerInstantiationScope pis = new PerInstantiationScope(this_, parentPis, isBox()); - + PerInstantiationScope pis = new PerInstantiationScope(idContextParent, idContext, this_, isBox()); + pis.idContext.putDollar(id, this_); + // FIXME needs to obey the new application-ordering rules for (int i=0; children!=null && i<children.size(); i++) { JS[] kidHolder = new JS[1]; - ((Template)children.get(i)).apply(kidHolder, null, pis); + ((Template)children.get(i)).apply(kidHolder, null, idContextParent, pis.idContext); JS ind = Main.SCHEDULER.getAndTriggerTraps(this_,SC_numchildren); Main.SCHEDULER.putAndTriggerTraps(this_, ind, kidHolder[0]); } - for (int i=0; subtemplates!=null && i<subtemplates.size(); i++) { - SubBlessing subTemplate = (SubBlessing)subtemplates.get(i); - Main.SCHEDULER.putAndTriggerTraps(this_, subTemplate.property, subTemplate); + if(subtemplates!=null){ + Iterator I = subtemplates.keySet().iterator(); + while(I.hasNext()){ + JS property = (JS)I.next(); + Template subTemplate = (Template)subtemplates.get(property); + SubBlessing subBlessing = new SubBlessing(pis, property, subTemplate); + Main.SCHEDULER.putAndTriggerTraps(this_, property, subBlessing); + } } if (keys!=null) { @@ -267,7 +280,7 @@ if (script==null) { //pisParserParam = TemplateBuilder.instance.createPIChecker(uriPrefixes, this); - script = VMLBuilder.parseScript(content, content_start, sourceName); + script = VMLBuilder.parseScript(content, contentStart, sourceName); content = null; // FIXME: UGLY - avoiding adding an init param if (script==null) { @@ -277,17 +290,13 @@ if (script!=JSU.F) { JSU.cloneWithNewGlobalScope((Function)script, pis).apply(null, args!=null?args:EMPTY_JS_ARRAY); } - - // FIXME: nix this - pis.parentBoxPis = null; - } finally { Main.SCHEDULER.findCurrentInterpreter().exitNonJSCall(); } } public String traceLine() { - return sourceName +":" +startLine + "(apply)"; + return sourceName +":" +elementStart + "(apply)"; } /** @@ -310,39 +319,57 @@ * $x for child boxes + uri prefix objects + global + static object * </p> */ - class PerInstantiationScope extends JS.Obj { - PerInstantiationScope parentBoxPis; - final JS box; + class PerInstantiationScope extends JS.Immutable { + final PerInstantiationScope idContextParent; + final PerInstantiationScope idContext; + final JS object; final boolean jsObj; private JS subComponents; + + public PerInstantiationScope(PerInstantiationScope idContextParent, PerInstantiationScope idContext, JS object, boolean isBox) { + this.idContextParent = idContextParent; + this.idContext = idContext==null?this:idContext; + this.object = object; + this.jsObj = !isBox; + } + + void putDollar(String key, JS target) throws JSExn { - if (parentBoxPis!=null) { - parentBoxPis.putDollar(key, target); - } JS jskey = JSU.S("$" + key); - sput(jskey, target); + idContext.putDollar(jskey, target); } // JS:FIXME: ugly - void sput(JS key, JS val) throws JSExn { + private void putDollar(JS key, JS val) throws JSExn { if (subComponents==null) { subComponents = new JS.Obj(); - box.put(SC_subComponents, subComponents); + object.put(SC_subComponents, subComponents); } subComponents.put(key,val); } - public PerInstantiationScope(JS box, PerInstantiationScope parentBoxPis, boolean isBox) { - this.parentBoxPis = parentBoxPis; - this.box = box; - this.jsObj = !isBox; + + public JS getDollar(JS key) throws JSExn{ + if (subComponents!=null){ + JS r = subComponents.get(key); + if(r!=null) return r; + } + if(idContextParent!=null){ + return idContextParent.getDollar(key); + } + return null; } + + public JS get(JS key) throws JSExn { JS r; if (JSU.isString(key)) { + String s = JSU.toString(key); // FIXME This is a hack // 1.returns $x for named child boxes - if (subComponents!=null && subComponents.get(key)!=null) { - return subComponents.get(key); - } + if(s.startsWith("$")){ + return idContext.getDollar(key); + + } + // FEATURE store null placeholder here if uri prefix doesn't // exist and cache values using super.put to save one hash lookup // 2.return prefix @@ -355,34 +382,33 @@ return r; } // HACK. Use 'this' keyword instead? - String s = JSU.toString(key); if (jsObj && "thisobj".equals(s)) { - return box; + return object; } } // FIXME: This won't work with traps that do blocking operations - return Main.SCHEDULER.getAndTriggerTraps(box,key); + return Main.SCHEDULER.getAndTriggerTraps(object,key); } // FIXME should come from JSGlobalScope ... or something public void put(JS key, JS val) throws JSExn { - Main.SCHEDULER.putAndTriggerTraps(box,key,val); + Main.SCHEDULER.putAndTriggerTraps(object,key,val); } public JS callMethod(JS this_, JS method, JS[] args) throws JSExn { - return box.callMethod(box, method, args); + return object.callMethod(object, method, args); } // FIXME this should come from JSGlobalScope or something - public void addTrap(JS key, JS f) throws JSExn { box.addTrap(key,f); } - public void delTrap(JS key, JS f) throws JSExn { box.delTrap(key,f); } - public Trap getTrap(JS key) { return box.getTrap(key); } + public void addTrap(JS key, JS f) throws JSExn { object.addTrap(key,f); } + public void delTrap(JS key, JS f) throws JSExn { object.delTrap(key,f); } + public Trap getTrap(JS key) { return object.getTrap(key); } public String toString() { return "PIS of " + Template.this.toString(); } } public String toString() { - return sourceName +":"+ startLine; + return sourceName +":"+ elementStart; } } } @@ -391,8 +417,8 @@ final boolean apply; Template template; - public SubTemplate(CodeBlock parent, boolean apply) { - super(parent); + public SubTemplate(CodeBlock parent, int elementStart, boolean apply) { + super(parent, elementStart); this.apply = apply; } } @@ -403,14 +429,15 @@ // Only used during parsing ///////////////////////////////////////////////////////////////// StringBuffer content = null; ///< during XML parsing, this holds partially-read character data; null otherwise - int content_start = 0; ///< line number of the first line of <tt>content</tt> - int startLine = -1; ///< the line number that this element starts on + int contentStart = -1; ///< line number of the first line of <tt>content</tt> + int elementStart = -1; ///< the line number that this element starts on Prefixes uriPrefixes; /// Uri prefixes->Blessings - CodeBlock(CodeBlock parent) { + CodeBlock(CodeBlock parent, int elementStart) { this.parent = parent; + this.elementStart = elementStart; } /** Modified: branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/VMLBuilder.java =================================================================== --- branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/VMLBuilder.java 2013-06-01 18:35:31 UTC (rev 4531) +++ branches/vexi3/org.vexi-core.main/src/main/java/org/vexi/core/VMLBuilder.java 2013-06-20 17:03:57 UTC (rev 4532) @@ -214,7 +214,7 @@ if (Log.user.isDebug()) { Log.debug(Helper.class, "Parsing template: " + sourceName()); } - Function staticScript = parseScript(static_.content, static_.content_start, sourceName()); + Function staticScript = parseScript(static_.content, static_.contentStart, sourceName()); if (t != null) { static_.template = t; Main.SCHEDULER.findCurrentInterpreter().enterNonJSCall( static_); @@ -332,28 +332,28 @@ case STATE_IN_ROOT_NODE: case STATE_IN_APPLY_NODE: case STATE_IN_SUB_TEMPLATE_NODE: - CodeBlock parent = state!=STATE_IN_ROOT_NODE?cb.parent:null; + CodeBlock parent = state!=STATE_IN_ROOT_NODE?cb.parent:null; Template preapply = t; - cb = t = static_.new Template(parent, preapply, getLine()); + cb = t = static_.new Template(parent, getLine(), preapply); state = STATE_IN_TEMPLATE_NODE; break; case STATE_IN_TEMPLATE_NODE: if (langUri){ if("apply".equals(cur.getLocalName())) { - cb = new SubTemplate(t, true); + cb = new SubTemplate(t, getLine(), true); t = null; state = STATE_IN_APPLY_NODE; cb.uriPrefixes = prefixes; return; }else if("subtemplate".equals(cur.getLocalName())){ - cb = new SubTemplate(t, false); + cb = new SubTemplate(t, getLine(), false); t = null; state = STATE_IN_SUB_TEMPLATE_NODE; cb.uriPrefixes = prefixes; return; } } - cb = t = static_.new Template(t, null, getLine()); + cb = t = static_.new Template(t, getLine(), null); break; } // JS Code has access to namespace objects @@ -469,7 +469,8 @@ cb = (CodeBlock) nodeStack.lastElement(); nodeStack.setSize(nodeStack.size() - 1); if (cb.content != null) { - insertNewLines(cb.content, getLine() - oldCb.startLine); + int lines = getLine() - oldCb.elementStart; + insertNewLines(cb.content, lines); } // UGLY ... @@ -510,7 +511,7 @@ return; default: if (cb.content == null) { - cb.content_start = getLine(); + cb.contentStart = getLine(); cb.content = new StringBuffer(); } cb.content.append(ch, start, length); @@ -540,7 +541,7 @@ case STATE_IN_ROOT_NODE: case STATE_IN_TEMPLATE_NODE: if (cb.content == null) { - cb.content_start = getLine(); + cb.contentStart = getLine(); cb.content = new StringBuffer(); } StringBuffer sb = cb.content; Modified: branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/TestGUT.java =================================================================== --- branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/TestGUT.java 2013-06-01 18:35:31 UTC (rev 4531) +++ branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/TestGUT.java 2013-06-20 17:03:57 UTC (rev 4532) @@ -15,7 +15,7 @@ public static void main(String[] args) throws Throwable { CoreTestSuite cts = new CoreTestSuite(TestGUT.class); - TestCase t = cts.createTestCase(cts.getResourceDirs(), "dontvirtualize.t"); + TestCase t = cts.createTestCase(cts.getResourceDirs(), "evaltemplate2.t"); t.runBare(); } } Modified: branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/evaltemplate.t =================================================================== --- branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/evaltemplate.t 2013-06-01 18:35:31 UTC (rev 4531) +++ branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/evaltemplate.t 2013-06-20 17:03:57 UTC (rev 4532) @@ -9,8 +9,8 @@ "<ui:box x=\"1\"/>"+ "</vexi>"); .util..assertEquals("I'm alive!",.x..f()); - var x = .x(vexi.box); - .util..assertEquals(1,x.x); + .util..assertEquals(1,.x(vexi.box).x); + .util..assertEquals(1,new .x().x); }; Added: branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/evaltemplate2.t =================================================================== --- branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/evaltemplate2.t (rev 0) +++ branches/vexi3/org.vexi-core.main/src/test/java/test/core/gut/evaltemplate2.t 2013-06-20 17:03:57 UTC (rev 4532) @@ -0,0 +1,25 @@ +<vexi xmlns:ui="vexi://ui" xmlns=""> + + const TEMPLATE = """ + <vexi xmlns:ui=\"vexi://ui\"> + static.f=function(){return \"I'm alive!\";} + <ui:box x=\"1\"/> + </vexi> + """; + + vexi.thread = function(){ + var templateStream = vexi.stream.fromString(TEMPLATE); + var template = vexi.bless(templateStream); + + trace(template..f()); + .util..assertEquals("I'm alive!",template..f()); + + var anInstance = new template(); + trace(anInstance.x); + .util..assertEquals(1,anInstance.x); + }; + + + + <ui:box/> +</vexi> Modified: branches/vexi3/org.vexi-core.main/src/test/java/test/core/template/TestTemplate.java =================================================================== --- branches/vexi3/org.vexi-core.main/src/test/java/test/core/template/TestTemplate.java 2013-06-01 18:35:31 UTC (rev 4531) +++ branches/vexi3/org.vexi-core.main/src/test/java/test/core/template/TestTemplate.java 2013-06-20 17:03:57 UTC (rev 4532) @@ -17,7 +17,7 @@ CoreTestSuite cts = new CoreTestSuite(TestTemplate.class); // TestCase t = cts.createTestCase(cts.getResourceDirs(), "lang_apply.t"); - TestCase t = cts.createTestCase(cts.getResourceDirs(), "lang_subtemplate.t"); + TestCase t = cts.createTestCase(cts.getResourceDirs(), "lang_subtemplate_ids.t"); t.runBare(); } } Added: branches/vexi3/org.vexi-core.main/src/test/java/test/core/template/lang_subtemplate_ids.t =================================================================== --- branches/vexi3/org.vexi-core.main/src/test/java/test/core/template/lang_subtemplate_ids.t (rev 0) +++ branches/vexi3/org.vexi-core.main/src/test/java/test/core/template/lang_subtemplate_ids.t 2013-06-20 17:03:57 UTC (rev 4532) @@ -0,0 +1,37 @@ +<vexi xmlns:ui="vexi://ui" xmlns:lang="vexi://lang"> + <ui:Box id="outer" text="Outer" redirect=":$content"> + <ui:Box id="title" text="Ids Test"/> + <ui:Box id="main" text="Moo"> + thisbox.path ++= function(){ + return $outer.text+" / "+$title.text+" / "+text; + }; + </ui:Box> + + + <ui:Box id="content"/> + + + + <lang:subtemplate property="sub"> + <ui:Box> + <ui:Box id="item"/> + $item.text = arguments[0]; + + thisbox.path ++= function(){ + return $outer.text+" / "+$title.text +" / "+$item.text; + }; + + </ui:Box> + </lang:subtemplate> + .util..assertEquals(0,thisbox.numchildren); + + thisbox.add(new sub("A")); + thisbox.add(new sub("B")); + + .util..assertEquals("Outer / Ids Test / Moo",$main.path); + .util..assertEquals("Outer / Ids Test / A",thisbox[0].path); + .util..assertEquals("Outer / Ids Test / B",thisbox[1].path); + + </ui:Box> + +</vexi> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ This SF.net email is sponsored by Windows: Build for Windows Store. http://p.sf.net/sfu/windows-dev2dev _______________________________________________ Vexi-svn mailing list Vexi-svn@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/vexi-svn