extern.mli 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. (** Transform extern variables into getter/setter functions. *)
  2. (**
  3. In CiviC, a global variable defined in one compilation unit can be used in
  4. different compilation units. To do this, the variable definition needs to be
  5. marked with the [export] keyword in the first compilation units and other
  6. compilation unit need to contain a extern variable declaration.
  7. Unfortunately, the CiviC VM does not support exporting global variables.
  8. This phase solves this problem by replacing exported variables by getter and
  9. setter functions. This phase works in three steps.
  10. In the first step, getter and setter functions are added for all exported
  11. variables definitions and the export flag is removed from these variable
  12. definition. For example:
  13. {v export int foo;
  14. export int[2] bar; v}
  15. becomes:
  16. {v int foo;
  17. export int _foo_get() \{
  18. return foo;
  19. \}
  20. export void _foo_set(int _value_1) \{
  21. foo = _value_1;
  22. \}
  23. int _bar_1 = 2;
  24. export int __bar_1_get() \{
  25. return _bar_1;
  26. \}
  27. export void __bar_1_set(int _value_2) \{
  28. _bar_1 = _value_2;
  29. \}
  30. int[_bar_1] bar;
  31. export int _bar_get(int _index_3) \{
  32. return bar[_index_3];
  33. \}
  34. export void _bar_set(int _index_4, int _value_5) \{
  35. bar[_index_4] = _value_5;
  36. \} v}
  37. Note that array dimensions are renamed during the desugaring phase, [2] is
  38. moved to a variable [_bar_1] because it is the first dimension of [bar]. After
  39. that, it is handled as a regulary exported integer for which setter and getter
  40. functions are created implicitly.
  41. In the second step, external variable declarations are replaced by function
  42. declarations for the corresponding getter and setter functions. For example:
  43. {v extern int foo;
  44. extern int[n] bar; v}
  45. becomes:
  46. {v extern int _foo_get();
  47. extern void _foo_set(int value);
  48. extern int _bar_get(int index);
  49. extern void _bar_set(int index, int value);
  50. extern int __bar_1_get();
  51. extern void __bar_1_set(int value); v}
  52. Again, note that [n] is renamed to [_bar_1]. Also note that this is not already
  53. done during the desugaring phase for external arrays, since the dimensions are
  54. not prevented from being evaluated more than once (See {!Desug} for an
  55. explanation about this).
  56. In the third step, all occurrences of external variables are replaced by
  57. function call to a getter or setter function. For example:
  58. {v /* extern int foo; */
  59. /* extern int [n] bar; */
  60. export void main() \{
  61. bar[foo] = n;
  62. \} v}
  63. becomes:
  64. {v ...
  65. export void main() \{
  66. _bar_set(_foo_get(), __bar_1_get());
  67. \} v}
  68. *)
  69. (** Main phase function, called by {!Main}. *)
  70. val phase : Main.phase_func