[ZPT] CVS: Packages/TAL - TALInterpreter.py:1.56.2.1
Evan Simpson
evan@zope.com
Tue, 9 Oct 2001 16:23:45 -0400
Update of /cvs-repository/Packages/TAL
In directory cvs.zope.org:/tmp/cvs-serv7789
Modified Files:
Tag: tal-1_4_0
TALInterpreter.py
Log Message:
Fix macro nesting behaviour; Tests all pass now.
=== Packages/TAL/TALInterpreter.py 1.56 => 1.56.2.1 ===
taldict = {}
if self.enabled and self.repldict:
- taldict["attributes"] = ""
+ taldict["attributes"] = "x x"
TALGenerator.emitStartElement(self, name, attrlist,
taldict, metaldict, position, isend)
@@ -208,14 +208,11 @@
assert self.level == level
assert self.scopeLevel == scopeLevel
- def pushMacro(self, what, macroName, slots):
+ def pushMacro(self, macroName, slots, entering=1):
if len(self.macroStack) >= self.stackLimit:
raise METALError("macro nesting limit (%d) exceeded "
- "by %s %s" % (self.stackLimit, what, `macroName`))
- self.macroStack.append((what, macroName, slots))
-
- def popMacro(self):
- return self.macroStack.pop()
+ "by %s" % (self.stackLimit, `macroName`))
+ self.macroStack.append([macroName, slots, entering])
def macroContext(self, what):
macroStack = self.macroStack
@@ -331,89 +328,63 @@
name, value, action = item[:3]
if action == 1 or (action > 1 and not self.showtal):
return 0, name, value
- ok = 1
- if action == 2 and self.metal:
+ macs = self.macroStack
+ if action == 2 and self.metal and macs:
+ if len(macs) > 1 or not macs[-1][2]:
+ # Drop all METAL attributes at a use-depth above one.
+ return 0, name, value
+ # Clear 'entering' flag
+ macs[-1][2] = 0
+ # Convert or drop depth-one METAL attributes.
i = rfind(name, ":") + 1
prefix, suffix = name[:i], name[i:]
- ##self.dumpMacroStack(prefix, suffix, value)
- what, macroName, slots = self.macroStack[-1]
if suffix == "define-macro":
- if what == "use-macro":
- name = prefix + "use-macro"
- value = macroName
- else:
- assert what == "define-macro"
- i = self.macroContext("use-macro")
- if i >= 0:
- j = self.macroContext("define-slot")
- if j > i:
- name = prefix + "use-macro"
- else:
- return 0, name, value
+ # Convert define-macro as we enter depth one.
+ name = prefix + "use-macro"
+ value = macs[-1][0] # Macro name
elif suffix == "define-slot":
- assert what == "define-slot"
- if self.macroContext("use-macro") >= 0:
- name = prefix + "fill-slot"
+ name = prefix + "fill-slot"
+ elif suffix == "fill-slot":
+ pass
+ else:
+ return 0, name, value
if value is None:
value = name
else:
value = "%s=%s" % (name, quote(value))
- return ok, name, value
+ return 1, name, value
def attrAction_tal(self, item):
name, value, action = item[:3]
- if action > 1 and not self.showtal:
- return 0, name, value
+ if action > 1:
+ return self.attrAction(item)
ok = 1
- if action <= 1:
- if self.html and lower(name) in BOOLEAN_HTML_ATTRS:
- evalue = self.engine.evaluateBoolean(item[3])
- if evalue is self.Default:
- if action == 1: # Cancelled insert
- ok = 0
- elif evalue:
- value = None
- else:
+ if self.html and lower(name) in BOOLEAN_HTML_ATTRS:
+ evalue = self.engine.evaluateBoolean(item[3])
+ if evalue is self.Default:
+ if action == 1: # Cancelled insert
ok = 0
+ elif evalue:
+ value = None
else:
- evalue = self.engine.evaluateText(item[3])
- if evalue is self.Default:
- if action == 1: # Cancelled insert
- ok = 0
- else:
- if evalue is None:
- ok = 0
- value = evalue
- elif action == 2 and self.metal:
- i = rfind(name, ":") + 1
- prefix, suffix = name[:i], name[i:]
- ##self.dumpMacroStack(prefix, suffix, value)
- what, macroName, slots = self.macroStack[-1]
- if suffix == "define-macro":
- if what == "use-macro":
- name = prefix + "use-macro"
- value = macroName
- else:
- assert what == "define-macro"
- i = self.macroContext("use-macro")
- if i >= 0:
- j = self.macroContext("define-slot")
- if j > i:
- name = prefix + "use-macro"
- else:
- ok = 0
- elif suffix == "define-slot":
- assert what == "define-slot"
- if self.macroContext("use-macro") >= 0:
- name = prefix + "fill-slot"
-
+ ok = 0
+ else:
+ evalue = self.engine.evaluateText(item[3])
+ if evalue is self.Default:
+ if action == 1: # Cancelled insert
+ ok = 0
+ else:
+ if evalue is None:
+ ok = 0
+ value = evalue
if ok:
if value is None:
value = name
else:
value = "%s=%s" % (name, quote(value))
return ok, name, value
+
bytecode_handlers["<attrAction>"] = attrAction
def no_tag(self, start, program):
@@ -592,12 +563,15 @@
bytecode_handlers["condition"] = do_condition
def do_defineMacro(self, (macroName, macro)):
- if not self.metal:
- self.interpret(macro)
- return
- self.pushMacro("define-macro", macroName, None)
+ macs = self.macroStack
+ if len(macs) == 1:
+ entering = macs[-1][2]
+ if not entering:
+ macs.append(None)
+ self.interpret(macro)
+ macs.pop()
+ return
self.interpret(macro)
- self.popMacro()
bytecode_handlers["defineMacro"] = do_defineMacro
def do_useMacro(self, (macroName, macroExpr, compiledSlots, block)):
@@ -606,44 +580,44 @@
return
macro = self.engine.evaluateMacro(macroExpr)
if macro is self.Default:
- self.interpret(block)
- return
- if not isCurrentVersion(macro):
- raise METALError("macro %s has incompatible version %s" %
- (`macroName`, `getProgramVersion(macro)`),
- self.position)
- mode = getProgramMode(macro)
- if mode != (self.html and "html" or "xml"):
- raise METALError("macro %s has incompatible mode %s" %
- (`macroName`, `mode`), self.position)
- self.pushMacro("use-macro", macroName, compiledSlots)
+ macro = block
+ else:
+ if not isCurrentVersion(macro):
+ raise METALError("macro %s has incompatible version %s" %
+ (`macroName`, `getProgramVersion(macro)`),
+ self.position)
+ mode = getProgramMode(macro)
+ if mode != (self.html and "html" or "xml"):
+ raise METALError("macro %s has incompatible mode %s" %
+ (`macroName`, `mode`), self.position)
+ self.pushMacro(macroName, compiledSlots)
self.interpret(macro)
self.popMacro()
bytecode_handlers["useMacro"] = do_useMacro
def do_fillSlot(self, (slotName, block)):
- if not self.metal:
- self.interpret(block)
- return
- self.pushMacro("fill-slot", slotName, None)
+ # This is only executed if the enclosing 'use-macro' evaluates
+ # to 'default'.
self.interpret(block)
- self.popMacro()
bytecode_handlers["fillSlot"] = do_fillSlot
def do_defineSlot(self, (slotName, block)):
if not self.metal:
self.interpret(block)
return
- slot = None
- for what, macroName, slots in self.macroStack:
- if what == "use-macro" and slots is not None:
- slot = slots.get(slotName, slot)
- self.pushMacro("define-slot", slotName, None)
- if slot:
- self.interpret(slot)
- else:
- self.interpret(block)
- self.popMacro()
+ macs = self.macroStack
+ if macs and macs[-1] is not None:
+ macroName, slots = self.popMacro()[:2]
+ slot = slots.get(slotName)
+ if slot is not None:
+ self.interpret(slot)
+ self.pushMacro(macroName, slots, entering=0)
+ return
+ self.pushMacro(macroName, slots)
+ if len(macs) == 1:
+ self.interpret(block)
+ return
+ self.interpret(block)
bytecode_handlers["defineSlot"] = do_defineSlot
def do_onError(self, (block, handler)):