Import Upstream version 20180207
[hcoop/debian/mlton.git] / mlton / ast / ast-mlbs.fun
CommitLineData
7f918cf1
CE
1(* Copyright (C) 2017-2018 Matthew Fluet.
2 * Copyright (C) 1999-2007 Henry Cejtin, Matthew Fluet, Suresh
3 * Jagannathan, and Stephen Weeks.
4 * Copyright (C) 1997-2000 NEC Research Institute.
5 *
6 * MLton is released under a BSD-style license.
7 * See the file MLton-LICENSE for details.
8 *)
9
10functor AstMLBs (S: AST_MLBS_STRUCTS): AST_MLBS =
11struct
12
13open S
14
15structure AstPrograms = AstPrograms (S)
16
17open AstPrograms Layout
18
19fun mkCtxt (x, lay) () =
20 seq [str "in: ", lay x]
21
22val layouts = List.map
23structure Wrap = Region.Wrap
24val node = Wrap.node
25
26(*---------------------------------------------------*)
27(* Basdecs and Basexps *)
28(*---------------------------------------------------*)
29
30datatype basexpNode =
31 Bas of basdec
32 | Let of basdec * basexp
33 | Var of Basid.t
34and basdecNode =
35 Ann of string * Region.t * basdec
36 | Basis of {name: Basid.t, def: basexp} vector
37 | Defs of ModIdBind.t
38 | Local of basdec * basdec
39 | MLB of {fileAbs: File.t, fileUse: File.t} * basdec Promise.t
40 | Open of Basid.t vector
41 | Prim
42 | Prog of {fileAbs: File.t, fileUse: File.t} * Program.t Promise.t
43 | Seq of basdec list
44withtype basexp = basexpNode Wrap.t
45 and basdec = basdecNode Wrap.t
46
47fun layoutBasexp exp =
48 case node exp of
49 Bas dec => align [str "bas", indent (layoutBasdec dec, 3), str "end"]
50 | Let (dec, exp) => Pretty.lett (layoutBasdec dec, layoutBasexp exp)
51 | Var basid => Basid.layout basid
52and layoutBasdec dec =
53 case node dec of
54 Ann (anns,_, dec) =>
55 align [str "ann",
56 indent (seq [str String.dquote, str anns, str String.dquote], 3),
57 str "in",
58 indent (layoutBasdec dec, 3),
59 str "end"]
60 | Basis basbnds =>
61 layoutAndsBind
62 ("basis", "=", basbnds, fn {name, def} =>
63 (case node def of Var _ => OneLine | _ => Split 3,
64 Basid.layout name, layoutBasexp def))
65 | Defs def => ModIdBind.layout def
66 | Local (dec1, dec2) => Pretty.locall (layoutBasdec dec1, layoutBasdec dec2)
67 | MLB ({fileUse, ...}, _) => File.layout fileUse
68 | Open bs => seq [str "open ",
69 seq (separate (Vector.toListMap (bs, Basid.layout),
70 " "))]
71 | Prim => str "_prim"
72 | Prog ({fileUse, ...}, _) => File.layout fileUse
73 | Seq decs => align (layoutBasdecs decs)
74and layoutBasdecs decs = layouts (decs, layoutBasdec)
75
76fun checkSyntaxBasexp (e: basexp): unit =
77 case node e of
78 Bas dec => checkSyntaxBasdec dec
79 | Let (dec, exp) => (checkSyntaxBasdec dec
80 ; checkSyntaxBasexp exp)
81 | Var _ => ()
82and checkSyntaxBasdec (d: basdec): unit =
83 case node d of
84 Ann (_, _, dec) => checkSyntaxBasdec dec
85 | Basis basbnds =>
86 reportDuplicates
87 (basbnds, {ctxt = mkCtxt (d, layoutBasdec),
88 equals = (fn ({name = id, ...}, {name = id', ...}) =>
89 Basid.equals (id, id')),
90 layout = Basid.layout o #name,
91 name = "basis definition",
92 region = Basid.region o #name})
93 | Defs def => ModIdBind.checkSyntax def
94 | Local (dec1, dec2) =>
95 (checkSyntaxBasdec dec1
96 ; checkSyntaxBasdec dec2)
97 | MLB _ => ()
98 | Open _ => ()
99 | Prim => ()
100 | Prog _ => ()
101 | Seq decs => List.foreach (decs, checkSyntaxBasdec)
102
103fun sourceFiles (d: basdec): File.t vector =
104 let
105 val sourceFiles : File.t Buffer.t =
106 Buffer.new {dummy = "<dummy>"}
107 val psi : File.t -> bool ref =
108 String.memoize (fn _ => ref false)
109
110 fun sourceFilesBasexp (e: basexp): unit =
111 case node e of
112 Bas dec => sourceFilesBasdec dec
113 | Let (dec, exp) => (sourceFilesBasdec dec
114 ; sourceFilesBasexp exp)
115 | Var _ => ()
116 and sourceFilesBasdec (d: basdec): unit =
117 case node d of
118 Ann (_, _, dec) => sourceFilesBasdec dec
119 | Basis basbnds =>
120 Vector.foreach
121 (basbnds, fn {def, ...} =>
122 sourceFilesBasexp def)
123 | Defs _ => ()
124 | Local (dec1, dec2) => (sourceFilesBasdec dec1
125 ; sourceFilesBasdec dec2)
126 | MLB ({fileAbs, fileUse, ...}, dec) =>
127 let
128 val b = psi fileAbs
129 in
130 if !b
131 then ()
132 else let
133 val () = b := true
134 in
135 Buffer.add (sourceFiles, fileUse)
136 ; sourceFilesBasdec (Promise.force dec)
137 end
138 end
139 | Open _ => ()
140 | Prim => ()
141 | Prog ({fileUse, ...}, _) => Buffer.add (sourceFiles, fileUse)
142 | Seq decs => List.foreach (decs, sourceFilesBasdec)
143 val () = sourceFilesBasdec d
144 in
145 Buffer.toVector sourceFiles
146 end
147val sourceFiles =
148 Trace.trace
149 ("AstMLBs.sourceFiles", Layout.ignore, Vector.layout File.layout)
150 sourceFiles
151
152
153structure Basexp =
154 struct
155 open Wrap
156 type basdec = basdec
157 type t = basexp
158 datatype node = datatype basexpNode
159 type node' = node
160 type obj = t
161
162 val layout = layoutBasexp
163 end
164
165structure Basdec =
166 struct
167 open Wrap
168 type t = basdec
169 datatype node = datatype basdecNode
170 type node' = node
171 type obj = t
172
173 fun make n = makeRegion (n, Region.bogus)
174 val seq = make o Seq
175 val empty = seq []
176 val checkSyntax = checkSyntaxBasdec
177 val layout = layoutBasdec
178 val sourceFiles = sourceFiles
179 end
180end