summaryrefslogtreecommitdiff
path: root/testsuite/tests/exotic-syntax/exotic.ml
blob: 94666e7fab23836b88328514ac0a1fd957542f97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
(* TEST
*)

(* Exotic OCaml syntax constructs found in the manual that are not *)
(* used in the source of the OCaml distribution (even in the tests). *)

(* Spaces between the parts of the ?label: token in a typexpr.
   (used in bin-prot) *)
type t1 = ? label : int -> int -> int;;

(* Lazy in a pattern. (used in advi) *)
function lazy y -> y;;

(* Spaces between the parts of the ?label: token in a class-type. *)
class c1 =
  (fun ?label:x y -> object end : ? label : int -> int -> object end)
;;

(* type-class annotation in class-expr *)
class c2 = (object end : object end);;

(* virtual object field *)
class virtual c3 = object val virtual x : int end;;
class virtual c4 = object val mutable virtual x : int end;;

(* abstract module type in a signature *)
module type T = sig
  module type U
end;;

(* associativity rules for patterns *)
function Some Some x -> x | _ -> 0;;
function Some `Tag x -> x | _ -> 0;;
function `Tag Some x -> x | _ -> 0;;
function `Tag `Tag x -> x | _ -> 0;;

(* negative int32, int64, nativeint constants in patterns *)
function -1l -> () | _ -> ();;
function -1L -> () | _ -> ();;
function -1n -> () | _ -> ();;

(* surprising places where you can use an operator as a variable name *)
function (+) -> (+);;
function _ as (+) -> (+);;
for (+) = 0 to 1 do () done;;

(* access a class-type through an extended-module-path *)
module F (X : sig end) = struct
  class type t = object end
end;;
module M1 = struct end;;
class type u = F(M1).t;;

(* conjunctive constraints on tags (used by the compiler to print some
   inferred types) *)
type 'a t2 = [< `A of int & int & int ] as 'a;;

(* same for a parameterless tag (triggers a very strange error message) *)
(*type ('a, 'b) t3 = [< `A of & 'b ] as 'a;;*)

(* negative float constant in a pattern *)
function -1.0 -> 1 | _ -> 2;;

(* combining language extensions (sec. 7.13 and 7.17) *)
class c5 = object method f = 1 end;;
object
  inherit c5
  method! f : type t . int = 2
end;;

(* private polymorphic method with local type *)
object method private f : type t . int = 1 end;;

(* type annotations on record fields, both in patterns and expressions, and both
   with and without punning *)
let get_int { contents : int } = contents
let get_int2 { contents : int = c } = c
let set_int contents = { contents : int }
let set_int2 c = { contents : int = c }
;;

(* applying a functor to the unpacking of a first-class module *)
module M() = struct
  module type String = module type of String
  let string = (module String : String)
  module M = Set.Make(val string)
end ;;

(* More exotic: not even found in the manual (up to version 4.00),
   but used in some programs found in the wild.
*)

(* local functor *)
let module M (M1 : sig end) = struct end in ();;

(* let-binding with a type coercion *)
let x :> int = 1;;
let x : int :> int = 1;;

(* "begin end" as an alias for "()" *)
begin end;;

(* putting "virtual" before "mutable" or "private" *)
class type virtual ct = object
  val mutable virtual x : int
  val virtual mutable y : int
  method private virtual f : int
  method virtual private g : int
end;;
class virtual c = object
  val mutable virtual x : int
  val virtual mutable y : int
  method private virtual f : int
  method virtual private g : int
end;;

(* Double-semicolon at the beginning of a module body [ocp-indent] *)
module M2 = struct ;; end;;


(**********************

(* Most exotic: not found in the manual (up to 4.00) and not used
   deliberately by anyone, but still implemented by the compiler. *)

(* whitespace inside val!, method!, inherit! [found in ocamlspot] *)
object
  val x = 1
  val ! x = 2
  method m = 1
  method ! m = 2
  inherit ! object val x = 3 end
end;;

(* Using () as a constructor name [found in gettext] *)
type t = ();;
let x : t = ();;

(* Using :: as a constructor name *)
type t = :: of int * int;;

(* Prefix syntax for :: in expressions *)
(::) (1, 1);;

(* Prefix syntax for :: in patterns *)
function (::) (_, _) -> 1;;

(* Unary plus in expressions (ints and float) *)
+1;;
+1l;;
+1L;;
+1n;;
+1.0;;

(* Unary plus in patterns (ints and floats) *)
function +1 -> ();;
function +1l -> ();;
function +1L -> ();;
function +1n -> ();;
function +1.0 -> ();;

**********************)