/src/tools/semantics/code/feature_local_context/liberty_feature_definition_context.e

http://github.com/tybor/Liberty · Specman e · 520 lines · 445 code · 59 blank · 16 comment · 22 complexity · fc28715b26240a315fb41a452ad4bd36 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_CONTEXT
  16. inherit
  17. LIBERTY_FEATURE_LOCAL_CONTEXT
  18. insert
  19. LIBERTY_AST_HANDLER
  20. create {LIBERTY_BUILDER_TOOLS}
  21. make
  22. feature {ANY}
  23. current_type: LIBERTY_ACTUAL_TYPE is
  24. do
  25. Result := current_entity.result_type
  26. end
  27. result_type: LIBERTY_TYPE is
  28. do
  29. if result_entity /= Void then
  30. Result := result_entity.result_type
  31. end
  32. end
  33. parameters: TRAVERSABLE[LIBERTY_PARAMETER] is
  34. do
  35. Result := parameters_list
  36. ensure then
  37. definition: Result = parameters_list
  38. end
  39. locals: TRAVERSABLE[LIBERTY_LOCAL] is
  40. do
  41. Result := locals_list
  42. ensure then
  43. definition: Result = locals_list
  44. end
  45. is_parameter (name: ABSTRACT_STRING): BOOLEAN is
  46. do
  47. Result := parameters_map.has(name.intern)
  48. end
  49. parameter (name: ABSTRACT_STRING): LIBERTY_PARAMETER is
  50. do
  51. Result := parameters_map.reference_at(name.intern)
  52. end
  53. is_local (name: ABSTRACT_STRING): BOOLEAN is
  54. do
  55. Result := locals_map.has(name.intern)
  56. end
  57. local_var (name: ABSTRACT_STRING): LIBERTY_LOCAL is
  58. do
  59. Result := locals_map.reference_at(name.intern)
  60. end
  61. current_entity: LIBERTY_CURRENT
  62. result_entity: LIBERTY_RESULT
  63. can_retry: BOOLEAN is True
  64. retry_instruction (a_position: LIBERTY_POSITION): LIBERTY_RETRY is
  65. do
  66. create Result.make(a_position)
  67. retries.add_last(Result)
  68. end
  69. feature {LIBERTY_BUILDER_TOOLS, LIBERTY_FEATURE_LOCAL_CONTEXT}
  70. add_parameter (a_parameter: LIBERTY_PARAMETER) is
  71. do
  72. parameters_list.add_last(a_parameter)
  73. parameters_map.add(a_parameter, a_parameter.name)
  74. end
  75. add_local (a_local: LIBERTY_LOCAL) is
  76. do
  77. locals_list.add_last(a_local)
  78. locals_map.add(a_local, a_local.name)
  79. end
  80. reconcile_retry_instructions (a_feature: LIBERTY_FEATURE) is
  81. do
  82. retries.do_all(agent {LIBERTY_RETRY}.set_feature(a_feature))
  83. end
  84. set_result_type (a_result_type: like result_type) is
  85. do
  86. result_entity := a_result_type.result_entity
  87. end
  88. set_feature_names (a_feature_names: like feature_names) is
  89. require
  90. a_feature_names /= Void
  91. do
  92. feature_names := a_feature_names
  93. compute_written_feature_names
  94. compute_best_accelerator
  95. ensure
  96. feature_names = a_feature_names
  97. written_feature_names /= Void
  98. best_accelerator /= Void
  99. end
  100. best_accelerator: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]]
  101. written_feature_names: FIXED_STRING
  102. find_precursor (parent: LIBERTY_ACTUAL_TYPE; redefined_features: DICTIONARY[LIBERTY_FEATURE_REDEFINED, LIBERTY_FEATURE_NAME];
  103. ast: LIBERTY_AST_ONE_CLASS; file: FIXED_STRING): LIBERTY_FEATURE is
  104. local
  105. i: INTEGER; fn: LIBERTY_AST_FEATURE_NAME
  106. do
  107. from
  108. i := feature_names.lower
  109. until
  110. Result /= Void or else i > feature_names.upper
  111. loop
  112. fn ::= feature_names.item(i)
  113. Result := redefined_features.reference_at(create {LIBERTY_FEATURE_NAME}.make_from_ast(fn.feature_name_or_alias, ast, file))
  114. i := i + 1
  115. end
  116. if Result /= Void then
  117. Result := Result.find_precursor(parent)
  118. end
  119. if Result = Void then
  120. breakpoint
  121. end
  122. end
  123. feature {LIBERTY_FEATURE, LIBERTY_SEMANTICS_BUILDER}
  124. specialized_in (a_type: like current_type): like Current is
  125. do
  126. Result := twin
  127. Result.set_specialized_in(a_type)
  128. end
  129. debug_display_signature (o: OUTPUT_STREAM) is
  130. local
  131. i: INTEGER
  132. do
  133. if not parameters_list.is_empty then
  134. o.put_character('(')
  135. from
  136. i := parameters_list.lower
  137. until
  138. i > parameters_list.upper
  139. loop
  140. if i > parameters_list.lower then
  141. o.put_string(once "; ")
  142. end
  143. o.put_string(parameters_list.item(i).name)
  144. o.put_string(once ": ")
  145. o.put_string(parameters_list.item(i).result_type.full_name)
  146. i := i + 1
  147. end
  148. o.put_character(')')
  149. end
  150. if result_type /= Void then
  151. o.put_string(once ": ")
  152. o.put_string(result_type.full_name)
  153. end
  154. end
  155. feature {LIBERTY_FEATURE_DEFINITION_CONTEXT}
  156. set_specialized_in (a_type: like current_type) is
  157. local
  158. i: INTEGER; p: LIBERTY_PARAMETER; l: LIBERTY_LOCAL
  159. pl: like parameters_list; pm: like parameters_map
  160. ll: like locals_list; lm: like locals_map
  161. do
  162. current_entity := a_type.current_entity
  163. if result_entity /= Void then
  164. set_result_type(result_type.specialized_in(a_type))
  165. end
  166. from
  167. pl := parameters_list
  168. pm := parameters_map
  169. i := pl.lower
  170. until
  171. i > pl.upper
  172. loop
  173. p := pl.item(i).specialized_in(a_type)
  174. if p /= pl.item(i) then
  175. if pl = parameters_list then
  176. pl := pl.twin
  177. pm := pm.twin
  178. end
  179. pl.put(p, i)
  180. pm.put(p, p.name)
  181. end
  182. i := i + 1
  183. end
  184. if pl /= parameters_list then
  185. parameters_list := pl
  186. parameters_map := pm
  187. end
  188. from
  189. ll := locals_list
  190. lm := locals_map
  191. i := ll.lower
  192. until
  193. i > ll.upper
  194. loop
  195. l := ll.item(i).specialized_in(a_type)
  196. if l /= ll.item(i) then
  197. if ll = locals_list then
  198. ll := ll.twin
  199. lm := lm.twin
  200. end
  201. ll.put(l, i)
  202. lm.put(l, l.name)
  203. end
  204. i := i + 1
  205. end
  206. if ll /= locals_list then
  207. locals_list := ll
  208. locals_map := lm
  209. end
  210. --|*** TODO: retries
  211. end
  212. feature {}
  213. parameters_map: DICTIONARY[LIBERTY_PARAMETER, FIXED_STRING]
  214. parameters_list: COLLECTION[LIBERTY_PARAMETER]
  215. locals_map: DICTIONARY[LIBERTY_LOCAL, FIXED_STRING]
  216. locals_list: COLLECTION[LIBERTY_LOCAL]
  217. retries: COLLECTION[LIBERTY_RETRY]
  218. feature_names: EIFFEL_LIST_NODE
  219. make (a_current_type: like current_type) is
  220. require
  221. a_current_type /= Void
  222. do
  223. current_entity := a_current_type.current_entity
  224. create {FAST_ARRAY[LIBERTY_PARAMETER]} parameters_list.make(0)
  225. create {HASHED_DICTIONARY[LIBERTY_PARAMETER, FIXED_STRING]} parameters_map.with_capacity(3)
  226. create {FAST_ARRAY[LIBERTY_LOCAL]} locals_list.make(0)
  227. create {HASHED_DICTIONARY[LIBERTY_LOCAL, FIXED_STRING]} locals_map.with_capacity(3)
  228. create {FAST_ARRAY[LIBERTY_RETRY]} retries.with_capacity(1)
  229. ensure
  230. current_type = a_current_type
  231. end
  232. compute_written_feature_names is
  233. require
  234. written_feature_names = Void
  235. local
  236. i: INTEGER
  237. fn: LIBERTY_AST_FEATURE_NAME
  238. fnoa: LIBERTY_AST_FEATURE_NAME_OR_ALIAS
  239. buffer: STRING
  240. do
  241. buffer := once ""
  242. buffer.clear_count
  243. from
  244. i := feature_names.lower
  245. until
  246. i > feature_names.upper
  247. loop
  248. fn ::= feature_names.item(i)
  249. fnoa := fn.feature_name_or_alias
  250. if fnoa.is_regular then
  251. buffer.append(fnoa.entity_name.image.image.intern)
  252. elseif fnoa.is_prefix then
  253. buffer.append(once "prefix ")
  254. buffer.append(fnoa.free_operator_name.image.image.intern)
  255. else
  256. check fnoa.is_infix end
  257. buffer.append(once "infix ")
  258. buffer.append(fnoa.free_operator_name.image.image.intern)
  259. end
  260. if i < feature_names.upper then
  261. buffer.append(once ", ")
  262. end
  263. i := i + 1
  264. end
  265. written_feature_names := buffer.intern
  266. ensure
  267. written_feature_names /= Void
  268. end
  269. compute_best_accelerator is
  270. local
  271. i: INTEGER
  272. fn: LIBERTY_AST_FEATURE_NAME
  273. fnoa: LIBERTY_AST_FEATURE_NAME_OR_ALIAS
  274. full_feature_name: STRING
  275. second_best_accelerator: like best_accelerator
  276. do
  277. -- Heuristics to accelerate the feature calls (at least in the interpreter builtins).
  278. best_accelerator := Void
  279. from
  280. full_feature_name := once ""
  281. i := feature_names.lower
  282. until
  283. best_accelerator /= Void or else i > feature_names.upper
  284. loop
  285. fn ::= feature_names.item(i)
  286. fnoa := fn.feature_name_or_alias
  287. if fnoa.is_regular then
  288. full_feature_name.copy(fnoa.entity_name.image.image)
  289. elseif fnoa.is_prefix then
  290. full_feature_name.copy(once "prefix ")
  291. full_feature_name.append(fnoa.free_operator_name.image.image)
  292. else
  293. check fnoa.is_infix end
  294. full_feature_name.copy(once "infix ")
  295. full_feature_name.append(fnoa.free_operator_name.image.image)
  296. end
  297. inspect
  298. full_feature_name
  299. when "infix %"implies%"" then
  300. best_accelerator := accelerator_implies
  301. when "infix %"or else%"" then
  302. best_accelerator := accelerator_or_else
  303. when "infix %"or%"" then
  304. best_accelerator := accelerator_or
  305. when "infix %"xor%"" then
  306. best_accelerator := accelerator_xor
  307. when "infix %"and then%"" then
  308. best_accelerator := accelerator_and_then
  309. when "infix %"and%"" then
  310. best_accelerator := accelerator_and
  311. when "infix %"<=%"" then
  312. best_accelerator := accelerator_less_or_equal
  313. when "infix %"<%"" then
  314. best_accelerator := accelerator_less_than
  315. when "infix %">=%"" then
  316. best_accelerator := accelerator_greater_or_equal
  317. when "infix %">%"" then
  318. best_accelerator := accelerator_greater_than
  319. when "infix %"+%"" then
  320. best_accelerator := accelerator_add
  321. when "infix %"-%"" then
  322. best_accelerator := accelerator_subtract
  323. when "infix %"*%"" then
  324. best_accelerator := accelerator_times
  325. when "infix %"/%"" then
  326. best_accelerator := accelerator_divide
  327. when "infix %"//%"" then
  328. best_accelerator := accelerator_int_divide
  329. when "infix %"\\%"" then
  330. best_accelerator := accelerator_int_remainder
  331. when "infix %"^%"" then
  332. best_accelerator := accelerator_power
  333. when "prefix %"+%"" then
  334. best_accelerator := accelerator_positive
  335. when "prefix %"-%"" then
  336. best_accelerator := accelerator_negative
  337. when "prefix %"not%"" then
  338. best_accelerator := accelerator_not
  339. else
  340. if second_best_accelerator /= Void then
  341. if fnoa.is_prefix then
  342. second_best_accelerator := accelerator_free_prefix
  343. elseif fnoa.is_infix then
  344. second_best_accelerator := accelerator_free_infix
  345. end
  346. end
  347. end
  348. i := i + 1
  349. end
  350. if best_accelerator = Void then
  351. if second_best_accelerator /= Void then
  352. best_accelerator := second_best_accelerator
  353. else
  354. best_accelerator := accelerator_other
  355. end
  356. end
  357. ensure
  358. best_accelerator /= Void
  359. end
  360. errors: LIBERTY_ERRORS
  361. feature {} -- Accelerators
  362. accelerator_implies: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  363. once
  364. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_implies
  365. end
  366. accelerator_or_else: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  367. once
  368. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_or_else
  369. end
  370. accelerator_or: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  371. once
  372. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_or
  373. end
  374. accelerator_xor: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  375. once
  376. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_xor
  377. end
  378. accelerator_and_then: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  379. once
  380. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_and_then
  381. end
  382. accelerator_and: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  383. once
  384. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_and
  385. end
  386. accelerator_less_or_equal: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  387. once
  388. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_less_or_equal
  389. end
  390. accelerator_less_than: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  391. once
  392. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_less_than
  393. end
  394. accelerator_greater_or_equal: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  395. once
  396. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_greater_or_equal
  397. end
  398. accelerator_greater_than: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  399. once
  400. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_greater_than
  401. end
  402. accelerator_add: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  403. once
  404. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_add
  405. end
  406. accelerator_subtract: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  407. once
  408. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_subtract
  409. end
  410. accelerator_times: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  411. once
  412. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_times
  413. end
  414. accelerator_divide: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  415. once
  416. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_divide
  417. end
  418. accelerator_int_divide: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  419. once
  420. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_int_divide
  421. end
  422. accelerator_int_remainder: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  423. once
  424. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_int_remainder
  425. end
  426. accelerator_power: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  427. once
  428. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_power
  429. end
  430. accelerator_positive: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  431. once
  432. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_positive
  433. end
  434. accelerator_negative: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  435. once
  436. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_negative
  437. end
  438. accelerator_not: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  439. once
  440. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_not
  441. end
  442. accelerator_free_prefix: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  443. once
  444. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_free_prefix
  445. end
  446. accelerator_free_infix: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  447. once
  448. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_free_infix
  449. end
  450. accelerator_other: PROCEDURE[TUPLE[LIBERTY_FEATURE_ACCELERATOR, LIBERTY_FEATURE]] is
  451. once
  452. Result := agent {LIBERTY_FEATURE_ACCELERATOR}.call_other
  453. end
  454. invariant
  455. current_type /= Void
  456. parameters_list /= Void
  457. locals_list /= Void
  458. parameters_map /= Void
  459. locals_map /= Void
  460. retries /= Void
  461. end