Skip to content
Draft
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
9 changes: 9 additions & 0 deletions compiler/core/js_of_lam_option.ml
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,12 @@ let null_to_opt e = E.econd (E.is_null e) none (some e)
let undef_to_opt e = E.econd (E.is_undef e) none (some e)

let null_undef_to_opt e = E.econd (E.is_null_undefined e) none (some e)

let option_for_each opt f =
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternative implementation:

  E.econd (is_not_none opt)
    (E.call ~info:(Js_call_info.na_full_call false) f [opt])
    E.unit

destruct_optional opt ~for_sure_none:E.unit
~for_sure_some:(fun x ->
E.call ~info:(Js_call_info.na_full_call false) f [x])
~not_sure:(fun () ->
E.econd (is_not_none opt)
(E.call ~info:(Js_call_info.na_full_call false) f [opt])
E.unit)
2 changes: 2 additions & 0 deletions compiler/core/js_of_lam_option.mli
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,5 @@ val null_to_opt : J.expression -> J.expression
val undef_to_opt : J.expression -> J.expression

val null_undef_to_opt : J.expression -> J.expression

val option_for_each : J.expression -> J.expression -> J.expression
2 changes: 1 addition & 1 deletion compiler/core/lam_analysis.ml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ let rec no_side_effects (lam : Lam.t) : bool =
->
true
| Pjs_apply | Pjs_runtime_apply | Pjs_call _ | Pinit_mod | Pupdate_mod
| Pjs_unsafe_downgrade _ | Pdebugger | Pjs_fn_method
| Pjs_unsafe_downgrade _ | Pdebugger | Pjs_fn_method | Poption_for_each
(* Await promise *)
| Pawait
(* TODO *)
Expand Down
4 changes: 4 additions & 0 deletions compiler/core/lam_compile_primitive.ml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ let translate output_prefix loc (cxt : Lam_compile_context.t)
| Pval_from_option ->
Js_of_lam_option.val_from_option (Ext_list.singleton_exn args)
| Pval_from_option_not_nest -> Ext_list.singleton_exn args
| Poption_for_each -> (
match args with
| [opt; f] -> Js_of_lam_option.option_for_each opt f
| _ -> assert false)
| Pfield (i, fld_info) ->
Js_of_lam_block.field fld_info
(Ext_list.singleton_exn args)
Expand Down
1 change: 1 addition & 0 deletions compiler/core/lam_convert.ml
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t =
| Pval_from_option -> prim ~primitive:Pval_from_option ~args loc
| Pval_from_option_not_nest ->
prim ~primitive:Pval_from_option_not_nest ~args loc
| Poption_for_each -> prim ~primitive:Poption_for_each ~args loc
| Pjscomp x -> prim ~primitive:(Pjscomp x) ~args loc
| Pfield (id, info) -> prim ~primitive:(Pfield (id, info)) ~args loc
| Psetfield (id, info) -> prim ~primitive:(Psetfield (id, info)) ~args loc
Expand Down
13 changes: 7 additions & 6 deletions compiler/core/lam_primitive.ml
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ type t =
| Pis_not_none (* no info about its type *)
| Pval_from_option
| Pval_from_option_not_nest
| Poption_for_each
| Psome
| Psome_not_nest
| Phash
Expand Down Expand Up @@ -223,12 +224,12 @@ let eq_primitive_approx (lhs : t) (rhs : t) =
| Pawait
(* etc *)
| Pjs_apply | Pjs_runtime_apply | Pval_from_option | Pval_from_option_not_nest
| Pnull_to_opt | Pnull_undefined_to_opt | Pis_null | Pis_not_none | Psome
| Psome_not_nest | Pis_undefined | Pis_null_undefined | Pimport | Ptypeof
| Pfn_arity | Pis_poly_var_block | Pdebugger | Pinit_mod | Pupdate_mod
| Pduprecord | Pmakearray | Parraylength | Parrayrefu | Parraysetu
| Parrayrefs | Parraysets | Pjs_fn_make_unit | Pjs_fn_method | Phash
| Phash_mixstring | Phash_mixint | Phash_finalmix ->
| Poption_for_each | Pnull_to_opt | Pnull_undefined_to_opt | Pis_null
| Pis_not_none | Psome | Psome_not_nest | Pis_undefined | Pis_null_undefined
| Pimport | Ptypeof | Pfn_arity | Pis_poly_var_block | Pdebugger | Pinit_mod
| Pupdate_mod | Pduprecord | Pmakearray | Parraylength | Parrayrefu
| Parraysetu | Parrayrefs | Parraysets | Pjs_fn_make_unit | Pjs_fn_method
| Phash | Phash_mixstring | Phash_mixint | Phash_finalmix ->
rhs = lhs
| Pcreate_extension a -> (
match rhs with
Expand Down
1 change: 1 addition & 0 deletions compiler/core/lam_primitive.mli
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ type t =
| Pis_not_none
| Pval_from_option
| Pval_from_option_not_nest
| Poption_for_each
| Psome
| Psome_not_nest
| Phash
Expand Down
1 change: 1 addition & 0 deletions compiler/core/lam_print.ml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ let primitive ppf (prim : Lam_primitive.t) =
| Psome_not_nest -> fprintf ppf "[some-not-nest]"
| Pval_from_option -> fprintf ppf "[?unbox]"
| Pval_from_option_not_nest -> fprintf ppf "[?unbox-not-nest]"
| Poption_for_each -> fprintf ppf "[option_for_each]"
| Pis_undefined -> fprintf ppf "[?undefined]"
| Pis_null_undefined -> fprintf ppf "[?null?undefined]"
| Pimport -> fprintf ppf "[import]"
Expand Down
1 change: 1 addition & 0 deletions compiler/ml/lambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ type primitive =
| Pis_not_none
| Pval_from_option
| Pval_from_option_not_nest
| Poption_for_each
| Pis_poly_var_block
| Pjs_raw_expr
| Pjs_raw_stmt
Expand Down
1 change: 1 addition & 0 deletions compiler/ml/lambda.mli
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ type primitive =
| Pis_not_none
| Pval_from_option
| Pval_from_option_not_nest
| Poption_for_each
| Pis_poly_var_block
| Pjs_raw_expr
| Pjs_raw_stmt
Expand Down
1 change: 1 addition & 0 deletions compiler/ml/printlambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ let primitive ppf = function
| Pis_not_none -> fprintf ppf "#is_not_none"
| Pval_from_option -> fprintf ppf "#val_from_option"
| Pval_from_option_not_nest -> fprintf ppf "#val_from_option_not_nest"
| Poption_for_each -> fprintf ppf "#option_for_each"
| Pis_poly_var_block -> fprintf ppf "#is_poly_var_block"
| Pjs_raw_expr -> fprintf ppf "#raw_expr"
| Pjs_raw_stmt -> fprintf ppf "#raw_stmt"
Expand Down
1 change: 1 addition & 0 deletions compiler/ml/translcore.ml
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ let primitives_table =
("%nullable_to_opt", Pnullable_to_opt);
("%function_arity", Pfn_arity);
("%wrap_exn", Pwrap_exn);
("%option_for_each", Poption_for_each);
("%curry_apply1", Pcurry_apply 1);
("%curry_apply2", Pcurry_apply 2);
("%curry_apply3", Pcurry_apply 3);
Expand Down
8 changes: 0 additions & 8 deletions lib/es6/Stdlib_Option.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ function filter(opt, p) {

}

function forEach(opt, f) {
if (opt !== undefined) {
return f(Primitive_option.valFromOption(opt));
}

}

function getOrThrow(x, message) {
if (x !== undefined) {
return Primitive_option.valFromOption(x);
Expand Down Expand Up @@ -205,7 +198,6 @@ let getWithDefault = getOr;

export {
filter,
forEach,
getExn,
getOrThrow,
mapOr,
Expand Down
8 changes: 0 additions & 8 deletions lib/js/Stdlib_Option.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ function filter(opt, p) {

}

function forEach(opt, f) {
if (opt !== undefined) {
return f(Primitive_option.valFromOption(opt));
}

}

function getOrThrow(x, message) {
if (x !== undefined) {
return Primitive_option.valFromOption(x);
Expand Down Expand Up @@ -204,7 +197,6 @@ let mapWithDefault = mapOr;
let getWithDefault = getOr;

exports.filter = filter;
exports.forEach = forEach;
exports.getExn = getExn;
exports.getOrThrow = getOrThrow;
exports.mapOr = mapOr;
Expand Down
6 changes: 1 addition & 5 deletions runtime/Stdlib_Option.res
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,7 @@ let filter = (opt, p) =>
| _ => None
}

let forEach = (opt, f) =>
switch opt {
| Some(x) => f(x)
| None => ()
}
external forEach: (option<'a>, 'a => unit) => unit = "%option_for_each"

let getOrThrow = (x, ~message=?) =>
switch x {
Expand Down
2 changes: 1 addition & 1 deletion runtime/Stdlib_Option.resi
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Option.forEach(Some("thing"), x => Console.log(x)) // logs "thing"
Option.forEach(None, x => Console.log(x)) // returns ()
```
*/
let forEach: (option<'a>, 'a => unit) => unit
external forEach: (option<'a>, 'a => unit) => unit = "%option_for_each"

/**
`getExn(opt, ~message=?)` returns `value` if `opt` is `Some(value)`, otherwise throws an exception with the message provided, or a generic message if no message was provided.
Expand Down
39 changes: 39 additions & 0 deletions tests/tests/src/OptionForEachTest.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Generated by ReScript, PLEASE EDIT WITH CARE


function testSome(opt) {
if (opt !== undefined) {
console.log(opt);
return;
}

}

function testNone() {

}

function testWithSideEffect() {
let counter = {
contents: 0
};
(param => {
counter.contents = counter.contents + 1 | 0;
})(42);
}

function testDirect(opt) {
if (opt !== undefined) {
console.log(opt);
return;
}

}

export {
testSome,
testNone,
testWithSideEffect,
testDirect,
}
/* No side effect */
20 changes: 20 additions & 0 deletions tests/tests/src/OptionForEachTest.res
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
let testSome = (opt: option<int>) => {
opt->Option.forEach(x => Js.log(x))
}

let testNone = () => {
let opt: option<string> = None
opt->Option.forEach(x => Js.log(x))
}

let testWithSideEffect = () => {
let counter = ref(0)
Some(42)->Option.forEach(_ => counter := counter.contents + 1)
None->Option.forEach(_ => counter := counter.contents + 1)
}

external directPrimitive: (option<'a>, 'a => unit) => unit = "%option_for_each"

let testDirect = (opt: option<float>) => {
directPrimitive(opt, x => Js.log(x))
}
Loading