github.com/tardisgo/tardisgo@v0.0.0-20161119180838-e0dd9a7e46b5/pogo/begin.go (about) 1 // Copyright 2014 Elliott Stoneham and The TARDIS Go Authors 2 // Use of this source code is governed by an MIT-style 3 // license that can be found in the LICENSE file. 4 5 package pogo 6 7 import ( 8 "fmt" 9 "go/token" 10 "sort" 11 "strconv" 12 "strings" 13 14 "go/constant" 15 "golang.org/x/tools/go/ssa" 16 ) 17 18 // Recycle the Compilation resources. 19 func (comp *Compilation) Recycle() { LanguageList[comp.TargetLang] = LanguageEntry{} } 20 21 // Compile provides the entry point for the pogo package, 22 // returning a pogo.Compilation structure and error 23 func Compile(mainPkg *ssa.Package, debug, trace bool, langName, testFSname string) (*Compilation, error) { 24 comp := &Compilation{ 25 mainPackage: mainPkg, 26 rootProgram: mainPkg.Prog, 27 DebugFlag: debug, 28 TraceFlag: trace, 29 } 30 31 k, e := FindTargetLang(langName) 32 if e != nil { 33 return nil, e 34 } 35 // make a new language list entry for this compilation 36 newLang := LanguageList[k] 37 languageListAppendMutex.Lock() 38 LanguageList = append(LanguageList, newLang) 39 comp.TargetLang = len(LanguageList) - 1 40 languageListAppendMutex.Unlock() 41 LanguageList[comp.TargetLang].Language = 42 LanguageList[comp.TargetLang].Language.InitLang( 43 comp, &LanguageList[comp.TargetLang]) 44 LanguageList[comp.TargetLang].TestFS = testFSname 45 //fmt.Printf("DEBUG created TargetLang[%d]=%#v\n", 46 // comp.TargetLang, LanguageList[comp.TargetLang]) 47 48 comp.initErrors() 49 comp.initTypes() 50 comp.setupPosHash() 51 comp.loadSpecialConsts() 52 comp.emitFileStart() 53 comp.emitFunctions() 54 comp.emitGoClass(comp.mainPackage) 55 comp.emitTypeInfo() 56 comp.emitFileEnd() 57 if comp.hadErrors && comp.stopOnError { 58 err := fmt.Errorf("no output files generated") 59 comp.LogError("", "pogo", err) 60 return nil, err 61 } 62 comp.writeFiles() 63 return comp, nil 64 } 65 66 // The main Go class contains those elements that don't fit in functions 67 func (comp *Compilation) emitGoClass(mainPkg *ssa.Package) { 68 comp.emitGoClassStart() 69 comp.emitNamedConstants() 70 comp.emitGlobals() 71 comp.emitGoClassEnd(mainPkg) 72 comp.WriteAsClass("Go", "") 73 } 74 75 // special constant name used in TARDIS Go to put text in the header of files 76 const pogoHeader = "tardisgoHeader" 77 const pogoLibList = "tardisgoLibList" 78 79 func (comp *Compilation) loadSpecialConsts() { 80 hxPkg := "" 81 l := comp.TargetLang 82 ph := LanguageList[l].HeaderConstVarName 83 targetPackage := LanguageList[l].PackageConstVarName 84 header := "" 85 allPack := comp.rootProgram.AllPackages() 86 sort.Sort(PackageSorter(allPack)) 87 for _, pkg := range allPack { 88 allMem := MemberNamesSorted(pkg) 89 for _, mName := range allMem { 90 mem := pkg.Members[mName] 91 if mem.Token() == token.CONST { 92 switch mName { 93 case ph, pogoHeader: // either the language-specific constant, or the standard one 94 lit := mem.(*ssa.NamedConst).Value 95 switch lit.Value.Kind() { 96 case constant.String: 97 h, err := strconv.Unquote(lit.Value.String()) 98 if err != nil { 99 comp.LogError(comp.CodePosition(lit.Pos())+"Special pogo header constant "+ph+" or "+pogoHeader, 100 "pogo", err) 101 } else { 102 header += h + "\n" 103 } 104 } 105 case targetPackage: 106 lit := mem.(*ssa.NamedConst).Value 107 switch lit.Value.Kind() { 108 case constant.String: 109 hp, err := strconv.Unquote(lit.Value.String()) 110 if err != nil { 111 comp.LogError(comp.CodePosition(lit.Pos())+"Special targetPackage constant ", "pogo", err) 112 } 113 hxPkg = hp 114 default: 115 comp.LogError(comp.CodePosition(lit.Pos()), "pogo", 116 fmt.Errorf("special targetPackage constant not a string")) 117 } 118 case pogoLibList: 119 lit := mem.(*ssa.NamedConst).Value 120 switch lit.Value.Kind() { 121 case constant.String: 122 lrp, err := strconv.Unquote(lit.Value.String()) 123 if err != nil { 124 comp.LogError(comp.CodePosition(lit.Pos())+"Special "+pogoLibList+" constant ", "pogo", err) 125 } 126 comp.LibListNoDCE = strings.Split(lrp, ",") 127 for lib := range comp.LibListNoDCE { 128 comp.LibListNoDCE[lib] = strings.TrimSpace(comp.LibListNoDCE[lib]) 129 } 130 default: 131 comp.LogError(comp.CodePosition(lit.Pos()), "pogo", 132 fmt.Errorf("special targetPackage constant not a string")) 133 } 134 } 135 } 136 } 137 } 138 comp.hxPkgName = hxPkg 139 comp.headerText = header 140 } 141 142 // emit the standard file header for target language 143 func (comp *Compilation) emitFileStart() { 144 l := comp.TargetLang 145 fmt.Fprintln(&LanguageList[l].buffer, 146 LanguageList[l].FileStart(comp.hxPkgName, comp.headerText)) 147 } 148 149 // emit the tail of the required language file 150 func (comp *Compilation) emitFileEnd() { 151 l := comp.TargetLang 152 fmt.Fprintln(&LanguageList[l].buffer, LanguageList[l].FileEnd()) 153 for w := range comp.warnings { 154 comp.emitComment(comp.warnings[w]) 155 } 156 comp.emitComment("Package List:") 157 allPack := comp.rootProgram.AllPackages() 158 sort.Sort(PackageSorter(allPack)) 159 for pkgIdx := range allPack { 160 comp.emitComment(" " + allPack[pkgIdx].String()) 161 } 162 } 163 164 // emit the start of the top level type definition for each language 165 func (comp *Compilation) emitGoClassStart() { 166 l := comp.TargetLang 167 fmt.Fprintln(&LanguageList[l].buffer, LanguageList[l].GoClassStart()) 168 } 169 170 // emit the end of the top level type definition for each language file 171 func (comp *Compilation) emitGoClassEnd(pak *ssa.Package) { 172 l := comp.TargetLang 173 fmt.Fprintln(&LanguageList[l].buffer, LanguageList[l].GoClassEnd(pak)) 174 } 175 176 /* 177 func (comp *Compilation) UsingPackage(pkgName string) bool { 178 //println("DEBUG UsingPackage() looking for: ", pkgName) 179 pkgName = "package " + pkgName 180 pkgs := comp.rootProgram.AllPackages() 181 for p := range pkgs { 182 //println("DEBUG UsingPackage() considering pkg: ", pkgs[p].String()) 183 if pkgs[p].String() == pkgName { 184 //println("DEBUG UsingPackage() ", pkgName, " = true") 185 return true 186 } 187 } 188 //println("DEBUG UsingPackage() ", pkgName, " =false") 189 return false 190 } 191 */