extern.mli 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  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 [n] bar; v}
  15. becomes:
  16. {v int foo;
  17. int bar$1;
  18. int [bar$1] bar;
  19. export void foo$set(int new_value) \{
  20. foo = new_value;
  21. \}
  22. export int foo$get() \{
  23. return foo;
  24. \}
  25. export void bar$set(int index, int new_value) \{
  26. bar[index] = new_value;
  27. \}
  28. export int bar$get(int index) \{
  29. return bar[index];
  30. \}
  31. export void bar$1$set(int new_value) \{
  32. bar$1 = new_value;
  33. \}
  34. export int bar$1$get() \{
  35. return bar$1;
  36. \} v}
  37. Note that array dimensions are renamed during the desugaring phase, [n] is
  38. renamed to [bar$1] because it is the first dimension of bar. After that, it is
  39. handled as a regulary exported integer for which setter and getter functions are
  40. created.
  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 void foo$set(int new_value);
  47. extern int foo$get();
  48. extern void bar$set(int index, int new_value);
  49. extern int bar$get(int index);
  50. extern int bar$1$get(int new_value);
  51. extern int bar$1$set(int index, int new_value); v}
  52. Again, note that [n] is renamed to [bar$1]. This is, however, not done during
  53. the desugaring phase, since the dimensions are not prevented from being
  54. evaluated more than once (See {!Desug} for an explanation about this).
  55. In the third step, all occurrences of external variables are replaced by
  56. function call to a getter or setter function. For example:
  57. {v /* extern int foo; */
  58. /* extern int [n] bar; */
  59. export void main() \{
  60. bar[foo] = n;
  61. \} v}
  62. becomes:
  63. {v export void main() \{
  64. bar$set(foo$get(), bar$1$get());
  65. \} v}
  66. *)
  67. (** Main phase function, called by \{!Main\}. *)
  68. val phase : Main.phase_func