node.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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. }
  44. func (im moduleInfo) entryName() string {
  45. return im.moduleLocalName + "_init"
  46. }
  47. type inheritedModule interface {
  48. name() string
  49. entryName() string
  50. emitSelect(gctx *generationContext)
  51. isLoadAlways() bool
  52. }
  53. type inheritedStaticModule struct {
  54. *moduleInfo
  55. loadAlways bool
  56. }
  57. func (im inheritedStaticModule) name() string {
  58. return fmt.Sprintf("%q", MakePath2ModuleName(im.originalPath))
  59. }
  60. func (im inheritedStaticModule) emitSelect(_ *generationContext) {
  61. }
  62. func (im inheritedStaticModule) isLoadAlways() bool {
  63. return im.loadAlways
  64. }
  65. type inheritedDynamicModule struct {
  66. path interpolateExpr
  67. candidateModules []*moduleInfo
  68. loadAlways bool
  69. }
  70. func (i inheritedDynamicModule) name() string {
  71. return "_varmod"
  72. }
  73. func (i inheritedDynamicModule) entryName() string {
  74. return i.name() + "_init"
  75. }
  76. func (i inheritedDynamicModule) emitSelect(gctx *generationContext) {
  77. gctx.newLine()
  78. gctx.writef("_entry = {")
  79. gctx.indentLevel++
  80. for _, mi := range i.candidateModules {
  81. gctx.newLine()
  82. gctx.writef(`"%s": (%q, %s),`, mi.originalPath, mi.moduleLocalName, mi.entryName())
  83. }
  84. gctx.indentLevel--
  85. gctx.newLine()
  86. gctx.write("}.get(")
  87. i.path.emit(gctx)
  88. gctx.write(")")
  89. gctx.newLine()
  90. gctx.writef("(%s, %s) = _entry if _entry else (None, None)", i.name(), i.entryName())
  91. if i.loadAlways {
  92. gctx.newLine()
  93. gctx.writef("if not %s:", i.entryName())
  94. gctx.indentLevel++
  95. gctx.newLine()
  96. gctx.write(`rblf.mkerror("cannot")`)
  97. gctx.indentLevel--
  98. }
  99. }
  100. func (i inheritedDynamicModule) isLoadAlways() bool {
  101. return i.loadAlways
  102. }
  103. type inheritNode struct {
  104. module inheritedModule
  105. }
  106. func (inn *inheritNode) emit(gctx *generationContext) {
  107. // Unconditional case:
  108. // rblf.inherit(handle, <module>, module_init)
  109. // Conditional case:
  110. // if <module>_init != None:
  111. // same as above
  112. inn.module.emitSelect(gctx)
  113. name := inn.module.name()
  114. entry := inn.module.entryName()
  115. gctx.newLine()
  116. if inn.module.isLoadAlways() {
  117. gctx.writef("%s(handle, %s, %s)", cfnInherit, name, entry)
  118. return
  119. }
  120. gctx.writef("if %s:", entry)
  121. gctx.indentLevel++
  122. gctx.newLine()
  123. gctx.writef("%s(handle, %s, %s)", cfnInherit, name, entry)
  124. gctx.indentLevel--
  125. }
  126. type includeNode struct {
  127. module inheritedModule
  128. }
  129. func (inn *includeNode) emit(gctx *generationContext) {
  130. inn.module.emitSelect(gctx)
  131. entry := inn.module.entryName()
  132. gctx.newLine()
  133. if inn.module.isLoadAlways() {
  134. gctx.writef("%s(g, handle)", entry)
  135. return
  136. }
  137. gctx.writef("if %s != None:", entry)
  138. gctx.indentLevel++
  139. gctx.newLine()
  140. gctx.writef("%s(g, handle)", entry)
  141. gctx.indentLevel--
  142. }
  143. type assignmentFlavor int
  144. const (
  145. // Assignment flavors
  146. asgnSet assignmentFlavor = iota // := or =
  147. asgnMaybeSet assignmentFlavor = iota // ?= and variable may be unset
  148. asgnAppend assignmentFlavor = iota // += and variable has been set before
  149. asgnMaybeAppend assignmentFlavor = iota // += and variable may be unset
  150. )
  151. type assignmentNode struct {
  152. lhs variable
  153. value starlarkExpr
  154. mkValue *mkparser.MakeString
  155. flavor assignmentFlavor
  156. isTraced bool
  157. previous *assignmentNode
  158. }
  159. func (asgn *assignmentNode) emit(gctx *generationContext) {
  160. gctx.newLine()
  161. gctx.inAssignment = true
  162. asgn.lhs.emitSet(gctx, asgn)
  163. gctx.inAssignment = false
  164. if asgn.isTraced {
  165. gctx.newLine()
  166. gctx.tracedCount++
  167. gctx.writef(`print("%s.%d: %s := ", `, gctx.starScript.mkFile, gctx.tracedCount, asgn.lhs.name())
  168. asgn.lhs.emitGet(gctx, true)
  169. gctx.writef(")")
  170. }
  171. }
  172. type exprNode struct {
  173. expr starlarkExpr
  174. }
  175. func (exn *exprNode) emit(gctx *generationContext) {
  176. gctx.newLine()
  177. exn.expr.emit(gctx)
  178. }
  179. type ifNode struct {
  180. isElif bool // true if this is 'elif' statement
  181. expr starlarkExpr
  182. }
  183. func (in *ifNode) emit(gctx *generationContext) {
  184. ifElif := "if "
  185. if in.isElif {
  186. ifElif = "elif "
  187. }
  188. gctx.newLine()
  189. if bad, ok := in.expr.(*badExpr); ok {
  190. gctx.write("# MK2STAR ERROR converting:")
  191. gctx.newLine()
  192. gctx.writef("# %s", bad.node.Dump())
  193. gctx.newLine()
  194. gctx.writef("# %s", bad.message)
  195. gctx.newLine()
  196. // The init function emits a warning if the conversion was not
  197. // fullly successful, so here we (arbitrarily) take the false path.
  198. gctx.writef("%sFalse:", ifElif)
  199. return
  200. }
  201. gctx.write(ifElif)
  202. in.expr.emit(gctx)
  203. gctx.write(":")
  204. }
  205. type elseNode struct{}
  206. func (br *elseNode) emit(gctx *generationContext) {
  207. gctx.newLine()
  208. gctx.write("else:")
  209. }
  210. // switchCase represents as single if/elseif/else branch. All the necessary
  211. // info about flavor (if/elseif/else) is supposed to be kept in `gate`.
  212. type switchCase struct {
  213. gate starlarkNode
  214. nodes []starlarkNode
  215. }
  216. func (cb *switchCase) newNode(node starlarkNode) {
  217. cb.nodes = append(cb.nodes, node)
  218. }
  219. func (cb *switchCase) emit(gctx *generationContext) {
  220. cb.gate.emit(gctx)
  221. gctx.indentLevel++
  222. hasStatements := false
  223. emitNode := func(node starlarkNode) {
  224. if _, ok := node.(*commentNode); !ok {
  225. hasStatements = true
  226. }
  227. node.emit(gctx)
  228. }
  229. if len(cb.nodes) > 0 {
  230. emitNode(cb.nodes[0])
  231. for _, node := range cb.nodes[1:] {
  232. emitNode(node)
  233. }
  234. if !hasStatements {
  235. gctx.emitPass()
  236. }
  237. } else {
  238. gctx.emitPass()
  239. }
  240. gctx.indentLevel--
  241. }
  242. // A single complete if ... elseif ... else ... endif sequences
  243. type switchNode struct {
  244. ssCases []*switchCase
  245. }
  246. func (ssw *switchNode) newNode(node starlarkNode) {
  247. switch br := node.(type) {
  248. case *switchCase:
  249. ssw.ssCases = append(ssw.ssCases, br)
  250. default:
  251. panic(fmt.Errorf("expected switchCase node, got %t", br))
  252. }
  253. }
  254. func (ssw *switchNode) emit(gctx *generationContext) {
  255. if len(ssw.ssCases) == 0 {
  256. gctx.emitPass()
  257. } else {
  258. ssw.ssCases[0].emit(gctx)
  259. for _, ssCase := range ssw.ssCases[1:] {
  260. ssCase.emit(gctx)
  261. }
  262. }
  263. }