Skip to content

Commit

Permalink
Prefix JS keywords that are used as OCaml identifiers.
Browse files Browse the repository at this point in the history
We were already disallowing some JS keywords from being used as
identifiers, this patch completes the set of recognised keywords.

Instead of disallowing, we can safely prefix or suffix the name with a
character that is not permitted in OCaml identifiers, but is permitted
in JS identifiers. This includes $ and a substantial set of unicode
characters. (Those listed in the below tables, AND contain at least one
byte that is forbidden by the OCaml rules).

In this case, I've opted to prefix the variables by 𝕍 (Mathematical
Double-Struck Capital V).

I've also updated the substitution of the ' (Apostrophe) character from
$ to ʹ (Modifier Letter Prime), to improve the readability of the code.

https://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:ID_Start=Yes:]
https://unicode.org/cldr/utility/list-unicodeset.jsp?a=[:ID_Continue=Yes:]
  • Loading branch information
IgnoredAmbience committed Nov 14, 2017
1 parent 5121ab7 commit 68fef4b
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions generator/js_of_ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -384,11 +384,19 @@ let ppf_pat_array id_list array_expr =
let ppf_field_access expr field =
Printf.sprintf "%s.%s" expr field

(* List of JavaScript keywords that cannot be used as identifiers *)
let js_keywords =
["await"; "break"; "case"; "catch"; "class"; "const"; "continue"; "debugger"; "default"; "delete"; "do"; "else";
"export"; "extends"; "finally"; "for"; "function"; "if"; "import"; "in"; "instanceof"; "new"; "return"; "super";
"switch"; "this"; "throw"; "try"; "typeof"; "var"; "void"; "while"; "with"; "yield"; "enum"]

let ppf_ident_name x =
if List.mem x ["arguments"; "eval"; "caller"]
then unsupported ("use of reserved keyword: " ^ x);
(* TODO: complete the list *)
Str.global_replace (Str.regexp "'") "$" x
if List.mem x js_keywords then
(* Variable name clashes with JS keyword: prefix with a \mathbb{V} character (\u1d54d) *)
"\xf0\x9d\x95\x8d" ^ x
else
(* Variable name contains ' (not supported by JS): replace with unicode prime symbol (\u02b9) *)
Str.global_replace (Str.regexp "'") "\xca\xb9" x

let ppf_ident i =
i |> Ident.name |> ppf_ident_name
Expand Down

0 comments on commit 68fef4b

Please sign in to comment.