Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 99 additions & 9 deletions jscomp/others/bs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,97 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *)


(** A stdlib shipped with BuckleScript *)
(** A stdlib shipped with BuckleScript

This stdlib is still in beta status, but we encourage you to try it out and
provide feedback.

{b Motivation }

The motivation of creating such library is to provide BuckleScript users a
better end-to-end user experience, since the original OCaml stdlib was not
writte with JS platform in mind, below are a list of areas this lib aims to
improve: {ol
{- 1. Consistency in name convention: camlCase, and arguments order}
{- 2. Exception thrown functions are all suffixed with {i Exn}, e.g, {i getExn}}
{- 3. Beter peformance and smaller code size running on JS platform}
}

{b Name Convention}

For higher order functions, it will be suffixed {b U} if it takes uncurried
callback.

{[
val forEach : 'a t -> ('a -> unit) -> unit
val forEachU : 'a t -> ('a -> unit [\@bs]) -> unit
]}

In general, uncurried version will be faster, but it is less familiar to
people who have a background in functional programming.

{b A special encoding for collection safety}

When we create a collection library for a custom data type, take {i Set} for
example, suppose its element type is a pair of ints,
it needs a custom {i compare} function. However, the {i Set} could not
just be typed as [ Set.t (int * int) ],
its customized {i compare} function needs to be
manifested in the signature, otherwise, if the user create another
customized {i compare} function, and the two collection would mix which
would result in runtime error.

The original OCaml stdlib solved the problem using {i functor} which is a big
closure in runtime; it makes dead code elimination much harder.
We introduced a phantom type to solve the problem

{[
type t = int * int
module I0 =
(val Bs.Dict.comparableU ~cmp:(fun[\@bs] ((a0,a1) : t) ((b0,b1) : t) ->
match compare a0 b0 with
| 0 -> compare a1 b1
| c -> c
))
let s0 = Bs.Set.make (module I0)
module I1 =
(val Bs.Dict.comparableU ~cmp:(fun[\@bs] ((a0,a1) : t) ((b0,b1) : t) ->
match compare a1 b1 with
| 0 -> compare a0 b0
| c -> c
))
let s1 = Bs.Set.make (module I1)
]}

Here the compiler would infer [s0] and [s1] having different type so that
it would not mix.

{[
val s0 : Bs.Set.t ((int * int), I0.id)
val s1 : Bs.Set.t ((int * int), I1.id)
]}


{b Collection Hierachy}

In general, we provide a generic collection module, but also create specialized
modules for commonly used data type, take {i Bs.Set} for example

{[
Bs.Set
Bs.Set.Int
Bs.Set.String
]}

The specialized module {i Bs.Set.Int}, {i Bs.Set.String} is in general more
efficient.

Currently, both {i Bs_Set} and {i Bs.Set} are accessible to users for some
technical rasons,
we {b strongly recommend} users stick to qualified import, {i Bs.Sort}, we may hide
the internal, {i i.e}, {i Bs_Set} in the future

*)

(** {!Bs.Dict}

Expand All @@ -37,8 +127,8 @@
module Dict = Bs_Dict

(** {!Bs.Array}
Utililites for Array functions

{b mutable array}: Utililites functions
*)
module Array = Bs_Array

Expand Down Expand Up @@ -77,7 +167,7 @@ module Range = Bs_Range

(** {!Bs.Set}

The toplevel provides generic immutable set operations.
The toplevel provides generic {b immutable} set operations.

It also has three specialized inner modules
{!Bs.Set.Int} and {!Bs.Set.String}
Expand All @@ -90,7 +180,7 @@ module Set = Bs_Set

(** {!Bs.Map},

The toplevel provides generic immutable map operations.
The toplevel provides generic {b immutable} map operations.

It also has three specialized inner modules
{!Bs.Map.Int} and {!Bs.Map.String}
Expand All @@ -102,7 +192,7 @@ module Map = Bs_Map

(** {!Bs.MutableSet}

The toplevel provides generic mutable set operations.
The toplevel provides generic {b mutable} set operations.

It also has two specialized inner modules
{!Bs.MutableSet.Int} and {!Bs.MutableSet.String}
Expand All @@ -111,7 +201,7 @@ module MutableSet = Bs_MutableSet

(** {!Bs.MutableMap}

The toplevel provides generic mutable map operations.
The toplevel provides generic {b mutable} map operations.

It also has two specialized inner modules
{!Bs.MutableMap.Int} and {!Bs.MutableMap.String}
Expand All @@ -122,7 +212,7 @@ module MutableMap = Bs_MutableMap

(** {!Bs.HashSet}

The toplevel provides generic mutable hash set operations.
The toplevel provides generic {b mutable} hash set operations.

It also has two specialized inner modules
{!Bs.HashSet.Int} and {!Bs.HashSet.String}
Expand All @@ -132,7 +222,7 @@ module HashSet = Bs_HashSet

(** {!Bs.HashMap}

The toplevel provides generic mutable hash map operations.
The toplevel provides generic {b mutable} hash map operations.

It also has two specialized inner modules
{!Bs.HashMap.Int} and {!Bs.HashMap.String}
Expand Down
41 changes: 33 additions & 8 deletions jscomp/others/bs_Array.ml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ let getExn arr i =
[%assert i >= 0 && i < length arr] ;
getUnsafe arr i
let set arr i v =
if i >= 0 && i < length arr then setUnsafe arr i v
if i >= 0 && i < length arr then (setUnsafe arr i v; true) else false

let setExn arr i v =
[%assert i >= 0 && i < length arr];
Expand Down Expand Up @@ -311,29 +311,54 @@ let rec everyAux arr i b len =
everyAux arr (i + 1) b len
else false

let rec someAux arr i b len =
if i = len then false
else
if b (getUnsafe arr i) [@bs] then true
else someAux arr (i + 1) b len

let everyU arr b =
let len = length arr in
everyAux arr 0 b len

let every arr f = everyU arr (fun[@bs] b -> f b)

let someU arr b =
let len = length arr in
someAux arr 0 b len
let some arr f = someU arr (fun [@bs] b -> f b)

let rec everyAux2 arr1 arr2 i b len =
if i = len then true
else if b (getUnsafe arr1 i) (getUnsafe arr2 i) [@bs] then
everyAux2 arr1 arr2 (i + 1) b len
else false

let rec someAux2 arr1 arr2 i b len =
if i = len then false
else if b (getUnsafe arr1 i) (getUnsafe arr2 i) [@bs] then
true
else someAux2 arr1 arr2 (i + 1) b len


let every2U a b p =
let lena = length a in
let lenb = length b in
if lena <> lenb then false
else
everyAux2 a b 0 p lena
everyAux2 a b 0 p (min (length a) (length b))

let every2 a b p = every2U a b (fun[@bs] a b -> p a b)

let some2U a b p =
someAux2 a b 0 p (min (length a) (length b))

let some2 a b p = some2U a b (fun [@bs] a b -> p a b)

let eqU = every2U
let eq = every2
let eqU a b p =
let lena = length a in
let lenb = length b in
if lena = lenb then
everyAux2 a b 0 p lena
else false

let eq a b p = eqU a b (fun [@bs] a b -> p a b )

let rec everyCmpAux2 arr1 arr2 i b len =
if i = len then 0
Expand Down
Loading