// walkChild only executes a subset of nodes, intended to be used on child templates. func (s *state) walkChild(node parse.Node) error { s.enter(node) defer s.leave(node) switch node := node.(type) { case *parse.BodyNode: for _, c := range node.Children() { err := s.walkChild(c) if err != nil { return err } } case *parse.UseNode: return s.walkUseNode(node) } return nil }
// Method walk is the main entry-point into template execution. func (s *state) walk(node parse.Node) error { s.enter(node) defer s.leave(node) switch node := node.(type) { case *parse.ModuleNode: if p := node.Parent(); p != nil { tplName, err := s.evalExpr(p.TemplateRef()) if err != nil { return err } tree, err := s.load(CoerceString(tplName)) if err != nil { return err } s.blocks = append(s.blocks, tree.Blocks()) err = s.walkChild(node.BodyNode) if err != nil { return err } return s.walk(tree.Root()) } return s.walk(node.BodyNode) case *parse.BodyNode: for _, c := range node.Children() { err := s.walk(c) if err != nil { return err } } case *parse.TextNode: io.WriteString(s.out, node.Text()) case *parse.PrintNode: v, err := s.evalExpr(node.Expr()) if err != nil { return err } io.WriteString(s.out, CoerceString(v)) case *parse.BlockNode: name := node.Name() if block := s.getBlock(name); block != nil { return s.walk(block.Body()) } // TODO: It seems this should never occur. return errors.New("Unable to locate block " + name) case *parse.IfNode: v, err := s.evalExpr(node.Cond()) if err != nil { return err } if CoerceBool(v) { s.walk(node.Body()) } else { s.walk(node.Else()) } case *parse.IncludeNode: tpl, ctx, err := s.walkIncludeNode(node) if err != nil { return err } err = execute(tpl, s.out, ctx, s.env) if err != nil { return err } case *parse.EmbedNode: tpl, ctx, err := s.walkIncludeNode(node.IncludeNode) if err != nil { return err } // TODO: We duplicate most of the "execute" function here. si := newState(s.out, ctx, s.env) tree, err := s.load(tpl) if err != nil { return err } si.blocks = append(s.blocks, node.Blocks(), tree.Blocks()) err = si.walk(tree.Root()) if err != nil { return err } case *parse.UseNode: return s.walkUseNode(node) case *parse.ForNode: return s.walkForNode(node) default: return errors.New("Unknown node " + node.String()) } return nil }