fix(gengo): hoist every BEGINDUMP-supplied import, not just fmt/strings
doGenerate's deferred-imports patch handled only "fmt" and "strings" — enough for inline RTL but a dead end for #pragma BEGINDUMP blocks that import third-party / private packages (e.g. solmade's internal/dartapi). hoistGoImports() registered every imported path in g.imports correctly, but the final placeholder replacement never emitted them, so the generated .go file's import block stayed incomplete and `go build` failed with "undefined: dartapi". Now every entry of g.imports that isn't already in the header gets appended to the DEFERRED_IMPORTS substitution. Sorted output for stable diffs. Verified: a 4-line BEGINDUMP block in /tmp/poc_dartapi.prg that imports "encoding/json" + "gitea.fivego.org/kwon_ai/solmade/internal/dartapi" now compiles into a single 23 MB binary that calls dartapi.AllAliases() at run time and returns the real count (3). Full Five regression: go test compiler/, compat 56/56, std.ch 17/17, FRB 7/7 all pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -180,14 +180,29 @@ func doGenerate(file *ast.File, debug, library bool) string {
|
||||
}
|
||||
g.emitSymCache()
|
||||
|
||||
// Patch deferred imports: inline RTL may add "fmt"/"strings" after header was emitted.
|
||||
// Patch deferred imports: emitDecl may add to g.imports after the
|
||||
// header was written. The common cases are inline RTL pulling in
|
||||
// "fmt"/"strings", but #pragma BEGINDUMP blocks can also hoist
|
||||
// third-party / private modules (e.g. solmade's internal/dartapi).
|
||||
// Dump every import not already in the header so external Go
|
||||
// packages used inside BEGINDUMP actually link.
|
||||
result := g.buf.String()
|
||||
var deferred string
|
||||
if g.imports["fmt"] && !strings.Contains(result, "\"fmt\"") {
|
||||
deferred += "\t\"fmt\"\n"
|
||||
var deferredLines []string
|
||||
for imp := range g.imports {
|
||||
if strings.Contains(result, "\""+imp+"\"") {
|
||||
continue // already emitted in the initial import block
|
||||
}
|
||||
if g.imports["strings"] && !strings.Contains(result, "\"strings\"") {
|
||||
deferred += "\t\"strings\"\n"
|
||||
if alias, ok := g.importAlias[imp]; ok && alias != "" {
|
||||
deferredLines = append(deferredLines, fmt.Sprintf("\t%s %q", alias, imp))
|
||||
} else {
|
||||
deferredLines = append(deferredLines, fmt.Sprintf("\t%q", imp))
|
||||
}
|
||||
}
|
||||
// Sorted for deterministic diffs.
|
||||
sort.Strings(deferredLines)
|
||||
deferred := strings.Join(deferredLines, "\n")
|
||||
if deferred != "" {
|
||||
deferred += "\n"
|
||||
}
|
||||
result = strings.Replace(result, "\t/*DEFERRED_IMPORTS*/\n", deferred, 1)
|
||||
// Patch guards
|
||||
|
||||
Reference in New Issue
Block a user