/src/tools/semantics/code/entities/liberty_feature_definition.e

http://github.com/tybor/Liberty · Specman e · 524 lines · 460 code · 46 blank · 18 comment · 32 complexity · fae24fb6c7b034fafd198aa7c37c200b MD5 · raw file

  1. -- This file is part of Liberty Eiffel.
  2. --
  3. -- Liberty Eiffel is free software: you can redistribute it and/or modify
  4. -- it under the terms of the GNU General Public License as published by
  5. -- the Free Software Foundation, version 3 of the License.
  6. --
  7. -- Liberty Eiffel is distributed in the hope that it will be useful,
  8. -- but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. -- GNU General Public License for more details.
  11. --
  12. -- You should have received a copy of the GNU General Public License
  13. -- along with Liberty Eiffel. If not, see <http://www.gnu.org/licenses/>.
  14. --
  15. class LIBERTY_FEATURE_DEFINITION
  16. inherit
  17. LIBERTY_ENTITY
  18. redefine copy, out_in_tagged_out_memory
  19. end
  20. insert
  21. LIBERTY_REACHABLE_MARKED
  22. redefine
  23. copy, out_in_tagged_out_memory
  24. end
  25. LOGGING
  26. redefine
  27. copy, out_in_tagged_out_memory
  28. end
  29. creation {LIBERTY_BUILDER_TOOLS}
  30. make
  31. creation {LIBERTY_FEATURE_DEFINITION}
  32. specialized
  33. feature {ANY}
  34. feature_name: LIBERTY_FEATURE_NAME
  35. creation_clients: COLLECTION[LIBERTY_TYPE]
  36. clients: COLLECTION[LIBERTY_TYPE]
  37. is_frozen: BOOLEAN
  38. the_feature: LIBERTY_FEATURE
  39. current_type: LIBERTY_ACTUAL_TYPE
  40. out_in_tagged_out_memory is
  41. do
  42. tagged_out_memory.append(once "feature definition: ")
  43. feature_name.out_in_tagged_out_memory
  44. end
  45. name: FIXED_STRING is
  46. do
  47. Result := feature_name.name
  48. end
  49. is_regular: BOOLEAN is
  50. do
  51. Result := feature_name.is_regular
  52. end
  53. is_prefix: BOOLEAN is
  54. do
  55. Result := feature_name.is_prefix
  56. end
  57. is_infix: BOOLEAN is
  58. do
  59. Result := feature_name.is_infix
  60. end
  61. is_creation: BOOLEAN is
  62. do
  63. Result := creation_clients /= Void
  64. end
  65. result_type: LIBERTY_TYPE is
  66. do
  67. if the_feature /= Void then
  68. Result := the_feature.result_type
  69. else
  70. -- should not happen??
  71. not_yet_implemented
  72. end
  73. end
  74. copy (other: like Current) is
  75. do
  76. feature_name := other.feature_name
  77. current_type := other.current_type
  78. clients := other.clients.twin
  79. is_frozen := other.is_frozen
  80. the_feature := other.the_feature
  81. end
  82. specialized_in (a_type: LIBERTY_ACTUAL_TYPE): like Current is
  83. local
  84. cl, ccl: COLLECTION[LIBERTY_TYPE]
  85. f, pf: like the_feature
  86. p: like precursors
  87. i: INTEGER
  88. do
  89. debug ("feature.specialization")
  90. log.trace.put_string(once "Specializing in ")
  91. log.trace.put_string(a_type.full_name)
  92. debug_display(log.trace, False)
  93. end
  94. cl := specialized_clients(clients, a_type)
  95. if creation_clients /= Void then
  96. ccl := specialized_clients(creation_clients, a_type)
  97. end
  98. if the_feature /= Void then
  99. f := the_feature.specialized_in(a_type)
  100. end
  101. p := precursors
  102. if p /= Void then
  103. from
  104. i := p.lower
  105. until
  106. i > p.upper
  107. loop
  108. pf := p.item(i).specialized_in(a_type)
  109. if pf /= p.item(i) then
  110. if p = precursors then
  111. p := p.twin
  112. end
  113. p.fast_put(pf, p.key(i))
  114. end
  115. i := i + 1
  116. end
  117. end
  118. if a_type = current_type and then cl = clients and then ccl = creation_clients and then f = the_feature and then p = precursors then
  119. Result := Current
  120. else
  121. create Result.specialized(feature_name, f.current_type, ccl, cl, is_frozen, f, p, position)
  122. end
  123. debug ("feature.specialization")
  124. log.trace.put_string(once "Specialized in ")
  125. log.trace.put_string(a_type.full_name)
  126. log.trace.put_string(once ": ")
  127. Result.debug_display(log.trace, True)
  128. end
  129. end
  130. feature {}
  131. specialized_clients (a_clients: like clients; a_type: LIBERTY_ACTUAL_TYPE): like clients is
  132. require
  133. a_type /= Void
  134. a_clients /= Void
  135. local
  136. t: LIBERTY_TYPE
  137. i: INTEGER
  138. do
  139. from
  140. Result := a_clients
  141. i := Result.lower
  142. until
  143. i > Result.upper
  144. loop
  145. t := Result.item(i).specialized_in(a_type)
  146. if t /= Result.item(i) then
  147. if Result = a_clients then
  148. Result := Result.twin
  149. end
  150. Result.put(t, i)
  151. end
  152. i := i + 1
  153. end
  154. end
  155. feature {LIBERTY_UNIVERSE}
  156. set_reachable (mark: like reachable_mark) is
  157. do
  158. if not is_reachable then
  159. log.trace.put_string(once "Marked reachable the feature definition: ")
  160. log.trace.put_line(feature_name.name)
  161. torch.burn
  162. end
  163. if reachable_mark < mark then
  164. reachable_mark := mark
  165. if the_feature /= Void then
  166. the_feature.mark_reachable_code(mark)
  167. end
  168. end
  169. end
  170. feature {LIBERTY_REACHABLE, LIBERTY_REACHABLE_COLLECTION_MARKER}
  171. mark_reachable_code (mark: INTEGER) is
  172. do
  173. set_reachable(mark)
  174. end
  175. feature {ANY}
  176. debug_display (o: OUTPUT_STREAM; show_details: BOOLEAN) is
  177. do
  178. o.put_string(once " feature ")
  179. debug_clients(o, clients)
  180. if is_creation then
  181. o.put_string(once " create ")
  182. debug_clients(o, creation_clients)
  183. end
  184. if is_frozen then
  185. o.put_string(once " frozen")
  186. end
  187. if is_prefix then
  188. o.put_string(once " prefix ")
  189. elseif is_infix then
  190. o.put_string(once " infix ")
  191. else
  192. o.put_character(' ')
  193. end
  194. o.put_string(name.out)
  195. if show_details then
  196. if the_feature = Void then
  197. o.put_line(once " is not yet attached")
  198. else
  199. o.put_line(once " is")
  200. the_feature.debug_display(o, 2)
  201. o.put_line(once " end")
  202. end
  203. else
  204. o.put_new_line
  205. end
  206. end
  207. feature {}
  208. debug_clients (o: OUTPUT_STREAM; c: like clients) is
  209. local
  210. i: INTEGER
  211. do
  212. o.put_character('{')
  213. from
  214. i := c.lower
  215. until
  216. i > c.upper
  217. loop
  218. o.put_string(c.item(i).full_name.out)
  219. if i < c.upper then
  220. o.put_string(once ", ")
  221. end
  222. i := i + 1
  223. end
  224. o.put_character('}')
  225. end
  226. feature {LIBERTY_BUILDER_TOOLS}
  227. set_clients (a_clients: like clients) is
  228. require
  229. a_clients /= Void
  230. do
  231. clients := a_clients
  232. ensure
  233. clients = a_clients
  234. end
  235. set_the_feature (a_feature: like the_feature) is
  236. require
  237. a_feature.current_type = current_type
  238. do
  239. the_feature := a_feature
  240. ensure
  241. the_feature = a_feature
  242. end
  243. set_creation_clients (a_creation_clients: like creation_clients) is
  244. require
  245. a_creation_clients /= Void
  246. do
  247. creation_clients := a_creation_clients
  248. ensure
  249. is_creation
  250. creation_clients = a_creation_clients
  251. end
  252. join (fd: like Current; a_parent_type: LIBERTY_ACTUAL_TYPE) is
  253. require
  254. fd.current_type = current_type
  255. fd.has_precursor(a_parent_type)
  256. local
  257. old_feature: like the_feature
  258. do
  259. if not same_clients(fd.clients) then
  260. --| *** TODO: warning: the inherited features don't have the same export clauses (the second set
  261. --| is ignored)
  262. end
  263. old_feature := the_feature
  264. if fd.the_feature /= Void then
  265. if old_feature = Void then
  266. the_feature := fd.the_feature
  267. elseif old_feature.id /= fd.the_feature.id then
  268. the_feature := old_feature.join(current_type, fd.the_feature, Current, fd)
  269. end
  270. end
  271. if not has_precursor(a_parent_type) then
  272. add_precursor(fd.precursor_feature(a_parent_type), a_parent_type)
  273. else
  274. check
  275. precursor_feature(a_parent_type) = fd.precursor_feature(a_parent_type)
  276. end
  277. end
  278. ensure
  279. has_precursor(a_parent_type)
  280. end
  281. re_name (a_name: like feature_name) is
  282. require
  283. a_name /= Void
  284. do
  285. feature_name := a_name
  286. ensure
  287. feature_name = a_name
  288. end
  289. feature {LIBERTY_FEATURE, LIBERTY_FEATURE_DEFINITION}
  290. fatal_join_error_redefined_concrete (type: LIBERTY_ACTUAL_TYPE; with: LIBERTY_FEATURE_DEFINITION) is
  291. do
  292. debug ("type.building")
  293. log.trace.put_string(once "Cannot join redefined feature ")
  294. log.trace.put_string(feature_name.name)
  295. log.trace.put_string(once " from ")
  296. log.trace.put_string(the_feature.definition_type.full_name)
  297. log.trace.put_string(once " with concrete feature ")
  298. log.trace.put_string(with.feature_name.name)
  299. log.trace.put_string(once " from ")
  300. log.trace.put_string(with.the_feature.definition_type.full_name)
  301. log.trace.put_string(once " in type ")
  302. log.trace.put_line(type.full_name)
  303. breakpoint
  304. end
  305. not_yet_implemented
  306. ensure
  307. errors.has_error
  308. end
  309. fatal_join_error_concrete_redefined (type: LIBERTY_ACTUAL_TYPE; with: LIBERTY_FEATURE_DEFINITION) is
  310. do
  311. with.fatal_join_error_redefined_concrete(type, Current)
  312. ensure
  313. errors.has_error
  314. end
  315. fatal_join_error_concrete_concrete (type: LIBERTY_ACTUAL_TYPE; with: LIBERTY_FEATURE_DEFINITION) is
  316. do
  317. debug ("type.building")
  318. log.trace.put_string(once "Cannot join concrete feature ")
  319. log.trace.put_string(feature_name.name)
  320. log.trace.put_string(once " from ")
  321. log.trace.put_string(the_feature.definition_type.full_name)
  322. log.trace.put_string(once " with concrete feature ")
  323. log.trace.put_string(with.feature_name.name)
  324. log.trace.put_string(once " from ")
  325. log.trace.put_string(with.the_feature.definition_type.full_name)
  326. log.trace.put_string(once " in type ")
  327. log.trace.put_line(type.full_name)
  328. breakpoint
  329. end
  330. not_yet_implemented
  331. ensure
  332. errors.has_error
  333. end
  334. feature {LIBERTY_BUILDER_TOOLS, LIBERTY_FEATURE_DEFINITION}
  335. add_precursor (a_precursor_feature: LIBERTY_FEATURE; a_precursor_type: LIBERTY_ACTUAL_TYPE) is
  336. require
  337. not has_precursor(a_precursor_type)
  338. a_precursor_feature.current_type = current_type
  339. do
  340. if precursors = Void then
  341. create {HASHED_DICTIONARY[LIBERTY_FEATURE, LIBERTY_ACTUAL_TYPE]} precursors.with_capacity(3)
  342. end
  343. precursors.add(a_precursor_feature, a_precursor_type)
  344. torch.burn
  345. ensure
  346. precursor_feature(a_precursor_type) = a_precursor_feature
  347. end
  348. has_precursor (a_precursor_type: LIBERTY_ACTUAL_TYPE): BOOLEAN is
  349. do
  350. if precursors /= Void then
  351. if a_precursor_type /= Void then
  352. Result := precursors.fast_has(a_precursor_type)
  353. else
  354. Result := precursors.count = 1
  355. end
  356. end
  357. end
  358. precursor_feature (a_precursor_type: LIBERTY_ACTUAL_TYPE): LIBERTY_FEATURE is
  359. require
  360. has_precursor(a_precursor_type)
  361. do
  362. if a_precursor_type /= Void then
  363. Result := precursors.fast_at(a_precursor_type)
  364. else
  365. Result := precursors.first
  366. end
  367. end
  368. feature {LIBERTY_ACTUAL_TYPE}
  369. copy_precursors (other: like Current) is
  370. local
  371. f: LIBERTY_FEATURE; t: LIBERTY_ACTUAL_TYPE
  372. i: INTEGER
  373. do
  374. if other.precursors /= Void then
  375. if precursors = Void then
  376. precursors := other.precursors
  377. else
  378. from
  379. i := precursors.lower
  380. until
  381. i > precursors.upper
  382. loop
  383. t := precursors.key(i)
  384. f := precursors.item(i)
  385. if precursors.fast_has(t) then
  386. breakpoint
  387. else
  388. precursors.add(f, t)
  389. end
  390. i := i + 1
  391. end
  392. end
  393. end
  394. end
  395. feature {}
  396. same_clients (a_clients: like clients): BOOLEAN is
  397. do
  398. Result := clients.count = a_clients.count
  399. and then include(clients, a_clients)
  400. and then include(a_clients, clients)
  401. end
  402. include (set, subset: like clients): BOOLEAN is
  403. local
  404. i, j: INTEGER
  405. do
  406. from
  407. Result := set.count >= subset.count
  408. i := subset.lower
  409. until
  410. not Result or else i > subset.upper
  411. loop
  412. from
  413. Result := False
  414. j := set.lower
  415. until
  416. Result or else j > set.upper
  417. loop
  418. Result := set.item(j) = subset.item(i)
  419. j := j + 1
  420. end
  421. i := i + 1
  422. end
  423. end
  424. feature {}
  425. make (a_name: like feature_name; a_type: like current_type; a_clients: like clients; a_frozen: like is_frozen; a_position: like position) is
  426. require
  427. a_name /= Void
  428. a_type /= Void
  429. a_clients /= Void
  430. a_position /= Void
  431. do
  432. feature_name := a_name
  433. current_type := a_type
  434. clients := a_clients
  435. is_frozen := a_frozen
  436. position := a_position
  437. debug ("full_name")
  438. debug_full_name := a_name.full_name.out
  439. end
  440. ensure
  441. feature_name = a_name
  442. current_type = a_type
  443. clients = a_clients
  444. is_frozen = a_frozen
  445. position = a_position
  446. end
  447. specialized (a_name: like feature_name; a_type: like current_type; a_creation_clients: like creation_clients; a_clients: like clients;
  448. a_frozen: like is_frozen; a_feature: like the_feature; a_precursors: like precursors; a_position: like position) is
  449. do
  450. make(a_name, a_type, a_clients, a_frozen, a_position)
  451. the_feature := a_feature
  452. precursors := a_precursors
  453. if a_creation_clients /= Void then
  454. set_creation_clients(a_creation_clients)
  455. end
  456. debug ("full_name")
  457. debug_full_name := a_name.full_name.out
  458. end
  459. end
  460. torch: LIBERTY_ENLIGHTENING_THE_WORLD
  461. errors: LIBERTY_ERRORS
  462. debug_full_name: STRING
  463. feature {LIBERTY_FEATURE_DEFINITION}
  464. precursors: DICTIONARY[LIBERTY_FEATURE, LIBERTY_ACTUAL_TYPE]
  465. -- For correct "Precursor" management. All the features have the same `current_type'.
  466. feature {ANY}
  467. accept (v: VISITOR) is
  468. local
  469. v0: LIBERTY_FEATURE_DEFINITION_VISITOR
  470. do
  471. v0 ::= v
  472. v0.visit_liberty_feature_definition(Current)
  473. end
  474. invariant
  475. feature_name /= Void
  476. clients /= Void
  477. the_feature /= Void implies the_feature.current_type = current_type
  478. end