node.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. // Copyright 2021 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package mk2rbc
  15. import (
  16. "fmt"
  17. "strings"
  18. mkparser "android/soong/androidmk/parser"
  19. )
  20. // A parsed node for which starlark code will be generated
  21. // by calling emit().
  22. type starlarkNode interface {
  23. emit(ctx *generationContext)
  24. }
  25. // Types used to keep processed makefile data:
  26. type commentNode struct {
  27. text string
  28. }
  29. func (c *commentNode) emit(gctx *generationContext) {
  30. chunks := strings.Split(c.text, "\\\n")
  31. gctx.newLine()
  32. gctx.write(chunks[0]) // It has '#' at the beginning already.
  33. for _, chunk := range chunks[1:] {
  34. gctx.newLine()
  35. gctx.write("#", chunk)
  36. }
  37. }
  38. type moduleInfo struct {
  39. path string // Converted Starlark file path
  40. originalPath string // Makefile file path
  41. moduleLocalName string
  42. optional bool
  43. missing bool // a module may not exist if a module that depends on it is loaded dynamically
  44. }
  45. func (im moduleInfo) entryName() string {
  46. return im.moduleLocalName + "_init"
  47. }
  48. func (mi moduleInfo) name() string {
  49. return fmt.Sprintf("%q", MakePath2ModuleName(mi.originalPath))
  50. }
  51. type inheritedModule interface {
  52. name() string
  53. entryName() string
  54. emitSelect(gctx *generationContext)
  55. pathExpr() starlarkExpr
  56. needsLoadCheck() bool
  57. }
  58. type inheritedStaticModule struct {
  59. *moduleInfo
  60. loadAlways bool
  61. }
  62. func (im inheritedStaticModule) emitSelect(_ *generationContext) {
  63. }
  64. func (im inheritedStaticModule) pathExpr() starlarkExpr {
  65. return &stringLiteralExpr{im.path}
  66. }
  67. func (im inheritedStaticModule) needsLoadCheck() bool {
  68. return im.missing
  69. }
  70. type inheritedDynamicModule struct {
  71. path starlarkExpr
  72. candidateModules []*moduleInfo
  73. loadAlways bool
  74. location ErrorLocation
  75. needsWarning bool
  76. }
  77. func (i inheritedDynamicModule) name() string {
  78. return "_varmod"
  79. }
  80. func (i inheritedDynamicModule) entryName() string {
  81. return i.name() + "_init"
  82. }
  83. func (i inheritedDynamicModule) emitSelect(gctx *generationContext) {
  84. if i.needsWarning {
  85. gctx.newLine()
  86. gctx.writef("%s.mkwarning(%q, %q)", baseName, i.location, "Please avoid starting an include path with a variable. See https://source.android.com/setup/build/bazel/product_config/issues/includes for details.")
  87. }
  88. gctx.newLine()
  89. gctx.writef("_entry = {")
  90. gctx.indentLevel++
  91. for _, mi := range i.candidateModules {
  92. gctx.newLine()
  93. gctx.writef(`"%s": (%s, %s),`, mi.originalPath, mi.name(), mi.entryName())
  94. }
  95. gctx.indentLevel--
  96. gctx.newLine()
  97. gctx.write("}.get(")
  98. i.path.emit(gctx)
  99. gctx.write(")")
  100. gctx.newLine()
  101. gctx.writef("(%s, %s) = _entry if _entry else (None, None)", i.name(), i.entryName())
  102. }
  103. func (i inheritedDynamicModule) pathExpr() starlarkExpr {
  104. return i.path
  105. }
  106. func (i inheritedDynamicModule) needsLoadCheck() bool {
  107. return true
  108. }
  109. type inheritNode struct {
  110. module inheritedModule
  111. loadAlways bool
  112. }
  113. func (inn *inheritNode) emit(gctx *generationContext) {
  114. // Unconditional case:
  115. // maybe check that loaded
  116. // rblf.inherit(handle, <module>, module_init)
  117. // Conditional case:
  118. // if <module>_init != None:
  119. // same as above
  120. inn.module.emitSelect(gctx)
  121. name := inn.module.name()
  122. entry := inn.module.entryName()
  123. if inn.loadAlways {
  124. gctx.emitLoadCheck(inn.module)
  125. gctx.newLine()
  126. gctx.writef("%s(handle, %s, %s)", cfnInherit, name, entry)
  127. return
  128. }
  129. gctx.newLine()
  130. gctx.writef("if %s:", entry)
  131. gctx.indentLevel++
  132. gctx.newLine()
  133. gctx.writef("%s(handle, %s, %s)", cfnInherit, name, entry)
  134. gctx.indentLevel--
  135. }
  136. type includeNode struct {
  137. module inheritedModule
  138. loadAlways bool
  139. }
  140. func (inn *includeNode) emit(gctx *generationContext) {
  141. inn.module.emitSelect(gctx)
  142. entry := inn.module.entryName()
  143. if inn.loadAlways {
  144. gctx.emitLoadCheck(inn.module)
  145. gctx.newLine()
  146. gctx.writef("%s(g, handle)", entry)
  147. return
  148. }
  149. gctx.newLine()
  150. gctx.writef("if %s != None:", entry)
  151. gctx.indentLevel++
  152. gctx.newLine()
  153. gctx.writef("%s(g, handle)", entry)
  154. gctx.indentLevel--
  155. }
  156. type assignmentFlavor int
  157. const (
  158. // Assignment flavors
  159. asgnSet assignmentFlavor = iota // := or =
  160. asgnMaybeSet assignmentFlavor = iota // ?=
  161. asgnAppend assignmentFlavor = iota // +=
  162. )
  163. type assignmentNode struct {
  164. lhs variable
  165. value starlarkExpr
  166. mkValue *mkparser.MakeString
  167. flavor assignmentFlavor
  168. location ErrorLocation
  169. isTraced bool
  170. }
  171. func (asgn *assignmentNode) emit(gctx *generationContext) {
  172. gctx.newLine()
  173. gctx.inAssignment = true
  174. asgn.lhs.emitSet(gctx, asgn)
  175. gctx.inAssignment = false
  176. if asgn.isTraced {
  177. gctx.newLine()
  178. gctx.tracedCount++
  179. gctx.writef(`print("%s.%d: %s := ", `, gctx.starScript.mkFile, gctx.tracedCount, asgn.lhs.name())
  180. asgn.lhs.emitGet(gctx)
  181. gctx.writef(")")
  182. }
  183. }
  184. func (asgn *assignmentNode) isSelfReferential() bool {
  185. if asgn.flavor == asgnAppend {
  186. return true
  187. }
  188. isSelfReferential := false
  189. asgn.value.transform(func(expr starlarkExpr) starlarkExpr {
  190. if ref, ok := expr.(*variableRefExpr); ok && ref.ref.name() == asgn.lhs.name() {
  191. isSelfReferential = true
  192. }
  193. return nil
  194. })
  195. return isSelfReferential
  196. }
  197. type exprNode struct {
  198. expr starlarkExpr
  199. }
  200. func (exn *exprNode) emit(gctx *generationContext) {
  201. gctx.newLine()
  202. exn.expr.emit(gctx)
  203. }
  204. type ifNode struct {
  205. isElif bool // true if this is 'elif' statement
  206. expr starlarkExpr
  207. }
  208. func (in *ifNode) emit(gctx *generationContext) {
  209. ifElif := "if "
  210. if in.isElif {
  211. ifElif = "elif "
  212. }
  213. gctx.newLine()
  214. gctx.write(ifElif)
  215. in.expr.emit(gctx)
  216. gctx.write(":")
  217. }
  218. type elseNode struct{}
  219. func (br *elseNode) emit(gctx *generationContext) {
  220. gctx.newLine()
  221. gctx.write("else:")
  222. }
  223. // switchCase represents as single if/elseif/else branch. All the necessary
  224. // info about flavor (if/elseif/else) is supposed to be kept in `gate`.
  225. type switchCase struct {
  226. gate starlarkNode
  227. nodes []starlarkNode
  228. }
  229. func (cb *switchCase) emit(gctx *generationContext) {
  230. cb.gate.emit(gctx)
  231. gctx.indentLevel++
  232. gctx.pushVariableAssignments()
  233. hasStatements := false
  234. for _, node := range cb.nodes {
  235. if _, ok := node.(*commentNode); !ok {
  236. hasStatements = true
  237. }
  238. node.emit(gctx)
  239. }
  240. if !hasStatements {
  241. gctx.emitPass()
  242. }
  243. gctx.indentLevel--
  244. gctx.popVariableAssignments()
  245. }
  246. // A single complete if ... elseif ... else ... endif sequences
  247. type switchNode struct {
  248. ssCases []*switchCase
  249. }
  250. func (ssw *switchNode) emit(gctx *generationContext) {
  251. for _, ssCase := range ssw.ssCases {
  252. ssCase.emit(gctx)
  253. }
  254. }
  255. type foreachNode struct {
  256. varName string
  257. list starlarkExpr
  258. actions []starlarkNode
  259. }
  260. func (f *foreachNode) emit(gctx *generationContext) {
  261. gctx.pushVariableAssignments()
  262. gctx.newLine()
  263. gctx.writef("for %s in ", f.varName)
  264. f.list.emit(gctx)
  265. gctx.write(":")
  266. gctx.indentLevel++
  267. hasStatements := false
  268. for _, a := range f.actions {
  269. if _, ok := a.(*commentNode); !ok {
  270. hasStatements = true
  271. }
  272. a.emit(gctx)
  273. }
  274. if !hasStatements {
  275. gctx.emitPass()
  276. }
  277. gctx.indentLevel--
  278. gctx.popVariableAssignments()
  279. }