Preserve Gotlin semantics across packages

This commit is contained in:
pavel 2026-08-27 22:18:45 +02:00
commit acb42a5702
10 changed files with 525 additions and 34 deletions

View file

@ -11,17 +11,25 @@ import (
)
func GenerateGo(program *Program) ([]byte, error) {
return generateGo(program, "")
return generateGo(program, "", nil)
}
func GenerateGoMain(program *Program) ([]byte, error) {
return generateGo(program, "main")
return generateGo(program, "main", nil)
}
func generateGo(program *Program, packageOverride string) ([]byte, error) {
semantic, err := Analyze(program)
if err != nil {
return nil, err
func GenerateGoWithMetadata(program *Program, metadata []*PackageMetadata) ([]byte, error) {
return generateGo(program, "", metadata)
}
func GenerateGoMainWithMetadata(program *Program, metadata []*PackageMetadata) ([]byte, error) {
return generateGo(program, "main", metadata)
}
func generateGo(program *Program, packageOverride string, metadata []*PackageMetadata) ([]byte, error) {
semantic, diagnostics := AnalyzeWithMetadata(program, metadata)
if len(diagnostics) > 0 {
return nil, diagnostics[0]
}
g := goGenerator{semantic: semantic}
if err := g.program(program, packageOverride); err != nil {
@ -1260,10 +1268,15 @@ func (g *goGenerator) expr(expr Expr, expectedType string) (string, error) {
if ident, ok := e.Receiver.(IdentExpr); ok && g.semantic.Imports[ident.Name] {
name = exportedGoName(name)
} else if class, ok := g.classForType(g.exprType(e.Receiver)); ok {
for _, field := range class.Fields {
if field.Name == name && class.Data && !field.Private {
name = exportedGoName(name)
break
resolvedType, _ := g.semantic.ResolveType(g.exprType(e.Receiver))
if isImportedClassType(resolvedType) {
name = exportedGoName(name)
} else {
for _, field := range class.Fields {
if field.Name == name && class.Data && !field.Private {
name = exportedGoName(name)
break
}
}
}
} else if ident, ok := e.Receiver.(IdentExpr); ok && (ident.Name == "this" || ident.Name == "self") && g.currentClass != nil {
@ -2445,10 +2458,15 @@ func (g *goGenerator) isExternalGoCall(callee Expr) bool {
}
func (g *goGenerator) classForType(typ string) (ClassDecl, bool) {
typ = strings.TrimPrefix(typ, "*")
typ = strings.TrimSuffix(typ, "?")
class, ok := g.semantic.Classes[typ]
return class, ok
resolved, err := g.semantic.ResolveType(typ)
if err != nil {
return ClassDecl{}, false
}
class, _ := classInstance(resolved)
if class == nil || class.Decl == nil {
return ClassDecl{}, false
}
return *class.Decl, true
}
func (g *goGenerator) isDefined(name string) bool {