2016-12-16 10:37:42 +00:00
|
|
|
package main
|
|
|
|
import "log"
|
|
|
|
import "fmt"
|
2017-01-17 07:55:46 +00:00
|
|
|
import "bytes"
|
2016-12-16 10:37:42 +00:00
|
|
|
import "strings"
|
2016-12-17 03:39:53 +00:00
|
|
|
import "strconv"
|
2017-01-17 07:55:46 +00:00
|
|
|
//import "regexp"
|
2016-12-16 10:37:42 +00:00
|
|
|
import "reflect"
|
|
|
|
import "path/filepath"
|
|
|
|
import "io/ioutil"
|
|
|
|
import "text/template/parse"
|
|
|
|
|
2017-01-01 15:45:43 +00:00
|
|
|
var ctemplates []string
|
|
|
|
var tmpl_ptr_map map[string]interface{} = make(map[string]interface{})
|
2017-02-11 14:51:16 +00:00
|
|
|
var text_overlap_list map[string]int
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
text_overlap_list = make(map[string]int)
|
|
|
|
}
|
2017-01-01 15:45:43 +00:00
|
|
|
|
2016-12-16 10:37:42 +00:00
|
|
|
type VarItem struct
|
|
|
|
{
|
|
|
|
Name string
|
|
|
|
Destination string
|
|
|
|
Type string
|
|
|
|
}
|
|
|
|
|
|
|
|
type VarItemReflect struct
|
|
|
|
{
|
|
|
|
Name string
|
|
|
|
Destination string
|
|
|
|
Value reflect.Value
|
|
|
|
}
|
|
|
|
|
|
|
|
type CTemplateSet struct
|
|
|
|
{
|
|
|
|
tlist map[string]*parse.Tree
|
|
|
|
dir string
|
|
|
|
funcMap map[string]interface{}
|
|
|
|
importMap map[string]string
|
2017-01-17 07:55:46 +00:00
|
|
|
Fragments map[string]int
|
|
|
|
FragmentCursor map[string]int
|
|
|
|
FragOut string
|
2016-12-16 10:37:42 +00:00
|
|
|
varList map[string]VarItem
|
|
|
|
localVars map[string]map[string]VarItemReflect
|
2016-12-17 03:39:53 +00:00
|
|
|
stats map[string]int
|
|
|
|
pVarList string
|
|
|
|
pVarPosition int
|
2016-12-18 12:56:06 +00:00
|
|
|
previousNode parse.NodeType
|
|
|
|
currentNode parse.NodeType
|
|
|
|
nextNode parse.NodeType
|
2016-12-16 10:37:42 +00:00
|
|
|
//tempVars map[string]string
|
|
|
|
doImports bool
|
|
|
|
expectsInt interface{}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_template(name string, dir string, expects string, expectsInt interface{}, varList map[string]VarItem) (out string) {
|
|
|
|
c.dir = dir
|
|
|
|
c.doImports = true
|
|
|
|
c.funcMap = make(map[string]interface{})
|
|
|
|
c.funcMap["and"] = "&&"
|
|
|
|
c.funcMap["not"] = "!"
|
|
|
|
c.funcMap["or"] = "||"
|
|
|
|
c.funcMap["eq"] = true
|
|
|
|
c.funcMap["ge"] = true
|
|
|
|
c.funcMap["gt"] = true
|
|
|
|
c.funcMap["le"] = true
|
|
|
|
c.funcMap["lt"] = true
|
|
|
|
c.funcMap["ne"] = true
|
2017-01-21 18:16:27 +00:00
|
|
|
c.funcMap["add"] = true
|
|
|
|
c.funcMap["subtract"] = true
|
|
|
|
c.funcMap["multiply"] = true
|
|
|
|
c.funcMap["divide"] = true
|
2016-12-16 10:37:42 +00:00
|
|
|
c.importMap = make(map[string]string)
|
2016-12-17 03:39:53 +00:00
|
|
|
c.importMap["io"] = "io"
|
2016-12-16 10:37:42 +00:00
|
|
|
c.importMap["strconv"] = "strconv"
|
|
|
|
c.varList = varList
|
2016-12-17 03:39:53 +00:00
|
|
|
//c.pVarList = ""
|
|
|
|
//c.pVarPosition = 0
|
|
|
|
c.stats = make(map[string]int)
|
2016-12-16 10:37:42 +00:00
|
|
|
c.expectsInt = expectsInt
|
|
|
|
holdreflect := reflect.ValueOf(expectsInt)
|
|
|
|
|
|
|
|
res, err := ioutil.ReadFile(dir + name)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2017-02-11 14:51:16 +00:00
|
|
|
|
2016-12-16 10:37:42 +00:00
|
|
|
content := string(res)
|
2017-02-11 14:51:16 +00:00
|
|
|
if !debug {
|
|
|
|
content = minify(content)
|
|
|
|
}
|
2016-12-16 10:37:42 +00:00
|
|
|
|
|
|
|
tree := parse.New(name, c.funcMap)
|
|
|
|
var treeSet map[string]*parse.Tree = make(map[string]*parse.Tree)
|
|
|
|
tree, err = tree.Parse(content,"{{","}}", treeSet, c.funcMap)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
if debug {
|
|
|
|
fmt.Println(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
out = ""
|
|
|
|
fname := strings.TrimSuffix(name, filepath.Ext(name))
|
|
|
|
c.tlist = make(map[string]*parse.Tree)
|
|
|
|
c.tlist[fname] = tree
|
|
|
|
varholder := "tmpl_" + fname + "_vars"
|
|
|
|
|
|
|
|
if debug {
|
|
|
|
fmt.Println(c.tlist)
|
|
|
|
}
|
|
|
|
c.localVars = make(map[string]map[string]VarItemReflect)
|
|
|
|
c.localVars[fname] = make(map[string]VarItemReflect)
|
|
|
|
c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect}
|
2017-01-17 07:55:46 +00:00
|
|
|
if c.Fragments == nil {
|
|
|
|
c.Fragments = make(map[string]int)
|
|
|
|
}
|
|
|
|
c.FragmentCursor = make(map[string]int)
|
|
|
|
c.FragmentCursor[fname] = 0
|
2016-12-16 10:37:42 +00:00
|
|
|
|
|
|
|
subtree := c.tlist[fname]
|
|
|
|
if debug {
|
|
|
|
fmt.Println(subtree.Root)
|
|
|
|
}
|
|
|
|
|
2016-12-18 12:56:06 +00:00
|
|
|
treeLength := len(subtree.Root.Nodes)
|
|
|
|
for index, node := range subtree.Root.Nodes {
|
2016-12-16 10:37:42 +00:00
|
|
|
if debug {
|
|
|
|
fmt.Println("Node: " + node.String())
|
|
|
|
}
|
2016-12-18 12:56:06 +00:00
|
|
|
|
|
|
|
c.previousNode = c.currentNode
|
|
|
|
c.currentNode = node.Type()
|
|
|
|
if treeLength != (index + 1) {
|
|
|
|
c.nextNode = subtree.Root.Nodes[index + 1].Type()
|
|
|
|
}
|
2016-12-16 10:37:42 +00:00
|
|
|
out += c.compile_switch(varholder, holdreflect, fname, node)
|
|
|
|
}
|
|
|
|
|
|
|
|
var importList string
|
|
|
|
if c.doImports {
|
|
|
|
for _, item := range c.importMap {
|
|
|
|
importList += "import \"" + item + "\"\n"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var varString string
|
|
|
|
for _, varItem := range c.varList {
|
|
|
|
varString += "var " + varItem.Name + " " + varItem.Type + " = " + varItem.Destination + "\n"
|
|
|
|
}
|
|
|
|
|
2017-01-01 15:45:43 +00:00
|
|
|
fout := "/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */\n"
|
|
|
|
fout += "package main\n" + importList + c.pVarList + "\n"
|
|
|
|
fout += "func init() {\n\ttemplate_" + fname +"_handle = template_" + fname + "\n\t//o_template_" + fname +"_handle = template_" + fname + "\n\tctemplates = append(ctemplates,\"" + fname + "\")\n\ttmpl_ptr_map[\"" + fname + "\"] = &template_" + fname + "_handle\n\ttmpl_ptr_map[\"o_" + fname + "\"] = template_" + fname + "\n}\n\n"
|
|
|
|
fout += "func template_" + fname + "(tmpl_" + fname + "_vars " + expects + ", w io.Writer) {\n" + varString + out + "}\n"
|
2016-12-17 03:39:53 +00:00
|
|
|
|
2017-01-01 15:45:43 +00:00
|
|
|
fout = strings.Replace(fout,`))
|
2016-12-17 03:39:53 +00:00
|
|
|
w.Write([]byte(`," + ",-1)
|
2017-01-01 15:45:43 +00:00
|
|
|
fout = strings.Replace(fout,"` + `","",-1)
|
2017-01-17 07:55:46 +00:00
|
|
|
//spstr := "`([:space:]*)`"
|
|
|
|
//whitespace_writes := regexp.MustCompile(`(?s)w.Write\(\[\]byte\(`+spstr+`\)\)`)
|
|
|
|
//fout = whitespace_writes.ReplaceAllString(fout,"")
|
2016-12-17 03:39:53 +00:00
|
|
|
|
|
|
|
for index, count := range c.stats {
|
|
|
|
fmt.Println(index + ": " + strconv.Itoa(count))
|
|
|
|
}
|
2016-12-18 12:56:06 +00:00
|
|
|
fmt.Println(" ")
|
2016-12-17 03:39:53 +00:00
|
|
|
|
2016-12-16 10:37:42 +00:00
|
|
|
if debug {
|
|
|
|
fmt.Println("Output!")
|
2017-01-01 15:45:43 +00:00
|
|
|
fmt.Println(fout)
|
2016-12-16 10:37:42 +00:00
|
|
|
}
|
2017-01-01 15:45:43 +00:00
|
|
|
return fout
|
2016-12-16 10:37:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Value, template_name string, node interface{}) (out string) {
|
|
|
|
switch node := node.(type) {
|
|
|
|
case *parse.ActionNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Action Node")
|
|
|
|
}
|
|
|
|
|
|
|
|
if node.Pipe == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
for _, cmd := range node.Pipe.Cmds {
|
|
|
|
out += c.compile_subswitch(varholder, holdreflect, template_name, cmd)
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
case *parse.IfNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("If Node: ")
|
|
|
|
fmt.Println(node.Pipe)
|
|
|
|
}
|
|
|
|
|
|
|
|
var expr string
|
|
|
|
for _, cmd := range node.Pipe.Cmds {
|
|
|
|
if debug {
|
|
|
|
fmt.Println("If Node Bit: ")
|
|
|
|
fmt.Println(cmd)
|
|
|
|
fmt.Println(reflect.ValueOf(cmd).Type().Name())
|
|
|
|
}
|
|
|
|
expr += c.compile_varswitch(varholder, holdreflect, template_name, cmd)
|
|
|
|
}
|
|
|
|
|
2016-12-18 12:56:06 +00:00
|
|
|
c.previousNode = c.currentNode
|
|
|
|
c.currentNode = parse.NodeList
|
|
|
|
c.nextNode = -1
|
2016-12-16 10:37:42 +00:00
|
|
|
if node.ElseList == nil {
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Branch 1")
|
|
|
|
}
|
|
|
|
return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "}\n"
|
|
|
|
} else {
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Branch 2")
|
|
|
|
}
|
|
|
|
return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "} else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n"
|
|
|
|
}
|
|
|
|
case *parse.ListNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("List Node")
|
|
|
|
}
|
|
|
|
for _, subnode := range node.Nodes {
|
|
|
|
out += c.compile_switch(varholder, holdreflect, template_name, subnode)
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
case *parse.RangeNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Range Node!")
|
|
|
|
fmt.Println(node.Pipe)
|
|
|
|
}
|
|
|
|
|
|
|
|
var outVal reflect.Value
|
|
|
|
for _, cmd := range node.Pipe.Cmds {
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Range Bit: ")
|
|
|
|
fmt.Println(cmd)
|
|
|
|
}
|
|
|
|
out, outVal = c.compile_reflectswitch(varholder, holdreflect, template_name, cmd)
|
|
|
|
}
|
|
|
|
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Returned: ")
|
|
|
|
fmt.Println(out)
|
|
|
|
fmt.Println("Range Kind Switch!")
|
|
|
|
}
|
|
|
|
|
|
|
|
switch outVal.Kind() {
|
|
|
|
case reflect.Map:
|
|
|
|
var item reflect.Value
|
|
|
|
for _, key := range outVal.MapKeys() {
|
|
|
|
item = outVal.MapIndex(key)
|
|
|
|
}
|
|
|
|
|
2016-12-21 02:30:32 +00:00
|
|
|
if node.ElseList != nil {
|
|
|
|
out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n} else {\n" + c.compile_switch("item", item, template_name, node.ElseList) + "}\n"
|
|
|
|
} else {
|
|
|
|
out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n}"
|
|
|
|
}
|
2016-12-18 12:56:06 +00:00
|
|
|
case reflect.Slice:
|
|
|
|
item := outVal.Index(0)
|
|
|
|
|
2016-12-16 10:37:42 +00:00
|
|
|
out = "if len(" + out + ") != 0 {\nfor _, item := range " + out + " {\n" + c.compile_switch("item", item, template_name, node.List) + "}\n}"
|
|
|
|
case reflect.Invalid:
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
if node.ElseList != nil {
|
|
|
|
out += " else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n"
|
|
|
|
} else {
|
|
|
|
out += "\n"
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
case *parse.TemplateNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Template Node")
|
|
|
|
}
|
|
|
|
return c.compile_subtemplate(varholder, holdreflect, node)
|
|
|
|
case *parse.TextNode:
|
2016-12-18 12:56:06 +00:00
|
|
|
c.previousNode = c.currentNode
|
|
|
|
c.currentNode = node.Type()
|
|
|
|
c.nextNode = 0
|
2017-01-17 07:55:46 +00:00
|
|
|
tmpText := bytes.TrimSpace(node.Text)
|
|
|
|
if len(tmpText) == 0 {
|
|
|
|
return ""
|
|
|
|
} else {
|
|
|
|
//return "w.Write([]byte(`" + string(node.Text) + "`))\n"
|
|
|
|
fragment_name := template_name + "_" + strconv.Itoa(c.FragmentCursor[template_name])
|
|
|
|
_, ok := c.Fragments[fragment_name]
|
|
|
|
if !ok {
|
|
|
|
c.Fragments[fragment_name] = len(node.Text)
|
|
|
|
c.FragOut += "var " + fragment_name + " []byte = []byte(`" + string(node.Text) + "`)\n"
|
|
|
|
}
|
|
|
|
c.FragmentCursor[template_name] = c.FragmentCursor[template_name] + 1
|
|
|
|
return "w.Write(" + fragment_name + ")\n"
|
|
|
|
}
|
2016-12-16 10:37:42 +00:00
|
|
|
default:
|
|
|
|
panic("Unknown Node in main switch")
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
|
|
|
|
firstWord := node.Args[0]
|
|
|
|
switch n := firstWord.(type) {
|
|
|
|
case *parse.FieldNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Field Node: ")
|
|
|
|
fmt.Println(n.Ident)
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
|
|
|
|
cur := holdreflect
|
|
|
|
|
|
|
|
var varbit string
|
|
|
|
if cur.Kind() == reflect.Interface {
|
|
|
|
cur = cur.Elem()
|
|
|
|
varbit += ".(" + cur.Type().Name() + ")"
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, id := range n.Ident {
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Data Kind: ")
|
|
|
|
fmt.Println(cur.Kind().String())
|
|
|
|
fmt.Println("Field Bit: ")
|
|
|
|
fmt.Println(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = cur.FieldByName(id)
|
|
|
|
if cur.Kind() == reflect.Interface {
|
|
|
|
cur = cur.Elem()
|
2016-12-17 03:39:53 +00:00
|
|
|
/*if cur.Kind() == reflect.String && cur.Type().Name() != "string" {
|
|
|
|
varbit = "string(" + varbit + "." + id + ")"*/
|
|
|
|
//if cur.Kind() == reflect.String && cur.Type().Name() != "string" {
|
2016-12-18 12:56:06 +00:00
|
|
|
if cur.Type().PkgPath() != "main" && cur.Type().PkgPath() != "" {
|
2016-12-17 03:39:53 +00:00
|
|
|
c.importMap["html/template"] = "html/template"
|
|
|
|
varbit += "." + id + ".(" + strings.TrimPrefix(cur.Type().PkgPath(),"html/") + "." + cur.Type().Name() + ")"
|
2016-12-16 10:37:42 +00:00
|
|
|
} else {
|
|
|
|
varbit += "." + id + ".(" + cur.Type().Name() + ")"
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
varbit += "." + id
|
|
|
|
}
|
|
|
|
if debug {
|
|
|
|
fmt.Println("End Cycle")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out = c.compile_varsub(varholder + varbit, cur)
|
|
|
|
|
|
|
|
for _, varItem := range c.varList {
|
|
|
|
if strings.HasPrefix(out, varItem.Destination) {
|
|
|
|
out = strings.Replace(out, varItem.Destination, varItem.Name, 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
case *parse.DotNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Dot Node")
|
|
|
|
fmt.Println(node.String())
|
|
|
|
}
|
|
|
|
return c.compile_varsub(varholder, holdreflect)
|
|
|
|
case *parse.NilNode:
|
|
|
|
panic("Nil is not a command x.x")
|
|
|
|
case *parse.VariableNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Variable Node")
|
|
|
|
fmt.Println(n.String())
|
|
|
|
fmt.Println(n.Ident)
|
|
|
|
}
|
2017-01-12 02:55:08 +00:00
|
|
|
varname, reflectVal := c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
|
|
|
return c.compile_varsub(varname, reflectVal)
|
2016-12-16 10:37:42 +00:00
|
|
|
case *parse.StringNode:
|
|
|
|
return n.Quoted
|
2017-01-21 18:16:27 +00:00
|
|
|
case *parse.IdentifierNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Identifier Node: ")
|
|
|
|
fmt.Println(node)
|
|
|
|
fmt.Println(node.Args)
|
|
|
|
}
|
|
|
|
return c.compile_varsub(c.compile_identswitch(varholder, holdreflect, template_name, node))
|
2016-12-16 10:37:42 +00:00
|
|
|
default:
|
|
|
|
fmt.Println("Unknown Kind: ")
|
|
|
|
fmt.Println(reflect.ValueOf(firstWord).Elem().Kind())
|
|
|
|
fmt.Println("Unknown Type: ")
|
|
|
|
fmt.Println(reflect.ValueOf(firstWord).Elem().Type().Name())
|
|
|
|
panic("I don't know what node this is")
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
|
|
|
|
firstWord := node.Args[0]
|
|
|
|
switch n := firstWord.(type) {
|
|
|
|
case *parse.FieldNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Field Node: ")
|
|
|
|
fmt.Println(n.Ident)
|
|
|
|
|
|
|
|
for _, id := range n.Ident {
|
|
|
|
fmt.Println("Field Bit: ")
|
|
|
|
fmt.Println(id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
|
|
|
|
return c.compile_boolsub(n.String(), varholder, template_name, holdreflect)
|
|
|
|
case *parse.ChainNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Chain Node: ")
|
|
|
|
fmt.Println(n.Node)
|
|
|
|
fmt.Println(node.Args)
|
|
|
|
}
|
|
|
|
break
|
|
|
|
case *parse.IdentifierNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Identifier Node: ")
|
|
|
|
fmt.Println(node)
|
|
|
|
fmt.Println(node.Args)
|
|
|
|
}
|
2017-01-21 18:16:27 +00:00
|
|
|
return c.compile_identswitch_n(varholder, holdreflect, template_name, node)
|
2016-12-16 10:37:42 +00:00
|
|
|
case *parse.DotNode:
|
|
|
|
return varholder
|
|
|
|
case *parse.VariableNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Variable Node")
|
|
|
|
fmt.Println(n.String())
|
|
|
|
fmt.Println(n.Ident)
|
|
|
|
}
|
|
|
|
out, _ = c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
|
|
|
return out
|
|
|
|
case *parse.NilNode:
|
|
|
|
panic("Nil is not a command x.x")
|
|
|
|
case *parse.PipeNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Pipe Node!")
|
|
|
|
fmt.Println(n)
|
|
|
|
fmt.Println("Args: ")
|
|
|
|
fmt.Println(node.Args)
|
|
|
|
}
|
2017-01-21 18:16:27 +00:00
|
|
|
out += c.compile_identswitch_n(varholder, holdreflect, template_name, node)
|
2016-12-16 10:37:42 +00:00
|
|
|
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Out: ")
|
|
|
|
fmt.Println(out)
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
default:
|
|
|
|
fmt.Println("Unknown Kind: ")
|
|
|
|
fmt.Println(reflect.ValueOf(firstWord).Elem().Kind())
|
|
|
|
fmt.Println("Unknown Type: ")
|
|
|
|
fmt.Println(reflect.ValueOf(firstWord).Elem().Type().Name())
|
|
|
|
panic("I don't know what node this is! Grr...")
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2017-01-21 18:16:27 +00:00
|
|
|
func (c *CTemplateSet) compile_identswitch_n(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
|
|
|
|
out, _ = c.compile_identswitch(varholder, holdreflect, template_name, node)
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string, val reflect.Value) {
|
2016-12-16 10:37:42 +00:00
|
|
|
ArgLoop:
|
|
|
|
for pos, id := range node.Args {
|
|
|
|
if debug {
|
|
|
|
fmt.Println(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
switch id.String() {
|
|
|
|
case "not":
|
|
|
|
out += "!"
|
|
|
|
case "or":
|
|
|
|
out += " || "
|
|
|
|
case "and":
|
|
|
|
out += " && "
|
|
|
|
case "le":
|
|
|
|
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " <= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
2017-01-21 18:16:27 +00:00
|
|
|
if debug {
|
|
|
|
fmt.Println(node.Args[pos + 1])
|
|
|
|
fmt.Println(node.Args[pos + 2])
|
|
|
|
}
|
2016-12-16 10:37:42 +00:00
|
|
|
break ArgLoop
|
2017-01-12 02:55:08 +00:00
|
|
|
case "lt":
|
|
|
|
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " < " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
2017-01-21 18:16:27 +00:00
|
|
|
if debug {
|
|
|
|
fmt.Println(node.Args[pos + 1])
|
|
|
|
fmt.Println(node.Args[pos + 2])
|
|
|
|
}
|
2017-01-12 02:55:08 +00:00
|
|
|
break ArgLoop
|
|
|
|
case "gt":
|
|
|
|
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " > " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
2017-01-21 18:16:27 +00:00
|
|
|
if debug {
|
|
|
|
fmt.Println(node.Args[pos + 1])
|
|
|
|
fmt.Println(node.Args[pos + 2])
|
|
|
|
}
|
2017-01-12 02:55:08 +00:00
|
|
|
break ArgLoop
|
|
|
|
case "ge":
|
|
|
|
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " >= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
2017-01-21 18:16:27 +00:00
|
|
|
if debug {
|
|
|
|
fmt.Println(node.Args[pos + 1])
|
|
|
|
fmt.Println(node.Args[pos + 2])
|
|
|
|
}
|
2017-01-12 02:55:08 +00:00
|
|
|
break ArgLoop
|
|
|
|
case "eq":
|
|
|
|
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " == " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
2017-01-21 18:16:27 +00:00
|
|
|
if debug {
|
|
|
|
fmt.Println(node.Args[pos + 1])
|
|
|
|
fmt.Println(node.Args[pos + 2])
|
|
|
|
}
|
2017-01-12 02:55:08 +00:00
|
|
|
break ArgLoop
|
|
|
|
case "ne":
|
|
|
|
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " != " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
2017-01-21 18:16:27 +00:00
|
|
|
if debug {
|
|
|
|
fmt.Println(node.Args[pos + 1])
|
|
|
|
fmt.Println(node.Args[pos + 2])
|
|
|
|
}
|
|
|
|
break ArgLoop
|
|
|
|
case "add":
|
|
|
|
param1, val2 := c.compile_if_varsub(node.Args[pos + 1].String(), varholder, template_name, holdreflect)
|
|
|
|
param2, val3 := c.compile_if_varsub(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
|
|
|
|
|
|
|
if val2.IsValid() {
|
|
|
|
val = val2
|
|
|
|
} else if val3.IsValid() {
|
|
|
|
val = val3
|
|
|
|
} else {
|
|
|
|
numSample := 1
|
|
|
|
val = reflect.ValueOf(numSample)
|
|
|
|
}
|
|
|
|
|
|
|
|
out += param1 + " + " + param2
|
|
|
|
if debug {
|
|
|
|
fmt.Println("add")
|
|
|
|
fmt.Println(node.Args[pos + 1])
|
|
|
|
fmt.Println(node.Args[pos + 2])
|
|
|
|
}
|
|
|
|
break ArgLoop
|
|
|
|
case "subtract":
|
|
|
|
param1, val2 := c.compile_if_varsub(node.Args[pos + 1].String(), varholder, template_name, holdreflect)
|
|
|
|
param2, val3 := c.compile_if_varsub(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
|
|
|
|
|
|
|
if val2.IsValid() {
|
|
|
|
val = val2
|
|
|
|
} else if val3.IsValid() {
|
|
|
|
val = val3
|
|
|
|
} else {
|
|
|
|
numSample := 1
|
|
|
|
val = reflect.ValueOf(numSample)
|
|
|
|
}
|
|
|
|
|
|
|
|
out += param1 + " - " + param2
|
|
|
|
if debug {
|
|
|
|
fmt.Println("subtract")
|
|
|
|
fmt.Println(node.Args[pos + 1])
|
|
|
|
fmt.Println(node.Args[pos + 2])
|
|
|
|
}
|
|
|
|
break ArgLoop
|
|
|
|
case "divide":
|
|
|
|
param1, val2 := c.compile_if_varsub(node.Args[pos + 1].String(), varholder, template_name, holdreflect)
|
|
|
|
param2, val3 := c.compile_if_varsub(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
|
|
|
|
|
|
|
if val2.IsValid() {
|
|
|
|
val = val2
|
|
|
|
} else if val3.IsValid() {
|
|
|
|
val = val3
|
|
|
|
} else {
|
|
|
|
numSample := 1
|
|
|
|
val = reflect.ValueOf(numSample)
|
|
|
|
}
|
|
|
|
|
|
|
|
out += param1 + " / " + param2
|
|
|
|
if debug {
|
|
|
|
fmt.Println("divide")
|
|
|
|
fmt.Println(node.Args[pos + 1])
|
|
|
|
fmt.Println(node.Args[pos + 2])
|
|
|
|
}
|
|
|
|
break ArgLoop
|
|
|
|
case "multiply":
|
|
|
|
param1, val2 := c.compile_if_varsub(node.Args[pos + 1].String(), varholder, template_name, holdreflect)
|
|
|
|
param2, val3 := c.compile_if_varsub(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
|
|
|
|
|
|
|
|
if val2.IsValid() {
|
|
|
|
val = val2
|
|
|
|
} else if val3.IsValid() {
|
|
|
|
val = val3
|
|
|
|
} else {
|
|
|
|
numSample := 1
|
|
|
|
val = reflect.ValueOf(numSample)
|
|
|
|
}
|
|
|
|
|
|
|
|
out += param1 + " * " + param2
|
|
|
|
if debug {
|
|
|
|
fmt.Println("multiply")
|
|
|
|
fmt.Println(node.Args[pos + 1])
|
|
|
|
fmt.Println(node.Args[pos + 2])
|
|
|
|
}
|
2017-01-12 02:55:08 +00:00
|
|
|
break ArgLoop
|
2016-12-16 10:37:42 +00:00
|
|
|
default:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Variable!")
|
|
|
|
}
|
|
|
|
out += c.compile_if_varsub_n(id.String(), varholder, template_name, holdreflect)
|
|
|
|
}
|
|
|
|
}
|
2017-01-21 18:16:27 +00:00
|
|
|
return out, val
|
2016-12-16 10:37:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_reflectswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string, outVal reflect.Value) {
|
|
|
|
firstWord := node.Args[0]
|
|
|
|
switch n := firstWord.(type) {
|
|
|
|
case *parse.FieldNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Field Node: ")
|
|
|
|
fmt.Println(n.Ident)
|
|
|
|
|
|
|
|
for _, id := range n.Ident {
|
|
|
|
fmt.Println("Field Bit: ")
|
|
|
|
fmt.Println(id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
|
|
|
|
return c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
|
|
|
case *parse.ChainNode:
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Chain Node: ")
|
|
|
|
fmt.Println(n.Node)
|
|
|
|
fmt.Println(node.Args)
|
|
|
|
}
|
|
|
|
return "", outVal
|
|
|
|
case *parse.DotNode:
|
|
|
|
return varholder, holdreflect
|
|
|
|
case *parse.NilNode:
|
|
|
|
panic("Nil is not a command x.x")
|
|
|
|
default:
|
|
|
|
//panic("I don't know what node this is")
|
|
|
|
}
|
|
|
|
return "", outVal
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_if_varsub_n(varname string, varholder string, template_name string, cur reflect.Value) (out string) {
|
|
|
|
out, _ = c.compile_if_varsub(varname, varholder, template_name, cur)
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, template_name string, cur reflect.Value) (out string, val reflect.Value) {
|
|
|
|
if varname[0] != '.' && varname[0] != '$' {
|
|
|
|
return varname, cur
|
|
|
|
}
|
|
|
|
|
|
|
|
bits := strings.Split(varname,".")
|
|
|
|
if varname[0] == '$' {
|
|
|
|
var res VarItemReflect
|
|
|
|
if varname[1] == '.' {
|
|
|
|
res = c.localVars[template_name]["."]
|
|
|
|
} else {
|
|
|
|
res = c.localVars[template_name][strings.TrimPrefix(bits[0],"$")]
|
|
|
|
}
|
|
|
|
out += res.Destination
|
|
|
|
cur = res.Value
|
|
|
|
|
|
|
|
if cur.Kind() == reflect.Interface {
|
|
|
|
cur = cur.Elem()
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if cur.Kind() == reflect.Interface {
|
|
|
|
cur = cur.Elem()
|
|
|
|
out += varholder + ".(" + cur.Type().Name() + ")"
|
|
|
|
} else {
|
|
|
|
out += varholder
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bits[0] = strings.TrimPrefix(bits[0],"$")
|
|
|
|
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Cur Kind: ")
|
|
|
|
fmt.Println(cur.Kind())
|
|
|
|
fmt.Println("Cur Type: ")
|
|
|
|
fmt.Println(cur.Type().Name())
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, bit := range bits {
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Variable Field!")
|
|
|
|
fmt.Println(bit)
|
|
|
|
}
|
|
|
|
|
|
|
|
if bit == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = cur.FieldByName(bit)
|
|
|
|
if cur.Kind() == reflect.Interface {
|
|
|
|
cur = cur.Elem()
|
|
|
|
out += "." + bit + ".(" + cur.Type().Name() + ")"
|
|
|
|
} else {
|
|
|
|
out += "." + bit
|
|
|
|
}
|
|
|
|
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Data Kind: ")
|
|
|
|
fmt.Println(cur.Kind())
|
|
|
|
fmt.Println("Data Type: ")
|
|
|
|
fmt.Println(cur.Type().Name())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-21 18:16:27 +00:00
|
|
|
if debug {
|
|
|
|
fmt.Println("Out Value: ")
|
|
|
|
fmt.Println(out)
|
|
|
|
fmt.Println("Out Kind: ")
|
|
|
|
fmt.Println(cur.Kind())
|
|
|
|
fmt.Println("Out Type: ")
|
|
|
|
fmt.Println(cur.Type().Name())
|
|
|
|
}
|
|
|
|
|
2016-12-16 10:37:42 +00:00
|
|
|
for _, varItem := range c.varList {
|
|
|
|
if strings.HasPrefix(out, varItem.Destination) {
|
|
|
|
out = strings.Replace(out, varItem.Destination, varItem.Name, 1)
|
|
|
|
}
|
|
|
|
}
|
2016-12-17 03:39:53 +00:00
|
|
|
|
2017-01-21 18:16:27 +00:00
|
|
|
if debug {
|
|
|
|
fmt.Println("Out Value: ")
|
|
|
|
fmt.Println(out)
|
|
|
|
fmt.Println("Out Kind: ")
|
|
|
|
fmt.Println(cur.Kind())
|
|
|
|
fmt.Println("Out Type: ")
|
|
|
|
fmt.Println(cur.Type().Name())
|
|
|
|
}
|
|
|
|
|
2016-12-17 03:39:53 +00:00
|
|
|
_, ok := c.stats[out]
|
|
|
|
if ok {
|
|
|
|
c.stats[out]++
|
|
|
|
} else {
|
|
|
|
c.stats[out] = 1
|
|
|
|
}
|
|
|
|
|
2016-12-16 10:37:42 +00:00
|
|
|
return out, cur
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_boolsub(varname string, varholder string, template_name string, val reflect.Value) string {
|
|
|
|
out, val := c.compile_if_varsub(varname, varholder, template_name, val)
|
|
|
|
switch val.Kind() {
|
|
|
|
case reflect.Int:
|
|
|
|
out += " > 0"
|
|
|
|
case reflect.Bool:
|
|
|
|
// Do nothing
|
|
|
|
case reflect.String:
|
|
|
|
out += " != \"\""
|
|
|
|
case reflect.Int64:
|
|
|
|
out += " > 0"
|
|
|
|
default:
|
2017-01-21 18:16:27 +00:00
|
|
|
fmt.Println(varname)
|
|
|
|
fmt.Println(varholder)
|
|
|
|
fmt.Println(val.Kind())
|
2016-12-16 10:37:42 +00:00
|
|
|
panic("I don't know what this variable's type is o.o\n")
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_varsub(varname string, val reflect.Value) string {
|
|
|
|
for _, varItem := range c.varList {
|
|
|
|
if strings.HasPrefix(varname, varItem.Destination) {
|
|
|
|
varname = strings.Replace(varname, varItem.Destination, varItem.Name, 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-17 03:39:53 +00:00
|
|
|
_, ok := c.stats[varname]
|
|
|
|
if ok {
|
|
|
|
c.stats[varname]++
|
|
|
|
} else {
|
|
|
|
c.stats[varname] = 1
|
|
|
|
}
|
|
|
|
|
2016-12-16 10:37:42 +00:00
|
|
|
if val.Kind() == reflect.Interface {
|
|
|
|
val = val.Elem()
|
|
|
|
}
|
|
|
|
|
|
|
|
switch val.Kind() {
|
|
|
|
case reflect.Int:
|
2016-12-17 03:39:53 +00:00
|
|
|
return "w.Write([]byte(strconv.Itoa(" + varname + ")))\n"
|
2016-12-16 10:37:42 +00:00
|
|
|
case reflect.Bool:
|
2016-12-17 03:39:53 +00:00
|
|
|
return "if " + varname + " {\nw.Write([]byte(\"true\"))} else {\nw.Write([]byte(\"false\"))\n}\n"
|
2016-12-16 10:37:42 +00:00
|
|
|
case reflect.String:
|
2016-12-17 03:39:53 +00:00
|
|
|
if val.Type().Name() != "string" && !strings.HasPrefix(varname,"string(") {
|
|
|
|
return "w.Write([]byte(string(" + varname + ")))\n"
|
2016-12-16 10:37:42 +00:00
|
|
|
} else {
|
2016-12-17 03:39:53 +00:00
|
|
|
return "w.Write([]byte(" + varname + "))\n"
|
2016-12-16 10:37:42 +00:00
|
|
|
}
|
|
|
|
case reflect.Int64:
|
2016-12-17 03:39:53 +00:00
|
|
|
return "w.Write([]byte(strconv.FormatInt(" + varname + ", 10)))"
|
2016-12-16 10:37:42 +00:00
|
|
|
default:
|
2017-01-21 18:16:27 +00:00
|
|
|
fmt.Println("Unknown Variable Name: ")
|
|
|
|
fmt.Println(varname)
|
2016-12-16 10:37:42 +00:00
|
|
|
fmt.Println("Unknown Kind: ")
|
|
|
|
fmt.Println(val.Kind())
|
|
|
|
fmt.Println("Unknown Type: ")
|
|
|
|
fmt.Println(val.Type().Name())
|
|
|
|
panic("// I don't know what this variable's type is o.o\n")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect reflect.Value, node *parse.TemplateNode) (out string) {
|
|
|
|
if debug {
|
|
|
|
fmt.Println("Template Node: " + node.Name)
|
|
|
|
}
|
|
|
|
|
|
|
|
fname := strings.TrimSuffix(node.Name, filepath.Ext(node.Name))
|
|
|
|
varholder := "tmpl_" + fname + "_vars"
|
|
|
|
var holdreflect reflect.Value
|
|
|
|
if node.Pipe != nil {
|
|
|
|
for _, cmd := range node.Pipe.Cmds {
|
|
|
|
firstWord := cmd.Args[0]
|
|
|
|
switch firstWord.(type) {
|
|
|
|
case *parse.DotNode:
|
|
|
|
varholder = pvarholder
|
|
|
|
holdreflect = pholdreflect
|
|
|
|
break
|
|
|
|
case *parse.NilNode:
|
|
|
|
panic("Nil is not a command x.x")
|
|
|
|
default:
|
|
|
|
out = "var " + varholder + " := false\n"
|
|
|
|
out += c.compile_command(cmd)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err := ioutil.ReadFile(c.dir + node.Name)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2017-02-11 14:51:16 +00:00
|
|
|
|
2016-12-16 10:37:42 +00:00
|
|
|
content := string(res)
|
2017-02-11 14:51:16 +00:00
|
|
|
if !debug {
|
|
|
|
content = minify(content)
|
|
|
|
}
|
2016-12-16 10:37:42 +00:00
|
|
|
|
|
|
|
tree := parse.New(node.Name, c.funcMap)
|
|
|
|
var treeSet map[string]*parse.Tree = make(map[string]*parse.Tree)
|
|
|
|
tree, err = tree.Parse(content,"{{","}}", treeSet, c.funcMap)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
c.tlist[fname] = tree
|
|
|
|
subtree := c.tlist[fname]
|
|
|
|
if debug {
|
|
|
|
fmt.Println(subtree.Root)
|
|
|
|
}
|
|
|
|
|
|
|
|
c.localVars[fname] = make(map[string]VarItemReflect)
|
|
|
|
c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect}
|
2017-01-17 07:55:46 +00:00
|
|
|
c.FragmentCursor[fname] = 0
|
2016-12-16 10:37:42 +00:00
|
|
|
|
2016-12-18 12:56:06 +00:00
|
|
|
treeLength := len(subtree.Root.Nodes)
|
|
|
|
for index, node := range subtree.Root.Nodes {
|
2016-12-16 10:37:42 +00:00
|
|
|
if debug {
|
|
|
|
fmt.Println("Node: " + node.String())
|
|
|
|
}
|
2016-12-18 12:56:06 +00:00
|
|
|
|
|
|
|
c.previousNode = c.currentNode
|
|
|
|
c.currentNode = node.Type()
|
|
|
|
if treeLength != (index + 1) {
|
|
|
|
c.nextNode = subtree.Root.Nodes[index + 1].Type()
|
|
|
|
}
|
2016-12-16 10:37:42 +00:00
|
|
|
out += c.compile_switch(varholder, holdreflect, fname, node)
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *CTemplateSet) compile_command(*parse.CommandNode) (out string) {
|
|
|
|
return ""
|
2017-02-11 14:51:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func minify(data string) string {
|
|
|
|
data = strings.Replace(data,"\t","",-1)
|
|
|
|
data = strings.Replace(data,"\v","",-1)
|
|
|
|
data = strings.Replace(data,"\n","",-1)
|
|
|
|
data = strings.Replace(data,"\r","",-1)
|
|
|
|
data = strings.Replace(data," "," ",-1)
|
|
|
|
return data
|
|
|
|
}
|