util.mli 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. (** Utility functions used by multiple phases. *)
  2. (** {2 Generating variables} *)
  3. (** Generate a new variable from a given prefix, e.g. ["foo"] becomes ["foo$1"].
  4. Uses an [int] reference defined in the implementation file as a counter to
  5. assert uniqueness of the generated variable. *)
  6. val fresh_var : string -> string
  7. (** Generate a new constant (a variable that is known to be assigned only once
  8. in total) from a given prefix, e.g. ["foo"] becomes ["foo$$1"]. Uses the
  9. same counter as {!fresh_var}. *)
  10. val fresh_const : string -> string
  11. (** {2 AST traversal} *)
  12. (** Default transformation traversal for AST nodes of arbitrary constructor.
  13. For each constructor that has one or more children of type {!Types.node},
  14. the children are transformed with the given transformation function, and a
  15. new node is returned with the transformed children. For [Program] nodes,
  16. {!flatten_blocks} is called on the resulting declaration list. This allows
  17. the transformation function to return multiple nodes as a replacement, in
  18. the form of a [Block] node with multiple children. *)
  19. val transform_children : (Types.node -> Types.node) -> Types.node -> Types.node
  20. (** Flatten [Block] nodes into containing node lists.
  21. E.g., [[A; Block [B; Block [C; D]]; E] -> [A; B; C; D; E]].
  22. Traverses into elements of the list recursively first, so this is
  23. essentially a traversal, as can be seen in the example. Therefore the best
  24. practice is to call this function once on the children of a [Program] node
  25. after any traversal that may generate [Block] nodes that need to be
  26. flattened. *)
  27. val flatten_blocks : Types.node list -> Types.node list
  28. (** Extract the list of child nodes from a [Block] node. *)
  29. val block_body : Types.node -> Types.node list
  30. (** {2 AST node annotations} *)
  31. (** Add a single annotation to a node. *)
  32. val annotate : Types.annotation -> Types.node -> Types.node
  33. (** Extract annotations from a node of arbitrary constructor. *)
  34. val annof : Types.node -> Types.annotation list
  35. (** Get the value of the [Loc] annotation of a node, or {!noloc} if no location
  36. can be found. *)
  37. val locof : Types.node -> Types.location
  38. (** Empty node location: [("", 0, 0, 0, 0)]. Used then location of a node is
  39. unknown (if the annotation was removed at some point) or
  40. non-existant/irrelevant (for generated nodes on which no errors will occur --
  41. hopefully...). *)
  42. val noloc : Types.location
  43. (** Get the value of the [Depth] annotation of a node. Raises
  44. {!Types.InvalidNode} if the annotation can not be found. *)
  45. val depthof : Types.node -> int
  46. (** Get the value of the [Index] annotation of a node. Raises
  47. {!Types.InvalidNode} if the annotation can not be found. *)
  48. val indexof : Types.node -> int
  49. (** Get the value of the [Type] annotation of a node. Some node types
  50. do not need to be annotated since they have inherent types. For example, a
  51. [VarDec] node has a type attribute, and a [Dim] node is always an [Int]
  52. (because array dimensions are integers). All nodes which have inherent types
  53. are [VarDec], [Param], [FunDec], [FunDef], [GlobalDec], [GlobalDef],
  54. [TypeCast], and [Dim]. Raises a {!Types.InvalidNode} if the annotation can
  55. not be found, and the type has no inherent type. *)
  56. val typeof : Types.node -> Types.ctype
  57. (** Get the value of the [LabelName] annotation of a node. Raises
  58. {!Types.InvalidNode} if the annotation can not be found. *)
  59. val labelof : Types.node -> string
  60. (** Get the basic type of a declaration, removing array dimensions *)
  61. val basetypeof : Types.node -> Types.ctype
  62. (** Get the value of the name attribute from a variable or function declaration
  63. (similar to {!typeof} for nodes that have types attributes). Raises
  64. {!Types.InvalidNode} if the node is not one of [GlobalDec], [GlobalDef],
  65. [FunDec], [FunDef], [VarDec], [Param], or [Dim]. *)
  66. val nameof : Types.node -> string
  67. (** Get the CiviC data type of a constant value. *)
  68. val const_type : Types.const -> Types.ctype
  69. (** Check if a constant value is eligible for creating optimized assembly
  70. instructions. E.g. [Intval (-1)] is eligible because the instruction
  71. [iloadc_m1] exists. Used to decide on which {!Types.instr} constructor to
  72. use during the assembly phases. This function always returns [false] when
  73. optimizations are disabled (when {!Globals.args}[.optimize = false]). *)
  74. val is_immediate_const : Types.const -> bool
  75. (** Check if a node has an array type. I.e., [Array] or [ArrayDims]. *)
  76. val is_array : Types.node -> bool
  77. (** {2 Logging} *)
  78. (** Horizontal line of ['-'] characters, used to separate output sections. *)
  79. val hline : string
  80. (** Print the stringification of a node to [stderr] (uses
  81. {!Stringify.node2str}). *)
  82. val prt_node : Types.node -> unit
  83. (** Output a line to stderr if the verbosity level in {!Globals.args} is at
  84. least as high as the specified verbosity level. The line is indented with a
  85. number of spaces to match the longest phase identifier (so that logged lines
  86. align with ideitifiers logged by {!Main.main}). A newline is added
  87. automatically. *)
  88. val log_line : int -> string -> unit
  89. (** Print a line to [stderr] without indent (but do add a newline). *)
  90. val log_plain_line : int -> string -> unit
  91. (** Same as {!log_line}, but prints a node stringification instead of a literal
  92. string. *)
  93. val log_node : int -> Types.node -> unit
  94. (** Generate an Types.location tuple from Lexing data structures *)
  95. val loc_from_lexpos : Lexing.position -> Lexing.position -> Types.location
  96. (** Print location tuple to stderr. Produces
  97. something like the following: {v
  98. int foo;
  99. ^^^ v}
  100. The location tuple is likely to originate from a node annotation, extracted
  101. using {!locof}.*)
  102. val prerr_loc : Types.location -> unit
  103. (** Print location tuple to stderr, along with an error message. Produces
  104. something like the following: {v
  105. File "foo.cvc", line 10, characters 8-11:
  106. <message>
  107. int foo;
  108. ^^^ v} *)
  109. val prerr_loc_msg : Types.location -> string -> unit
  110. (** Print an error message for a node. Calls prerr_loc_msg. *)
  111. val node_error : Types.node -> string -> unit
  112. (** Print a warning message for a node. Calls prerr_loc_msg. *)
  113. val node_warning : Types.node -> string -> unit
  114. (** {2 String utitities} *)
  115. (** [repeat s n] returns a new string of [n] times [s]. *)
  116. val repeat : string -> int -> string
  117. (** [expand n s] adds spaces to [s] until the resulting string is at least [n]
  118. characters long. *)
  119. val expand : int -> string -> string
  120. (** {2 List utitities} *)
  121. (** [optmap f opt] maps [f] to the list value of [opt] if [opt] exists, and
  122. [None] otherwise. *)
  123. val optmap : ('a -> 'b) -> 'a list option -> 'b list option
  124. (** Same as {!optmap}, but returns the list value instead, or an empty list if
  125. [opt] is [None]. *)
  126. val optmapl : ('a -> 'b) -> 'a list option -> 'b list
  127. (** [List.mapi] clone (only available in OCaml version >= 4.00. Maps a function
  128. to a list like [List.map] does, but the iterator function is called with the
  129. element's index as an additional argument. *)
  130. val mapi : (int -> 'a -> 'b) -> 'a list -> 'b list