diff --git a/README.md b/README.md index e226550..c78d55a 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ This library includes the following custom modules: - Bool (for basic operations on booleans) - Char (for basic operations on characters) +- Fatal (for throwing exceptions, and making assertions) - Float (for basic operations on floating point numbers) - Int (for basic operations on integers) - List (functional list data structure) @@ -23,19 +24,16 @@ This library includes the following custom modules: - Set (functional set implemented as a red-black tree) - Stack (functional stack data structure) - String (for basic operations on strings) +- Terminal (for terminal IO) - Tree (functional generic tree type with some general functions to manipulate it) ## Exposure of Functions from Standard Library -With respect to the exposed parts of the standard library, these are all handled in the `FromStdlib` module, which redefines some definitions directly from the standard library so that this file can be safely included separately, exposing only the desired functions. As such, it is recommended that this file is opened in the code that uses this library, while others are not, and referenced from the module level instead (with one additional exception of `Exposed`, mentioned in the following section). - -All files are compiled with `-nopervasives` except `FromStdlib` (to avoid the headaches in exposing functions like `printf` which have many dependencies). Linking is also done without `-nopervasives` so that `fromStdlib.cmx` can find the corresponding functions. - -Some functions exist in the `FromStdlib` module which have names starting with `stdlib`. These functions can be called directly, but it is generally recommended they are called from the corresponding module in the custom standard library. They exist in `FromStdlib` to be exposed more neatly elsewhere. +Some functions from the OCaml standard library are exposed through this library. They are handled by the `FromStdlib` module which SHOULD NOT be accessed directly in projects using this library. All functions and types from this module that are exposed to be used in projects are redefined in another module and should be accessed there. The reason for this module is to allow the rest of the modules to be compile with the `-nopervasives` flag yet still access a few of the official OCaml standard module functions. ## Type Declarations and General Functions -In order to prevent duplicate definitions of common types like collections, but still allow things like list literals to work, and to prevent the need of a type annotation at the module level, a `Exposed` module is provided to be opened in code files which exposes types like `'a queue` and other collections. `Exposed` also includes generic operators that should be opened file wide, such as function composition (`>>`). This should always be opened at the top of project files. +In order to prevent duplicate definitions of common types like collections, but still allow things like list literals to work, and to prevent the need of a type annotation at the module level, the `General` module is provided to be opened in code files which exposes types like `'a queue` and other collections. `General` also includes generic operators that should be opened file wide, such as function composition (`>>`). This should always be opened at the top of project files. ## Compiler Options @@ -51,7 +49,7 @@ In the root folder of this repository, a makefile is provided to be used for pro To create a new project, simply create the file you wish to add in the top level. For example, let's say we are creating a file called `main.ml`. -We first create the file in the root directory, and then change the build section of makefile from this: +We first create the file in the root directory, add the line `open General` to the top of the file, and then change the build section of makefile from this: ``` build: @@ -98,7 +96,7 @@ Just as with the project in the top level, file order should be consistent acros ## The Core Library -One of the unfortunate consequences of the way OCaml's compilation works, is that there is a library called the core library (not to be confused with Jane Street's Core), documented [here](https://ocaml.org/manual/core.html), which contains some definitions for types and exceptions, yet does not include the code from the stdlib that uses them. When compiling with the `-nopervasives` flag, this is still included but without the standard library. While this makes sense from the perspective of having some fundamental exceptions always available, having types like `list` included makes it very annoying when implemented a custom standard library. This quirk is why my library has no type definition for `list`, `bool`, `option`, etc. but still uses these types. +One of the unfortunate consequences of the way OCaml's compilation works, is that there is a library called the core library (not to be confused with Jane Street's Core), documented [here](https://ocaml.org/manual/core.html), which contains some definitions for types and exceptions, yet does not include the code from the stdlib that uses them. When compiling with the `-nopervasives` flag, this is still included but without the standard library. While this makes sense from the perspective of having some fundamental exceptions always available, having types like `list` included makes it very annoying when implemented a custom standard library (with the benefit of list literals still functioning properly). This quirk is why my library has no type definition for `list`, `bool`, `option`, etc. but still uses these types. ## Planned Changes @@ -107,7 +105,10 @@ The following modules are some that I plan on introducing in future iterations o - Array: for operations with mutable arrays. - Random: for random number generation. - File: for file IO. -- Input: for command line inputs and arguments. + +I also intend on modifying the following modules: + +- Terminal: this module still needs input functions. ## Tests diff --git a/lib/bool.ml b/lib/bool.ml index 7cb1cb5..786a257 100644 --- a/lib/bool.ml +++ b/lib/bool.ml @@ -1,3 +1,3 @@ -open FromStdlib open Exposed +open General -let of_string = stdlib_bool_of_string_opt +let of_string = FromStdlib.bool_of_string_opt diff --git a/lib/bool.mli b/lib/bool.mli index d5b194a..47f8ad0 100644 --- a/lib/bool.mli +++ b/lib/bool.mli @@ -1,2 +1,4 @@ +open General + (** Converts the string to a bool, returning option type to account for invalid strings. *) val of_string : string -> bool option \ No newline at end of file diff --git a/lib/char.ml b/lib/char.ml index b0a618c..058597e 100644 --- a/lib/char.ml +++ b/lib/char.ml @@ -1,3 +1,3 @@ -open FromStdlib open Exposed +open General -let of_int = stdlib_char_of_int \ No newline at end of file +let of_int = FromStdlib.char_of_int \ No newline at end of file diff --git a/lib/char.mli b/lib/char.mli index a9f79c3..31be230 100644 --- a/lib/char.mli +++ b/lib/char.mli @@ -1,2 +1,4 @@ +open General + (** Converts an int to a char. *) val of_int : int -> char \ No newline at end of file diff --git a/lib/exposed.ml b/lib/exposed.ml deleted file mode 100644 index 6996d6b..0000000 --- a/lib/exposed.ml +++ /dev/null @@ -1,20 +0,0 @@ -type 'a queue = { front : 'a list; back : 'a list } - -type 'a result = - | Error of string - | Success of 'a - -type 'a stack = - | Empty - | Stacked of 'a * 'a stack - -type 'a tree = - | Leaf - | Branch of 'a * 'a tree list - - -let id (x : 'a) = x - -let ( >> ) f g x = g (f x) - -let ( << ) g f x = g (f x) \ No newline at end of file diff --git a/lib/exposed.mli b/lib/exposed.mli deleted file mode 100644 index adaf392..0000000 --- a/lib/exposed.mli +++ /dev/null @@ -1,25 +0,0 @@ -(** Purely functional queue, implemented as a pair of lists. *) -type 'a queue = { front : 'a list; back : 'a list } - -type 'a result = - | Error of string - | Success of 'a - -(** Purely functional stack. *) -type 'a stack = - | Empty - | Stacked of 'a * 'a stack - -(* A purely functional tree with arbitrarily many branches at each node. *) -type 'a tree = - | Leaf - | Branch of 'a * 'a tree list - -(** Identity function. *) -val id : 'a -> 'a - -(** Function composition. (f >> g) x represents g (f x). *) -val ( >> ) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c - -(** Function composition. (f << g) x represents f (g x). *) -val ( << ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b \ No newline at end of file diff --git a/lib/fatal.ml b/lib/fatal.ml new file mode 100644 index 0000000..7638172 --- /dev/null +++ b/lib/fatal.ml @@ -0,0 +1,11 @@ +open General + +let failwith = FromStdlib.failwith + +let guarantee b = + if not b then + failwith "guarantee failed.\n" + +let guarantee_equal a b = + if a <> b then + failwith "guarantee_equal failed." \ No newline at end of file diff --git a/lib/fatal.mli b/lib/fatal.mli new file mode 100644 index 0000000..61f1c44 --- /dev/null +++ b/lib/fatal.mli @@ -0,0 +1,10 @@ +open General + +(** Throws an exception with a message. *) +val failwith : string -> 'a + +(** Throws an exception if the provided bool is not true. *) +val guarantee : bool -> unit + +(** Throws an exception if the provided arguments are not equal. *) +val guarantee_equal : 'a -> 'a -> unit \ No newline at end of file diff --git a/lib/float.ml b/lib/float.ml index 31fb776..3daa26b 100644 --- a/lib/float.ml +++ b/lib/float.ml @@ -1,11 +1,11 @@ -open FromStdlib open Exposed +open General -let ( + ) a b = stdlib_plus_float a b +let ( + ) a b = FromStdlib.plus_float a b -let ( - ) a b = stdlib_minus_float a b +let ( - ) a b = FromStdlib.minus_float a b -let ( * ) a b = stdlib_multiply_float a b +let ( * ) a b = FromStdlib.multiply_float a b -let ( / ) a b = stdlib_divide_float a b +let ( / ) a b = FromStdlib.divide_float a b -let of_string = stdlib_float_of_string_opt +let of_string = FromStdlib.float_of_string_opt diff --git a/lib/float.mli b/lib/float.mli index d4dd6c8..4262976 100644 --- a/lib/float.mli +++ b/lib/float.mli @@ -1,3 +1,5 @@ +open General + val ( + ) : float -> float -> float val ( - ) : float -> float -> float diff --git a/lib/fromStdlib.ml b/lib/fromStdlib.ml index a12441e..32c945b 100644 --- a/lib/fromStdlib.ml +++ b/lib/fromStdlib.ml @@ -1,37 +1,46 @@ (* https://github.com/ocaml/ocaml/blob/cce52acc7c7903e92078e9fe40745e11a1b944f0/stdlib/pervasives.ml *) +(* For fatal.ml *) let failwith = Stdlib.failwith + + +(* For terminal.ml *) let printf = Printf.printf - -external ( |> ) : 'a -> ('a -> 'b) -> 'b = "%revapply" -external ignore : 'a -> unit = "%ignore" +type 'a printf_format = ('a, out_channel, unit) format -external stdlib_int_of_char : char -> int = "%identity" -let stdlib_char_of_int = char_of_int -let stdlib_string_of_bool = string_of_bool -let stdlib_bool_of_string = bool_of_string -let stdlib_bool_of_string_opt = bool_of_string_opt -let stdlib_string_of_int = string_of_int -external stdlib_int_of_string : string -> int = "caml_int_of_string" -let stdlib_int_of_string_opt = int_of_string_opt -let stdlib_string_of_float = string_of_float -external stdlib_float_of_string : string -> float = "caml_float_of_string" -let stdlib_float_of_string_opt = float_of_string_opt +(* For int.ml *) +external int_of_char : char -> int = "%identity" +let int_of_string_opt = int_of_string_opt -external stdlib_plus_int : int -> int -> int = "%addint" -external stdlib_minus_int : int -> int -> int = "%subint" -external stdlib_multiply_int : int -> int -> int = "%mulint" -external stdlib_divide_int : int -> int -> int = "%divint" -external stdlib_mod_int : int -> int -> int = "%modint" +external plus_int : int -> int -> int = "%addint" +external minus_int : int -> int -> int = "%subint" +external multiply_int : int -> int -> int = "%mulint" +external divide_int : int -> int -> int = "%divint" +external mod_int : int -> int -> int = "%modint" -external stdlib_plus_float : float -> float -> float = "%addfloat" -external stdlib_minus_float : float -> float -> float = "%subfloat" -external stdlib_multiply_float : float -> float -> float = "%mulfloat" -external stdlib_divide_float : float -> float -> float = "%divfloat" -external stdlib_string_length : string -> int = "%string_length" +(* For float.ml *) +let float_of_string_opt = float_of_string_opt +external plus_float : float -> float -> float = "%addfloat" +external minus_float : float -> float -> float = "%subfloat" +external multiply_float : float -> float -> float = "%mulfloat" +external divide_float : float -> float -> float = "%divfloat" + + +(* For char.ml *) +let char_of_int = char_of_int + + +(* For string.ml *) +let string_of_bool = string_of_bool +let string_of_int = string_of_int +let string_of_float = string_of_float + +external string_length : string -> int = "%string_length" + + (* This block are not exposed *) external bytes_create : int -> bytes = "caml_create_bytes" external string_blit : string -> int -> bytes -> int -> int -> unit = "caml_blit_string" [@@noalloc] @@ -39,24 +48,32 @@ external bytes_blit : bytes -> int -> bytes -> int -> int -> unit = "caml_blit_bytes" [@@noalloc] external bytes_unsafe_to_string : bytes -> string = "%bytes_to_string" -let stdlib_string_concat s1 s2 = - let l1 = stdlib_string_length s1 and l2 = stdlib_string_length s2 in +let string_concat s1 s2 = + let l1 = string_length s1 and l2 = string_length s2 in let s = bytes_create (l1 + l2) in string_blit s1 0 s 0 l1; string_blit s2 0 s l1 l2; bytes_unsafe_to_string s -external ( = ) : 'a -> 'a -> bool = "%equal" -external ( <> ) : 'a -> 'a -> bool = "%notequal" -external ( < ) : 'a -> 'a -> bool = "%lessthan" -external ( > ) : 'a -> 'a -> bool = "%greaterthan" -external ( <= ) : 'a -> 'a -> bool = "%lessequal" -external ( >= ) : 'a -> 'a -> bool = "%greaterequal" +(* For bool.ml *) +let bool_of_string_opt = bool_of_string_opt + + +(* For general.ml *) +external equal : 'a -> 'a -> bool = "%equal" +external not_equal : 'a -> 'a -> bool = "%notequal" + +external less_than : 'a -> 'a -> bool = "%lessthan" +external greater_than : 'a -> 'a -> bool = "%greaterthan" +external less_than_or_equal : 'a -> 'a -> bool = "%lessequal" +external greater_than_or_equal : 'a -> 'a -> bool = "%greaterequal" external not : bool -> bool = "%boolnot" -external ( or ) : bool -> bool -> bool = "%sequor" -external ( & ) : bool -> bool -> bool = "%sequand" - +external or_ : bool -> bool -> bool = "%sequor" +external and_ : bool -> bool -> bool = "%sequand" + +external pipeline : 'a -> ('a -> 'b) -> 'b = "%revapply" +external ignore : 'a -> unit = "%ignore" diff --git a/lib/fromStdlib.mli b/lib/fromStdlib.mli index 5a1f941..3330076 100644 --- a/lib/fromStdlib.mli +++ b/lib/fromStdlib.mli @@ -1,43 +1,61 @@ +(* For fatal.ml *) val failwith : string -> 'a + + +(* For terminal.ml *) val printf : ('a, out_channel, unit) format -> 'a +type 'a printf_format = ('a, out_channel, unit) format -external ( |> ) : 'a -> ('a -> 'b) -> 'b = "%revapply" -external ignore : 'a -> unit = "%ignore" -external stdlib_int_of_char : char -> int = "%identity" -val stdlib_char_of_int : int -> char -val stdlib_string_of_bool : bool -> string -val stdlib_bool_of_string : string -> bool -val stdlib_bool_of_string_opt : string -> bool option -val stdlib_string_of_int : int -> string -external stdlib_int_of_string : string -> int = "caml_int_of_string" -val stdlib_int_of_string_opt : string -> int option -val stdlib_string_of_float : float -> string -external stdlib_float_of_string : string -> float = "caml_float_of_string" -val stdlib_float_of_string_opt : string -> float option +(* For int.ml *) +external int_of_char : char -> int = "%identity" +val int_of_string_opt : string -> int option -external stdlib_plus_int : int -> int -> int = "%addint" -external stdlib_minus_int : int -> int -> int = "%subint" -external stdlib_multiply_int : int -> int -> int = "%mulint" -external stdlib_divide_int : int -> int -> int = "%divint" -external stdlib_mod_int : int -> int -> int = "%modint" +external plus_int : int -> int -> int = "%addint" +external minus_int : int -> int -> int = "%subint" +external multiply_int : int -> int -> int = "%mulint" +external divide_int : int -> int -> int = "%divint" +external mod_int : int -> int -> int = "%modint" -external stdlib_plus_float : float -> float -> float = "%addfloat" -external stdlib_minus_float : float -> float -> float = "%subfloat" -external stdlib_multiply_float : float -> float -> float = "%mulfloat" -external stdlib_divide_float : float -> float -> float = "%divfloat" -external stdlib_string_length : string -> int = "%string_length" -val stdlib_string_concat : string -> string -> string +(* For float.ml *) +val float_of_string_opt : string -> float option -external ( = ) : 'a -> 'a -> bool = "%equal" -external ( <> ) : 'a -> 'a -> bool = "%notequal" +external plus_float : float -> float -> float = "%addfloat" +external minus_float : float -> float -> float = "%subfloat" +external multiply_float : float -> float -> float = "%mulfloat" +external divide_float : float -> float -> float = "%divfloat" -external ( < ) : 'a -> 'a -> bool = "%lessthan" -external ( > ) : 'a -> 'a -> bool = "%greaterthan" -external ( <= ) : 'a -> 'a -> bool = "%lessequal" -external ( >= ) : 'a -> 'a -> bool = "%greaterequal" + +(* For char.ml *) +val char_of_int : int -> char + + +(* For string.ml *) +val string_of_bool : bool -> string +val string_of_int : int -> string +val string_of_float : float -> string + +external string_length : string -> int = "%string_length" +val string_concat : string -> string -> string + + +(* For bool.ml *) +val bool_of_string_opt : string -> bool option + + +(* For general.ml *) +external equal : 'a -> 'a -> bool = "%equal" +external not_equal : 'a -> 'a -> bool = "%notequal" + +external less_than : 'a -> 'a -> bool = "%lessthan" +external greater_than : 'a -> 'a -> bool = "%greaterthan" +external less_than_or_equal : 'a -> 'a -> bool = "%lessequal" +external greater_than_or_equal : 'a -> 'a -> bool = "%greaterequal" external not : bool -> bool = "%boolnot" -external ( or ) : bool -> bool -> bool = "%sequor" -external ( & ) : bool -> bool -> bool = "%sequand" \ No newline at end of file +external or_ : bool -> bool -> bool = "%sequor" +external and_ : bool -> bool -> bool = "%sequand" + +external pipeline : 'a -> ('a -> 'b) -> 'b = "%revapply" +external ignore : 'a -> unit = "%ignore" \ No newline at end of file diff --git a/lib/general.ml b/lib/general.ml new file mode 100644 index 0000000..0eab9b9 --- /dev/null +++ b/lib/general.ml @@ -0,0 +1,42 @@ +type 'a queue = { front : 'a list; back : 'a list } + +type 'a result = + | Error of string + | Success of 'a + +type 'a stack = + | Empty + | Stacked of 'a * 'a stack + +type 'a tree = + | Leaf + | Branch of 'a * 'a tree list + +let ignore = FromStdlib.ignore + +let id (x : 'a) = x + +let ( >> ) f g x = g (f x) + +let ( << ) g f x = g (f x) + +let ( |> ) = FromStdlib.pipeline + +let ( = ) = FromStdlib.equal + +let ( <> ) = FromStdlib.not_equal + +let ( < ) = FromStdlib.less_than + +let ( > ) = FromStdlib.greater_than + +let ( <= ) = FromStdlib.less_than_or_equal + +let ( >= ) = FromStdlib.greater_than_or_equal + +let not = FromStdlib.not + +let ( or ) = FromStdlib.or_ + +let ( & ) = FromStdlib.and_ + diff --git a/lib/general.mli b/lib/general.mli new file mode 100644 index 0000000..e8d3bb1 --- /dev/null +++ b/lib/general.mli @@ -0,0 +1,58 @@ +(** Purely functional queue, implemented as a pair of lists. *) +type 'a queue = { front : 'a list; back : 'a list } + +type 'a result = + | Error of string + | Success of 'a + +(** Purely functional stack. *) +type 'a stack = + | Empty + | Stacked of 'a * 'a stack + +(* A purely functional tree with arbitrarily many branches at each node. *) +type 'a tree = + | Leaf + | Branch of 'a * 'a tree list + +(** Identity function. *) +val id : 'a -> 'a + +(** Suppresses compiler warnings for unassigned return value from function. *) +val ignore : 'a -> unit + +(** Function composition. (f >> g) x represents g (f x). *) +val ( >> ) : ('a -> 'b) -> ('b -> 'c) -> 'a -> 'c + +(** Function composition. (f << g) x represents f (g x). *) +val ( << ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b + +(** Pipeline operator, to reverse function application order. *) +val ( |> ) : 'a -> ('a -> 'b) -> 'b + +(** Checks for structural equality. *) +val ( = ) : 'a -> 'a -> bool + +(** Checks for structural inequality. *) +val ( <> ) : 'a -> 'a -> bool + +(** Polymorphic less than. *) +val ( < ) : 'a -> 'a -> bool + +(** Polymorphic greater than. *) +val ( > ) : 'a -> 'a -> bool + +(** Polymorphic less than or equal to. *) +val ( <= ) : 'a -> 'a -> bool + +(** Polymorphic greater than or equal to. *) +val ( >= ) : 'a -> 'a -> bool + +(** Logical negation. *) +val not : bool -> bool + +(** Logical or (infix). *) +val ( or ) : bool -> bool -> bool + +(** Logical and. *) +val ( & ) : bool -> bool -> bool \ No newline at end of file diff --git a/lib/int.ml b/lib/int.ml index 61ae6b6..aaafa99 100644 --- a/lib/int.ml +++ b/lib/int.ml @@ -1,16 +1,16 @@ -open FromStdlib +open General -let ( + ) a b = stdlib_plus_int a b +let ( + ) a b = FromStdlib.plus_int a b -let ( - ) a b = stdlib_minus_int a b +let ( - ) a b = FromStdlib.minus_int a b -let ( * ) a b = stdlib_multiply_int a b +let ( * ) a b = FromStdlib.multiply_int a b -let ( / ) a b = stdlib_divide_int a b +let ( / ) a b = FromStdlib.divide_int a b -let ( mod ) a b = stdlib_mod_int a b +let ( mod ) a b = FromStdlib.mod_int a b -let of_char = stdlib_int_of_char +let of_char = FromStdlib.int_of_char -let of_string = stdlib_int_of_string_opt +let of_string = FromStdlib.int_of_string_opt diff --git a/lib/int.mli b/lib/int.mli index 6586f06..049d886 100644 --- a/lib/int.mli +++ b/lib/int.mli @@ -1,3 +1,5 @@ +open General + val ( + ) : int -> int -> int val ( - ) : int -> int -> int diff --git a/lib/list.ml b/lib/list.ml index 884b2f4..c1bfefe 100644 --- a/lib/list.ml +++ b/lib/list.ml @@ -1,5 +1,4 @@ -open FromStdlib -open Exposed +open General let empty : 'a list = [] @@ -71,8 +70,8 @@ let rec zip2_rev_tr_helper (ls1 : 'a list) (ls2 : 'b list) (acc : ('a * 'b) list else if (first_head = None & second_head <> None) or (first_head <> None & second_head = None) then Error "The two lists must be of the same length." else - let a = match first_head with | Some x -> x | None -> failwith "if this exception is raised there is an error in the implementation of the function that called it" in - let b = match second_head with | Some x -> x | None -> failwith "if this exception is raised there is an error in the implementation of the function that called it" in + let a = match first_head with | Some x -> x | None -> Fatal.failwith "if this exception is raised there is an error in the implementation of the function that called it" in + let b = match second_head with | Some x -> x | None -> Fatal.failwith "if this exception is raised there is an error in the implementation of the function that called it" in zip2_rev_tr_helper (tail ls1) (tail ls2) ((a, b) :: acc) diff --git a/lib/list.mli b/lib/list.mli index 5716fdb..9305893 100644 --- a/lib/list.mli +++ b/lib/list.mli @@ -1,4 +1,4 @@ -open Exposed +open General (** The empty list *) val empty : 'a list diff --git a/lib/makefile b/lib/makefile index 892075f..02ff73b 100644 --- a/lib/makefile +++ b/lib/makefile @@ -6,10 +6,11 @@ build: # fromStdlib manages things that need to be exposed from the standard library ocamlopt $(STANDARD_FLAGS) -c fromStdlib.mli fromStdlib.ml - # exposed types and functions, that can be opened module wide - ocamlopt $(STANDARD_FLAGS) -nopervasives -c exposed.mli exposed.ml + # types and functions that should be opened module wide + ocamlopt $(STANDARD_FLAGS) -nopervasives -c general.mli general.ml # the following files make up the core custom standard library code + $(STANDARD_COMPILE) fatal.mli fatal.ml $(STANDARD_COMPILE) int.mli int.ml $(STANDARD_COMPILE) float.mli float.ml $(STANDARD_COMPILE) option.mli option.ml @@ -22,8 +23,9 @@ build: $(STANDARD_COMPILE) string.mli string.ml $(STANDARD_COMPILE) char.mli char.ml $(STANDARD_COMPILE) bool.mli bool.ml + $(STANDARD_COMPILE) terminal.mli terminal.ml - ocamlopt -a fromStdlib.cmx exposed.cmx int.cmx float.cmx option.cmx stack.cmx list.cmx map.cmx queue.cmx set.cmx tree.cmx string.cmx -o $(LIB_NAME).cmxa + ocamlopt -a fromStdlib.cmx general.cmx fatal.cmx int.cmx float.cmx option.cmx stack.cmx list.cmx map.cmx queue.cmx set.cmx tree.cmx string.cmx char.cmx bool.cmx terminal.cmx -o $(LIB_NAME).cmxa clean: rm -f *.o *.a *.s *.cmi *.cmx *.cmxa *.cmo *.cma diff --git a/lib/map.ml b/lib/map.ml index 55fa06d..b05e688 100644 --- a/lib/map.ml +++ b/lib/map.ml @@ -1,4 +1,4 @@ -open FromStdlib +open General module type Map = sig type key @@ -63,6 +63,6 @@ module RBTreeMap (M : MapSpecification) : Map with type key = M.key = struct let insert ((k, v) : (key * 'v)) map = match insert_helper (k, v) map with | Branch (_, (key, value), left, right) -> Branch (Black, (key, value), left, right) - | Leaf -> failwith "if this exception is raised there is an error in the implementation of the function that called it" + | Leaf -> Fatal.failwith "if this exception is raised there is an error in the implementation of the function that called it" end \ No newline at end of file diff --git a/lib/map.mli b/lib/map.mli index b6085c2..be0c228 100644 --- a/lib/map.mli +++ b/lib/map.mli @@ -1,3 +1,5 @@ +open General + module type Map = sig (** The type of keys in the map. *) type key diff --git a/lib/option.ml b/lib/option.ml index 8830bfd..67c7185 100644 --- a/lib/option.ml +++ b/lib/option.ml @@ -1,4 +1,4 @@ -open Exposed +open General let return (x : 'a) : 'a option = Some x diff --git a/lib/option.mli b/lib/option.mli index 546e4c7..07180ef 100644 --- a/lib/option.mli +++ b/lib/option.mli @@ -1,3 +1,5 @@ +open General + (* Monadic return for option type. Trivially boxes the variable of type 'a into a 'a option by applying the Some constructor. *) val return : 'a -> 'a option diff --git a/lib/queue.ml b/lib/queue.ml index 8b77e65..6e29156 100644 --- a/lib/queue.ml +++ b/lib/queue.ml @@ -1,5 +1,5 @@ +open General open List -open Exposed let enqueue (a : 'a) (qu : 'a queue) : 'a queue = { qu with front = a :: qu.back } diff --git a/lib/queue.mli b/lib/queue.mli index 4b7cd1c..700e66f 100644 --- a/lib/queue.mli +++ b/lib/queue.mli @@ -1,4 +1,4 @@ -open Exposed +open General (** Adds an element to the back of the queue, returning the new queue. Runs in O(1). *) val enqueue : 'a -> 'a queue -> 'a queue diff --git a/lib/set.ml b/lib/set.ml index 57ef253..94fbf06 100644 --- a/lib/set.ml +++ b/lib/set.ml @@ -1,4 +1,4 @@ -open FromStdlib +open General module type RBTreeSet = sig type member @@ -73,7 +73,7 @@ module RBTreeSet (M : SetSpecification) : RBTreeSet with type member = M.member let insert (v : member) (set : set) : set = match insert_helper v set with | Branch (_, value, left, right) -> Branch (Black, value, left, right) - | Leaf -> failwith "if this exception is raised there is an error in the implementation of the function that called it" + | Leaf -> Fatal.failwith "if this exception is raised there is an error in the implementation of the function that called it" let rec union set1 set2 = match set1 with diff --git a/lib/set.mli b/lib/set.mli index a27f150..8b38696 100644 --- a/lib/set.mli +++ b/lib/set.mli @@ -1,3 +1,5 @@ +open General + module type RBTreeSet = sig (** Type of members in the set. *) type member diff --git a/lib/stack.ml b/lib/stack.ml index 99d0ee2..65e9d28 100644 --- a/lib/stack.ml +++ b/lib/stack.ml @@ -1,4 +1,4 @@ -open FromStdlib open Exposed +open General let pop (st : 'a stack) : 'a option * 'a stack = match st with diff --git a/lib/stack.mli b/lib/stack.mli index a73fadc..a41bbe3 100644 --- a/lib/stack.mli +++ b/lib/stack.mli @@ -1,4 +1,4 @@ -open Exposed +open General (** Removes the top element from the stack, returning a tuple of the new stack, and None if the stack was empty, or Some [x] if [x] was on top of the stack. Popping an empty stack will result in the returned stack also being empty. Runs in O(1). *) val pop : 'a stack -> 'a option * 'a stack diff --git a/lib/string.ml b/lib/string.ml index 51eab7a..6358b69 100644 --- a/lib/string.ml +++ b/lib/string.ml @@ -1,11 +1,11 @@ -open FromStdlib open Exposed +open General -let ( + ) = stdlib_string_concat +let ( + ) = FromStdlib.string_concat -let length = stdlib_string_length +let length = FromStdlib.string_length -let of_int = stdlib_string_of_int +let of_int = FromStdlib.string_of_int -let of_float = stdlib_string_of_float +let of_float = FromStdlib.string_of_float -let of_bool = stdlib_string_of_bool \ No newline at end of file +let of_bool = FromStdlib.string_of_bool \ No newline at end of file diff --git a/lib/string.mli b/lib/string.mli index b6f69a6..b67f710 100644 --- a/lib/string.mli +++ b/lib/string.mli @@ -1,3 +1,5 @@ +open General + (** Concatenates two strings together in the provided order. *) val ( + ) : string -> string -> string diff --git a/lib/terminal.ml b/lib/terminal.ml new file mode 100644 index 0000000..170d98d --- /dev/null +++ b/lib/terminal.ml @@ -0,0 +1,6 @@ +open General + +let printf = FromStdlib.printf + + +let print s = printf "%s" s \ No newline at end of file diff --git a/lib/terminal.mli b/lib/terminal.mli new file mode 100644 index 0000000..6c0ef17 --- /dev/null +++ b/lib/terminal.mli @@ -0,0 +1,7 @@ +open General + +(** Formatted print to terminal. *) +val printf : 'a FromStdlib.printf_format -> 'a + +(** Prints the provided string to the terminal. *) +val print : string -> unit \ No newline at end of file diff --git a/lib/tree.ml b/lib/tree.ml index 45b9b65..11b248c 100644 --- a/lib/tree.ml +++ b/lib/tree.ml @@ -1,5 +1,4 @@ -open FromStdlib -open Exposed +open General let combine (tr1 : 'a tree) (tr2 : 'a tree) (topBranch : 'a) : 'a tree = Branch (topBranch, tr1 :: tr2 :: []) diff --git a/lib/tree.mli b/lib/tree.mli index 7c86b99..514f15e 100644 --- a/lib/tree.mli +++ b/lib/tree.mli @@ -1,4 +1,4 @@ -open Exposed +open General (* Combines two trees of the same type, with the specified value at the new top node. Runs in O(1). *) val combine : 'a tree -> 'a tree -> 'a -> 'a tree