func (d *renderEndRepeat) render(rc *renderContext) error {
	candidate, ok := rc.talesContext.repeatVariables.GetValue(d.repeatName)
	if !ok {
		return nil
	}
	repeatVar := candidate.(*repeatVariable)
	if repeatVar.repeatId != d.repeatId {
		return nil
	}
	repeatVar.sequencePosition++
	if repeatVar.sequencePosition == repeatVar.sequenceLength {
		rc.talesContext.repeatVariables.RemoveValue()
		rc.talesContext.localVariables.RemoveValue()
		return nil
	}
	rc.talesContext.localVariables.SetValue(d.repeatName, repeatVar.indexedValue())
	rc.instructionPointer += d.repeatStartOffset
	return nil
}
/*
render for ending a loop of a tal:repeat command.

A check is made to confirm that we are already in a loop by looking for a repeat
variable with this name and then verifying the repeatIds match.

The sequence position is advanced.  If this takes it beyond the length of the
sequence, the repeat and local variables are removed.  Otherwise the
instruction pointer is set to the first instruction after the start of the
repeat loop.
package tal
import (
	"fmt"
	"golang.org/x/net/html"
	"io"
	"strings"
)
type RenderConfig func(t *Template, rc *renderContext)
func RenderDebugLogging(logger func(fmt string, args ...interface{})) RenderConfig {
	return func(t *Template, rc *renderContext) {
		rc.talesContext.debug = logger
		rc.debug = logger
	}
}
type attributesList []html.Attribute
func (a *attributesList) Remove(name string) bool {
	curList := *a
	for i, att := range curList {
		if att.Key == name {
			res := append(curList[:i], curList[i+1:]...)
			*a = res
			return true
		}
	}
	return false
}
func (a *attributesList) Set(name string, value string) bool {
	curList := *a
	for i, att := range curList {
		if att.Key == name {
			curList[i].Val = value
			return true
		}
	}
	res := append(curList, html.Attribute{Key: name, Val: value})
	*a = res
	return false
}
func (a *attributesList) Get(name string) interface{} {
	curList := *a
	for _, att := range curList {
		if att.Key == name {
			return att.Val
		}
	}
	return notFound
}
type templateInstruction interface {
	render(*renderContext) error
}
type defineSlot struct {
	name string
	endTagOffset int
}
func (d *defineSlot) render(rc *renderContext) error {
	slotFilling, ok := rc.slots.GetValue(d.name)
	if ok {
		slotFillingTemplate := slotFilling.(*Template)
		err := slotFillingTemplate.renderAsSubtemplate(rc.talesContext, rc.out, rc.slots, rc.config...)
		rc.instructionPointer += d.endTagOffset
		return err
	}
	return nil
}
func (d *defineSlot) String() string {
	return fmt.Sprintf("[Define Slot] %v (end offset %v)", d.name, d.endTagOffset)
}
type useMacro struct {
	expression string
	originalAttributes attributesList
	endTagOffset int
	filledSlots map[string]*Template
}
func (u *useMacro) render(rc *renderContext) error {
	contextValue := rc.talesContext.evaluate(u.expression, u.originalAttributes)
	if contextValue == Default {
		return nil
	}
	if contextValue == nil {
		rc.instructionPointer += u.endTagOffset
		return nil
	}
	mv, ok := contextValue.(*Template)
	if ok {
		rc.slots.SaveAll()
		for k, v := range u.filledSlots {
			rc.slots.SetValue(k, v)
		}
		err := mv.renderAsSubtemplate(rc.talesContext, rc.out, rc.slots, rc.config...)
		rc.slots.RestoreAll()
		rc.instructionPointer += u.endTagOffset
		return err
	}
	return nil
}
func (u *useMacro) String() string {
	return fmt.Sprintf("[Use Macro] %v", u.expression)
}
type renderEndTag struct {
	tagName []byte
	checkOmitTagFlag bool
}
func (d *renderEndTag) render(rc *renderContext) error {
	render := true
	if d.checkOmitTagFlag {
		rc.debug("Checking omit tag flag\n")
		render = !rc.getOmitTagFlag()
	}
	if render {
		rc.debug("End Tag will be rendered\n")
		rc.buffer.reset()
		rc.buffer.appendString("</")
		rc.buffer.append(d.tagName)
		rc.buffer.appendString(">")
		rc.out.Write(rc.buffer)
	} else {
		rc.debug("Rendering of end tag suppressed.\n")
	}
	return nil
}
func (d *renderEndTag) String() string {
	return fmt.Sprintf("[End Tag] %v (check omit flag: %v)", string(d.tagName), d.checkOmitTagFlag)
}
type defineVariable struct {
	name string
	global bool
	expression string
	originalAttributes attributesList
}
func (d *defineVariable) render(rc *renderContext) error {
	contextValue := rc.talesContext.evaluate(d.expression, d.originalAttributes)
	if d.global {
		rc.talesContext.globalVariables.SetValue(d.name, contextValue)
	} else {
		rc.talesContext.localVariables.AddValue(d.name, contextValue)
	}
	return nil
}
func (d *defineVariable) String() string {
	typeOfVar := "local"
	if d.global {
		typeOfVar = "global"
	}
	return fmt.Sprintf("[Define Variable] %v %v to '%v'", typeOfVar, d.name, d.expression)
}
type removeLocalVariable struct {
}
func (d *removeLocalVariable) render(rc *renderContext) error {
	rc.talesContext.localVariables.RemoveValue()
	return nil
}
func (d *removeLocalVariable) String() string {
	return "[Remove Local Variable]"
}
type renderRepeat struct {
	repeatName string
	condition string
	endTagOffset int
	repeatId int
	originalAttributes attributesList
}
func (d *renderRepeat) render(rc *renderContext) error {
	var contentValue interface{} = nil
	if d.condition != "" {
		contentValue = rc.talesContext.evaluate(d.condition, d.originalAttributes)
	}
	if contentValue == Default {
		return nil
	}
	if !isValueSequence(contentValue) {
		rc.instructionPointer += d.endTagOffset
		return nil
	}
	newRepeatVar := newRepeatVariable(d.repeatId, contentValue)
	rc.talesContext.repeatVariables.AddValue(d.repeatName, newRepeatVar)
	rc.talesContext.localVariables.AddValue(d.repeatName, newRepeatVar.indexedValue())
	return nil
}
func (d *renderRepeat) String() string {
	return fmt.Sprintf("[Repeat] %v condition '%v' (End Offset %v)", d.repeatName, d.condition, d.endTagOffset)
}
type renderEndRepeat struct {
	repeatName string
	repeatId int
	repeatStartOffset int
}