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
4 changes: 4 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ Unreleased
JavaScript with `@mel.as`
([#714](https://github.com/melange-re/melange/pull/714), fixes
[#713](https://github.com/melange-re/melange/pull/713)).
- [melange]: Allow using `@mel.as` in external declarations without explicitly
annotating `@mel.{string,int}`
([#722](https://github.com/melange-re/melange/pull/714), fixes
[#578](https://github.com/melange-re/melange/pull/713)).

1.0.0 2023-05-31
---------------
Expand Down
1 change: 1 addition & 0 deletions ppx/ast_attributes.mli
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,5 @@ type as_const_payload = Int of int | Str of string | Js_literal_str of string

val iter_process_bs_string_or_int_as : t -> as_const_payload option
val unboxable_type_in_prim_decl : attr
val is_mel_as : attr -> bool
val has_mel_as_payload : t -> attr option
33 changes: 33 additions & 0 deletions ppx/ast_external_process.ml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,39 @@ let spec_of_ptyp (nolabel : bool) (ptyp : Parsetree.core_type) :
match ptyp_desc with
| Ptyp_constr ({ txt = Lident "unit"; _ }, []) ->
if nolabel then Extern_unit else Nothing
| Ptyp_variant (row_fields, Closed, None) -> (
(* No `@mel.string` / `@mel.int` present. Try to infer `@mel.as`, if
present, in polyvariants.

https://github.com/melange-re/melange/issues/578 *)
let mel_as_type =
List.fold_left
(fun mel_as_type { prf_attributes; prf_loc; _ } ->
match List.filter Ast_attributes.is_mel_as prf_attributes with
| [] -> mel_as_type
| [ { attr_payload; attr_loc = loc; _ } ] -> (
match
( mel_as_type,
Ast_payload.is_single_string attr_payload,
Ast_payload.is_single_int attr_payload )
with
| (`Nothing | `String), Some _, None -> `String
| (`Nothing | `Int), None, Some _ -> `Int
| (`Nothing | `String | `Int), None, None -> `Nothing
| `String, None, Some _ ->
Error.err ~loc Expect_string_literal
| `Int, Some _, None -> Error.err ~loc Expect_int_literal
| _, Some _, Some _ -> assert false)
| _ :: _ -> Error.err ~loc:prf_loc Duplicated_mel_as)
`Nothing row_fields
in
match mel_as_type with
| `Nothing -> Nothing
| `String ->
Ast_polyvar.map_row_fields_into_strings ptyp.ptyp_loc row_fields
| `Int ->
Int
(Ast_polyvar.map_row_fields_into_ints ptyp.ptyp_loc row_fields))
| _ -> Nothing)

(* is_optional = false
Expand Down
78 changes: 78 additions & 0 deletions test/blackbox-tests/as-without-mel-string.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
Test `@mel.as` without `@mel.string` / `@mel.int` in external polyvars

$ . ./setup.sh
$ cat > x.ml <<EOF
> type t = unit
> external transition_timing_function :
> t ->
> [ \`ease
> | \`easeIn [@mel.as "ease-in"]
> ] ->
> unit = "transitionTimingFunction"
> let () = transition_timing_function () \`easeIn
> EOF
$ melc -ppx melppx x.ml
// Generated by Melange
'use strict';


transitionTimingFunction(undefined, "ease-in");

/* Not a pure module */

$ cat > x.ml <<EOF
> type t = unit
> external transition_timing_function :
> t ->
> [ \`ease
> | \`easeIn [@mel.as 1]
> | \`easeOut [@mel.as 2]
> ] ->
> unit = "transitionTimingFunction"
> let () = transition_timing_function () \`easeIn
> EOF
$ melc -ppx melppx x.ml
// Generated by Melange
'use strict';


transitionTimingFunction(undefined, 1);

/* Not a pure module */

$ cat > x.ml <<EOF
> type t = unit
> external transition_timing_function :
> t ->
> [ \`ease
> | \`easeIn [@mel.as "ease-in"]
> | \`easeOut [@mel.as 1]
> ] ->
> unit = "transitionTimingFunction"
> let () = transition_timing_function () \`easeIn
> EOF
$ melc -ppx melppx x.ml
File "x.ml", line 6, characters 13-24:
6 | | `easeOut [@mel.as 1]
^^^^^^^^^^^
Error: expect string literal
[2]

$ cat > x.ml <<EOF
> type t = unit
> external transition_timing_function :
> t ->
> [ \`ease
> | \`easeIn [@mel.as 1] [@mel.as "ease-in"]
> | \`easeOut
> ] ->
> unit = "transitionTimingFunction"
> let () = transition_timing_function () \`easeIn
> EOF
$ melc -ppx melppx x.ml
File "x.ml", line 5, characters 4-43:
5 | | `easeIn [@mel.as 1] [@mel.as "ease-in"]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: duplicate @as
[2]

37 changes: 0 additions & 37 deletions test/blackbox-tests/mel-as-in-external.t
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,6 @@ Test the attribute @mel.as in external with @mel.set
> (preprocess (pps melange.ppx)))
> EOF

When `mel.string` is not used, the compiler complains

$ dune build @melange
File "x.ml", line 8, characters 14-20:
8 | | `easeIn [@mel.as "ease-in"]
^^^^^^
Alert unused: Unused attribute [@mel.as]
This means such annotation is not annotated properly.
For example, some annotations are only meaningful in externals


File "x.ml", line 9, characters 15-21:
9 | | `easeOut [@mel.as "ease-out"]
^^^^^^
Alert unused: Unused attribute [@mel.as]
This means such annotation is not annotated properly.
For example, some annotations are only meaningful in externals


File "x.ml", line 10, characters 17-23:
10 | | `easeInOut [@mel.as "ease-in-out"]
^^^^^^
Alert unused: Unused attribute [@mel.as]
This means such annotation is not annotated properly.
For example, some annotations are only meaningful in externals

The `mel.as` attribute has no effect in the output

$ cat ./_build/default/out/x.js
// Generated by Melange
'use strict';


document.transitionTimingFunction = "easeIn";

/* Not a pure module */

$ cat > x.ml <<\EOF
> type document
>
Expand Down