Commit 28d45ade authored by Evan Simpson's avatar Evan Simpson

Merge macro fixes from branch

parent f47ce923
...@@ -143,7 +143,7 @@ class AltTALGenerator(TALGenerator): ...@@ -143,7 +143,7 @@ class AltTALGenerator(TALGenerator):
metaldict = {} metaldict = {}
taldict = {} taldict = {}
if self.enabled and self.repldict: if self.enabled and self.repldict:
taldict["attributes"] = "" taldict["attributes"] = "x x"
TALGenerator.emitStartElement(self, name, attrlist, TALGenerator.emitStartElement(self, name, attrlist,
taldict, metaldict, position, isend) taldict, metaldict, position, isend)
...@@ -208,14 +208,11 @@ class TALInterpreter: ...@@ -208,14 +208,11 @@ class TALInterpreter:
assert self.level == level assert self.level == level
assert self.scopeLevel == scopeLevel assert self.scopeLevel == scopeLevel
def pushMacro(self, what, macroName, slots): def pushMacro(self, macroName, slots, entering=1):
if len(self.macroStack) >= self.stackLimit: if len(self.macroStack) >= self.stackLimit:
raise METALError("macro nesting limit (%d) exceeded " raise METALError("macro nesting limit (%d) exceeded "
"by %s %s" % (self.stackLimit, what, `macroName`)) "by %s" % (self.stackLimit, `macroName`))
self.macroStack.append((what, macroName, slots)) self.macroStack.append([macroName, slots, entering])
def popMacro(self):
return self.macroStack.pop()
def macroContext(self, what): def macroContext(self, what):
macroStack = self.macroStack macroStack = self.macroStack
...@@ -331,42 +328,38 @@ class TALInterpreter: ...@@ -331,42 +328,38 @@ class TALInterpreter:
name, value, action = item[:3] name, value, action = item[:3]
if action == 1 or (action > 1 and not self.showtal): if action == 1 or (action > 1 and not self.showtal):
return 0, name, value return 0, name, value
ok = 1 macs = self.macroStack
if action == 2 and self.metal: 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 i = rfind(name, ":") + 1
prefix, suffix = name[:i], name[i:] prefix, suffix = name[:i], name[i:]
##self.dumpMacroStack(prefix, suffix, value)
what, macroName, slots = self.macroStack[-1]
if suffix == "define-macro": if suffix == "define-macro":
if what == "use-macro": # Convert define-macro as we enter depth one.
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" name = prefix + "use-macro"
else: value = macs[-1][0] # Macro name
return 0, name, value
elif suffix == "define-slot": 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: if value is None:
value = name value = name
else: else:
value = "%s=%s" % (name, quote(value)) value = "%s=%s" % (name, quote(value))
return ok, name, value return 1, name, value
def attrAction_tal(self, item): def attrAction_tal(self, item):
name, value, action = item[:3] name, value, action = item[:3]
if action > 1 and not self.showtal: if action > 1:
return 0, name, value return self.attrAction(item)
ok = 1 ok = 1
if action <= 1:
if self.html and lower(name) in BOOLEAN_HTML_ATTRS: if self.html and lower(name) in BOOLEAN_HTML_ATTRS:
evalue = self.engine.evaluateBoolean(item[3]) evalue = self.engine.evaluateBoolean(item[3])
if evalue is self.Default: if evalue is self.Default:
...@@ -385,35 +378,13 @@ class TALInterpreter: ...@@ -385,35 +378,13 @@ class TALInterpreter:
if evalue is None: if evalue is None:
ok = 0 ok = 0
value = evalue 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"
if ok: if ok:
if value is None: if value is None:
value = name value = name
else: else:
value = "%s=%s" % (name, quote(value)) value = "%s=%s" % (name, quote(value))
return ok, name, value return ok, name, value
bytecode_handlers["<attrAction>"] = attrAction bytecode_handlers["<attrAction>"] = attrAction
def no_tag(self, start, program): def no_tag(self, start, program):
...@@ -592,12 +563,15 @@ class TALInterpreter: ...@@ -592,12 +563,15 @@ class TALInterpreter:
bytecode_handlers["condition"] = do_condition bytecode_handlers["condition"] = do_condition
def do_defineMacro(self, (macroName, macro)): def do_defineMacro(self, (macroName, macro)):
if not self.metal: macs = self.macroStack
if len(macs) == 1:
entering = macs[-1][2]
if not entering:
macs.append(None)
self.interpret(macro) self.interpret(macro)
macs.pop()
return return
self.pushMacro("define-macro", macroName, None)
self.interpret(macro) self.interpret(macro)
self.popMacro()
bytecode_handlers["defineMacro"] = do_defineMacro bytecode_handlers["defineMacro"] = do_defineMacro
def do_useMacro(self, (macroName, macroExpr, compiledSlots, block)): def do_useMacro(self, (macroName, macroExpr, compiledSlots, block)):
...@@ -606,8 +580,8 @@ class TALInterpreter: ...@@ -606,8 +580,8 @@ class TALInterpreter:
return return
macro = self.engine.evaluateMacro(macroExpr) macro = self.engine.evaluateMacro(macroExpr)
if macro is self.Default: if macro is self.Default:
self.interpret(block) macro = block
return else:
if not isCurrentVersion(macro): if not isCurrentVersion(macro):
raise METALError("macro %s has incompatible version %s" % raise METALError("macro %s has incompatible version %s" %
(`macroName`, `getProgramVersion(macro)`), (`macroName`, `getProgramVersion(macro)`),
...@@ -616,34 +590,34 @@ class TALInterpreter: ...@@ -616,34 +590,34 @@ class TALInterpreter:
if mode != (self.html and "html" or "xml"): if mode != (self.html and "html" or "xml"):
raise METALError("macro %s has incompatible mode %s" % raise METALError("macro %s has incompatible mode %s" %
(`macroName`, `mode`), self.position) (`macroName`, `mode`), self.position)
self.pushMacro("use-macro", macroName, compiledSlots) self.pushMacro(macroName, compiledSlots)
self.interpret(macro) self.interpret(macro)
self.popMacro() self.popMacro()
bytecode_handlers["useMacro"] = do_useMacro bytecode_handlers["useMacro"] = do_useMacro
def do_fillSlot(self, (slotName, block)): def do_fillSlot(self, (slotName, block)):
if not self.metal: # This is only executed if the enclosing 'use-macro' evaluates
self.interpret(block) # to 'default'.
return
self.pushMacro("fill-slot", slotName, None)
self.interpret(block) self.interpret(block)
self.popMacro()
bytecode_handlers["fillSlot"] = do_fillSlot bytecode_handlers["fillSlot"] = do_fillSlot
def do_defineSlot(self, (slotName, block)): def do_defineSlot(self, (slotName, block)):
if not self.metal: if not self.metal:
self.interpret(block) self.interpret(block)
return return
slot = None macs = self.macroStack
for what, macroName, slots in self.macroStack: if macs and macs[-1] is not None:
if what == "use-macro" and slots is not None: macroName, slots = self.popMacro()[:2]
slot = slots.get(slotName, slot) slot = slots.get(slotName)
self.pushMacro("define-slot", slotName, None) if slot is not None:
if slot:
self.interpret(slot) self.interpret(slot)
else: self.pushMacro(macroName, slots, entering=0)
return
self.pushMacro(macroName, slots)
if len(macs) == 1:
self.interpret(block)
return
self.interpret(block) self.interpret(block)
self.popMacro()
bytecode_handlers["defineSlot"] = do_defineSlot bytecode_handlers["defineSlot"] = do_defineSlot
def do_onError(self, (block, handler)): def do_onError(self, (block, handler)):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment