Rework how we handle state and calling and returning
This commit is contained in:
122
main.go
122
main.go
@@ -40,6 +40,7 @@ func main() {
|
||||
fmt.Fprintf(os.Stderr, " or direct assignment: %s \"<value>(\\d+)</value>\" \"=0\" data.xml\n", os.Args[0])
|
||||
fmt.Fprintf(os.Stderr, "\nNote: v1, v2, etc. are used to refer to capture groups.\n")
|
||||
fmt.Fprintf(os.Stderr, " If expression starts with an operator like *, /, +, -, =, etc., v1 is automatically prepended\n")
|
||||
fmt.Fprintf(os.Stderr, " You can use any valid Lua code, including if statements, loops, etc.\n")
|
||||
}
|
||||
|
||||
flag.Parse()
|
||||
@@ -54,8 +55,8 @@ func main() {
|
||||
luaExpr := args[1]
|
||||
files := args[2:]
|
||||
|
||||
// Generate the Lua script
|
||||
luaScript := buildLuaScript(luaExpr)
|
||||
// Prepare the Lua expression
|
||||
luaExpr = buildLuaScript(luaExpr)
|
||||
|
||||
if strings.Contains(regexPattern, "!num") {
|
||||
regexPattern = strings.ReplaceAll(regexPattern, "!num", "(\\d*\\.?\\d+)")
|
||||
@@ -75,7 +76,7 @@ func main() {
|
||||
|
||||
// Process each file
|
||||
for _, file := range files {
|
||||
err := processFile(file, pattern, luaScript)
|
||||
err := processFile(file, pattern, luaExpr)
|
||||
if err != nil {
|
||||
Error.Printf("Error processing file %s: %v", file, err)
|
||||
}
|
||||
@@ -84,65 +85,32 @@ func main() {
|
||||
|
||||
// buildLuaScript creates a complete Lua script from the expression
|
||||
func buildLuaScript(luaExpr string) string {
|
||||
log.Printf("Building Lua script from expression: %s", luaExpr)
|
||||
|
||||
// Check if the expression needs v1 to be prepended
|
||||
if strings.HasPrefix(luaExpr, "*") || strings.HasPrefix(luaExpr, "/") ||
|
||||
strings.HasPrefix(luaExpr, "+") || strings.HasPrefix(luaExpr, "-") ||
|
||||
strings.HasPrefix(luaExpr, "^") || strings.HasPrefix(luaExpr, "%") {
|
||||
luaExpr = "v1" + luaExpr
|
||||
log.Printf("Prepended 'v1' to expression, new expression: %s", luaExpr)
|
||||
// Check if the expression starts with an operator that needs special handling
|
||||
if strings.HasPrefix(luaExpr, "*") {
|
||||
luaExpr = "v1 = v1" + luaExpr
|
||||
} else if strings.HasPrefix(luaExpr, "/") {
|
||||
luaExpr = "v1 = v1" + luaExpr
|
||||
} else if strings.HasPrefix(luaExpr, "+") {
|
||||
luaExpr = "v1 = v1" + luaExpr
|
||||
} else if strings.HasPrefix(luaExpr, "-") {
|
||||
luaExpr = "v1 = v1" + luaExpr
|
||||
} else if strings.HasPrefix(luaExpr, "^") {
|
||||
luaExpr = "v1 = v1" + luaExpr
|
||||
} else if strings.HasPrefix(luaExpr, "%") {
|
||||
luaExpr = "v1 = v1" + luaExpr
|
||||
} else if strings.HasPrefix(luaExpr, "=") {
|
||||
// Handle direct assignment with = operator
|
||||
luaExpr = "v1 " + luaExpr
|
||||
log.Printf("Handled direct assignment, new expression: %s", luaExpr)
|
||||
}
|
||||
|
||||
// Replace shorthand v1, v2, etc. with their direct variable names (no need for array notation)
|
||||
// Note: we're keeping this regex in case the user writes v[1] style, but we'll convert it to v1
|
||||
// Replace shorthand v1, v2, etc. with their direct variable names
|
||||
shorthandRegex := regexp.MustCompile(`\bv\[(\d+)\]\b`)
|
||||
luaExpr = shorthandRegex.ReplaceAllString(luaExpr, "v$1")
|
||||
log.Printf("Converted shorthand variables, new expression: %s", luaExpr)
|
||||
|
||||
// Add custom script header with helper functions
|
||||
scriptHeader := `
|
||||
-- Custom Lua helpers for math operations
|
||||
function min(a, b) return math.min(a, b) end
|
||||
function max(a, b) return math.max(a, b) end
|
||||
function round(x) return math.floor(x + 0.5) end
|
||||
function floor(x) return math.floor(x) end
|
||||
function ceil(x) return math.ceil(x) end
|
||||
`
|
||||
|
||||
// Generate the full script
|
||||
var fullScript string
|
||||
if strings.Contains(luaExpr, "v1 =") || strings.Contains(luaExpr, "v2 =") ||
|
||||
strings.Contains(luaExpr, "v3 =") || strings.Contains(luaExpr, "return") {
|
||||
// Already has assignments, use as is
|
||||
fullScript = fmt.Sprintf(`%s
|
||||
function process(...)
|
||||
%s
|
||||
return v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
|
||||
end
|
||||
`, scriptHeader, luaExpr)
|
||||
log.Println("Generated Lua script with assignments.")
|
||||
} else {
|
||||
// Simple expression, assign to v1
|
||||
fullScript = fmt.Sprintf(`%s
|
||||
function process(...)
|
||||
local result = %s
|
||||
v1 = result
|
||||
return v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12
|
||||
end
|
||||
`, scriptHeader, luaExpr)
|
||||
log.Println("Generated Lua script for simple expression.")
|
||||
}
|
||||
|
||||
log.Printf("Final Lua script: %s", fullScript)
|
||||
return fullScript
|
||||
return luaExpr
|
||||
}
|
||||
|
||||
func processFile(filename string, pattern *regexp.Regexp, luaScript string) error {
|
||||
func processFile(filename string, pattern *regexp.Regexp, luaExpr string) error {
|
||||
fullPath := filepath.Join(".", filename)
|
||||
log.Printf("Processing file: %s", fullPath)
|
||||
|
||||
@@ -154,7 +122,7 @@ func processFile(filename string, pattern *regexp.Regexp, luaScript string) erro
|
||||
log.Printf("Successfully read file: %s, content length: %d bytes", fullPath, len(content))
|
||||
|
||||
fileContent := string(content)
|
||||
result, err := process(fileContent, pattern, luaScript)
|
||||
result, err := process(fileContent, pattern, luaExpr)
|
||||
if err != nil {
|
||||
Error.Printf("Error processing content of file %s: %v", fullPath, err)
|
||||
return err
|
||||
@@ -171,7 +139,7 @@ func processFile(filename string, pattern *regexp.Regexp, luaScript string) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func process(data string, pattern *regexp.Regexp, luaScript string) (string, error) {
|
||||
func process(data string, pattern *regexp.Regexp, luaExpr string) (string, error) {
|
||||
L := lua.NewState()
|
||||
defer L.Close()
|
||||
|
||||
@@ -182,22 +150,26 @@ func process(data string, pattern *regexp.Regexp, luaScript string) (string, err
|
||||
Error.Printf("Error loading Lua math library: %v", err)
|
||||
return data, fmt.Errorf("error loading Lua math library: %v", err)
|
||||
}
|
||||
log.Println("Lua math library loaded successfully.")
|
||||
|
||||
// Load the Lua script
|
||||
log.Printf("Executing Lua script: %s", luaScript)
|
||||
if err := L.DoString(luaScript); err != nil {
|
||||
Error.Printf("Error in Lua script: %v", err)
|
||||
return data, fmt.Errorf("error in Lua script: %v", err)
|
||||
// Initialize helper functions
|
||||
helperScript := `
|
||||
-- Custom Lua helpers for math operations
|
||||
function min(a, b) return math.min(a, b) end
|
||||
function max(a, b) return math.max(a, b) end
|
||||
function round(x) return math.floor(x + 0.5) end
|
||||
function floor(x) return math.floor(x) end
|
||||
function ceil(x) return math.ceil(x) end
|
||||
`
|
||||
if err := L.DoString(helperScript); err != nil {
|
||||
Error.Printf("Error loading helper functions: %v", err)
|
||||
return data, fmt.Errorf("error loading helper functions: %v", err)
|
||||
}
|
||||
log.Printf("Lua script executed successfully. Script: %s", luaScript)
|
||||
|
||||
// Process all regex matches
|
||||
result := pattern.ReplaceAllStringFunc(data, func(match string) string {
|
||||
captures := pattern.FindStringSubmatch(match)
|
||||
if len(captures) <= 1 {
|
||||
// No capture groups, return unchanged
|
||||
log.Printf("No capture groups found for match: %s", match)
|
||||
return match
|
||||
}
|
||||
|
||||
@@ -207,41 +179,29 @@ func process(data string, pattern *regexp.Regexp, luaScript string) (string, err
|
||||
floatVal, err := strconv.ParseFloat(capture, 64)
|
||||
if err == nil {
|
||||
L.SetGlobal(fmt.Sprintf("v%d", i+1), lua.LNumber(floatVal))
|
||||
log.Printf("Set v%d to %f (capture: %s)", i+1, floatVal, capture)
|
||||
} else {
|
||||
L.SetGlobal(fmt.Sprintf("v%d", i+1), lua.LString(capture))
|
||||
log.Printf("Set v%d to %s (capture: %s)", i+1, capture, capture)
|
||||
}
|
||||
}
|
||||
|
||||
// Call the Lua function
|
||||
L.Push(L.GetGlobal("process"))
|
||||
if err := L.PCall(0, 12, nil); err != nil { // We're returning up to 12 values
|
||||
// Execute the user's Lua code
|
||||
if err := L.DoString(luaExpr); err != nil {
|
||||
Error.Printf("Error executing Lua script: %v", err)
|
||||
return match // Return unchanged on error
|
||||
}
|
||||
log.Println("Lua function 'process' called successfully.")
|
||||
|
||||
// Get the return values (up to 12)
|
||||
// Get the values of v1-v12 after code execution
|
||||
returnValues := make([]lua.LValue, 12)
|
||||
for i := 0; i < 12; i++ {
|
||||
// Get the value from the stack (if exists)
|
||||
if L.GetTop() >= i+1 {
|
||||
returnValues[i] = L.Get(-12 + i)
|
||||
log.Printf("Return value v%d: %v", i+1, returnValues[i])
|
||||
} else {
|
||||
returnValues[i] = lua.LNil
|
||||
}
|
||||
varName := fmt.Sprintf("v%d", i+1)
|
||||
returnValues[i] = L.GetGlobal(varName)
|
||||
}
|
||||
// Pop all return values
|
||||
L.Pop(L.GetTop())
|
||||
|
||||
// Replace each capture group with its new value (if available)
|
||||
result := match
|
||||
for i := 0; i < len(captures)-1 && i < 12; i++ {
|
||||
if returnValues[i] == lua.LNil {
|
||||
log.Printf("Return value v%d is nil, skipping replacement.", i+1)
|
||||
continue // Skip if nil return
|
||||
continue // Skip if nil
|
||||
}
|
||||
|
||||
oldVal := captures[i+1]
|
||||
@@ -258,7 +218,6 @@ func process(data string, pattern *regexp.Regexp, luaScript string) (string, err
|
||||
|
||||
// If we have a value, replace it
|
||||
if newVal != "" {
|
||||
log.Printf("Replacing '%s' with '%s'", oldVal, newVal)
|
||||
result = strings.Replace(result, oldVal, newVal, 1)
|
||||
}
|
||||
}
|
||||
@@ -266,6 +225,5 @@ func process(data string, pattern *regexp.Regexp, luaScript string) (string, err
|
||||
return result
|
||||
})
|
||||
|
||||
log.Println("Processing completed successfully.")
|
||||
return result, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user