77 lines
1.9 KiB
Go
77 lines
1.9 KiB
Go
package compiler
|
|
|
|
import (
|
|
"bytes"
|
|
"strings"
|
|
|
|
"go.starlark.net/lib/math"
|
|
"go.starlark.net/starlark"
|
|
)
|
|
|
|
// executeScript runs a Starlark script and returns the output lines
|
|
func executeScript(scriptLines []string, ctx *CompilerContext) ([]string, error) {
|
|
// Join script lines
|
|
scriptText := strings.Join(scriptLines, "\n")
|
|
|
|
// Expand |varname| -> actual variable names
|
|
scriptText = expandVariables(scriptText, ctx)
|
|
|
|
// Wrap in function (Starlark requires control flow inside functions)
|
|
wrappedScript := "def _main():\n"
|
|
for _, line := range strings.Split(scriptText, "\n") {
|
|
wrappedScript += " " + line + "\n"
|
|
}
|
|
wrappedScript += "_main()\n"
|
|
|
|
// Capture print output
|
|
var output bytes.Buffer
|
|
thread := &starlark.Thread{
|
|
Print: func(_ *starlark.Thread, msg string) {
|
|
output.WriteString(msg)
|
|
output.WriteString("\n")
|
|
},
|
|
}
|
|
|
|
// Set execution limit (prevent infinite loops)
|
|
thread.SetMaxExecutionSteps(1000000) // 1M steps
|
|
|
|
// Predeclared functions (math module)
|
|
predeclared := starlark.StringDict{
|
|
"math": math.Module,
|
|
}
|
|
|
|
// Execute
|
|
_, err := starlark.ExecFile(thread, "script.star", wrappedScript, predeclared)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Split output into lines for assembly
|
|
outputStr := output.String()
|
|
if outputStr == "" {
|
|
return []string{}, nil
|
|
}
|
|
lines := strings.Split(strings.TrimRight(outputStr, "\n"), "\n")
|
|
return lines, nil
|
|
}
|
|
|
|
// expandVariables replaces |varname| with expanded variable names from symbol table
|
|
func expandVariables(text string, ctx *CompilerContext) string {
|
|
result := text
|
|
for {
|
|
start := strings.IndexByte(result, '|')
|
|
if start == -1 {
|
|
break
|
|
}
|
|
end := strings.IndexByte(result[start+1:], '|')
|
|
if end == -1 {
|
|
break // unclosed, let script fail
|
|
}
|
|
end += start + 1
|
|
|
|
varName := result[start+1 : end]
|
|
expandedName := ctx.SymbolTable.ExpandName(varName, ctx.CurrentScope())
|
|
result = result[:start] + expandedName + result[end+1:]
|
|
}
|
|
return result
|
|
}
|