feat: improved performance and made execution of code like one script like in PHP.
This commit is contained in:
parent
de5de7a79a
commit
9f07bbb550
2 changed files with 107 additions and 31 deletions
114
main.go
114
main.go
|
@ -19,14 +19,35 @@ type Preprocessor struct {
|
||||||
|
|
||||||
// Evaluate the expression and return the value
|
// Evaluate the expression and return the value
|
||||||
// it would print.
|
// it would print.
|
||||||
func (pp *Preprocessor) Eval(data string) (string, error) {
|
func (pp *Preprocessor) Eval(codes []string) ([]string, error) {
|
||||||
const retHead = `
|
const retHead = `
|
||||||
|
__ret_one__ := ""
|
||||||
printf := func(format, ...vals) {
|
printf := func(format, ...vals) {
|
||||||
__ret__ += __Sprintf(format, vals...)
|
__ret_one__ += sprintf(format, vals...)
|
||||||
|
}
|
||||||
|
|
||||||
|
print := func(...vals) {
|
||||||
|
__ret_one__ += sprint(vals...)
|
||||||
|
}
|
||||||
|
|
||||||
|
println := func(...vals) {
|
||||||
|
__ret_one__ += sprintln(vals...)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
script := tengo.NewScript([]byte(retHead + pp.head + "\n" + data))
|
|
||||||
err := script.Add("__Sprintf", &tengo.UserFunction{
|
const retSeparator = `
|
||||||
|
__Separate(__ret_one__)
|
||||||
|
__ret_one__ = ""
|
||||||
|
`
|
||||||
|
rets := []string{}
|
||||||
|
|
||||||
|
fullCode := retHead + "\n" + pp.head
|
||||||
|
for _, code := range codes {
|
||||||
|
fullCode += "\n" + code + retSeparator + "\n"
|
||||||
|
}
|
||||||
|
script := tengo.NewScript([]byte(fullCode))
|
||||||
|
script.SetImports(pp.modules)
|
||||||
|
err := script.Add("sprintf", &tengo.UserFunction{
|
||||||
Value: func(args ...tengo.Object) (tengo.Object, error){
|
Value: func(args ...tengo.Object) (tengo.Object, error){
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return nil, tengo.ErrWrongNumArguments
|
return nil, tengo.ErrWrongNumArguments
|
||||||
|
@ -48,28 +69,71 @@ func (pp *Preprocessor) Eval(data string) (string, error) {
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = script.Add("__ret__", "")
|
err = script.Add("sprint", &tengo.UserFunction{
|
||||||
if err != nil{
|
Value: func(args ...tengo.Object) (tengo.Object, error){
|
||||||
return "", err
|
gargs := make([]any, len(args))
|
||||||
|
for i := range gargs {
|
||||||
|
gargs[i] = tengo.ToInterface(args[i])
|
||||||
}
|
}
|
||||||
compiled, err := script.RunContext(context.Background())
|
str := fmt.Sprint(gargs...)
|
||||||
|
return tengo.FromInterface(str)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
|
}
|
||||||
|
err = script.Add("sprintln", &tengo.UserFunction{
|
||||||
|
Value: func(args ...tengo.Object) (tengo.Object, error){
|
||||||
|
gargs := make([]any, len(args))
|
||||||
|
for i := range gargs {
|
||||||
|
gargs[i] = tengo.ToInterface(args[i])
|
||||||
|
}
|
||||||
|
str := fmt.Sprintln(gargs...)
|
||||||
|
return tengo.FromInterface(str)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = script.Add("__Separate", &tengo.UserFunction{
|
||||||
|
Value: func(args ...tengo.Object) (tengo.Object, error){
|
||||||
|
if len(args) < 1 {
|
||||||
|
return nil, tengo.ErrWrongNumArguments
|
||||||
|
}
|
||||||
|
str, ok := tengo.ToString(args[0])
|
||||||
|
if !ok {
|
||||||
|
return nil, tengo.ErrInvalidArgumentType{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rets = append(rets, str)
|
||||||
|
return nil, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return compiled.Get("__ret__").String(), nil
|
_, err = script.RunContext(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return rets, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the new preprocessor with default options.
|
// Get the new preprocessor with default options.
|
||||||
func NewPp() *Preprocessor {
|
func NewPp() *Preprocessor {
|
||||||
pp := &Preprocessor{
|
pp := &Preprocessor{
|
||||||
tags: [2]string{
|
tags: [2]string{
|
||||||
"<?tengo",
|
"<?",
|
||||||
"?>",
|
"?>",
|
||||||
},
|
},
|
||||||
modules: stdlib.GetModuleMap(stdlib.AllModuleNames()...)
|
modules: stdlib.GetModuleMap(stdlib.AllModuleNames()...),
|
||||||
}
|
}
|
||||||
return pp
|
return pp
|
||||||
}
|
}
|
||||||
|
@ -77,6 +141,8 @@ func NewPp() *Preprocessor {
|
||||||
func (pp *Preprocessor) Process(data string) (string, error) {
|
func (pp *Preprocessor) Process(data string) (string, error) {
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
last := 0
|
last := 0
|
||||||
|
texts := []string{}
|
||||||
|
codes := []string{}
|
||||||
for {
|
for {
|
||||||
idxStart := strings.Index(data[last:], pp.tags[0])
|
idxStart := strings.Index(data[last:], pp.tags[0])
|
||||||
idxEnd := strings.Index(data[last:], pp.tags[1])
|
idxEnd := strings.Index(data[last:], pp.tags[1])
|
||||||
|
@ -87,22 +153,34 @@ func (pp *Preprocessor) Process(data string) (string, error) {
|
||||||
What: "end tag",
|
What: "end tag",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Fprint(&b, data[last:])
|
texts = append(texts, data[last:])
|
||||||
break
|
break
|
||||||
} else if idxEnd < 0 {
|
} else if idxEnd < 0 {
|
||||||
return "", UnexpectedError{
|
return "", UnexpectedError{
|
||||||
What: "start tag",
|
What: "start tag",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Fprint(&b, data[last:idxStart])
|
text := data[last:idxStart]
|
||||||
|
texts = append(texts, text)
|
||||||
|
|
||||||
code := data[idxStart+len(pp.tags[0]):idxEnd]
|
code := data[idxStart+len(pp.tags[0]):idxEnd]
|
||||||
str, err := pp.Eval(code)
|
codes = append(codes, code)
|
||||||
|
|
||||||
|
data = data[idxEnd + len(pp.tags[1]):]
|
||||||
|
/*if len(data) > 0 && data[0] == '\n' {
|
||||||
|
data = data[1:]
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
codeRets, err := pp.Eval(codes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
fmt.Fprint(&b, str)
|
|
||||||
data = data[idxEnd + len(pp.tags[1])+1:]
|
for i, codeRet := range codeRets {
|
||||||
|
fmt.Fprint(&b, texts[i])
|
||||||
|
fmt.Fprintf(&b, codeRet)
|
||||||
}
|
}
|
||||||
|
fmt.Fprint(&b, texts[len(codeRets)])
|
||||||
|
|
||||||
return b.String(), nil
|
return b.String(), nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
# The index testing
|
<?
|
||||||
1 + 1 = <?tengo
|
newVar := "'this is gen shita'"
|
||||||
printf("%d", 1+1)
|
?># The index testing
|
||||||
printf("\ncock")
|
1 + 1 = <? print(1+1) ?>
|
||||||
?>
|
cock <? print(newVar, "and cock")?>
|
||||||
|
|
||||||
## The shit after
|
## The shit after
|
||||||
|
|
||||||
checking <?tengo
|
checking <? printf(newVar)?>
|
||||||
printf("second shit")
|
|
||||||
?>
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue