Parcourir la source

Documented all global modules (phases still need to be done)

Taddeus Kroes il y a 12 ans
Parent
commit
625095f367
7 fichiers modifiés avec 155 ajouts et 91 suppressions
  1. 2 3
      phases/print.ml
  2. 7 0
      phases/typecheck.ml
  3. 0 6
      stringify.ml
  4. 10 11
      stringify.mli
  5. 2 1
      types.mli
  6. 5 4
      util.ml
  7. 129 66
      util.mli

+ 2 - 3
phases/print.ml

@@ -1,6 +1,5 @@
 open Types
 open Util
-open Stringify
 
 let tab = "  "
 let max_instr_width = 26
@@ -65,7 +64,7 @@ let rec instr2str = function
   | Global ctype ->
     ".global " ^ (type2str ctype)
   | ConstDef value ->
-    ".const " ^ type2str (const_type value) ^ " " ^ const2str value
+    ".const " ^ type2str (const_type value) ^ " " ^ Stringify.const2str value
 
   (* Store *)
   | Store (ctype, scope, index) ->
@@ -162,7 +161,7 @@ let rec print_assembly oc instrs =
 let phase = function
   | Ast node as input ->
     prerr_endline hline;
-    prerr_endline (node2str node);
+    prerr_endline (Stringify.node2str node);
     prerr_endline hline;
     input
 

+ 7 - 0
phases/typecheck.ml

@@ -19,6 +19,13 @@ open Types
 open Util
 open Stringify
 
+(* Stringify a list of types for use in error messages.
+ * ctype list -> string *)
+let rec types2str = function
+  | [] -> ""
+  | [ctype] -> type2str ctype
+  | ctype :: tail -> type2str ctype ^ " or " ^ (types2str tail)
+
 let array_depth = function
   | ArrayDims (_, dims) -> List.length dims
   | _                   -> raise InvalidNode

+ 0 - 6
stringify.ml

@@ -166,9 +166,3 @@ and node2str node =
   | LocalFuns nodes -> concat "\n" nodes
 
   | DummyNode -> "<dummy>"
-
-(* ctype list -> string *)
-let rec types2str = function
-  | [] -> ""
-  | [ctype] -> type2str ctype
-  | ctype :: tail -> type2str ctype ^ " or " ^ (types2str tail)

+ 10 - 11
stringify.mli

@@ -1,16 +1,15 @@
 (** Stringification functions for AST elements. *)
 
-(**  *)
-val const2str : Types.const -> string
-
-(**  *)
-val op2str    : Types.operator -> string
+(** Stringify an AST node (e.g. ["int a;"] for a [VarDec] node).
+    [Block] node stringifications are multi-line, their contents are indented
+    with four spaces for each nesting level. *)
+val node2str : Types.node -> string
 
-(**  *)
-val node2str  : Types.node -> string
+(** Stringify a CiviC type (e.g. ["bool"] or ["int"]). *)
+val type2str : Types.ctype -> string
 
-(**  *)
-val type2str  : Types.ctype -> string
+(** Stringify a constant value (e.g. ["1"] or ["1.0"]). *)
+val const2str : Types.const -> string
 
-(**  *)
-val types2str : Types.ctype list -> string
+(** Stringify an operator (e.g. ["+"]). *)
+val op2str : Types.operator -> string

+ 2 - 1
types.mli

@@ -229,7 +229,8 @@ type args_record = {
 
 (** {2 Exceptions} *)
 
-(** Error occurred at a certain location in an input file. *)
+(** Error occurred at a certain location in an input file. Used in combination
+    with {!Util.prerr_loc} and {!Util.prerr_loc_msg}. *)
 exception LocError of location * string
 
 (** Error occurred at a certain AST node, to be transformed to {!LocError} using

+ 5 - 4
util.ml

@@ -13,12 +13,10 @@ let expand n text = text ^ repeat " " (n - String.length text)
 
 let hline = "-----------------------------------------------------------------"
 
-let prt_line = prerr_endline
-
-let prt_node node = prt_line (Stringify.node2str node)
+let prt_node node = prerr_endline (Stringify.node2str node)
 
 let log_plain_line verbosity line =
-  if Globals.args.verbose >= verbosity then prt_line line
+  if Globals.args.verbose >= verbosity then prerr_endline line
 
 let log_line verbosity line =
   log_plain_line verbosity (repeat " " 13 ^ line)
@@ -444,5 +442,8 @@ let is_array node = match typeof node with
   | ArrayDims _ | Array _ -> true
   | _ -> false
 
+let node_error node msg =
+  prerr_loc_msg (locof node) ("Error: " ^ msg)
+
 let node_warning node msg =
   prerr_loc_msg (locof node) ("Warning: " ^ msg)

+ 129 - 66
util.mli

@@ -1,106 +1,169 @@
 (** Utility functions used by multiple phases. *)
-(**
-Extended description...
-*)
 
-(**  *)
-val repeat : string -> int -> string
-
-(**  *)
-val expand : int -> string -> string
-
-(** Logging functions, they print to stderr and consider the verbosity flag *)
-val hline : string
-
-(**  *)
-val prt_line : string -> unit
-
-(**  *)
-val prt_node : Types.node -> unit
+(** {2 Generating variables} *)
 
-(**  *)
-val log_line : int -> string -> unit
-
-(**  *)
-val log_plain_line : int -> string -> unit
-
-(**  *)
-val log_node : int -> Types.node -> unit
-
-(** Generate a fresh variable from a given prefix, e.g. "foo" -> "foo$1"  *)
+(** Generate a new variable from a given prefix, e.g. ["foo"] becomes ["foo$1"].
+    Uses an [int] reference defined in the implementation file as a counter to
+    assert uniqueness of the generated variable. *)
 val fresh_var : string -> string
 
-(** Generate a fresg constant from a given prefix, e.g. "foo" -> "foo$$1"  *)
+(** Generate a new constant (a variable that is known to be assigned only once
+    in total) from a given prefix, e.g. ["foo"] becomes ["foo$$1"]. Uses the
+    same counter as {!fresh_var}. *)
 val fresh_const : string -> string
 
-(** Generate an Types.location tuple from Lexing data structures *)
-val loc_from_lexpos : Lexing.position -> Lexing.position -> Types.location
+(** {2 AST traversal} *)
 
-(** Default transformation traversal for AST nodes *)
+(** Default transformation traversal for AST nodes of arbitrary constructor.
+    For each constructor that has one or more children of type {!Types.node},
+    the children are transformed with the given transformation function, and a
+    new node is returned with the transformed children. For [Program] nodes,
+    {!flatten_blocks} is called on the resulting declaration list. This allows
+    the transformation function to return multiple nodes as a replacement, in
+    the form of a [Block] node with multiple children. *)
 val transform_children : (Types.node -> Types.node) -> Types.node -> Types.node
 
-(** Add a single annotation to a node (no traversal) *)
+(** Flatten [Block] nodes into containing node lists.
+    E.g., [[A; Block [B; Block [C; D]]; E] -> [A; B; C; D; E]].
+    Traverses into elements of the list recursively first, so this is
+    essentially a traversal, as can be seen in the example. Therefore the best
+    practice is to call this function once on the children of a [Program] node
+    after any traversal that may generate [Block] nodes that need to be
+    flattened. *)
+val flatten_blocks : Types.node list -> Types.node list
+
+(** Extract the list of child nodes from a [Block] node. *)
+val block_body : Types.node -> Types.node list
+
+(** {2 AST node annotations} *)
+
+(** Add a single annotation to a node. *)
 val annotate : Types.annotation -> Types.node -> Types.node
 
-(** Extract annotation from node *)
+(** Extract annotations from a node of arbitrary constructor. *)
 val annof : Types.node -> Types.annotation list
 
-(**  *)
+(** Get the value of the [Loc] annotation of a node, or {!noloc} if no location
+    can be found. *)
 val locof : Types.node -> Types.location
 
-(**  *)
+(** Empty node location: [("", 0, 0, 0, 0)]. Used then location of a node is
+    unknown (if the annotation was removed at some point) or
+    non-existant/irrelevant (for generated nodes on which no errors will occur --
+    hopefully...). *)
+val noloc : Types.location
+
+(** Get the value of the [Depth] annotation of a node. Raises
+    {!Types.InvalidNode} if the annotation can not be found. *)
 val depthof : Types.node -> int
 
-(**  *)
+(** Get the value of the [Index] annotation of a node. Raises
+    {!Types.InvalidNode} if the annotation can not be found. *)
 val indexof : Types.node -> int
 
-(**  *)
+(** Get the value of the [Type] annotation of a node. Some node types
+    do not need to be annotated since they have inherent types. For example, a
+    [VarDec] node has a type attribute, and a [Dim] node is always an [Int]
+    (because array dimensions are integers). All nodes which have inherent types
+    are [VarDec], [Param], [FunDec], [FunDef], [GlobalDec], [GlobalDef],
+    [TypeCast], and [Dim]. Raises a {!Types.InvalidNode} if the annotation can
+    not be found, and the type has no inherent type. *)
 val typeof : Types.node -> Types.ctype
 
-(**  *)
+(** Get the value of the [LabelName] annotation of a node. Raises
+    {!Types.InvalidNode} if the annotation can not be found. *)
 val labelof : Types.node -> string
 
-(**  *)
+(** Get the basic type of a declaration, removing array dimensions *)
+val basetypeof : Types.node -> Types.ctype
+
+(** Get the value of the name attribute from a variable or function declaration
+    (similar to {!typeof} for nodes that have types attributes). Raises
+    {!Types.InvalidNode} if the node is not one of [GlobalDec], [GlobalDef],
+    [FunDec], [FunDef], [VarDec], [Param], or [Dim]. *)
+val nameof : Types.node -> string
+
+(** Get the CiviC data type of a constant value. *)
 val const_type : Types.const -> Types.ctype
 
-(** Print file location to stderr *)
-val prerr_loc : Types.location -> unit
+(** Check if a constant value is eligible for creating optimized assembly
+    instructions. E.g. [Intval (-1)] is eligible because the instruction
+    [iloadc_m1] exists. Used to decide on which {!Types.instr} constructor to
+    use during the assembly phases. This function always returns [false] when
+    optimizations are disabled (when {!Globals.args}[.optimize = false]). *)
+val is_immediate_const : Types.const -> bool
 
-(** Print file location to stderr *)
-val prerr_loc_msg : Types.location -> string -> unit
+(** Check if a node has an array type. I.e., [Array] or [ArrayDims]. *)
+val is_array : Types.node -> bool
 
-(** Flatten Block nodes into the given array of nodes *)
-val flatten_blocks : Types.node list -> Types.node list
+(** {2 Logging} *)
 
-(** Extract the node list from a Block node *)
-val block_body : Types.node -> Types.node list
+(** Horizontal line of ['-'] characters, used to separate output sections. *)
+val hline : string
 
-(** Get the basic type of a declaration, removing array dimensions *)
-val basetypeof : Types.node -> Types.ctype
+(** Print the stringification of a node to [stderr] (uses
+    {!Stringify.node2str}). *)
+val prt_node : Types.node -> unit
 
-(** Get name from variable or function declaration *)
-val nameof : Types.node -> string
+(** Output a line to stderr if the verbosity level in {!Globals.args} is at
+    least as high as the specified verbosity level. The line is indented with a
+    number of spaces to match the longest phase identifier (so that logged lines
+    align with ideitifiers logged by {!Main.main}). A newline is added
+    automatically. *)
+val log_line : int -> string -> unit
 
-(**  *)
-val optmap : ('a -> 'b) -> 'a list option -> 'b list option
+(** Print a line to [stderr] without indent (but do add a newline). *)
+val log_plain_line : int -> string -> unit
 
-(**  *)
-val optmapl : ('a -> 'b) -> 'a list option -> 'b list
+(** Same as {!log_line}, but prints a node stringification instead of a literal
+    string. *)
+val log_node : int -> Types.node -> unit
 
-(** List.mapi clone (only available in OCaml version >= 4.00 *)
-val mapi : (int -> 'a -> 'b) -> 'a list -> 'b list
+(** Generate an Types.location tuple from Lexing data structures *)
+val loc_from_lexpos : Lexing.position -> Lexing.position -> Types.location
 
-(**  *)
-val is_immediate_const : Types.const -> bool
+(** Print location tuple to stderr. Produces
+    something like the following: {v
+int foo;
+    ^^^ v}
+    The location tuple is likely to originate from a node annotation, extracted
+    using {!locof}.*)
+val prerr_loc : Types.location -> unit
 
-(**  *)
-val is_array : Types.node -> bool
+(** Print location tuple to stderr, along with an error message. Produces
+    something like the following: {v
+File "foo.cvc", line 10, characters 8-11:
+<message>
+    int foo;
+        ^^^ v} *)
+val prerr_loc_msg : Types.location -> string -> unit
+
+(** Print an error message for a node. Calls prerr_loc_msg. *)
+val node_error : Types.node -> string -> unit
 
-(**  *)
+(** Print a warning message for a node. Calls prerr_loc_msg. *)
 val node_warning : Types.node -> string -> unit
 
-(**  *)
-val noloc : Types.location
+(** {2 String utitities} *)
+
+(** [repeat s n] returns a new string of [n] times [s]. *)
+val repeat : string -> int -> string
 
-(**  *)
-val immediate_consts : Types.const list
+(** [expand n s] adds spaces to [s] until the resulting string is at least [n]
+    characters long. *)
+val expand : int -> string -> string
+
+(** {2 List utitities} *)
+
+(** [optmap f opt] maps [f] to the list value of [opt] if [opt] exists, and
+    [None] otherwise. *)
+val optmap : ('a -> 'b) -> 'a list option -> 'b list option
+
+(** Same as {!optmap}, but returns the list value instead, or an empty list if
+    [opt] is [None]. *)
+val optmapl : ('a -> 'b) -> 'a list option -> 'b list
+
+(** [List.mapi] clone (only available in OCaml version >= 4.00. Maps a function
+    to a list like [List.map] does, but the iterator function is called with the
+    element's index as an additional argument. *)
+val mapi : (int -> 'a -> 'b) -> 'a list -> 'b list