removed some stdlib dependencies; license; bug fixes

This commit is contained in:
2022-02-15 22:05:11 +11:00
committed by aaron-jack-manning
parent e25b69bd44
commit f8f441648d
44 changed files with 284 additions and 101 deletions

68
lib/array.ml Normal file → Executable file
View File

@ -1,27 +1,73 @@
open General
external unsafe_get: 'a array -> int -> 'a = "%array_unsafe_get"
external unsafe_set: 'a array -> int -> 'a -> unit = "%array_unsafe_set"
external create: int -> 'a -> 'a array = "caml_make_vect"
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
external length : 'a array -> int = "%array_length"
let map = Stdlib.Array.map
external get : 'a array -> int -> 'a = "%array_safe_get"
let create = Stdlib.Array.init
external set : 'a array -> int -> 'a -> unit = "%array_safe_set"
let heap_sort = Stdlib.Array.sort
let of_list = function
| [] -> [||]
| x :: xs as l ->
let a = create (List.length l) x in
let rec fill i = function
| [] ->
a
| x::xs ->
unsafe_set a i x;
fill Int.(i + 1) xs
in
fill 1 xs
let merge_sort = Stdlib.Array.stable_sort
let create (length : int) (f : int -> 'a) : 'a array =
if length = 0 then
[||]
else if length < 0 then
Fatal.failwith "Cannot create an array with a size less than 0."
else
let result = create length (f 0) in
for i = 1 to Int.(length - 1) do
unsafe_set result i (f i)
done;
result
let copy = Stdlib.Array.copy
let append (arr1 : 'a array) (arr2 : 'b array) =
let open Int in
let arr1_length = length arr1 in
let arr2_length = length arr2 in
let init i =
if i < arr1_length then
get arr1 i
else
(get arr2 (i - arr1_length))
in
create (arr1_length + arr2_length) init
let concat (arrays : 'a array list) : 'a array =
arrays |> List.foldl append [||]
let map_mutate (f : 'a -> 'a) (arr : 'a array) : unit =
let open Int in
for i = 0 to length arr - 1 do
set arr i ((get arr i) |> f);
done;;
let copy (arr : 'a array) =
create (length arr) (fun i -> get arr i)
let map (f : 'a -> 'b) (arr : 'a array) : 'b array =
create (length arr) (fun i -> (get arr i) |> f)
let linear_search (arr : 'a array) (value : 'a) =
let i = ref 0 in

12
lib/array.mli Normal file → Executable file
View File

@ -3,24 +3,22 @@ open General
val of_list : 'a list -> 'a array
val length : 'a array -> int
external length : 'a array -> int = "%array_length"
val concat : 'a array list -> 'a array
val append : 'a array -> 'a array -> 'a array
val get : 'a array -> int -> 'a
external get: 'a array -> int -> 'a = "%array_safe_get"
val set : 'a array -> int -> 'a -> unit
external set: 'a array -> int -> 'a -> unit = "%array_safe_set"
val map_mutate : ('a -> 'a) -> 'a array -> 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

0
lib/bool.ml Normal file → Executable file
View File

0
lib/bool.mli Normal file → Executable file
View File

0
lib/char.ml Normal file → Executable file
View File

0
lib/char.mli Normal file → Executable file
View File

8
lib/console.ml Executable file
View File

@ -0,0 +1,8 @@
open General
external print : string -> unit = "print"
external read_line : int -> string = "read_line"
let print_all (contents : string list) : unit =
print (String.concat contents)

10
lib/console.mli Executable file
View File

@ -0,0 +1,10 @@
open General
(** Prints the provided string to the console. *)
external print : string -> unit = "print"
(** Reads a line from the console until a new line or EOF, using the specified buffer size. *)
external read_line : int -> string = "read_line"
(** Displays all provided strings to the console in order. *)
val print_all : string list -> unit

36
lib/console_external.c Executable file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
CAMLprim value print(value data)
{
CAMLparam1(data);
const char *data_string = String_val(data);
printf("%s", data_string);
return Val_unit;
}
CAMLprim value read_line(value input_length)
{
CAMLparam1(input_length);
const int input_length_int = Int_val(input_length);
char *input_line = malloc(sizeof (char) * input_length_int + 1);
char *result = fgets(input_line, input_length_int + 1, stdin);
if (result == NULL)
{
printf("Failed to read input line from stdin.\n");
exit(-1);
}
CAMLlocal1(return_string);
return_string = caml_copy_string(input_line);
free(input_line);
CAMLreturn(return_string);
}

0
lib/fatal.ml Normal file → Executable file
View File

0
lib/fatal.mli Normal file → Executable file
View File

0
lib/file.ml Normal file → Executable file
View File

0
lib/file.mli Normal file → Executable file
View File

90
lib/file_external.c Executable file
View File

@ -0,0 +1,90 @@
#include <stdio.h>
#include <caml/mlvalues.h>
#include <caml/memory.h>
#include <caml/alloc.h>
CAMLprim value write_all_lines(value file_path, value contents)
{
CAMLparam2(contents, file_path);
const char *contents_string = String_val(contents);
const char *file_path_string = String_val(file_path);
FILE *fp = fopen(file_path_string, "w");
if (fp == NULL)
{
printf("File %s was not opened correctly.\n", file_path_string);
exit(-1);
}
fprintf(fp, "%s", contents_string);
fclose(fp);
return Val_unit;
}
long file_length_from_pointer(FILE *fp)
{
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
return size;
}
long file_length(value file_path)
{
CAMLparam1(file_path);
const char *file_path_string = String_val(file_path);
FILE *fp = fopen(file_path_string, "r");
if (fp == NULL)
{
printf("File %s was not opened correctly.\n", file_path_string);
exit(-1);
}
long length = file_length_from_pointer(fp);
fclose(fp);
return Val_long(length);
}
CAMLprim value read_all_lines(value file_path)
{
// Copy input from value to c string.
CAMLparam1(file_path);
const char *file_path_string = String_val(file_path);
// Open the file.
FILE *fp = fopen(file_path_string, "r");
if (fp == NULL)
{
printf("File %s was not opened correctly.\n", file_path_string);
exit(-1);
}
// Calculate the file length.
long length = file_length_from_pointer(fp);
// Allocate the buffer
char *buffer = malloc(sizeof (char) * length + 1);
buffer[length] = '\0';
// Read the file.
size_t read_size = fread(buffer, sizeof (char), length, fp);
fclose(fp);
// Create the OCaml return value and copy over.
CAMLlocal1(file_contents);
file_contents = caml_copy_string(buffer);
// Free the buffer.
free(buffer);
return file_contents;
}

0
lib/float.ml Normal file → Executable file
View File

0
lib/float.mli Normal file → Executable file
View File

0
lib/general.ml Normal file → Executable file
View File

0
lib/general.mli Normal file → Executable file
View File

0
lib/int.ml Normal file → Executable file
View File

0
lib/int.mli Normal file → Executable file
View File

21
lib/list.ml Normal file → Executable file
View File

@ -152,5 +152,22 @@ 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
external unsafe_get: 'a array -> int -> 'a = "%array_unsafe_get"
external array_length : 'a array -> int = "%array_length"
let rec of_array_helper arr i res =
let open Int in
if i < 0 then
res
else
of_array_helper arr (i - 1) (unsafe_get arr i :: res)
let of_array arr =
let open Int in
of_array_helper arr (array_length arr - 1) []

0
lib/list.mli Normal file → Executable file
View File

28
lib/makefile Normal file → Executable file
View File

@ -1,11 +1,19 @@
STANDARD_FLAGS = -O3
STANDARD_COMPILE = ocamlopt $(STANDARD_FLAGS) -nopervasives -c
COMPILER = ocamlopt
EXT = .cmx
AEXT = .cmxa
STANDARD_FLAGS = -nopervasives -O3
STANDARD_COMPILE = $(COMPILER) $(STANDARD_FLAGS) -c
STANDARD_COMPILE_WITH_C = $(COMPILER) -ccopt -fPIC -c
LIB_NAME = library
COMPILED_FILES = general$(EXT) fatal$(EXT) int$(EXT) float$(EXT) option$(EXT) stack$(EXT) list$(EXT) map$(EXT) queue$(EXT) set$(EXT) tree$(EXT) string$(EXT) char$(EXT) bool$(EXT) console$(EXT) file$(EXT)
C_LIBS_FOR_LINKING = -cclib -lconsole_external -cclib -lfile_external
build:
make clean
ocamlopt $(STANDARD_FLAGS) -nopervasives -c general.mli general.ml
$(COMPILER) $(STANDARD_FLAGS) -c general.mli general.ml
$(STANDARD_COMPILE) fatal.mli fatal.ml
$(STANDARD_COMPILE) int.mli int.ml
@ -20,12 +28,14 @@ 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
$(STANDARD_COMPILE) file.mli file.ml
$(STANDARD_COMPILE) array.mli array.ml
$(STANDARD_COMPILE) random.mli random.ml
$(STANDARD_COMPILE_WITH_C) console_external.c console.mli console.ml
ocamlmklib console_external.o -o console_external
$(STANDARD_COMPILE_WITH_C) file_external.c file.mli file.ml
ocamlmklib file_external.o -o file_external
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
$(STANDARD_COMPILE) array.mli array.ml
$(COMPILER) -a $(C_LIBS_FOR_LINKING) $(COMPILED_FILES) -o library.cmxa
clean:
rm -f *.o *.a *.s *.cmi *.cmx *.cmxa *.cmo *.cma
rm -f *.o *.a *.s *.so *.cmi *.cmx *.cmxa *.cmo *.cma

0
lib/map.ml Normal file → Executable file
View File

0
lib/map.mli Normal file → Executable file
View File

0
lib/option.ml Normal file → Executable file
View File

0
lib/option.mli Normal file → Executable file
View File

5
lib/queue.ml Normal file → Executable file
View File

@ -2,9 +2,10 @@ open General
open List
let enqueue (a : 'a) (qu : 'a queue) : 'a queue =
{ qu with front = a :: qu.back }
match qu.front with
| [] -> { front = [a]; back = [] }
| _ -> { qu with back = a :: qu.back }
let dequeue (qu : 'a queue) : ('a option * 'a queue) =
match qu.front with

0
lib/queue.mli Normal file → Executable file
View File

View File

@ -1,17 +0,0 @@
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

View File

@ -1,11 +0,0 @@
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

0
lib/set.ml Normal file → Executable file
View File

0
lib/set.mli Normal file → Executable file
View File

0
lib/stack.ml Normal file → Executable file
View File

0
lib/stack.mli Normal file → Executable file
View File

5
lib/string.ml Normal file → Executable file
View File

@ -11,6 +11,8 @@ external format_float : string -> float -> string = "caml_format_float"
external length : string -> int = "%string_length"
external get : string -> int -> char = "%string_safe_get"
let of_int n =
format_int "%d" n
@ -31,6 +33,8 @@ let ( + ) s1 s2 =
bytes_unsafe_to_string s
let concat : string list -> string =
List.foldl (fun s m -> s + m) ""
external string_get : string -> int -> char = "%string_safe_get"
let valid_float_lexem s =
@ -44,6 +48,5 @@ let valid_float_lexem s =
loop 0
let of_float f =
valid_float_lexem (format_float "%.12g" f)

8
lib/string.mli Normal file → Executable file
View File

@ -4,6 +4,9 @@ open General
(** Calculates the length of the provided string. *)
external length : string -> int = "%string_length"
(** Gets the character at the specified index. *)
external get : string -> int -> char = "%string_safe_get"
(** Converts an int to a string. *)
val of_int : int -> string
@ -14,4 +17,7 @@ val of_float : float -> string
val of_bool : bool -> string
(** Concatenates two strings together in the provided order. *)
val ( + ) : string -> string -> string
val ( + ) : string -> string -> string
(** Concatenates a list of strings into a single string in sequence. *)
val concat : string list -> string

View File

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

View File

@ -1,11 +0,0 @@
open General
(** Formatted print to terminal. *)
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

0
lib/tree.ml Normal file → Executable file
View File

0
lib/tree.mli Normal file → Executable file
View File