new modules and neatened exposure of official stdlib code

This commit is contained in:
Aaron Manning 2022-02-04 14:06:51 +11:00 committed by aaron-jack-manning
parent e9368e17c1
commit e25b69bd44
41 changed files with 389 additions and 224 deletions

View File

@ -12,15 +12,18 @@ Also note that I use WSL for all OCaml programming, and this is my recommendatio
This library includes the following custom modules: This library includes the following custom modules:
- Array (for operations on mutable arrays)
- Bool (for basic operations on booleans) - Bool (for basic operations on booleans)
- Char (for basic operations on characters) - Char (for basic operations on characters)
- Fatal (for throwing exceptions, and making assertions) - Fatal (for throwing exceptions, and making assertions)
- File (for file IO)
- Float (for basic operations on floating point numbers) - Float (for basic operations on floating point numbers)
- Int (for basic operations on integers) - Int (for basic operations on integers)
- List (functional list data structure) - List (functional list data structure)
- Map (functional map implemented as a red-black tree) - Map (functional map implemented as a red-black tree)
- Option (functions for working with the option monad) - Option (functions for working with the option monad)
- Queue (functional queue implemented as two lists) - Queue (functional queue implemented as two lists)
- Random (for pseudorandom generation)
- Set (functional set implemented as a red-black tree) - Set (functional set implemented as a red-black tree)
- Stack (functional stack data structure) - Stack (functional stack data structure)
- String (for basic operations on strings) - String (for basic operations on strings)
@ -29,7 +32,7 @@ This library includes the following custom modules:
## Exposure of Functions from Standard Library ## Exposure of Functions from Standard Library
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. Some functions from the OCaml standard library are exposed through this library, for random number generation, file and terminal IO, and arrays. They are handled by direct reference to the `Stdlib` module and therefore all modules are compiled with the `-nopervasives` flag.
## Type Declarations and General Functions ## Type Declarations and General Functions
@ -89,7 +92,7 @@ $(STANDARD_COMPILE) newModule.mli newModule.ml
Then the final step within `build` also needs to be altered to include the corresponding `.cmx` file. Then the final step within `build` also needs to be altered to include the corresponding `.cmx` file.
``` ```
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 newModule.cmx -o $(LIB_NAME).cmxa ocamlopt -a exposed.cmx int.cmx float.cmx option.cmx stack.cmx list.cmx map.cmx queue.cmx set.cmx tree.cmx string.cmx newModule.cmx -o $(LIB_NAME).cmxa
``` ```
Just as with the project in the top level, file order should be consistent across compile lines and this final line. Just as with the project in the top level, file order should be consistent across compile lines and this final line.
@ -98,18 +101,8 @@ Just as with the project in the top level, file order should be consistent acros
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. 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 ## Planned Change;
The following modules are some that I plan on introducing in future iterations of this project: At some point I would like to remove all dependencies on the actual OCaml standard library by way of custom implementations for all the functions that currently reference the `Stdlib` module, and all external functions using code in the standard library.
- Array: for operations with mutable arrays.
- Random: for random number generation.
- File: for file IO.
I also intend on modifying the following modules:
- Terminal: this module still needs input functions.
## Tests
Unit tests are also planned for all collection modules, but have not been written yet. Unit tests are also planned for all collection modules, but have not been written yet.

50
lib/array.ml Normal file
View File

@ -0,0 +1,50 @@
open General
let of_list = Stdlib.Array.of_list
let length = Stdlib.Array.length
let concat = Stdlib.Array.concat
let append = Stdlib.Array.append
let get = Stdlib.Array.get
let set = Stdlib.Array.set
let map = Stdlib.Array.map
let create = Stdlib.Array.init
let heap_sort = Stdlib.Array.sort
let merge_sort = Stdlib.Array.stable_sort
let copy = Stdlib.Array.copy
let linear_search (arr : 'a array) (value : 'a) =
let i = ref 0 in
while (!i < length arr) & (get arr !i <> value) do
i := Int.(!i + 1)
done;
get arr !i
let rec binary_search_helper (arr : 'a array) (value : 'a) (first : int) (last : int) =
let midpoint = Int.((first + last) / 2) in
if midpoint < first or midpoint > last then
None
else if value < (get arr midpoint) then
binary_search_helper arr value first Int.(midpoint - 1)
else if (get arr midpoint) < value then
binary_search_helper arr value Int.(midpoint + 1) last
else if get arr midpoint = value then
Some (get arr midpoint)
else
None
let binary_search (arr : 'a array) (value : 'a) =
binary_search_helper arr value 0 Int.(length arr - 1)

28
lib/array.mli Normal file
View File

@ -0,0 +1,28 @@
open General
val of_list : 'a list -> 'a array
val length : 'a array -> int
val concat : 'a array list -> 'a array
val append : 'a array -> 'a array -> 'a array
val get : 'a array -> int -> 'a
val set : 'a array -> int -> 'a -> unit
val map : ('a -> 'b) -> 'a array -> 'b array
val create : int -> (int -> 'a) -> 'a array
val heap_sort : ('a -> 'a -> int) -> 'a array -> unit
val merge_sort : ('a -> 'a -> int) -> 'a array -> unit
val copy : 'a array -> 'a array
val linear_search : 'a array -> 'a -> 'a
val binary_search : 'a array -> 'a -> 'a option

View File

@ -1,3 +1,7 @@
open General open General
let of_string = FromStdlib.bool_of_string_opt
let of_string = function
| "true" -> Some true
| "false" -> Some false
| _ -> None

View File

@ -1,4 +1,5 @@
open General open General
(** Converts the string to a bool, returning option type to account for invalid strings. *) (** Converts the string to a bool, returning option type to account for invalid strings. *)
val of_string : string -> bool option val of_string : string -> bool option

View File

@ -1,3 +1,11 @@
open General open General
let of_int = FromStdlib.char_of_int
external unsafe_char_of_int : int -> char = "%identity"
let of_int n =
if n < 0 or n > 255 then
None
else
Some (unsafe_char_of_int n)

View File

@ -1,4 +1,5 @@
open General open General
(** Converts an int to a char. *) (** Converts an int to a char. *)
val of_int : int -> char val of_int : int -> char option

View File

@ -1,6 +1,10 @@
open General open General
let failwith = FromStdlib.failwith
external raise : exn -> 'a = "%raise"
let failwith m = raise (Failure m)
let guarantee b = let guarantee b =
if not b then if not b then
@ -8,4 +12,7 @@ let guarantee b =
let guarantee_equal a b = let guarantee_equal a b =
if a <> b then if a <> b then
failwith "guarantee_equal failed." failwith "guarantee_equal failed."

View File

@ -1,5 +1,6 @@
open General open General
(** Throws an exception with a message. *) (** Throws an exception with a message. *)
val failwith : string -> 'a val failwith : string -> 'a

29
lib/file.ml Normal file
View File

@ -0,0 +1,29 @@
open General
let open_out = Stdlib.open_out
let close_out = Stdlib.close_out
let printf = Stdlib.Printf.fprintf
let write_all_text filepath text =
let channel = open_out filepath in
let _ = printf channel "%s" text in
let _ = close_out channel in
()
let open_in = Stdlib.open_in
let close_in = Stdlib.close_in
let read_n_chars = Stdlib.really_input_string
let in_channel_length = Stdlib.in_channel_length
let read_all_text filepath =
let channel = open_in filepath in
let contents = read_n_chars channel (in_channel_length channel) in
let _ = close_in channel in
contents

26
lib/file.mli Normal file
View File

@ -0,0 +1,26 @@
open General
(** Opens and returns an output channel at the specified path. *)
val open_out : string -> Stdlib.out_channel
(** Closes the provided output channel. *)
val close_out : Stdlib.out_channel -> unit
(** Formatted printing to a provided output channel. *)
val printf : Stdlib.out_channel -> ('a, Stdlib.out_channel, unit) Stdlib.format -> 'a
(** Writes the given string to a file at the specified filepath. *)
val write_all_text : string -> string -> unit
(** Opens and returns an input channel at the specified path. *)
val open_in : string -> Stdlib.in_channel
(** Closes the provided input channel. *)
val close_in : Stdlib.in_channel -> unit
(** Reads the specified number of characters from the provided input channel as a string. *)
val read_n_chars : Stdlib.in_channel -> int -> string
(** Reads from the specified file as a string. *)
val read_all_text : string -> string

View File

@ -1,11 +1,22 @@
open General open General
let ( + ) a b = FromStdlib.plus_float a b
let ( - ) a b = FromStdlib.minus_float a b external ( + ) : float -> float -> float = "%addfloat"
let ( * ) a b = FromStdlib.multiply_float a b external ( - ) : float -> float -> float = "%subfloat"
let ( / ) a b = FromStdlib.divide_float a b external ( * ) : float -> float -> float = "%mulfloat"
let of_string = FromStdlib.float_of_string_opt external ( / ) : float -> float -> float = "%divfloat"
external float_of_string : string -> float = "caml_float_of_string"
let of_string s =
try
Some (float_of_string s)
with
Failure _ -> None
external of_int : int -> float = "%floatofint"

View File

@ -1,12 +1,16 @@
open General open General
val ( + ) : float -> float -> float
val ( - ) : float -> float -> float external ( + ) : float -> float -> float = "%addfloat"
val ( * ) : float -> float -> float external ( - ) : float -> float -> float = "%subfloat"
val ( / ) : float -> float -> float external ( * ) : float -> float -> float = "%mulfloat"
external ( / ) : float -> float -> float = "%divfloat"
(** Converts the string to a float, returning option type to account for invalid strings. *) (** Converts the string to a float, returning option type to account for invalid strings. *)
val of_string : string -> float option val of_string : string -> float option
(** Converts the int to a float. *)
val of_int : int -> float

View File

@ -1,79 +0,0 @@
(* https://github.com/ocaml/ocaml/blob/cce52acc7c7903e92078e9fe40745e11a1b944f0/stdlib/pervasives.ml *)
(* For fatal.ml *)
let failwith = Stdlib.failwith
(* For terminal.ml *)
let printf = Printf.printf
type 'a printf_format = ('a, out_channel, unit) format
(* For int.ml *)
external int_of_char : char -> int = "%identity"
let int_of_string_opt = int_of_string_opt
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"
(* 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]
external bytes_blit : bytes -> int -> bytes -> int -> int -> unit
= "caml_blit_bytes" [@@noalloc]
external bytes_unsafe_to_string : bytes -> string = "%bytes_to_string"
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
(* 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 and_ : bool -> bool -> bool = "%sequand"
external pipeline : 'a -> ('a -> 'b) -> 'b = "%revapply"
external ignore : 'a -> unit = "%ignore"

View File

@ -1,61 +0,0 @@
(* 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
(* For int.ml *)
external int_of_char : char -> int = "%identity"
val int_of_string_opt : string -> int option
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"
(* For float.ml *)
val float_of_string_opt : string -> float option
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 *)
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 and_ : bool -> bool -> bool = "%sequand"
external pipeline : 'a -> ('a -> 'b) -> 'b = "%revapply"
external ignore : 'a -> unit = "%ignore"

View File

@ -12,7 +12,7 @@ type 'a tree =
| Leaf | Leaf
| Branch of 'a * 'a tree list | Branch of 'a * 'a tree list
let ignore = FromStdlib.ignore let ignore (a : 'a) = ()
let id (x : 'a) = x let id (x : 'a) = x
@ -20,23 +20,38 @@ let ( >> ) f g x = g (f x)
let ( << ) g f x = g (f x) let ( << ) g f x = g (f x)
let ( |> ) = FromStdlib.pipeline let ( |> ) f g = g f
let ( = ) = FromStdlib.equal external ( = ) : 'a -> 'a -> bool = "%equal"
let ( <> ) = FromStdlib.not_equal external ( <> ) : 'a -> 'a -> bool = "%notequal"
let ( < ) = FromStdlib.less_than external ( < ) : 'a -> 'a -> bool = "%lessthan"
let ( > ) = FromStdlib.greater_than external ( > ) : 'a -> 'a -> bool = "%greaterthan"
let ( <= ) = FromStdlib.less_than_or_equal external ( <= ) : 'a -> 'a -> bool = "%lessequal"
let ( >= ) = FromStdlib.greater_than_or_equal external ( >= ) : 'a -> 'a -> bool = "%greaterequal"
let not = FromStdlib.not let not = function
| true -> false
| false -> true
let ( or ) = FromStdlib.or_ external ( or ) : bool -> bool -> bool = "%sequor"
external ( & ) : bool -> bool -> bool = "%sequand"
type 'a ref =
{ mutable contents : 'a }
let ref a =
{ contents = a }
let ( := ) (cell : 'a ref) (contents : 'a) =
cell.contents <- contents
let ( ! ) (cell : 'a ref) =
cell.contents
let ( & ) = FromStdlib.and_

View File

@ -1,6 +1,7 @@
(** Purely functional queue, implemented as a pair of lists. *) (** Purely functional queue, implemented as a pair of lists. *)
type 'a queue = { front : 'a list; back : 'a list } type 'a queue = { front : 'a list; back : 'a list }
(** Result type for error handling. *)
type 'a result = type 'a result =
| Error of string | Error of string
| Success of 'a | Success of 'a
@ -10,7 +11,7 @@ type 'a stack =
| Empty | Empty
| Stacked of 'a * 'a stack | Stacked of 'a * 'a stack
(* A purely functional tree with arbitrarily many branches at each node. *) (**A purely functional tree with arbitrarily many branches at each node. *)
type 'a tree = type 'a tree =
| Leaf | Leaf
| Branch of 'a * 'a tree list | Branch of 'a * 'a tree list
@ -31,28 +32,40 @@ val ( << ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
val ( |> ) : 'a -> ('a -> 'b) -> 'b val ( |> ) : 'a -> ('a -> 'b) -> 'b
(** Checks for structural equality. *) (** Checks for structural equality. *)
val ( = ) : 'a -> 'a -> bool external ( = ) : 'a -> 'a -> bool = "%equal"
(** Checks for structural inequality. *) (** Checks for structural inequality. *)
val ( <> ) : 'a -> 'a -> bool external ( <> ) : 'a -> 'a -> bool = "%notequal"
(** Polymorphic less than. *) (** Polymorphic less than. *)
val ( < ) : 'a -> 'a -> bool external ( < ) : 'a -> 'a -> bool = "%lessthan"
(** Polymorphic greater than. *) (** Polymorphic greater than. *)
val ( > ) : 'a -> 'a -> bool external ( > ) : 'a -> 'a -> bool = "%greaterthan"
(** Polymorphic less than or equal to. *) (** Polymorphic less than or equal to. *)
val ( <= ) : 'a -> 'a -> bool external ( <= ) : 'a -> 'a -> bool = "%lessequal"
(** Polymorphic greater than or equal to. *) (** Polymorphic greater than or equal to. *)
val ( >= ) : 'a -> 'a -> bool external ( >= ) : 'a -> 'a -> bool = "%greaterequal"
(** Logical negation. *) (** Logical negation. *)
val not : bool -> bool val not : bool -> bool
(** Logical or (infix). *) (** Logical or (infix). *)
val ( or ) : bool -> bool -> bool external ( or ) : bool -> bool -> bool = "%sequor"
(** Logical and. *) (** Logical and. *)
val ( & ) : bool -> bool -> bool external ( & ) : bool -> bool -> bool = "%sequand"
(** Reference cells for mutable variables. *)
type 'a ref = { mutable contents : 'a; }
(** Creates a reference cell. *)
val ref : 'a -> 'a ref
(** Updates a reference cell. *)
val ( := ) : 'a ref -> 'a -> unit
(** Returns the contents of a reference cell. *)
val ( ! ) : 'a ref -> 'a

View File

@ -1,16 +1,26 @@
open General open General
let ( + ) a b = FromStdlib.plus_int a b
let ( - ) a b = FromStdlib.minus_int a b external ( + ) : int -> int -> int = "%addint"
let ( * ) a b = FromStdlib.multiply_int a b external ( - ) : int -> int -> int = "%subint"
let ( / ) a b = FromStdlib.divide_int a b external ( * ) : int -> int -> int = "%mulint"
let ( mod ) a b = FromStdlib.mod_int a b external ( / ) : int -> int -> int = "%divint"
external ( mod ) : int -> int -> int = "%modint"
external of_char : char -> int = "%identity"
external int_of_string : string -> int = "caml_int_of_string"
let of_string s =
try
Some (int_of_string s)
with
| Failure _ -> None
let of_char = FromStdlib.int_of_char
let of_string = FromStdlib.int_of_string_opt

View File

@ -1,17 +1,18 @@
open General open General
val ( + ) : int -> int -> int
val ( - ) : int -> int -> int external ( + ) : int -> int -> int = "%addint"
val ( * ) : int -> int -> int external ( - ) : int -> int -> int = "%subint"
val ( / ) : int -> int -> int external ( * ) : int -> int -> int = "%mulint"
val ( mod ) : int -> int -> int external ( / ) : int -> int -> int = "%divint"
external ( mod ) : int -> int -> int = "%modint"
(** Converts the char to an int. *) (** Converts the char to an int. *)
val of_char : char -> int external of_char : char -> int = "%identity"
(** Converts the string to an int, returning option type to account for invalid strings. *) (** Converts the string to an int, returning option type to account for invalid strings. *)
val of_string : string -> int option val of_string : string -> int option

View File

@ -1,7 +1,15 @@
open General open General
let empty : 'a list = [] let empty : 'a list = []
let rec length_helper (list : 'a list) (length : int) =
match list with
| [] -> length
| _ :: xs -> length_helper xs Int.(length + 1)
let length (list : 'a list) = length_helper list 0
let head (ls : 'a list) : 'a option = let head (ls : 'a list) : 'a option =
match ls with match ls with
| x :: xs -> Some x | x :: xs -> Some x
@ -142,4 +150,7 @@ let rec initialize_helper (f : int -> 'a) (length : int) (index : int) (acc : 'a
initialize_helper f length Int.(index + 1) ((f index) :: acc) initialize_helper f length Int.(index + 1) ((f index) :: acc)
let initialize (f : int -> 'a) (length : int) : 'a list = let initialize (f : int -> 'a) (length : int) : 'a list =
initialize_helper f length 0 [] initialize_helper f length 0 []
let of_array =
Stdlib.Array.to_list

View File

@ -1,8 +1,12 @@
open General open General
(** The empty list *) (** The empty list *)
val empty : 'a list val empty : 'a list
(** Calculates the length of the given list. Runs in O(n) and should be stored rather then recalculated if many calls are made on an unchanging list. *)
val length : 'a list -> int
(** Returns Some [x] if [x] is the head of the list, or None for the empty list. Runs in O(1). *) (** Returns Some [x] if [x] is the head of the list, or None for the empty list. Runs in O(1). *)
val head : 'a list -> 'a option val head : 'a list -> 'a option
@ -55,4 +59,7 @@ val filter_rev_tr : ('a -> bool) -> 'a list -> 'a list
val find : ('a -> bool) -> 'a list -> ('a * int) option val find : ('a -> bool) -> 'a list -> ('a * int) option
(** Initializes a list using a length and a function from the index to the desired list value. Runs in O(n). *) (** Initializes a list using a length and a function from the index to the desired list value. Runs in O(n). *)
val initialize : (int -> 'a) -> int -> 'a list val initialize : (int -> 'a) -> int -> 'a list
(* Creates a list from the provided array. *)
val of_array : 'a array -> 'a list

View File

@ -3,13 +3,10 @@ STANDARD_COMPILE = ocamlopt $(STANDARD_FLAGS) -nopervasives -c
LIB_NAME = library LIB_NAME = library
build: build:
# fromStdlib manages things that need to be exposed from the standard library make clean
ocamlopt $(STANDARD_FLAGS) -c fromStdlib.mli fromStdlib.ml
# types and functions that should be opened module wide
ocamlopt $(STANDARD_FLAGS) -nopervasives -c general.mli general.ml 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) fatal.mli fatal.ml
$(STANDARD_COMPILE) int.mli int.ml $(STANDARD_COMPILE) int.mli int.ml
$(STANDARD_COMPILE) float.mli float.ml $(STANDARD_COMPILE) float.mli float.ml
@ -24,9 +21,11 @@ build:
$(STANDARD_COMPILE) char.mli char.ml $(STANDARD_COMPILE) char.mli char.ml
$(STANDARD_COMPILE) bool.mli bool.ml $(STANDARD_COMPILE) bool.mli bool.ml
$(STANDARD_COMPILE) terminal.mli terminal.ml $(STANDARD_COMPILE) terminal.mli terminal.ml
$(STANDARD_COMPILE) file.mli file.ml
$(STANDARD_COMPILE) array.mli array.ml
$(STANDARD_COMPILE) random.mli random.ml
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 ocamlopt -a 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 file.cmx array.cmx random.cmx -o $(LIB_NAME).cmxa
clean: clean:
rm -f *.o *.a *.s *.cmi *.cmx *.cmxa *.cmo *.cma rm -f *.o *.a *.s *.cmi *.cmx *.cmxa *.cmo *.cma

View File

@ -1,5 +1,6 @@
open General open General
module type Map = sig module type Map = sig
type key type key

View File

@ -1,5 +1,6 @@
open General open General
module type Map = sig module type Map = sig
(** The type of keys in the map. *) (** The type of keys in the map. *)
type key type key

View File

@ -1,5 +1,6 @@
open General open General
let return (x : 'a) : 'a option = Some x let return (x : 'a) : 'a option = Some x
let ( ~= ) = return let ( ~= ) = return

View File

@ -1,5 +1,6 @@
open General open General
(* Monadic return for option type. Trivially boxes the variable of type 'a into a 'a option by applying the Some constructor. *) (* 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 val return : 'a -> 'a option

View File

@ -1,6 +1,8 @@
open General open General
open List open List
let enqueue (a : 'a) (qu : 'a queue) : 'a queue = let enqueue (a : 'a) (qu : 'a queue) : 'a queue =
{ qu with front = a :: qu.back } { qu with front = a :: qu.back }

View File

@ -1,5 +1,6 @@
open General open General
(** Adds an element to the back of the queue, returning the new queue. Runs in O(1). *) (** Adds an element to the back of the queue, returning the new queue. Runs in O(1). *)
val enqueue : 'a -> 'a queue -> 'a queue val enqueue : 'a -> 'a queue -> 'a queue

17
lib/random.ml Normal file
View File

@ -0,0 +1,17 @@
open General
let init = Stdlib.Random.self_init
let integer low high =
init ();
Int.((Stdlib.Random.int (high - low)) + low)
let float low high =
init ();
Float.((Stdlib.Random.float (high - low)) + low)
let boolean =
init ();
Stdlib.Random.bool

11
lib/random.mli Normal file
View File

@ -0,0 +1,11 @@
open General
(** Generates a random integer between low (inclusive) and high (exclusive). *)
val integer : int -> int -> int
(** Generates a random float between low (inclusive) and high (exclusive). *)
val float : float -> float -> float
(** Generates a random boolean at even odds. *)
val boolean : unit -> bool

View File

@ -1,5 +1,6 @@
open General open General
module type RBTreeSet = sig module type RBTreeSet = sig
type member type member

View File

@ -1,5 +1,6 @@
open General open General
module type RBTreeSet = sig module type RBTreeSet = sig
(** Type of members in the set. *) (** Type of members in the set. *)
type member type member

View File

@ -1,5 +1,6 @@
open General open General
let pop (st : 'a stack) : 'a option * 'a stack = let pop (st : 'a stack) : 'a option * 'a stack =
match st with match st with
| Empty -> (None, Empty) | Empty -> (None, Empty)

View File

@ -1,5 +1,6 @@
open General 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). *) (** 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 val pop : 'a stack -> 'a option * 'a stack

View File

@ -1,11 +1,49 @@
open General open General
let ( + ) = FromStdlib.string_concat
let length = FromStdlib.string_length external bytes_create : int -> bytes = "caml_create_bytes"
external string_blit : string -> int -> bytes -> int -> int -> unit = "caml_blit_string" [@@noalloc]
external bytes_blit : bytes -> int -> bytes -> int -> int -> unit = "caml_blit_bytes" [@@noalloc]
external bytes_unsafe_to_string : bytes -> string = "%bytes_to_string"
external format_int : string -> int -> string = "caml_format_int"
external format_float : string -> float -> string = "caml_format_float"
let of_int = FromStdlib.string_of_int
let of_float = FromStdlib.string_of_float external length : string -> int = "%string_length"
let of_bool = FromStdlib.string_of_bool let of_int n =
format_int "%d" n
let of_bool bool =
if bool then
"true"
else
"false"
let ( + ) s1 s2 =
let l1 = length s1 in
let l2 = length s2 in
let s = bytes_create Int.(l1 + l2) in
string_blit s1 0 s 0 l1;
string_blit s2 0 s l1 l2;
bytes_unsafe_to_string s
external string_get : string -> int -> char = "%string_safe_get"
let valid_float_lexem s =
let l = length s in
let rec loop i =
if i >= l then s + "." else
match string_get s i with
| '0' .. '9' | '-' -> loop Int.(i + 1)
| _ -> s
in
loop 0
let of_float f =
valid_float_lexem (format_float "%.12g" f)

View File

@ -1,10 +1,8 @@
open General open General
(** Concatenates two strings together in the provided order. *)
val ( + ) : string -> string -> string
(** Calculates the length of the provided string. *) (** Calculates the length of the provided string. *)
val length : string -> int external length : string -> int = "%string_length"
(** Converts an int to a string. *) (** Converts an int to a string. *)
val of_int : int -> string val of_int : int -> string
@ -14,3 +12,6 @@ val of_float : float -> string
(** Converts a boolean to a string. *) (** Converts a boolean to a string. *)
val of_bool : bool -> string val of_bool : bool -> string
(** Concatenates two strings together in the provided order. *)
val ( + ) : string -> string -> string

View File

@ -1,6 +1,8 @@
open General open General
let printf = FromStdlib.printf
let printf = Stdlib.Printf.printf
let print s = printf "%s" s let print s = printf "%s" s
let read_line = Stdlib.read_line

View File

@ -1,7 +1,11 @@
open General open General
(** Formatted print to terminal. *) (** Formatted print to terminal. *)
val printf : 'a FromStdlib.printf_format -> 'a val printf : ('a, Stdlib.out_channel, unit) Stdlib.format -> 'a
(** Prints the provided string to the terminal. *) (** Prints the provided string to the terminal. *)
val print : string -> unit val print : string -> unit
(** Reads an input line from the terminal. *)
val read_line : unit -> string

View File

@ -1,5 +1,6 @@
open General open General
let combine (tr1 : 'a tree) (tr2 : 'a tree) (topBranch : 'a) : 'a tree = let combine (tr1 : 'a tree) (tr2 : 'a tree) (topBranch : 'a) : 'a tree =
Branch (topBranch, tr1 :: tr2 :: []) Branch (topBranch, tr1 :: tr2 :: [])

View File

@ -1,5 +1,6 @@
open General open General
(* Combines two trees of the same type, with the specified value at the new top node. Runs in O(1). *) (* 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 val combine : 'a tree -> 'a tree -> 'a -> 'a tree

View File

@ -5,10 +5,10 @@ build:
ocamlopt $(CUSTOM_LIBRARY_LOCATION)/library.cmxa -o program ocamlopt $(CUSTOM_LIBRARY_LOCATION)/library.cmxa -o program
mostlyclean: mostlyclean:
rm -f *.o *.a *.s *.cmi *.cmx *.cmxa *.cmo *.cma main.mli rm -f *.o *.a *.s *.cmi *.cmx *.cmxa *.cmo *.cma
clean: clean:
rm -f *.o *.a *.s *.cmi *.cmx *.cmxa *.cmo *.cma main.mli program rm -f *.o *.a *.s *.cmi *.cmx *.cmxa *.cmo *.cma program
make install: make install:
make build make build