d7cf48e43d
Added a test for one of the router algorithms. Added the ViewAdminLogs permission. Adminlogs are coming soon! The empty comments next to HandleFuncs on main.go are there to remind me about which routes I've added to the router generator route list. Fixed the Modlogs Page so that you can view it without the ManageThemes permissions. I accidentally used the wrong permission there before. Changed the router algorithm to align better with the upcoming generated router. It's faster too.
885 lines
24 KiB
Go
885 lines
24 KiB
Go
package main
|
|
import "log"
|
|
import "fmt"
|
|
import "bytes"
|
|
import "strings"
|
|
import "strconv"
|
|
//import "regexp"
|
|
import "reflect"
|
|
import "path/filepath"
|
|
import "io/ioutil"
|
|
import "text/template/parse"
|
|
|
|
var ctemplates []string
|
|
var tmpl_ptr_map map[string]interface{} = make(map[string]interface{})
|
|
var text_overlap_list map[string]int
|
|
|
|
func init() {
|
|
text_overlap_list = make(map[string]int)
|
|
}
|
|
|
|
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
|
|
Fragments map[string]int
|
|
FragmentCursor map[string]int
|
|
FragOut string
|
|
varList map[string]VarItem
|
|
localVars map[string]map[string]VarItemReflect
|
|
stats map[string]int
|
|
pVarList string
|
|
pVarPosition int
|
|
previousNode parse.NodeType
|
|
currentNode parse.NodeType
|
|
nextNode parse.NodeType
|
|
//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 = map[string]interface{}{
|
|
"and": "&&",
|
|
"not": "!",
|
|
"or": "||",
|
|
"eq": true,
|
|
"ge": true,
|
|
"gt": true,
|
|
"le": true,
|
|
"lt": true,
|
|
"ne": true,
|
|
"add": true,
|
|
"subtract": true,
|
|
"multiply": true,
|
|
"divide": true,
|
|
}
|
|
|
|
c.importMap = map[string]string{
|
|
"io":"io",
|
|
"strconv":"strconv",
|
|
}
|
|
c.varList = varList
|
|
//c.pVarList = ""
|
|
//c.pVarPosition = 0
|
|
c.stats = make(map[string]int)
|
|
c.expectsInt = expectsInt
|
|
holdreflect := reflect.ValueOf(expectsInt)
|
|
|
|
res, err := ioutil.ReadFile(dir + name)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
content := string(res)
|
|
if !debug {
|
|
content = minify(content)
|
|
}
|
|
|
|
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}
|
|
if c.Fragments == nil {
|
|
c.Fragments = make(map[string]int)
|
|
}
|
|
c.FragmentCursor = make(map[string]int)
|
|
c.FragmentCursor[fname] = 0
|
|
|
|
subtree := c.tlist[fname]
|
|
if debug {
|
|
fmt.Println(subtree.Root)
|
|
}
|
|
|
|
treeLength := len(subtree.Root.Nodes)
|
|
for index, node := range subtree.Root.Nodes {
|
|
if debug {
|
|
fmt.Println("Node: " + node.String())
|
|
}
|
|
|
|
c.previousNode = c.currentNode
|
|
c.currentNode = node.Type()
|
|
if treeLength != (index + 1) {
|
|
c.nextNode = subtree.Root.Nodes[index + 1].Type()
|
|
}
|
|
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"
|
|
}
|
|
|
|
fout := "// Code generated by. DO NOT EDIT.\n/* 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"
|
|
|
|
fout = strings.Replace(fout,`))
|
|
w.Write([]byte(`," + ",-1)
|
|
fout = strings.Replace(fout,"` + `","",-1)
|
|
//spstr := "`([:space:]*)`"
|
|
//whitespace_writes := regexp.MustCompile(`(?s)w.Write\(\[\]byte\(`+spstr+`\)\)`)
|
|
//fout = whitespace_writes.ReplaceAllString(fout,"")
|
|
|
|
for index, count := range c.stats {
|
|
fmt.Println(index + ": " + strconv.Itoa(count))
|
|
}
|
|
fmt.Println(" ")
|
|
|
|
if debug {
|
|
fmt.Println("Output!")
|
|
fmt.Println(fout)
|
|
}
|
|
return fout
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
c.previousNode = c.currentNode
|
|
c.currentNode = parse.NodeList
|
|
c.nextNode = -1
|
|
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)
|
|
}
|
|
|
|
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}"
|
|
}
|
|
case reflect.Slice:
|
|
item := outVal.Index(0)
|
|
|
|
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:
|
|
c.previousNode = c.currentNode
|
|
c.currentNode = node.Type()
|
|
c.nextNode = 0
|
|
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"
|
|
}
|
|
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()
|
|
/*if cur.Kind() == reflect.String && cur.Type().Name() != "string" {
|
|
varbit = "string(" + varbit + "." + id + ")"*/
|
|
//if cur.Kind() == reflect.String && cur.Type().Name() != "string" {
|
|
if cur.Type().PkgPath() != "main" && cur.Type().PkgPath() != "" {
|
|
c.importMap["html/template"] = "html/template"
|
|
varbit += "." + id + ".(" + strings.TrimPrefix(cur.Type().PkgPath(),"html/") + "." + cur.Type().Name() + ")"
|
|
} 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)
|
|
}
|
|
varname, reflectVal := c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
|
return c.compile_varsub(varname, reflectVal)
|
|
case *parse.StringNode:
|
|
return n.Quoted
|
|
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))
|
|
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)
|
|
}
|
|
return c.compile_identswitch_n(varholder, holdreflect, template_name, node)
|
|
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)
|
|
}
|
|
out += c.compile_identswitch_n(varholder, holdreflect, template_name, node)
|
|
|
|
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 ""
|
|
}
|
|
|
|
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) {
|
|
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)
|
|
if debug {
|
|
fmt.Println(node.Args[pos + 1])
|
|
fmt.Println(node.Args[pos + 2])
|
|
}
|
|
break ArgLoop
|
|
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)
|
|
if debug {
|
|
fmt.Println(node.Args[pos + 1])
|
|
fmt.Println(node.Args[pos + 2])
|
|
}
|
|
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)
|
|
if debug {
|
|
fmt.Println(node.Args[pos + 1])
|
|
fmt.Println(node.Args[pos + 2])
|
|
}
|
|
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)
|
|
if debug {
|
|
fmt.Println(node.Args[pos + 1])
|
|
fmt.Println(node.Args[pos + 2])
|
|
}
|
|
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)
|
|
if debug {
|
|
fmt.Println(node.Args[pos + 1])
|
|
fmt.Println(node.Args[pos + 2])
|
|
}
|
|
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)
|
|
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])
|
|
}
|
|
break ArgLoop
|
|
default:
|
|
if debug {
|
|
fmt.Println("Variable!")
|
|
}
|
|
out += c.compile_if_varsub_n(id.String(), varholder, template_name, holdreflect)
|
|
}
|
|
}
|
|
return out, val
|
|
}
|
|
|
|
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())
|
|
}
|
|
}
|
|
|
|
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())
|
|
}
|
|
|
|
for _, varItem := range c.varList {
|
|
if strings.HasPrefix(out, varItem.Destination) {
|
|
out = strings.Replace(out, varItem.Destination, varItem.Name, 1)
|
|
}
|
|
}
|
|
|
|
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())
|
|
}
|
|
|
|
_, ok := c.stats[out]
|
|
if ok {
|
|
c.stats[out]++
|
|
} else {
|
|
c.stats[out] = 1
|
|
}
|
|
|
|
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:
|
|
fmt.Println(varname)
|
|
fmt.Println(varholder)
|
|
fmt.Println(val.Kind())
|
|
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)
|
|
}
|
|
}
|
|
|
|
_, ok := c.stats[varname]
|
|
if ok {
|
|
c.stats[varname]++
|
|
} else {
|
|
c.stats[varname] = 1
|
|
}
|
|
|
|
if val.Kind() == reflect.Interface {
|
|
val = val.Elem()
|
|
}
|
|
|
|
switch val.Kind() {
|
|
case reflect.Int:
|
|
return "w.Write([]byte(strconv.Itoa(" + varname + ")))\n"
|
|
case reflect.Bool:
|
|
return "if " + varname + " {\nw.Write([]byte(\"true\"))} else {\nw.Write([]byte(\"false\"))\n}\n"
|
|
case reflect.String:
|
|
if val.Type().Name() != "string" && !strings.HasPrefix(varname,"string(") {
|
|
return "w.Write([]byte(string(" + varname + ")))\n"
|
|
} else {
|
|
return "w.Write([]byte(" + varname + "))\n"
|
|
}
|
|
case reflect.Int64:
|
|
return "w.Write([]byte(strconv.FormatInt(" + varname + ", 10)))"
|
|
default:
|
|
fmt.Println("Unknown Variable Name: ")
|
|
fmt.Println(varname)
|
|
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)
|
|
}
|
|
|
|
content := string(res)
|
|
if !debug {
|
|
content = minify(content)
|
|
}
|
|
|
|
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}
|
|
c.FragmentCursor[fname] = 0
|
|
|
|
treeLength := len(subtree.Root.Nodes)
|
|
for index, node := range subtree.Root.Nodes {
|
|
if debug {
|
|
fmt.Println("Node: " + node.String())
|
|
}
|
|
|
|
c.previousNode = c.currentNode
|
|
c.currentNode = node.Type()
|
|
if treeLength != (index + 1) {
|
|
c.nextNode = subtree.Root.Nodes[index + 1].Type()
|
|
}
|
|
out += c.compile_switch(varholder, holdreflect, fname, node)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (c *CTemplateSet) compile_command(*parse.CommandNode) (out string) {
|
|
panic("Uh oh! Something went wrong!")
|
|
return ""
|
|
}
|
|
|
|
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
|
|
}
|