github.com/goplus/llgo@v0.8.3/internal/llgen/llgen.go (about) 1 /* 2 * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package llgen 18 19 import ( 20 "go/ast" 21 "go/parser" 22 "go/token" 23 "go/types" 24 "os" 25 26 "github.com/goplus/gogen/packages" 27 "github.com/goplus/llgo/cl" 28 "github.com/goplus/llgo/internal/mod" 29 "golang.org/x/tools/go/ssa" 30 "golang.org/x/tools/go/ssa/ssautil" 31 32 llssa "github.com/goplus/llgo/ssa" 33 cpackages "golang.org/x/tools/go/packages" 34 ) 35 36 func Init() { 37 llssa.Initialize(llssa.InitAll) 38 llssa.SetDebug(llssa.DbgFlagAll) 39 cl.SetDebug(cl.DbgFlagAll) 40 } 41 42 func PkgPath(dir string) string { 43 _, pkgPath, err := mod.Load(dir) 44 check(err) 45 return pkgPath 46 } 47 48 func Do(pkgPath, inFile, outFile string) { 49 ret := Gen(pkgPath, inFile, nil) 50 err := os.WriteFile(outFile, []byte(ret), 0644) 51 check(err) 52 } 53 54 func Gen(pkgPath, inFile string, src any) string { 55 fset := token.NewFileSet() 56 f, err := parser.ParseFile(fset, inFile, src, parser.ParseComments) 57 check(err) 58 59 files := []*ast.File{f} 60 name := f.Name.Name 61 if pkgPath == "" { 62 pkgPath = name 63 } 64 pkg := types.NewPackage(pkgPath, name) 65 imp := packages.NewImporter(fset) 66 ssaPkg, _, err := ssautil.BuildPackage( 67 &types.Config{Importer: imp}, fset, pkg, files, ssa.SanityCheckFunctions) 68 check(err) 69 70 if Verbose { 71 ssaPkg.WriteTo(os.Stderr) 72 } 73 74 prog := llssa.NewProgram(nil) 75 initRtAndPy(prog, &cpackages.Config{ 76 Mode: loadSyntax | cpackages.NeedDeps, 77 }) 78 79 ret, err := cl.NewPackage(prog, ssaPkg, files) 80 check(err) 81 82 if prog.NeedPyInit { // call PyInit if needed 83 ret.PyInit() 84 } 85 86 return ret.String() 87 } 88 89 func check(err error) { 90 if err != nil { 91 panic(err) 92 } 93 } 94 95 var ( 96 Verbose = true 97 )