standardlib.py

Created by lilian-besson-1

Created on June 03, 2025

16.8 KB

Experimental standardlib file to be read from OCamlBoot’s interp NWA app


(**************************************************************************)
(*                                                                        *)
(*                                 OCaml                                  *)
(*                                                                        *)
(*             Xavier Leroy, projet Cristal, INRIA Rocquencourt           *)
(*                                                                        *)
(*   Copyright 1996 Institut National de Recherche en Informatique et     *)
(*     en Automatique.                                                    *)
(*                                                                        *)
(*   All rights reserved.  This file is distributed under the terms of    *)
(*   the GNU Lesser General Public License version 2.1, with the          *)
(*   special exception on linking described in the file LICENSE.          *)
(*                                                                        *)
(**************************************************************************)

module Pervasives = struct
(* type 'a option = None | Some of 'a *)

(* Exceptions *)

(* external register_named_value : string -> 'a -> unit
                              = "caml_register_named_value" *)

(* let () =
  (* for asmrun/fail.c *)
  register_named_value "Pervasives.array_bound_error"
    (Invalid_argument "index out of bounds") *)


external raise : exn -> 'a = "%raise"
external raise_notrace : exn -> 'a = "%raise_notrace"

let failwith s = raise(Failure s)
let invalid_arg s = raise(Invalid_argument s)

exception Exit

(* Composition operators *)

external ( |> ) : 'a -> ('a -> 'b) -> 'b = "%revapply"
external ( @@ ) : ('a -> 'b) -> 'a -> 'b = "%apply"

(* Debugging *)

external __LOC__ : string = "%loc_LOC"
external __FILE__ : string = "%loc_FILE"
external __LINE__ : int = "%loc_LINE"
external __MODULE__ : string = "%loc_MODULE"
external __POS__ : string * int * int * int = "%loc_POS"

external __LOC_OF__ : 'a -> string * 'a = "%loc_LOC"
external __LINE_OF__ : 'a -> int * 'a = "%loc_LINE"
external __POS_OF__ : 'a -> (string * int * int * int) * 'a = "%loc_POS"

(* Comparisons *)

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"
external compare : 'a -> 'a -> int = "%compare"

let min x y = if x <= y then x else y
let max x y = if x >= y then x else y

external ( == ) : 'a -> 'a -> bool = "%eq"
external ( != ) : 'a -> 'a -> bool = "%noteq"

(* Boolean operations *)

external not : bool -> bool = "%boolnot"
external ( & ) : bool -> bool -> bool = "%sequand"
external ( && ) : bool -> bool -> bool = "%sequand"
external ( or ) : bool -> bool -> bool = "%sequor"
external ( || ) : bool -> bool -> bool = "%sequor"

(* Integer operations *)

external ( ~- ) : int -> int = "%negint"
external ( ~+ ) : int -> int = "%identity"
external succ : int -> int = "%succint"
external pred : int -> int = "%predint"
external ( + ) : int -> int -> int = "%addint"
external ( - ) : int -> int -> int = "%subint"
external ( * ) : int -> int -> int = "%mulint"
external ( / ) : int -> int -> int = "%divint"
external ( mod ) : int -> int -> int = "%modint"

let abs x = if x >= 0 then x else -x

external ( land ) : int -> int -> int = "%andint"
external ( lor ) : int -> int -> int = "%orint"
external ( lxor ) : int -> int -> int = "%xorint"

let lnot x = x lxor (-1)

external ( lsl ) : int -> int -> int = "%lslint"
external ( lsr ) : int -> int -> int = "%lsrint"
external ( asr ) : int -> int -> int = "%asrint"

let max_int = (-1) lsr 1
let min_int = max_int + 1

(* Floating-point operations *)

external ( ~-. ) : float -> float = "%negfloat"
external ( ~+. ) : float -> float = "%identity"
external ( +. ) : float -> float -> float = "%addfloat"
external ( -. ) : float -> float -> float = "%subfloat"
external ( *. ) : float -> float -> float = "%mulfloat"
external ( /. ) : float -> float -> float = "%divfloat"
external ( ** ) : float -> float -> float = "caml_power_float" "pow"
  [@@unboxed] [@@noalloc]
external exp : float -> float = "caml_exp_float" "exp" [@@unboxed] [@@noalloc]
external expm1 : float -> float = "caml_expm1_float" "caml_expm1"
  [@@unboxed] [@@noalloc]
external acos : float -> float = "caml_acos_float" "acos"
  [@@unboxed] [@@noalloc]
external asin : float -> float = "caml_asin_float" "asin"
  [@@unboxed] [@@noalloc]
external atan : float -> float = "caml_atan_float" "atan"
  [@@unboxed] [@@noalloc]
external atan2 : float -> float -> float = "caml_atan2_float" "atan2"
  [@@unboxed] [@@noalloc]
external hypot : float -> float -> float
               = "caml_hypot_float" "caml_hypot" [@@unboxed] [@@noalloc]
external cos : float -> float = "caml_cos_float" "cos" [@@unboxed] [@@noalloc]
external cosh : float -> float = "caml_cosh_float" "cosh"
  [@@unboxed] [@@noalloc]
external log : float -> float = "caml_log_float" "log" [@@unboxed] [@@noalloc]
external log10 : float -> float = "caml_log10_float" "log10"
  [@@unboxed] [@@noalloc]
external log1p : float -> float = "caml_log1p_float" "caml_log1p"
  [@@unboxed] [@@noalloc]
external sin : float -> float = "caml_sin_float" "sin" [@@unboxed] [@@noalloc]
external sinh : float -> float = "caml_sinh_float" "sinh"
  [@@unboxed] [@@noalloc]
external sqrt : float -> float = "caml_sqrt_float" "sqrt"
  [@@unboxed] [@@noalloc]
external tan : float -> float = "caml_tan_float" "tan" [@@unboxed] [@@noalloc]
external tanh : float -> float = "caml_tanh_float" "tanh"
  [@@unboxed] [@@noalloc]
external ceil : float -> float = "caml_ceil_float" "ceil"
  [@@unboxed] [@@noalloc]
external floor : float -> float = "caml_floor_float" "floor"
  [@@unboxed] [@@noalloc]
external abs_float : float -> float = "%absfloat"
external copysign : float -> float -> float
                  = "caml_copysign_float" "caml_copysign"
                  [@@unboxed] [@@noalloc]
external mod_float : float -> float -> float = "caml_fmod_float" "fmod"
  [@@unboxed] [@@noalloc]
external frexp : float -> float * int = "caml_frexp_float"
external ldexp : (float [@unboxed]) -> (int [@untagged]) -> (float [@unboxed]) =
  "caml_ldexp_float" "caml_ldexp_float_unboxed" [@@noalloc]
external modf : float -> float * float = "caml_modf_float"
external float : int -> float = "%floatofint"
external float_of_int : int -> float = "%floatofint"
external truncate : float -> int = "%intoffloat"
external int_of_float : float -> int = "%intoffloat"

(* let () = print_endline "Defining manually infinity, neg_infinity, nan, max_float, min_float, epsilon_float" *)

(* The following constants are defined manually to avoid using the
   float_of_bits primitive which is not available in all OCaml
   versions. *)

(* These values are based on the IEEE 754 double-precision floating-point
   representation. *)

(* Uncomment the following lines if you want to use float_of_bits directly.
   Note that this requires a specific OCaml version that supports it. *)
(* external float_of_bits : int64 -> float
  = "caml_int64_float_of_bits" "caml_int64_float_of_bits_unboxed"
  [@@unboxed] [@@noalloc] *)

(* let infinity =
  float_of_bits 0x7F_F0_00_00_00_00_00_00L *)
(* let infinity = float_of_string "+inf" *)

(* let neg_infinity =
  float_of_bits 0xFF_F0_00_00_00_00_00_00L *)
(* let neg_infinity = float_of_string "-inf" *)

(* let nan =
  float_of_bits 0x7F_F0_00_00_00_00_00_01L *)
(* let nan = float_of_string "nan" *)

(* let max_float =
  float_of_bits 0x7F_EF_FF_FF_FF_FF_FF_FFL *)

let max_float = 1.79769313486231571e+308
(* let min_float =
  float_of_bits 0x00_10_00_00_00_00_00_00L *)

let min_float = 2.22507385850720138e-308
(* let epsilon_float =
  float_of_bits 0x3C_B0_00_00_00_00_00_00L *)

let epsilon_float = 2.22044604925031308e-16

type fpclass =
    FP_normal
  | FP_subnormal
  | FP_zero
  | FP_infinite
  | FP_nan
external classify_float : (float [@unboxed]) -> fpclass =
  "caml_classify_float" "caml_classify_float_unboxed" [@@noalloc]

(* String and byte sequence operations -- more in modules String and Bytes *)

external string_length : string -> int = "%string_length"
external bytes_length : bytes -> int = "%bytes_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"

let ( ^ ) 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

(* Character operations -- more in module Char *)

external int_of_char : char -> int = "%identity"
external unsafe_char_of_int : int -> char = "%identity"
let char_of_int n =
  if n < 0 || n > 255 then invalid_arg "char_of_int" else unsafe_char_of_int n

(* Unit operations *)

external ignore : 'a -> unit = "%ignore"

(* Pair operations *)

external fst : 'a * 'b -> 'a = "%field0"
external snd : 'a * 'b -> 'b = "%field1"

(* References *)

type 'a ref = { mutable contents : 'a }
external ref : 'a -> 'a ref = "%makemutable"
external ( ! ) : 'a ref -> 'a = "%field0"
external ( := ) : 'a ref -> 'a -> unit = "%setfield0"
external incr : int ref -> unit = "%incr"
external decr : int ref -> unit = "%decr"

(* Result type *)

type ('a,'b) result = Ok of 'a | Error of 'b

(* String conversion functions *)

external format_int : string -> int -> string = "caml_format_int"
external format_float : string -> float -> string = "caml_format_float"

let string_of_bool b =
  if b then "true" else "false"
let bool_of_string = function
  | "true" -> true
  | "false" -> false
  | _ -> invalid_arg "bool_of_string"

let bool_of_string_opt = function
  | "true" -> Some true
  | "false" -> Some false
  | _ -> None

let string_of_int n =
  format_int "%d" n

external int_of_string : string -> int = "caml_int_of_string"

let int_of_string_opt s =
  (* TODO: provide this directly as a non-raising primitive. *)
  try Some (int_of_string s)
  with Failure _ -> None

external string_get : string -> int -> char = "%string_safe_get"

let valid_float_lexem s =
  let l = string_length s in
  let rec loop i =
    if i >= l then s ^ "." else
    match string_get s i with
    | '0' .. '9' | '-' -> loop (i + 1)
    | _ -> s
  in
  loop 0

let string_of_float f = valid_float_lexem (format_float "%.12g" f)

(* external float_of_string : string -> float = "caml_float_of_string" *)
(* XXX Manual implementation of x ** (float_of_int n). *)
let rec power_float_of_int x n =
  if n = 0 then 1.0
  else if n < 0 then 1.0 /. power_float_of_int x (-n)
  else
    let rec aux acc x n =
      if n = 0 then acc
      else if n mod 2 = 1 then aux (acc *. x) (x *. x) (n / 2)
      else aux acc (x *. x) (n / 2)
    in
    aux 1.0 x n

(* XXX Manual implementation of float_of_string, helped by Google's AI Gemini and tested manually. *)
let float_of_string (s : string) : float =
  let len = String.length s in
  if len = 0 then invalid_arg "float_of_string: empty string";

  let i = ref 0 in

  (* Skip leading whitespace *)
  while !i < len && (s.[!i] = ' ' || s.[!i] = '\t' || s.[!i] = '\n' || s.[!i] = '\r') do
    incr i
  done;

  (* Handle sign *)
  let sign =
    if !i < len && s.[!i] = '-' then (incr i; -1.0)
    else if !i < len && s.[!i] = '+' then (incr i; 1.0)
    else 1.0
  in

  (* Check for special values: NaN, Inf, Infinity *)
  let parse_special () =
    let remaining_len = len - !i in
    if remaining_len >= 3 then
      let sub_lower = String.lowercase_ascii (String.sub s !i remaining_len) in
      if sub_lower = "nan" then (
        i := len; (* Consume the rest of the string *)
        Some nan
      ) else if remaining_len >= 3 && sub_lower = "inf" then (
        i := len; (* Consume the rest of the string *)
        Some (sign *. infinity)
      ) else if remaining_len >= 8 && sub_lower = "infinity" then (
        i := len; (* Consume the rest of the string *)
        Some (sign *. infinity)
      ) else
        None (* Not a special value *)
    else
      None
  in

  match parse_special () with
  | Some special_val -> special_val
  | None ->
    let current_val = ref 0.0 in
    let decimal_found = ref false in
    let decimal_place = ref 0.1 in (* For fractional part *)
    let digits_read = ref 0 in
    let parsing_digits = ref true in

    (* Parse integer and fractional part *)
    while !i < len && !parsing_digits do
      let c = s.[!i] in
      if c >= '0' && c <= '9' then (
        digits_read := !digits_read + 1;
        if not !decimal_found then
          current_val := !current_val *. 10.0 +. (float_of_int (Char.code c - Char.code '0'))
        else (
          current_val := !current_val +. (float_of_int (Char.code c - Char.code '0')) *. !decimal_place;
          decimal_place := !decimal_place *. 0.1;
        );
        incr i
      ) else if c = '.' && not !decimal_found then (
        decimal_found := true;
        incr i
      ) else
        parsing_digits := false (* Stop parsing digits *)
    done;

    if !digits_read = 0 then invalid_arg "float_of_string: no digits found";

    (* Handle exponent part *)
    let exponent_val = ref 0 in
    let exponent_sign = ref 1 in
    let parsing_exponent = ref true in

    if !i < len && (s.[!i] = 'e' || s.[!i] = 'E') then (
      incr i; (* Consume 'e' or 'E' *)
      if !i < len && s.[!i] = '-' then (exponent_sign := -1; incr i)
      else if !i < len && s.[!i] = '+' then (incr i);

      let exponent_digits_read = ref 0 in
      while !i < len && !parsing_exponent do
        let c = s.[!i] in
        if c >= '0' && c <= '9' then (
          exponent_digits_read := !exponent_digits_read + 1;
          exponent_val := !exponent_val * 10 + (Char.code c - Char.code '0');
          incr i
        ) else
          parsing_exponent := false (* Stop parsing exponent digits *)
      done;
      if !exponent_digits_read = 0 then
        invalid_arg "float_of_string: exponent has no digits"
    );

    (* Apply exponent *)
    (* let final_val = !current_val *. (10.0 ** (float_of_int (!exponent_val * !exponent_sign))) in *)
    let final_val = !current_val *. (power_float_of_int 10.0 (!exponent_val * !exponent_sign)) in
    let result = sign *. final_val in

    (* Skip trailing whitespace *)
    while !i < len && (s.[!i] = ' ' || s.[!i] = '\t' || s.[!i] = '\n' || s.[!i] = '\r') do
      incr i
    done;

    if !i <> len then invalid_arg "float_of_string: extraneous characters";

    result


let float_of_string_opt s =
  (* TODO: provide this directly as a non-raising primitive. *)
  try Some (float_of_string s)
  with Failure _ -> None

(* List operations -- more in module List *)

let rec ( @ ) l1 l2 =
  match l1 with
    [] -> l2
  | hd :: tl -> hd :: (tl @ l2)

(* Miscellaneous *)

external sys_exit : int -> 'a = "caml_sys_exit"

let exit_function = ref (fun () -> ())

let at_exit f =
  let g = !exit_function in
  (* MPR#7253, MPR#7796: make sure "f" is executed only once *)
  let f_already_ran = ref false in
  exit_function :=
    (fun () ->
      if not !f_already_ran then begin f_already_ran := true; f() end;
      g())

let do_at_exit () = (!exit_function) ()

let exit retcode =
  do_at_exit ();
  sys_exit retcode

(* let _ = register_named_value "Pervasives.do_at_exit" do_at_exit *)
end

include Pervasives

(* MODULE_ALIASES *)
(* module Arg          = Arg
module Array        = Array
(* module ArrayLabels  = ArrayLabels *)
(* module Bigarray     = Bigarray *)
module Buffer       = Buffer
module Bytes        = Bytes
(* module BytesLabels  = BytesLabels *)
module Callback     = Callback
module Char         = Char
module Complex      = Complex
module Digest       = Digest
module Ephemeron    = Ephemeron
module Filename     = Filename
module Float        = Float
(* module Format       = Format *)
module Gc           = Gc
module Genlex       = Genlex
module Hashtbl      = Hashtbl
(* module Int32        = Int32 *)
(* module Int64        = Int64 *)
module Lazy         = Lazy
module Lexing       = Lexing
module List         = List
(* module ListLabels   = ListLabels *)
module Map          = Map
module Marshal      = Marshal
(* module MoreLabels   = MoreLabels *)
(* module Nativeint    = Nativeint *)
module Obj          = Obj
module Oo           = Oo
module Parsing      = Parsing
module Printexc     = Printexc
module Printf       = Printf
module Queue        = Queue
(* module Random       = Random *)
(* module Scanf        = Scanf *)
module Seq          = Seq
module Set          = Set
module Sort         = Sort
(* module Spacetime    = Spacetime *)
module Stack        = Stack
(* module StdLabels    = StdLabels *)
module Stream       = Stream
module String       = String
(* module StringLabels = StringLabels *)
(* module Sys          = Sys *)
module Uchar        = Uchar
module Weak         = Weak *)

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.