expression_manipulation.jl 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. # StarPU --- Runtime system for heterogeneous multicore architectures.
  2. #
  3. # Copyright (C) 2020 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  4. #
  5. # StarPU is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU Lesser General Public License as published by
  7. # the Free Software Foundation; either version 2.1 of the License, or (at
  8. # your option) any later version.
  9. #
  10. # StarPU is distributed in the hope that it will be useful, but
  11. # WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. #
  14. # See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. #
  16. """
  17. Lenient comparison operator for structures and arrays.
  18. """
  19. @generated function ≂(x, y)
  20. if x != y || x <: Type
  21. :(x == y)
  22. elseif !isempty(fieldnames(x))
  23. mapreduce(n -> :(x.$n ≂ y.$n), (a,b)->:($a && $b), fieldnames(x))
  24. elseif x <: Array
  25. quote
  26. if length(x) != length(y)
  27. return false
  28. end
  29. for i in 1:length(x)
  30. if !(x[i] ≂ y[i])
  31. return false
  32. end
  33. end
  34. return true
  35. end
  36. else
  37. :(x == y)
  38. end
  39. end
  40. """
  41. Returns a new expression where every occurrence of expr_to_replace into expr
  42. has been replaced by new_expr
  43. """
  44. function substitute(expr :: StarpuExpr, expr_to_replace :: StarpuExpr, new_expr :: StarpuExpr)
  45. function func_to_apply(x :: StarpuExpr)
  46. if (x ≂ expr_to_replace)
  47. return new_expr
  48. end
  49. return x
  50. end
  51. return apply(func_to_apply, expr)
  52. end
  53. """
  54. Returns an expression where "€" symbols in expr were replaced
  55. by the following expression list.
  56. Ex : replace_pattern((@parse € = €), (@parse x), (@parse 1 + 1))
  57. --> (StarpuExpr) "x = 1 + 1"
  58. """
  59. function replace_pattern(expr :: StarpuExpr, replace_€ :: StarpuExpr...)
  60. replace_index = 0
  61. function func_to_apply(x :: StarpuExpr)
  62. if x == @parse €
  63. replace_index += 1
  64. return replace_€[replace_index]
  65. end
  66. if isa(x, StarpuExprTypedVar) && x.name == :€
  67. replace_index += 1
  68. if isa(replace_€[replace_index], StarpuExprVar)
  69. return StarpuExprTypedVar(replace_€[replace_index].name, x.typ)
  70. end
  71. return StarpuExprTypedExpr(replace_€[replace_index], x.typ)
  72. end
  73. if isa(x, StarpuExprFunction) && x.func == :€
  74. replace_index += 1
  75. if !(isa(replace_€[replace_index], StarpuExprVar))
  76. error("Can only replace a function name by a variable")
  77. end
  78. return StarpuExprFunction(x.ret_type, replace_€[replace_index].name, x.args, x.body)
  79. end
  80. return x
  81. end
  82. return apply(func_to_apply, expr)
  83. end
  84. import Base.any
  85. """
  86. Returns true if one of the sub-expression x in expr
  87. is such as cond(x) is true, otherwise, it returns false.
  88. """
  89. function any(cond :: Function, expr :: StarpuExpr)
  90. err_to_catch = "Catch me, condition is true somewhere !"
  91. function func_to_apply(x :: StarpuExpr)
  92. if cond(x)
  93. error(err_to_catch) # dirty but osef
  94. end
  95. return x
  96. end
  97. try
  98. apply(func_to_apply, expr)
  99. catch err
  100. if (isa(err, ErrorException) && err.msg == err_to_catch)
  101. return true
  102. end
  103. throw(err)
  104. end
  105. return false
  106. end
  107. import Base.all
  108. """
  109. Returns true if every sub-expression x in expr
  110. is such as cond(x) is true, otherwise, it returns false.
  111. """
  112. function all(cond :: Function, expr :: StarpuExpr)
  113. return !any(!cond, expr)
  114. end
  115. function visit_preorder(func :: Function, expr :: StarpuExprAffect)
  116. func(expr)
  117. visit_preorder(func, expr.var)
  118. visit_preorder(func, expr.expr)
  119. return expr
  120. end
  121. function visit_preorder(func :: Function, expr :: StarpuExprBlock)
  122. func(expr)
  123. for e in expr.exprs
  124. visit_preorder(func, e)
  125. end
  126. return expr
  127. end
  128. function visit_preorder(func :: Function, expr :: StarpuExprCall)
  129. func(expr)
  130. for a in expr.args
  131. visit_preorder(func, a)
  132. end
  133. return expr
  134. end
  135. function visit_preorder(func :: Function, expr :: StarpuExprCudaCall)
  136. func(expr)
  137. func(expr.nblocks)
  138. func(expr.threads_per_block)
  139. for a in expr.args
  140. visit_preorder(func, a)
  141. end
  142. return expr
  143. end
  144. function visit_preorder(func :: Function, expr :: StarpuExprField)
  145. func(expr)
  146. func(expr.left)
  147. func(expr.field)
  148. func(expr.is_an_arrow)
  149. return expr
  150. end
  151. function visit_preorder(func :: Function, expr :: StarpuExprFor)
  152. func(expr)
  153. for d in expr.set_declarations
  154. visit_preorder(func, d)
  155. end
  156. visit_preorder(func, expr.set)
  157. visit_preorder(func, expr.body)
  158. return expr
  159. end
  160. function visit_preorder(func :: Function, expr :: StarpuExprFunction)
  161. func(expr)
  162. for a in expr.args
  163. visit_preorder(func, a)
  164. end
  165. visit_preorder(func, e.body)
  166. return expr
  167. end
  168. function visit_preorder(func :: Function, expr :: StarpuExprIf)
  169. func(expr)
  170. visit_preorder(func, expr.cond)
  171. visit_preorder(func, expr.then_statement)
  172. return expr
  173. end
  174. function visit_preorder(func :: Function, expr :: StarpuExprIfElse)
  175. func(expr)
  176. visit_preorder(func, expr.cond)
  177. visit_preorder(func, expr.then_statement)
  178. visit_preorder(func, expr.else_statement)
  179. return expr
  180. end
  181. function visit_preorder(func :: Function, expr :: StarpuExprInterval)
  182. func(expr)
  183. visit_preorder(func, expr.start)
  184. visit_preorder(func, expr.step)
  185. visit_preorder(func, expr.stop)
  186. return expr
  187. end
  188. function visit_preorder(func :: Function, expr :: StarpuExprRef)
  189. func(expr)
  190. visit_preorder(func, expr.ref)
  191. for i in expr.indexes
  192. visit_preorder(func, i)
  193. end
  194. return expr
  195. end
  196. function visit_preorder(func :: Function, expr :: StarpuExprAddress)
  197. func(expr)
  198. visit_preorder(func, expr.ref)
  199. return expr
  200. end
  201. function visit_preorder(func :: Function, expr :: StarpuExprBreak)
  202. func(expr)
  203. return expr
  204. end
  205. function visit_preorder(func :: Function, expr :: StarpuExprReturn)
  206. func(expr)
  207. visit_preorder(func, expr.value)
  208. return expr
  209. end
  210. function visit_preorder(func :: Function, expr :: StarpuExpr)
  211. func(expr)
  212. return expr
  213. end
  214. function visit_preorder(func :: Function, expr :: StarpuExprTypedExpr)
  215. func(expr)
  216. visit_preorder(func, expr.expr)
  217. return expr
  218. end
  219. function visit_preorder(func :: Function, expr :: StarpuExprWhile)
  220. func(expr)
  221. visit_preorder(func, expr.cond)
  222. visit_preorder(func, expr.body)
  223. return expr
  224. end
  225. # function substitute_preorder(expr :: StarpuExprAffect, match :: StarpuExpr, replace :: StarpuExpr)
  226. # if expr == match
  227. # return replace
  228. # end
  229. # var = substitute_preorder(func, expr.var)
  230. # expr = substitute_preorder(func, expr.expr)
  231. # if var != expr.var || expr != expr.expr
  232. # return StarpuExprAffect(var, expr)
  233. # end
  234. # return expr
  235. # end
  236. # function substitute_preorder(expr :: StarpuExprBlock, match :: StarpuExpr, replace :: StarpuExpr)
  237. # if expr == match
  238. # return replace
  239. # end
  240. # modified = false
  241. # new_exprs = Vector{StarpuExpr}()
  242. # for e in expr.exprs
  243. # push!(new_exprs, substitute_preorder(func, e))
  244. # end
  245. # if new_exprs != expr.exprs
  246. # return StarpuExprBlock(new_exprs)
  247. # end
  248. # return expr
  249. # end
  250. # function substitute_preorder(expr :: StarpuExprCall, match :: StarpuExpr, replace :: StarpuExpr)
  251. # if expr == match
  252. # return replace
  253. # end
  254. # new_args = Vector{StarpuExpr}()
  255. # for a in expr.args
  256. # push!(new_args, substitute_preorder(func, a))
  257. # end
  258. # if new_args != expr.args
  259. # return StarpuExprCall(expr.func, new_args)
  260. # end
  261. # return expr
  262. # end
  263. # function substitute_preorder(expr :: StarpuExprCudaCall, match :: StarpuExpr, replace :: StarpuExpr)
  264. # if expr == match
  265. # return replace
  266. # end
  267. # new_args = Vector{StarpuExpr}()
  268. # for a in expr.args
  269. # push!(new_args, substitute_preorder(func, a))
  270. # end
  271. # if new_args != expr.args
  272. # return new StarpuExprCudaCall(expr.ker_name, expr.nblocks, expr.threads_per_block, new_args)
  273. # end
  274. # return expr
  275. # end
  276. # function substitute_preorder(expr :: StarpuExprField, match :: StarpuExpr, replace :: StarpuExpr)
  277. # if expr == match
  278. # return replace
  279. # end
  280. # left = substitute_preorder(expr.left, match, replace)
  281. # if left != expr.left
  282. # return StarpuExprField(left, expr.field, expr.is_an_arrow)
  283. # end
  284. # return expr
  285. # end
  286. # function substitute_preorder(expr :: StarpuExprFor, match :: StarpuExpr, replace :: StarpuExpr)
  287. # if expr == match
  288. # return replace
  289. # end
  290. # new_set_declarations = Vector{StarpuExpr}()
  291. # for d in expr.set_declarations
  292. # substitute_preorder(func, d)
  293. # end
  294. # substitute_preorder(expr.set, match :: StarpuExpr, replace :: StarpuExpr)
  295. # substitute_preorder(func, expr.body)
  296. # return expr
  297. # end
  298. # function substitute_preorder(expr :: StarpuExprFunction, match :: StarpuExpr, replace :: StarpuExpr)
  299. # if expr == match
  300. # return replace
  301. # end
  302. # for a in expr.args
  303. # substitute_preorder(func, a)
  304. # end
  305. # substitute_preorder(e.body, match :: StarpuExpr, replace :: StarpuExpr)
  306. # return expr
  307. # end
  308. # function substitute_preorder(expr :: StarpuExprIf, match :: StarpuExpr, replace :: StarpuExpr)
  309. # if expr == match
  310. # return replace
  311. # end
  312. # substitute_preorder(func, expr.cond)
  313. # substitute_preorder(func, expr.then_statement)
  314. # return expr
  315. # end
  316. # function substitute_preorder(expr :: StarpuExprIfElse, match :: StarpuExpr, replace :: StarpuExpr)
  317. # if expr == match
  318. # return replace
  319. # end
  320. # substitute_preorder(func, expr.cond)
  321. # substitute_preorder(func, expr.then_statement)
  322. # substitute_preorder(func, expr.else_statement)
  323. # return expr
  324. # end
  325. # function substitute_preorder(expr :: StarpuExprInterval, match :: StarpuExpr, replace :: StarpuExpr)
  326. # if expr == match
  327. # return replace
  328. # end
  329. # substitute_preorder(func, expr.start)
  330. # substitute_preorder(func, expr.step)
  331. # substitute_preorder(func, expr.stop)
  332. # return expr
  333. # end
  334. # function substitute_preorder(expr :: StarpuExprRef, match :: StarpuExpr, replace :: StarpuExpr)
  335. # if expr == match
  336. # return replace
  337. # end
  338. # substitute_preorder(func, expr.ref)
  339. # for i in expr.indexes
  340. # substitute_preorder(func, i)
  341. # end
  342. # return expr
  343. # end
  344. # function substitute_preorder(expr :: StarpuExprAddress, match :: StarpuExpr, replace :: StarpuExpr)
  345. # if expr == match
  346. # return replace
  347. # end
  348. # substitute_preorder(func, expr.ref)
  349. # return expr
  350. # end
  351. # function substitute_preorder(expr :: StarpuExprBreak, match :: StarpuExpr, replace :: StarpuExpr)
  352. # if expr == match
  353. # return replace
  354. # end
  355. # return expr
  356. # end
  357. # function substitute_preorder(expr :: StarpuExprReturn, match :: StarpuExpr, replace :: StarpuExpr)
  358. # if expr == match
  359. # return replace
  360. # end
  361. # substitute_preorder(func, expr.value)
  362. # return expr
  363. # end
  364. # function substitute_preorder(expr :: StarpuExpr, match :: StarpuExpr, replace :: StarpuExpr)
  365. # if expr == match
  366. # return replace
  367. # end
  368. # return expr
  369. # end
  370. # function substitute_preorder(expr :: StarpuExprTypedExpr, match :: StarpuExpr, replace :: StarpuExpr)
  371. # if expr == match
  372. # return replace
  373. # end
  374. # substitute_preorder(func, expr.expr)
  375. # return expr
  376. # end
  377. # function substitute_preorder(expr :: StarpuExprWhile, match :: StarpuExpr, replace :: StarpuExpr)
  378. # if expr == match
  379. # return replace
  380. # end
  381. # substitute_preorder(func, expr.cond)
  382. # substitute_preorder(func, expr.body)
  383. # return expr
  384. # end