package pfff

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file ast_ml.ml

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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
(* Yoann Padioleau
 *
 * Copyright (C) 2010, 2012 Facebook
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * version 2.1 as published by the Free Software Foundation, with the
 * special exception on linking described in file license.txt.
 * 
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the file
 * license.txt for more details.
 *)
open Common

(*****************************************************************************)
(* Prelude *)
(*****************************************************************************)
(*
 * A Concrete Syntax Tree for OCaml.
 * 
 * less: do an Abstract Syntax Tree as in ast_java.ml; need less CST
 * now that we use the fuzzy approach for sgrep and spatch?
 * Keep just the Parse_info.info for the identifiers and literals.
 *)

(*****************************************************************************)
(* The AST related types *)
(*****************************************************************************)

(* ------------------------------------------------------------------------- *)
(* Token/info *)
(* ------------------------------------------------------------------------- *)
type tok = Parse_info.info

(* a shortcut to annotate some information with token/position information *)
and 'a wrap = 'a * tok

and 'a paren   = tok * 'a * tok
and 'a brace   = tok * 'a * tok
and 'a bracket = tok * 'a * tok 

and 'a comma_list = ('a, tok (* ',' *)) Common.either list
and 'a and_list = ('a, tok (* 'and' *)) Common.either list
and 'a star_list = ('a, tok (* '*' *)) Common.either list
(* optional first | *)
and 'a pipe_list = ('a, tok (* '|' *)) Common.either list
(* optional final ; *)
and 'a semicolon_list = ('a, tok (* ';' *)) Common.either list

 (* with tarzan *)

(* ------------------------------------------------------------------------- *)
(* Names  *)
(* ------------------------------------------------------------------------- *)
type name = Name of string wrap

  (* lower and uppernames aliases, just for clarity *)
  and lname = name
  and uname = name

 (* with tarzan *)

type long_name = qualifier * name
 and qualifier = (name * tok (*'.'*)) list

 (* with tarzan *)

(* ------------------------------------------------------------------------- *)
(* Types *)
(* ------------------------------------------------------------------------- *)

type ty = 
  | TyName of long_name
  | TyVar of tok (* ' *) * name

  | TyTuple of ty star_list (* at least 2 *)
  | TyTuple2 of ty star_list paren (* at least 1 *)
  | TyFunction of ty * tok (* -> *) * ty
  | TyApp of ty_args * long_name (* todo? could be merged with TyName *)

  | TyTodo

 and ty_args = 
    | TyArg1 of ty
    | TyArgMulti of ty comma_list paren
    (* todo? | TyNoArg and merge TyName and TyApp ? *)

(* ------------------------------------------------------------------------- *)
(* Expressions *)
(* ------------------------------------------------------------------------- *)
and expr =
  | C of constant
  | L of long_name (* val_longident *)

  | Constr(*Algebric*) of long_name (* constr_longident *) * expr option
  | Tuple of expr comma_list
  | List of expr semicolon_list bracket

  (* can be empty; can not be singular as we use instead ParenExpr *) 
  | Sequence of seq_expr paren (* can also be 'begin'/'end' *)

  | Prefix of string wrap * expr
  | Infix of expr * string wrap * expr

  | FunCallSimple of long_name * argument list
  | FunCall of expr * argument list

  (* could be factorized with Prefix but it's not a usual prefix operator! *)
  | RefAccess of tok (* ! *) * expr
  | RefAssign of expr * tok (* := *) * expr

  | FieldAccess of expr * tok (* . *) * long_name
  | FieldAssign of expr * tok (* . *) * long_name * tok (* <- *) * expr
  | Record of record_expr brace

  | New of tok * long_name (* class_longident *)
  | ObjAccess of expr * tok (* # *) * name
  

  | LetIn of tok * rec_opt * let_binding and_list * tok (* in *) * seq_expr
  | Fun of tok * parameter list (* at least one *) * match_action
  | Function of tok * match_case pipe_list

  (* why they allow seq_expr ?? *)
  | If of tok * seq_expr * tok * expr * (tok * expr) option
  | Match of tok * seq_expr * tok * match_case pipe_list

  | Try of tok * seq_expr * tok * match_case pipe_list 

  | While of tok * seq_expr * tok * seq_expr * tok
  | For of tok * name * tok * seq_expr * for_direction * seq_expr * 
           tok * seq_expr * tok

  | ParenExpr of expr paren
  (* todo: LetOpenIn *)
  | ExprTodo

and seq_expr = expr semicolon_list

 and constant =
   | Int of string wrap
   | Float of string wrap
   | Char of string wrap
   | String of string wrap

 and record_expr =
   | RecordNormal of                         field_and_expr semicolon_list
   | RecordWith of expr * tok (* "with" *) * field_and_expr semicolon_list
   and field_and_expr = 
     | FieldExpr of long_name * tok (* = *) * expr
     (* new 3.12 feature *)
     | FieldImplicitExpr of long_name

 and argument = 
   | ArgExpr of expr

   | ArgLabelTilde of name (* todo: without the tilde and : ? *) * expr
   | ArgImplicitTildeExpr of tok * name

   (* apparently can do 'foo ?attr:1' *)
   | ArgLabelQuestion of name (* todo: without the tilde and : ? *) * expr
   | ArgImplicitQuestionExpr of tok * name


 and match_case =
  pattern * match_action

  and match_action =
    | Action of tok (* -> *) * seq_expr
    | WhenAction of tok (* when *) * seq_expr * tok (* -> *) * seq_expr


 and for_direction =
  | To of tok
  | Downto of tok

 and rec_opt = tok option

(* ------------------------------------------------------------------------- *)
(* Patterns *)
(* ------------------------------------------------------------------------- *)
and pattern = 
  | PatVar of name
  | PatConstant of pattern_signed_constant
  | PatConstr(*Algebric*) of long_name (* constr_longident *) * pattern option
  | PatConsInfix of pattern * tok (* :: *) * pattern
  | PatTuple of pattern comma_list
  | PatList of pattern semicolon_list bracket
  | PatUnderscore of tok
  | PatRecord of field_pattern semicolon_list brace

  | PatAs of pattern * tok (* as *) * name
  (* ocaml disjunction patterns extension *)
  | PatDisj of pattern * tok (* | *) * pattern

  | PatTyped of tok (*'('*) * pattern * tok (*':'*) * ty * tok (*')'*)

  | ParenPat of pattern paren
  | PatTodo
    
 (* less? merge with expr, no need for too precise AST, remember ast_php.ml *)
 and pattern_signed_constant = 
    | C2 of constant
    (* actually only valid for the Int and Float case, not Char and String
     * but don't want to introduce yet another intermediate type just for
     * the Int and Float
     *)
    | CMinus of tok * constant
    | CPlus of tok * constant

 and field_pattern =
  | PatField of long_name * tok (* = *) * pattern
  (* new 3.12 feature *)
  | PatImplicitField of long_name

(* ------------------------------------------------------------------------- *)
(* Let binding (global/local/function definition) *)
(* ------------------------------------------------------------------------- *)

and let_binding =
  | LetClassic of let_def
  | LetPattern of pattern * tok (* = *) * seq_expr

 (* was called fun_binding in the grammar *)
 and let_def = {
   l_name: name; (* val_ident *)
   l_params: parameter list; (* can be empty *)
   l_tok: tok; (* = *)
   l_body: seq_expr;
   (* todo: l_type: ty option *)
 }

 and parameter = 
   | ParamPat of pattern
   | ParamTodo

 and labeled_simple_pattern = unit

(* ------------------------------------------------------------------------- *)
(* Type declaration *)
(* ------------------------------------------------------------------------- *)

type type_declaration =
  | TyAbstract of ty_params * name
  | TyDef of ty_params * name * tok (* = *) * type_def_kind

 and ty_params =
   | TyNoParam
   | TyParam1 of ty_parameter
   | TyParamMulti of ty_parameter comma_list paren
 and ty_parameter = tok (* ' *) * name (* a TyVar *)

 and type_def_kind =
   | TyCore of ty
   (* or type *)
   | TyAlgebric of constructor_declaration pipe_list
   (* and type *)
   | TyRecord   of field_declaration semicolon_list brace

 (* OR type: algebric data type *)
 and constructor_declaration = name (* constr_ident *) * constructor_arguments
  and constructor_arguments =
    | NoConstrArg
    | Of of tok * ty star_list

 (* AND type: record *)
 and field_declaration = {
   fld_mutable: tok option;
   fld_name: name;
   fld_tok: tok; (* : *)
   fld_type: ty; (* poly_type ?? *)
 }


(* ------------------------------------------------------------------------- *)
(* Class *)
(* ------------------------------------------------------------------------- *)

(* ------------------------------------------------------------------------- *)
(* Module *)
(* ------------------------------------------------------------------------- *)
type module_type = unit (* todo *)

(* mutually recursive with item *)
type module_expr =
  | ModuleName of long_name
  | ModuleStruct of tok (* struct *) * item list * tok (* end *)
  | ModuleTodo


(* ------------------------------------------------------------------------- *)
(* Signature/Structure items *)
(* ------------------------------------------------------------------------- *)

(* could split in sig_item and struct_item but many constructions are
 * valid in both contexts.
 *)
and item = 
  | Type      of tok * type_declaration and_list

  | Exception of tok * name * constructor_arguments
  | External  of tok * name (* val_ident *) * tok (*:*) * ty * tok (* = *) *
      string wrap list (* primitive declarations *)
      
  | Open of tok * long_name
      
  (* only in sig_item *)
  | Val of tok * name (* val_ident *) * tok (*:*) * ty
      
  (* only in struct_item *)
  | Let of tok * rec_opt * let_binding and_list

  | Module of tok * uname * tok * module_expr
      
  | ItemTodo of tok

type sig_item = item
type struct_item = item

(* ------------------------------------------------------------------------- *)
(* Toplevel phrases *)
(* ------------------------------------------------------------------------- *)

type toplevel =
  | TopItem of item

  (* should both be removed *)
  | TopSeqExpr of seq_expr
  | ScSc of tok (* ;; *)

  (* some ml files contain some #! or even #load directives *)
  | TopDirective of tok

type program = toplevel list

 (* with tarzan *)

(*****************************************************************************)
(* Any *)
(*****************************************************************************)

type any =
  | Ty of ty
  | Expr of expr
  | Pattern of pattern

  | Item of item
  | Toplevel of toplevel
  | Program of program

  | TypeDeclaration of type_declaration
  | TypeDefKind of type_def_kind
  | FieldDeclaration of field_declaration

  | MatchCase of match_case
  | LetBinding of let_binding

  | Constant of constant

  | Argument of argument
  | Body of seq_expr

  | Info of tok
  | InfoList of tok list
  (* with tarzan *)

(*****************************************************************************)
(* Wrappers *)
(*****************************************************************************)

let str_of_name (Name (s,_)) = s
let info_of_name (Name (_,info)) = info

let uncomma xs = Common.map_filter (function
  | Left e -> Some e
  | Right _info -> None
  ) xs
let unpipe xs = uncomma xs

let name_of_long_name (_, name) = name
let module_of_long_name (qu, _) = 
  qu +> List.map fst +> List.map str_of_name +> Common.join "."
let module_infos_of_long_name (qu, _) = 
  qu +> List.map fst +> List.map info_of_name

OCaml

Innovation. Community. Security.