annotate vendor/github.com/eknkc/amber/compiler.go @ 66:787b5ee0289d draft

Use vendored modules Signed-off-by: Izuru Yakumo <yakumo.izuru@chaotic.ninja>
author yakumo.izuru
date Sun, 23 Jul 2023 13:18:53 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
66
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
1 package amber
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
2
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
3 import (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
4 "bytes"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
5 "container/list"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
6 "errors"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
7 "fmt"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
8 "go/ast"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
9 gp "go/parser"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
10 gt "go/token"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
11 "html/template"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
12 "io"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
13 "net/http"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
14 "os"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
15 "path/filepath"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
16 "reflect"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
17 "regexp"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
18 "sort"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
19 "strconv"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
20 "strings"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
21
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
22 "github.com/eknkc/amber/parser"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
23 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
24
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
25 var builtinFunctions = [...]string{
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
26 "len",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
27 "print",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
28 "printf",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
29 "println",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
30 "urlquery",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
31 "js",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
32 "json",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
33 "index",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
34 "html",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
35 "unescaped",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
36 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
37
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
38 const (
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
39 dollar = "__DOLLAR__"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
40 )
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
41
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
42 // Compiler is the main interface of Amber Template Engine.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
43 // In order to use an Amber template, it is required to create a Compiler and
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
44 // compile an Amber source to native Go template.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
45 // compiler := amber.New()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
46 // // Parse the input file
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
47 // err := compiler.ParseFile("./input.amber")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
48 // if err == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
49 // // Compile input file to Go template
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
50 // tpl, err := compiler.Compile()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
51 // if err == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
52 // // Check built in html/template documentation for further details
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
53 // tpl.Execute(os.Stdout, somedata)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
54 // }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
55 // }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
56 type Compiler struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
57 // Compiler options
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
58 Options
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
59 filename string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
60 node parser.Node
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
61 indentLevel int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
62 newline bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
63 buffer *bytes.Buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
64 tempvarIndex int
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
65 mixins map[string]*parser.Mixin
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
66 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
67
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
68 // New creates and initialize a new Compiler.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
69 func New() *Compiler {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
70 compiler := new(Compiler)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
71 compiler.filename = ""
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
72 compiler.tempvarIndex = 0
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
73 compiler.PrettyPrint = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
74 compiler.Options = DefaultOptions
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
75 compiler.mixins = make(map[string]*parser.Mixin)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
76
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
77 return compiler
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
78 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
79
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
80 // Options defines template output behavior.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
81 type Options struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
82 // Setting if pretty printing is enabled.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
83 // Pretty printing ensures that the output html is properly indented and in human readable form.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
84 // If disabled, produced HTML is compact. This might be more suitable in production environments.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
85 // Default: true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
86 PrettyPrint bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
87 // Setting if line number emitting is enabled
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
88 // In this form, Amber emits line number comments in the output template. It is usable in debugging environments.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
89 // Default: false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
90 LineNumbers bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
91 // Setting the virtual filesystem to use
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
92 // If set, will attempt to use a virtual filesystem provided instead of os.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
93 // Default: nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
94 VirtualFilesystem http.FileSystem
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
95 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
96
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
97 // DirOptions is used to provide options to directory compilation.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
98 type DirOptions struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
99 // File extension to match for compilation
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
100 Ext string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
101 // Whether or not to walk subdirectories
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
102 Recursive bool
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
103 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
104
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
105 // DefaultOptions sets pretty-printing to true and line numbering to false.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
106 var DefaultOptions = Options{true, false, nil}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
107
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
108 // DefaultDirOptions sets expected file extension to ".amber" and recursive search for templates within a directory to true.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
109 var DefaultDirOptions = DirOptions{".amber", true}
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
110
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
111 // Compile parses and compiles the supplied amber template string. Returns corresponding Go Template (html/templates) instance.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
112 // Necessary runtime functions will be injected and the template will be ready to be executed.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
113 func Compile(input string, options Options) (*template.Template, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
114 comp := New()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
115 comp.Options = options
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
116
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
117 err := comp.Parse(input)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
118 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
119 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
120 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
121
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
122 return comp.Compile()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
123 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
124
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
125 // Compile parses and compiles the supplied amber template []byte.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
126 // Returns corresponding Go Template (html/templates) instance.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
127 // Necessary runtime functions will be injected and the template will be ready to be executed.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
128 func CompileData(input []byte, filename string, options Options) (*template.Template, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
129 comp := New()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
130 comp.Options = options
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
131
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
132 err := comp.ParseData(input, filename)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
133 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
134 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
135 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
136
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
137 return comp.Compile()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
138 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
139
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
140 // MustCompile is the same as Compile, except the input is assumed error free. If else, panic.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
141 func MustCompile(input string, options Options) *template.Template {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
142 t, err := Compile(input, options)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
143 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
144 panic(err)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
145 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
146 return t
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
147 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
148
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
149 // CompileFile parses and compiles the contents of supplied filename. Returns corresponding Go Template (html/templates) instance.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
150 // Necessary runtime functions will be injected and the template will be ready to be executed.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
151 func CompileFile(filename string, options Options) (*template.Template, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
152 comp := New()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
153 comp.Options = options
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
154
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
155 err := comp.ParseFile(filename)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
156 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
157 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
158 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
159
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
160 return comp.Compile()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
161 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
162
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
163 // MustCompileFile is the same as CompileFile, except the input is assumed error free. If else, panic.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
164 func MustCompileFile(filename string, options Options) *template.Template {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
165 t, err := CompileFile(filename, options)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
166 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
167 panic(err)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
168 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
169 return t
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
170 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
171
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
172 // CompileDir parses and compiles the contents of a supplied directory path, with options.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
173 // Returns a map of a template identifier (key) to a Go Template instance.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
174 // Ex: if the dirname="templates/" had a file "index.amber" the key would be "index"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
175 // If option for recursive is True, this parses every file of relevant extension
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
176 // in all subdirectories. The key then is the path e.g: "layouts/layout"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
177 func CompileDir(dirname string, dopt DirOptions, opt Options) (map[string]*template.Template, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
178 dir, err := os.Open(dirname)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
179 if err != nil && opt.VirtualFilesystem != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
180 vdir, err := opt.VirtualFilesystem.Open(dirname)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
181 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
182 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
183 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
184 dir = vdir.(*os.File)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
185 } else if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
186 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
187 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
188 defer dir.Close()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
189
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
190 files, err := dir.Readdir(0)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
191 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
192 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
193 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
194
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
195 compiled := make(map[string]*template.Template)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
196 for _, file := range files {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
197 // filename is for example "index.amber"
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
198 filename := file.Name()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
199 fileext := filepath.Ext(filename)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
200
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
201 // If recursive is true and there's a subdirectory, recurse
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
202 if dopt.Recursive && file.IsDir() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
203 dirpath := filepath.Join(dirname, filename)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
204 subcompiled, err := CompileDir(dirpath, dopt, opt)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
205 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
206 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
207 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
208 // Copy templates from subdirectory into parent template mapping
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
209 for k, v := range subcompiled {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
210 // Concat with parent directory name for unique paths
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
211 key := filepath.Join(filename, k)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
212 compiled[key] = v
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
213 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
214 } else if fileext == dopt.Ext {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
215 // Otherwise compile the file and add to mapping
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
216 fullpath := filepath.Join(dirname, filename)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
217 tmpl, err := CompileFile(fullpath, opt)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
218 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
219 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
220 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
221 // Strip extension
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
222 key := filename[0 : len(filename)-len(fileext)]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
223 compiled[key] = tmpl
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
224 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
225 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
226
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
227 return compiled, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
228 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
229
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
230 // MustCompileDir is the same as CompileDir, except input is assumed error free. If else, panic.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
231 func MustCompileDir(dirname string, dopt DirOptions, opt Options) map[string]*template.Template {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
232 m, err := CompileDir(dirname, dopt, opt)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
233 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
234 panic(err)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
235 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
236 return m
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
237 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
238
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
239 // Parse given raw amber template string.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
240 func (c *Compiler) Parse(input string) (err error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
241 defer func() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
242 if r := recover(); r != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
243 err = errors.New(r.(string))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
244 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
245 }()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
246
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
247 parser, err := parser.StringParser(input)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
248
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
249 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
250 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
251 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
252
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
253 c.node = parser.Parse()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
254 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
255 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
256
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
257 // Parse given raw amber template bytes, and the filename that belongs with it
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
258 func (c *Compiler) ParseData(input []byte, filename string) (err error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
259 defer func() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
260 if r := recover(); r != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
261 err = errors.New(r.(string))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
262 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
263 }()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
264
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
265 parser, err := parser.ByteParser(input)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
266 parser.SetFilename(filename)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
267 if c.VirtualFilesystem != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
268 parser.SetVirtualFilesystem(c.VirtualFilesystem)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
269 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
270
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
271 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
272 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
273 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
274
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
275 c.node = parser.Parse()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
276 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
277 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
278
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
279 // ParseFile parses the amber template file in given path.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
280 func (c *Compiler) ParseFile(filename string) (err error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
281 defer func() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
282 if r := recover(); r != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
283 err = errors.New(r.(string))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
284 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
285 }()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
286
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
287 p, err := parser.FileParser(filename)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
288 if err != nil && c.VirtualFilesystem != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
289 p, err = parser.VirtualFileParser(filename, c.VirtualFilesystem)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
290 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
291 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
292 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
293 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
294
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
295 c.node = p.Parse()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
296 c.filename = filename
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
297 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
298 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
299
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
300 // Compile amber and create a Go Template (html/templates) instance.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
301 // Necessary runtime functions will be injected and the template will be ready to be executed.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
302 func (c *Compiler) Compile() (*template.Template, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
303 return c.CompileWithName(filepath.Base(c.filename))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
304 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
305
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
306 // CompileWithName is the same as Compile, but allows to specify a name for the template.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
307 func (c *Compiler) CompileWithName(name string) (*template.Template, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
308 return c.CompileWithTemplate(template.New(name))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
309 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
310
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
311 // CompileWithTemplate is the same as Compile but allows to specify a template.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
312 func (c *Compiler) CompileWithTemplate(t *template.Template) (*template.Template, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
313 data, err := c.CompileString()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
314
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
315 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
316 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
317 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
318
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
319 tpl, err := t.Funcs(FuncMap).Parse(data)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
320
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
321 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
322 return nil, err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
323 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
324
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
325 return tpl, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
326 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
327
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
328 // CompileWriter compiles amber and writes the Go Template source into given io.Writer instance.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
329 // You would not be using this unless debugging / checking the output. Please use Compile
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
330 // method to obtain a template instance directly.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
331 func (c *Compiler) CompileWriter(out io.Writer) (err error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
332 defer func() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
333 if r := recover(); r != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
334 err = errors.New(r.(string))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
335 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
336 }()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
337
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
338 c.buffer = new(bytes.Buffer)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
339 c.visit(c.node)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
340
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
341 if c.buffer.Len() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
342 c.write("\n")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
343 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
344
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
345 _, err = c.buffer.WriteTo(out)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
346 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
347 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
348
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
349 // CompileString compiles the template and returns the Go Template source.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
350 // You would not be using this unless debugging / checking the output. Please use Compile
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
351 // method to obtain a template instance directly.
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
352 func (c *Compiler) CompileString() (string, error) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
353 var buf bytes.Buffer
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
354
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
355 if err := c.CompileWriter(&buf); err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
356 return "", err
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
357 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
358
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
359 result := buf.String()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
360
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
361 return result, nil
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
362 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
363
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
364 func (c *Compiler) visit(node parser.Node) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
365 defer func() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
366 if r := recover(); r != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
367 if rs, ok := r.(string); ok && rs[:len("Amber Error")] == "Amber Error" {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
368 panic(r)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
369 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
370
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
371 pos := node.Pos()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
372
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
373 if len(pos.Filename) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
374 panic(fmt.Sprintf("Amber Error in <%s>: %v - Line: %d, Column: %d, Length: %d", pos.Filename, r, pos.LineNum, pos.ColNum, pos.TokenLength))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
375 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
376 panic(fmt.Sprintf("Amber Error: %v - Line: %d, Column: %d, Length: %d", r, pos.LineNum, pos.ColNum, pos.TokenLength))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
377 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
378 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
379 }()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
380
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
381 switch node.(type) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
382 case *parser.Block:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
383 c.visitBlock(node.(*parser.Block))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
384 case *parser.Doctype:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
385 c.visitDoctype(node.(*parser.Doctype))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
386 case *parser.Comment:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
387 c.visitComment(node.(*parser.Comment))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
388 case *parser.Tag:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
389 c.visitTag(node.(*parser.Tag))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
390 case *parser.Text:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
391 c.visitText(node.(*parser.Text))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
392 case *parser.Condition:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
393 c.visitCondition(node.(*parser.Condition))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
394 case *parser.Each:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
395 c.visitEach(node.(*parser.Each))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
396 case *parser.Assignment:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
397 c.visitAssignment(node.(*parser.Assignment))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
398 case *parser.Mixin:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
399 c.visitMixin(node.(*parser.Mixin))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
400 case *parser.MixinCall:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
401 c.visitMixinCall(node.(*parser.MixinCall))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
402 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
403 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
404
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
405 func (c *Compiler) write(value string) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
406 c.buffer.WriteString(value)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
407 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
408
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
409 func (c *Compiler) indent(offset int, newline bool) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
410 if !c.PrettyPrint {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
411 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
412 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
413
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
414 if newline && c.buffer.Len() > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
415 c.write("\n")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
416 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
417
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
418 for i := 0; i < c.indentLevel+offset; i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
419 c.write("\t")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
420 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
421 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
422
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
423 func (c *Compiler) tempvar() string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
424 c.tempvarIndex++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
425 return "$__amber_" + strconv.Itoa(c.tempvarIndex)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
426 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
427
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
428 func (c *Compiler) escape(input string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
429 return strings.Replace(strings.Replace(input, `\`, `\\`, -1), `"`, `\"`, -1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
430 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
431
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
432 func (c *Compiler) visitBlock(block *parser.Block) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
433 for _, node := range block.Children {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
434 if _, ok := node.(*parser.Text); !block.CanInline() && ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
435 c.indent(0, true)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
436 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
437
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
438 c.visit(node)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
439 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
440 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
441
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
442 func (c *Compiler) visitDoctype(doctype *parser.Doctype) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
443 c.write(doctype.String())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
444 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
445
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
446 func (c *Compiler) visitComment(comment *parser.Comment) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
447 if comment.Silent {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
448 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
449 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
450
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
451 c.indent(0, false)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
452
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
453 if comment.Block == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
454 c.write(`{{unescaped "<!-- ` + c.escape(comment.Value) + ` -->"}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
455 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
456 c.write(`<!-- ` + comment.Value)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
457 c.visitBlock(comment.Block)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
458 c.write(` -->`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
459 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
460 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
461
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
462 func (c *Compiler) visitCondition(condition *parser.Condition) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
463 c.write(`{{if ` + c.visitRawInterpolation(condition.Expression) + `}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
464 c.visitBlock(condition.Positive)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
465 if condition.Negative != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
466 c.write(`{{else}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
467 c.visitBlock(condition.Negative)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
468 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
469 c.write(`{{end}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
470 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
471
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
472 func (c *Compiler) visitEach(each *parser.Each) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
473 if each.Block == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
474 return
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
475 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
476
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
477 if len(each.Y) == 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
478 c.write(`{{range ` + each.X + ` := ` + c.visitRawInterpolation(each.Expression) + `}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
479 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
480 c.write(`{{range ` + each.X + `, ` + each.Y + ` := ` + c.visitRawInterpolation(each.Expression) + `}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
481 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
482 c.visitBlock(each.Block)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
483 c.write(`{{end}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
484 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
485
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
486 func (c *Compiler) visitAssignment(assgn *parser.Assignment) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
487 c.write(`{{` + assgn.X + ` := ` + c.visitRawInterpolation(assgn.Expression) + `}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
488 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
489
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
490 func (c *Compiler) visitTag(tag *parser.Tag) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
491 type attrib struct {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
492 name string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
493 value func() string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
494 condition string
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
495 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
496
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
497 attribs := make(map[string]*attrib)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
498
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
499 for _, item := range tag.Attributes {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
500 attritem := item
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
501 attr := new(attrib)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
502 attr.name = item.Name
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
503
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
504 attr.value = func() string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
505 if !attritem.IsRaw {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
506 return c.visitInterpolation(attritem.Value)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
507 } else if attritem.Value == "" {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
508 return ""
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
509 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
510 return attritem.Value
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
511 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
512 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
513
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
514 if len(attritem.Condition) != 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
515 attr.condition = c.visitRawInterpolation(attritem.Condition)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
516 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
517
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
518 if attr.name == "class" && attribs["class"] != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
519 prevclass := attribs["class"]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
520 prevvalue := prevclass.value
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
521
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
522 prevclass.value = func() string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
523 aval := attr.value()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
524
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
525 if len(attr.condition) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
526 aval = `{{if ` + attr.condition + `}}` + aval + `{{end}}`
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
527 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
528
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
529 if len(prevclass.condition) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
530 return `{{if ` + prevclass.condition + `}}` + prevvalue() + `{{end}} ` + aval
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
531 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
532
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
533 return prevvalue() + " " + aval
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
534 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
535 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
536 attribs[attritem.Name] = attr
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
537 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
538 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
539
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
540 keys := make([]string, 0, len(attribs))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
541 for key := range attribs {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
542 keys = append(keys, key)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
543 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
544 sort.Strings(keys)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
545
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
546 c.indent(0, true)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
547 c.write("<" + tag.Name)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
548
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
549 for _, name := range keys {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
550 value := attribs[name]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
551
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
552 if len(value.condition) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
553 c.write(`{{if ` + value.condition + `}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
554 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
555
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
556 val := value.value()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
557
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
558 if val == "" {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
559 c.write(` ` + name)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
560 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
561 c.write(` ` + name + `="` + val + `"`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
562 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
563
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
564 if len(value.condition) > 0 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
565 c.write(`{{end}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
566 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
567 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
568
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
569 if tag.IsSelfClosing() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
570 c.write(` />`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
571 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
572 c.write(`>`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
573
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
574 if tag.Block != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
575 if !tag.Block.CanInline() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
576 c.indentLevel++
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
577 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
578
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
579 c.visitBlock(tag.Block)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
580
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
581 if !tag.Block.CanInline() {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
582 c.indentLevel--
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
583 c.indent(0, true)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
584 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
585 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
586
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
587 c.write(`</` + tag.Name + `>`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
588 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
589 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
590
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
591 var textInterpolateRegexp = regexp.MustCompile(`#\{(.*?)\}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
592 var textEscapeRegexp = regexp.MustCompile(`\{\{(.*?)\}\}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
593
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
594 func (c *Compiler) visitText(txt *parser.Text) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
595 value := textEscapeRegexp.ReplaceAllStringFunc(txt.Value, func(value string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
596 return `{{"{{"}}` + value[2:len(value)-2] + `{{"}}"}}`
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
597 })
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
598
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
599 value = textInterpolateRegexp.ReplaceAllStringFunc(value, func(value string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
600 return c.visitInterpolation(value[2 : len(value)-1])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
601 })
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
602
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
603 lines := strings.Split(value, "\n")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
604 for i := 0; i < len(lines); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
605 c.write(lines[i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
606
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
607 if i < len(lines)-1 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
608 c.write("\n")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
609 c.indent(0, false)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
610 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
611 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
612 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
613
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
614 func (c *Compiler) visitInterpolation(value string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
615 return `{{` + c.visitRawInterpolation(value) + `}}`
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
616 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
617
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
618 func (c *Compiler) visitRawInterpolation(value string) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
619 if value == "" {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
620 value = "\"\""
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
621 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
622
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
623 value = strings.Replace(value, "$", dollar, -1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
624 expr, err := gp.ParseExpr(value)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
625 if err != nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
626 panic("Unable to parse expression.")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
627 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
628 value = strings.Replace(c.visitExpression(expr), dollar, "$", -1)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
629 return value
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
630 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
631
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
632 func (c *Compiler) visitExpression(outerexpr ast.Expr) string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
633 stack := list.New()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
634
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
635 pop := func() string {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
636 if stack.Front() == nil {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
637 return ""
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
638 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
639
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
640 val := stack.Front().Value.(string)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
641 stack.Remove(stack.Front())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
642 return val
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
643 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
644
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
645 var exec func(ast.Expr)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
646
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
647 exec = func(expr ast.Expr) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
648 switch expr := expr.(type) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
649 case *ast.BinaryExpr:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
650 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
651 be := expr
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
652
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
653 exec(be.Y)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
654 exec(be.X)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
655
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
656 negate := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
657 name := c.tempvar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
658 c.write(`{{` + name + ` := `)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
659
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
660 switch be.Op {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
661 case gt.ADD:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
662 c.write("__amber_add ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
663 case gt.SUB:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
664 c.write("__amber_sub ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
665 case gt.MUL:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
666 c.write("__amber_mul ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
667 case gt.QUO:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
668 c.write("__amber_quo ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
669 case gt.REM:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
670 c.write("__amber_rem ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
671 case gt.LAND:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
672 c.write("and ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
673 case gt.LOR:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
674 c.write("or ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
675 case gt.EQL:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
676 c.write("__amber_eql ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
677 case gt.NEQ:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
678 c.write("__amber_eql ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
679 negate = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
680 case gt.LSS:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
681 c.write("__amber_lss ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
682 case gt.GTR:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
683 c.write("__amber_gtr ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
684 case gt.LEQ:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
685 c.write("__amber_gtr ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
686 negate = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
687 case gt.GEQ:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
688 c.write("__amber_lss ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
689 negate = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
690 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
691 panic("Unexpected operator!")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
692 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
693
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
694 c.write(pop() + ` ` + pop() + `}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
695
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
696 if !negate {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
697 stack.PushFront(name)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
698 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
699 negname := c.tempvar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
700 c.write(`{{` + negname + ` := not ` + name + `}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
701 stack.PushFront(negname)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
702 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
703 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
704 case *ast.UnaryExpr:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
705 {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
706 ue := expr
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
707
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
708 exec(ue.X)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
709
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
710 name := c.tempvar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
711 c.write(`{{` + name + ` := `)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
712
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
713 switch ue.Op {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
714 case gt.SUB:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
715 c.write("__amber_minus ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
716 case gt.ADD:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
717 c.write("__amber_plus ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
718 case gt.NOT:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
719 c.write("not ")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
720 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
721 panic("Unexpected operator!")
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
722 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
723
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
724 c.write(pop() + `}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
725 stack.PushFront(name)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
726 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
727 case *ast.ParenExpr:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
728 exec(expr.X)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
729 case *ast.BasicLit:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
730 stack.PushFront(strings.Replace(expr.Value, dollar, "$", -1))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
731 case *ast.Ident:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
732 name := expr.Name
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
733 if len(name) >= len(dollar) && name[:len(dollar)] == dollar {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
734 if name == dollar {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
735 stack.PushFront(`.`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
736 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
737 stack.PushFront(`$` + expr.Name[len(dollar):])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
738 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
739 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
740 stack.PushFront(`.` + expr.Name)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
741 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
742 case *ast.SelectorExpr:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
743 se := expr
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
744 exec(se.X)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
745 x := pop()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
746
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
747 if x == "." {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
748 x = ""
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
749 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
750
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
751 name := c.tempvar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
752 c.write(`{{` + name + ` := ` + x + `.` + se.Sel.Name + `}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
753 stack.PushFront(name)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
754 case *ast.CallExpr:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
755 ce := expr
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
756
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
757 for i := len(ce.Args) - 1; i >= 0; i-- {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
758 exec(ce.Args[i])
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
759 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
760
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
761 name := c.tempvar()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
762 builtin := false
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
763
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
764 if ident, ok := ce.Fun.(*ast.Ident); ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
765 for _, fname := range builtinFunctions {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
766 if fname == ident.Name {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
767 builtin = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
768 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
769 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
770 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
771 for fname, _ := range FuncMap {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
772 if fname == ident.Name {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
773 builtin = true
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
774 break
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
775 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
776 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
777 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
778
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
779 if builtin {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
780 stack.PushFront(ce.Fun.(*ast.Ident).Name)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
781 c.write(`{{` + name + ` := ` + pop())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
782 } else if se, ok := ce.Fun.(*ast.SelectorExpr); ok {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
783 exec(se.X)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
784 x := pop()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
785
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
786 if x == "." {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
787 x = ""
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
788 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
789 stack.PushFront(se.Sel.Name)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
790 c.write(`{{` + name + ` := ` + x + `.` + pop())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
791 } else {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
792 exec(ce.Fun)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
793 c.write(`{{` + name + ` := call ` + pop())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
794 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
795
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
796 for i := 0; i < len(ce.Args); i++ {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
797 c.write(` `)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
798 c.write(pop())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
799 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
800
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
801 c.write(`}}`)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
802
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
803 stack.PushFront(name)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
804 default:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
805 panic("Unable to parse expression. Unsupported: " + reflect.TypeOf(expr).String())
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
806 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
807 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
808
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
809 exec(outerexpr)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
810 return pop()
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
811 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
812
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
813 func (c *Compiler) visitMixin(mixin *parser.Mixin) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
814 c.mixins[mixin.Name] = mixin
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
815 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
816
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
817 func (c *Compiler) visitMixinCall(mixinCall *parser.MixinCall) {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
818 mixin := c.mixins[mixinCall.Name]
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
819
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
820 switch {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
821 case mixin == nil:
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
822 panic(fmt.Sprintf("unknown mixin %q", mixinCall.Name))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
823
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
824 case len(mixinCall.Args) < len(mixin.Args):
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
825 panic(fmt.Sprintf(
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
826 "not enough arguments in call to mixin %q (have: %d, want: %d)",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
827 mixinCall.Name,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
828 len(mixinCall.Args),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
829 len(mixin.Args),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
830 ))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
831 case len(mixinCall.Args) > len(mixin.Args):
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
832 panic(fmt.Sprintf(
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
833 "too many arguments in call to mixin %q (have: %d, want: %d)",
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
834 mixinCall.Name,
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
835 len(mixinCall.Args),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
836 len(mixin.Args),
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
837 ))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
838 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
839
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
840 for i, arg := range mixin.Args {
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
841 c.write(fmt.Sprintf(`{{%s := %s}}`, arg, c.visitRawInterpolation(mixinCall.Args[i])))
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
842 }
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
843 c.visitBlock(mixin.Block)
787b5ee0289d Use vendored modules
yakumo.izuru
parents:
diff changeset
844 }