File: CGenParser_lib.ml

package info (click to toggle)
herdtools7 7.58-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 19,732 kB
  • sloc: ml: 128,583; ansic: 3,827; makefile: 670; python: 407; sh: 212; awk: 14
file content (246 lines) | stat: -rw-r--r-- 7,731 bytes parent folder | download
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
(****************************************************************************)
(*                           the diy toolsuite                              *)
(*                                                                          *)
(* Jade Alglave, University College London, UK.                             *)
(* Luc Maranget, INRIA Paris-Rocquencourt, France.                          *)
(*                                                                          *)
(* Copyright 2010-present Institut National de Recherche en Informatique et *)
(* en Automatique and the authors. All rights reserved.                     *)
(*                                                                          *)
(* This software is governed by the CeCILL-B license under French law and   *)
(* abiding by the rules of distribution of free software. You can use,      *)
(* modify and/ or redistribute the software under the terms of the CeCILL-B *)
(* license as circulated by CEA, CNRS and INRIA at the following URL        *)
(* "http://www.cecill.info". We also give a copy in LICENSE.txt.            *)
(****************************************************************************)

(******************************)
(* A 'generic' parsing module *)
(******************************)

(* Configuration, to change kinds and condition *)
module type Config = sig
  val debuglexer : bool
  val verbose : int
  val check_kind : string -> ConstrGen.kind option
  val check_cond : string -> string option
  val macros : string option
  val libfind : string -> string
end

module DefaultConfig = struct
  let debuglexer = false
  let verbose = 0
  let check_kind _ = None
  let check_cond _ = None
  let macros = None
  let libfind = Misc.identity
end
(* input signature, a lexer and a parser for a given architecture *)
module type LexParse = sig
  type token
  type pseudo

  val deep_lexer : Lexing.lexbuf -> token
  val deep_parser :
        (Lexing.lexbuf -> token) -> Lexing.lexbuf ->
	  pseudo list CAst.test list * MiscParser.extra_data

  val shallow_lexer : Lexing.lexbuf -> token
  val shallow_parser :
        (Lexing.lexbuf -> token) -> Lexing.lexbuf ->
	  string CAst.t list * MiscParser.extra_data

  type macro
  val macros_parser :
      (Lexing.lexbuf -> token) -> Lexing.lexbuf -> macro list
  val macros_expand : macro list -> pseudo -> pseudo
end

(* Output signature *)
module type S = sig
  type pseudo
  type init = MiscParser.state
  type prog = (MiscParser.proc * pseudo list) list
  type locations = MiscParser.LocSet.t

  val parse : in_channel -> Splitter.result ->  pseudo MiscParser.t
  val parse_string : string -> Splitter.result ->  pseudo MiscParser.t
end


module Make
    (O:Config)
    (A:ArchBase.S)
    (L: LexParse
    with type pseudo = A.pseudo) : S with type pseudo = A.pseudo =
  struct
    type pseudo = A.pseudo
    type init = MiscParser.state
    type prog = (MiscParser.proc * pseudo list) list
    type locations = MiscParser.LocSet.t

(****************)
(* Basic Checks *)
(****************)
    module U = GenParserUtils
    let call_parser = U.call_parser

    let check_procs procs =
      Misc.iteri
        (fun k p ->
          if k <> p then
            Warn.fatal "Processes must be P0, P1, ...")
        procs

    let check_regs = U.check_regs

(***********)
(* Parsing *)
(***********)

(* Lexers *)
module LexConfig = struct let debug = O.debuglexer end
module LU = LexUtils.Make (LexConfig)
module SL = StateLexer.Make (LexConfig)

let parse_cond lexbuf =
  let cond =  call_parser "cond" lexbuf SL.token StateParser.main_constr in
  cond

(* Compute hash as litmus does *)
module D = CTestHash.Make(DumpCAst)

module Do
         (I:
	    sig
	      type src
	      val call_parser_loc :
                string ->
                src -> Pos.pos2 ->
                'a -> ('a -> Lexing.lexbuf -> 'b) -> 'b
            end) = struct
  let parse chan
            {
              Splitter.locs = (init_loc, prog_loc,constr_loc,_) ;
              name = name ;
              info = info ; _
	    }  =
    let init =
      I.call_parser_loc "init"
		      chan init_loc SL.token StateParser.init in
    let prog,_ =
      I.call_parser_loc "prog" chan prog_loc L.deep_lexer L.deep_parser in
    let prog_litmus,data_litmus =
      I.call_parser_loc "prog_litmus" chan prog_loc L.shallow_lexer L.shallow_parser in
    (* Add parameter passsing as inits *)
    let full_init =
      let open CAst in
      List.fold_left
        (fun env f -> match f with
		      | Global _ -> env
		      | Test t ->
			 let p = t.proc in
			 List.fold_left
			   (fun env param ->
			    let loc = param.param_name in
			    let ty = TestType.TyDef in
			    (MiscParser.Location_reg (p,loc),
			     (ty,ParsedConstant.nameToV loc))::env)
			   env t.params)
        init prog_litmus in
    let procs = List.map (fun p -> p.CAst.proc) prog in
    check_procs procs ;
    let params =  List.map (fun p -> p.CAst.params) prog in

    let expand_body = match O.macros with
    | None -> Misc.identity
    | Some fmacros ->
        let fname =  O.libfind fmacros in
        let ms =
          Misc.input_protect
            (fun chan ->
              let buff = Lexing.from_channel chan in
              LexMisc.init_file fname buff ;
              call_parser "macros"
                buff
                L.deep_lexer
                L.macros_parser)
            fname in
        List.map (L.macros_expand ms) in

    let prog =  List.map (fun p -> (p.CAst.proc,None,MiscParser.Main),expand_body p.CAst.body) prog in
(*
    List.iter
      (fun (p,code) ->
        Printf.eprintf "++++++ %i\n" p ;
        List.iter
          (fun p ->
            A.pseudo_iter
              (fun i -> Printf.eprintf "%s\n" (A.dump_instruction i))
              p)
          code)
      prog ;
*)
    let (locs,filter,final,_quantifiers) =
      I.call_parser_loc "final"
		      chan constr_loc SL.token StateParser.constraints in
    check_regs procs init locs final ;
    let all_locs = U.get_visible_locs locs final in
    let parsed =
      {
        MiscParser.info; init=full_init; prog = prog;
        filter = filter;
        condition = final;
        locations = locs;
        extra_data = (MiscParser.CExtra params)::data_litmus;
      } in
    let name  = name.Name.name in
    let parsed =
      match O.check_cond name  with
      | None -> parsed
      | Some k ->
         let cond = parse_cond (Lexing.from_string k) in
         { parsed with
           MiscParser.condition = cond ;} in
    let parsed =
      match O.check_kind name  with
      | None -> parsed
      | Some k ->
         { parsed with
           MiscParser.condition =
             ConstrGen.set_kind k parsed.MiscParser.condition; } in
    let parsed = match MiscParser.get_hash parsed with
        | None ->
            let info = parsed.MiscParser.info in
            { parsed with MiscParser.info =
	       ("Hash",
		(* For computing hash, we must parse as litmus does.
                This includes stripping away toplevel '*' of types *)
		let prog = List.map CAstUtils.strip_pointers prog_litmus in
		D.digest info init prog all_locs)::info ; }
        | Some _ -> parsed in
    parsed
end


  let parse chan x =
    let module Src = struct
      type src = in_channel
      let call_parser_loc name chan loc =
        let lexbuf = LU.from_section loc chan in
        call_parser name lexbuf
    end in
    let module P = Do(Src) in
    P.parse chan x

  let parse_string s x =
    let module Src = struct
      type src = string
      let call_parser_loc name s loc =
        let lexbuf = LU.from_section_string loc s in
        call_parser name lexbuf
    end in
    let module P = Do(Src) in
    P.parse s x
end