new modules and neatened exposure of official stdlib code
This commit is contained in:
parent
e9368e17c1
commit
e25b69bd44
21
README.md
21
README.md
@ -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:
|
||||
|
||||
- Array (for operations on mutable arrays)
|
||||
- Bool (for basic operations on booleans)
|
||||
- Char (for basic operations on characters)
|
||||
- Fatal (for throwing exceptions, and making assertions)
|
||||
- File (for file IO)
|
||||
- Float (for basic operations on floating point numbers)
|
||||
- Int (for basic operations on integers)
|
||||
- List (functional list data structure)
|
||||
- Map (functional map implemented as a red-black tree)
|
||||
- Option (functions for working with the option monad)
|
||||
- Queue (functional queue implemented as two lists)
|
||||
- Random (for pseudorandom generation)
|
||||
- Set (functional set implemented as a red-black tree)
|
||||
- Stack (functional stack data structure)
|
||||
- String (for basic operations on strings)
|
||||
@ -29,7 +32,7 @@ This library includes the following custom modules:
|
||||
|
||||
## 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
|
||||
|
||||
@ -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.
|
||||
|
||||
```
|
||||
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.
|
||||
@ -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.
|
||||
|
||||
## Planned Changes
|
||||
## Planned Change;
|
||||
|
||||
The following modules are some that I plan on introducing in future iterations of this project:
|
||||
|
||||
- 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
|
||||
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.
|
||||
|
||||
Unit tests are also planned for all collection modules, but have not been written yet.
|
50
lib/array.ml
Normal file
50
lib/array.ml
Normal 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
28
lib/array.mli
Normal 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
|
@ -1,3 +1,7 @@
|
||||
open General
|
||||
|
||||
let of_string = FromStdlib.bool_of_string_opt
|
||||
|
||||
let of_string = function
|
||||
| "true" -> Some true
|
||||
| "false" -> Some false
|
||||
| _ -> None
|
||||
|
@ -1,4 +1,5 @@
|
||||
open General
|
||||
|
||||
|
||||
(** Converts the string to a bool, returning option type to account for invalid strings. *)
|
||||
val of_string : string -> bool option
|
10
lib/char.ml
10
lib/char.ml
@ -1,3 +1,11 @@
|
||||
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)
|
||||
|
@ -1,4 +1,5 @@
|
||||
open General
|
||||
|
||||
|
||||
(** Converts an int to a char. *)
|
||||
val of_int : int -> char
|
||||
val of_int : int -> char option
|
@ -1,6 +1,10 @@
|
||||
open General
|
||||
|
||||
let failwith = FromStdlib.failwith
|
||||
|
||||
external raise : exn -> 'a = "%raise"
|
||||
|
||||
|
||||
let failwith m = raise (Failure m)
|
||||
|
||||
let guarantee b =
|
||||
if not b then
|
||||
@ -9,3 +13,6 @@ let guarantee b =
|
||||
let guarantee_equal a b =
|
||||
if a <> b then
|
||||
failwith "guarantee_equal failed."
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
open General
|
||||
|
||||
|
||||
(** Throws an exception with a message. *)
|
||||
val failwith : string -> 'a
|
||||
|
||||
|
29
lib/file.ml
Normal file
29
lib/file.ml
Normal 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
26
lib/file.mli
Normal 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
|
21
lib/float.ml
21
lib/float.ml
@ -1,11 +1,22 @@
|
||||
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"
|
@ -1,12 +1,16 @@
|
||||
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. *)
|
||||
val of_string : string -> float option
|
||||
|
||||
(** Converts the int to a float. *)
|
||||
val of_int : int -> float
|
@ -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"
|
||||
|
||||
|
@ -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"
|
@ -12,7 +12,7 @@ type 'a tree =
|
||||
| Leaf
|
||||
| Branch of 'a * 'a tree list
|
||||
|
||||
let ignore = FromStdlib.ignore
|
||||
let ignore (a : 'a) = ()
|
||||
|
||||
let id (x : 'a) = x
|
||||
|
||||
@ -20,23 +20,38 @@ let ( >> ) f g 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_
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
(** Purely functional queue, implemented as a pair of lists. *)
|
||||
type 'a queue = { front : 'a list; back : 'a list }
|
||||
|
||||
(** Result type for error handling. *)
|
||||
type 'a result =
|
||||
| Error of string
|
||||
| Success of 'a
|
||||
@ -10,7 +11,7 @@ type 'a stack =
|
||||
| Empty
|
||||
| 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 =
|
||||
| Leaf
|
||||
| Branch of 'a * 'a tree list
|
||||
@ -31,28 +32,40 @@ val ( << ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b
|
||||
val ( |> ) : 'a -> ('a -> 'b) -> 'b
|
||||
|
||||
(** Checks for structural equality. *)
|
||||
val ( = ) : 'a -> 'a -> bool
|
||||
external ( = ) : 'a -> 'a -> bool = "%equal"
|
||||
|
||||
(** Checks for structural inequality. *)
|
||||
val ( <> ) : 'a -> 'a -> bool
|
||||
external ( <> ) : 'a -> 'a -> bool = "%notequal"
|
||||
|
||||
(** Polymorphic less than. *)
|
||||
val ( < ) : 'a -> 'a -> bool
|
||||
external ( < ) : 'a -> 'a -> bool = "%lessthan"
|
||||
|
||||
(** Polymorphic greater than. *)
|
||||
val ( > ) : 'a -> 'a -> bool
|
||||
external ( > ) : 'a -> 'a -> bool = "%greaterthan"
|
||||
|
||||
(** Polymorphic less than or equal to. *)
|
||||
val ( <= ) : 'a -> 'a -> bool
|
||||
external ( <= ) : 'a -> 'a -> bool = "%lessequal"
|
||||
|
||||
(** Polymorphic greater than or equal to. *)
|
||||
val ( >= ) : 'a -> 'a -> bool
|
||||
external ( >= ) : 'a -> 'a -> bool = "%greaterequal"
|
||||
|
||||
(** Logical negation. *)
|
||||
val not : bool -> bool
|
||||
|
||||
(** Logical or (infix). *)
|
||||
val ( or ) : bool -> bool -> bool
|
||||
external ( or ) : bool -> bool -> bool = "%sequor"
|
||||
|
||||
(** 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
|
24
lib/int.ml
24
lib/int.ml
@ -1,16 +1,26 @@
|
||||
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
|
||||
|
||||
|
13
lib/int.mli
13
lib/int.mli
@ -1,17 +1,18 @@
|
||||
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. *)
|
||||
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. *)
|
||||
val of_string : string -> int option
|
11
lib/list.ml
11
lib/list.ml
@ -1,7 +1,15 @@
|
||||
open General
|
||||
|
||||
|
||||
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 =
|
||||
match ls with
|
||||
| x :: xs -> Some x
|
||||
@ -143,3 +151,6 @@ let rec initialize_helper (f : int -> 'a) (length : int) (index : int) (acc : 'a
|
||||
|
||||
let initialize (f : int -> 'a) (length : int) : 'a list =
|
||||
initialize_helper f length 0 []
|
||||
|
||||
let of_array =
|
||||
Stdlib.Array.to_list
|
@ -1,8 +1,12 @@
|
||||
open General
|
||||
|
||||
|
||||
(** The empty 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). *)
|
||||
val head : 'a list -> 'a option
|
||||
|
||||
@ -56,3 +60,6 @@ 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). *)
|
||||
val initialize : (int -> 'a) -> int -> 'a list
|
||||
|
||||
(* Creates a list from the provided array. *)
|
||||
val of_array : 'a array -> 'a list
|
11
lib/makefile
11
lib/makefile
@ -3,13 +3,10 @@ STANDARD_COMPILE = ocamlopt $(STANDARD_FLAGS) -nopervasives -c
|
||||
LIB_NAME = library
|
||||
|
||||
build:
|
||||
# fromStdlib manages things that need to be exposed from the standard library
|
||||
ocamlopt $(STANDARD_FLAGS) -c fromStdlib.mli fromStdlib.ml
|
||||
make clean
|
||||
|
||||
# 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
|
||||
@ -24,9 +21,11 @@ build:
|
||||
$(STANDARD_COMPILE) char.mli char.ml
|
||||
$(STANDARD_COMPILE) bool.mli bool.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:
|
||||
rm -f *.o *.a *.s *.cmi *.cmx *.cmxa *.cmo *.cma
|
||||
|
@ -1,5 +1,6 @@
|
||||
open General
|
||||
|
||||
|
||||
module type Map = sig
|
||||
type key
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
open General
|
||||
|
||||
|
||||
module type Map = sig
|
||||
(** The type of keys in the map. *)
|
||||
type key
|
||||
|
@ -1,5 +1,6 @@
|
||||
open General
|
||||
|
||||
|
||||
let return (x : 'a) : 'a option = Some x
|
||||
|
||||
let ( ~= ) = return
|
||||
|
@ -1,5 +1,6 @@
|
||||
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
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
open General
|
||||
|
||||
open List
|
||||
|
||||
|
||||
let enqueue (a : 'a) (qu : 'a queue) : 'a queue =
|
||||
{ qu with front = a :: qu.back }
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
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
|
||||
|
||||
|
17
lib/random.ml
Normal file
17
lib/random.ml
Normal 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
11
lib/random.mli
Normal 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
|
@ -1,5 +1,6 @@
|
||||
open General
|
||||
|
||||
|
||||
module type RBTreeSet = sig
|
||||
type member
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
open General
|
||||
|
||||
|
||||
module type RBTreeSet = sig
|
||||
(** Type of members in the set. *)
|
||||
type member
|
||||
|
@ -1,5 +1,6 @@
|
||||
open General
|
||||
|
||||
|
||||
let pop (st : 'a stack) : 'a option * 'a stack =
|
||||
match st with
|
||||
| Empty -> (None, Empty)
|
||||
|
@ -1,5 +1,6 @@
|
||||
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
|
||||
|
||||
|
@ -1,11 +1,49 @@
|
||||
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)
|
||||
|
@ -1,10 +1,8 @@
|
||||
open General
|
||||
|
||||
(** Concatenates two strings together in the provided order. *)
|
||||
val ( + ) : string -> string -> string
|
||||
|
||||
(** Calculates the length of the provided string. *)
|
||||
val length : string -> int
|
||||
external length : string -> int = "%string_length"
|
||||
|
||||
(** Converts an int to a string. *)
|
||||
val of_int : int -> string
|
||||
@ -14,3 +12,6 @@ val of_float : float -> string
|
||||
|
||||
(** Converts a boolean to a string. *)
|
||||
val of_bool : bool -> string
|
||||
|
||||
(** Concatenates two strings together in the provided order. *)
|
||||
val ( + ) : string -> string -> string
|
@ -1,6 +1,8 @@
|
||||
open General
|
||||
|
||||
let printf = FromStdlib.printf
|
||||
|
||||
let printf = Stdlib.Printf.printf
|
||||
|
||||
let print s = printf "%s" s
|
||||
|
||||
let read_line = Stdlib.read_line
|
@ -1,7 +1,11 @@
|
||||
open General
|
||||
|
||||
|
||||
(** 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. *)
|
||||
val print : string -> unit
|
||||
|
||||
(** Reads an input line from the terminal. *)
|
||||
val read_line : unit -> string
|
@ -1,5 +1,6 @@
|
||||
open General
|
||||
|
||||
|
||||
let combine (tr1 : 'a tree) (tr2 : 'a tree) (topBranch : 'a) : 'a tree =
|
||||
Branch (topBranch, tr1 :: tr2 :: [])
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
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
|
||||
|
||||
|
4
makefile
4
makefile
@ -5,10 +5,10 @@ build:
|
||||
ocamlopt $(CUSTOM_LIBRARY_LOCATION)/library.cmxa -o program
|
||||
|
||||
mostlyclean:
|
||||
rm -f *.o *.a *.s *.cmi *.cmx *.cmxa *.cmo *.cma main.mli
|
||||
rm -f *.o *.a *.s *.cmi *.cmx *.cmxa *.cmo *.cma
|
||||
|
||||
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 build
|
||||
|
Loading…
Reference in New Issue
Block a user