environment.sml 65.1 KB
Newer Older
1
2
structure Environment : sig
   type environment
3

Axel Simon's avatar
Axel Simon committed
4
5
   structure SpanMap : ORD_MAP where type Key.ord_key = Error.span

Axel Simon's avatar
Axel Simon committed
6
7
   structure SymbolSet : ORD_SET where type Key.ord_key = SymbolTable.symid
   
8
9
10
   val primitiveEnvironment : (SymbolTable.symid *
                               Types.texp *
                               (BooleanDomain.bfun -> BooleanDomain.bfun) *
Axel Simon's avatar
Axel Simon committed
11
12
13
                               (Types.texp option)) list *
                               SizeConstraint.size_constraint list ->
                               environment
Axel Simon's avatar
Axel Simon committed
14
15
16
17
   
   val pushSingle : VarInfo.symid * Types.texp * environment -> environment
   
   (*add a group of bindings to the current environment, each element in a
Axel Simon's avatar
Axel Simon committed
18
19
20
   binding is identified by its symbol, the flag is true if the symbol
   is a decoder function*)
   val pushGroup : (VarInfo.symid * bool) list * environment ->
Axel Simon's avatar
Axel Simon committed
21
                  environment
22
23
   (*remove a binding group from the stack; the flag is true if the outermost
   scope should be kept, the result is a list of error messages about
24
   ambiguous type variables*)
25
   val popGroup : environment * bool ->
Axel Simon's avatar
Axel Simon committed
26
                  (Error.span * string) list * environment
mb0's avatar
Merge.    
mb0 committed
27
   
28
   (*ask for all the symbols in the binding group*)
mb0's avatar
Merge.    
mb0 committed
29
30
   val getGroupSyms : environment -> VarInfo.symid list
   
Axel Simon's avatar
Axel Simon committed
31
   val pushTop : environment -> environment
32
33
34
35
36
   
   (*pushes the given type onto the stack, if the flag is true, type variables
   are renamed*)
   val pushType : bool * Types.texp * environment -> environment

37
38
   val pushMonadType : Types.texp * environment -> environment
   
Axel Simon's avatar
Axel Simon committed
39
40
   (* push the width of a decode onto the stack*)
   val pushWidth : VarInfo.symid * environment -> environment
41

42
43
44
   (* For a function from a type containing several type variables to an
   algoebraic data type, generate implications from the arguments of the
   algebraic data type to the argument of this function. *)
45
   val genConstructorFlow : (bool * environment) -> environment
46
47
   
    (*given an occurrence of a symbol at a position, push its type onto the
Axel Simon's avatar
Axel Simon committed
48
49
50
51
    stack; arguments are the symbol to look up, the position it occurred and a
    Boolean flag indicating if this usage should be recorded (True) or if an
    existing type should be used (False) *)
   val pushSymbol : VarInfo.symid * Error.span * bool * environment -> environment
Axel Simon's avatar
Axel Simon committed
52

Axel Simon's avatar
Axel Simon committed
53
54
55
   (*search in the current stack for the symbol and, if unsuccessful, in the
   nested definitions and push all nested groups onto the stack, returns the
   new stack and the number of nested groups that had to be pushed*)
Axel Simon's avatar
Axel Simon committed
56
57
58
59
   val pushNested : VarInfo.symid * environment -> (int * environment)

   (*pops the nested groups that were pushed by pushNested*)
   val popNested : int * environment -> environment
Axel Simon's avatar
Axel Simon committed
60

Axel Simon's avatar
Axel Simon committed
61
62
   val getUsages : VarInfo.symid * environment -> Error.span list
   
Axel Simon's avatar
Axel Simon committed
63
   val getContextOfUsage : VarInfo.symid * Error.span * environment ->
64
                           VarInfo.symid
Axel Simon's avatar
Axel Simon committed
65

66
67
68
   val getCtxt : environment -> VarInfo.symid list

      (*stack: [...,t] -> [...] and type of f for call-site s is set to t*)
69
70
71
72
   val popToUsage : VarInfo.symid * Error.span * environment -> environment

   (*stack: [...] -> [...,t] where t is type of usage of f at call-site s*)
   val pushUsage : VarInfo.symid * Error.span * environment -> environment
Axel Simon's avatar
Axel Simon committed
73
   
74
   (*stack: [...] -> [..., x:a], 'a' fresh; primed version also returns 'a'*)
75
   val pushLambdaVar' : VarInfo.symid * environment -> (Types.texp * environment)
76
77
   val pushLambdaVar : VarInfo.symid * environment -> environment
   
78
79
80
81
   (*stack: [..., t0, t1, ... tn] -> [..., {f1:t1, ... fn:tn, t0:...}]*)
   val reduceToRecord : (BooleanDomain.bvar * FieldInfo.symid) list *
                        environment -> environment

Axel Simon's avatar
Axel Simon committed
82
83
84
   (*stack: [..., tn, ..., t2, t1, t0] -> [..., SUM (tn,..t0)]*)
   val reduceToSum : int * environment -> environment
   
85
   (*stack: [...,t1,t2,...,tn] -> [...,(t1, ... t n-1) -> tn]*)
86
   val reduceToFunction : environment * int -> environment
87
   
88
   (*stack: [...,t1 -> t2] -> [...t2]*)
89
   val reduceToResult : environment -> environment
90
91
92
93
94
95

   (*stack: [..., tn, ..., t2, t1, t0] -> [..., t0]*)
   val return : int * environment -> environment

   val popKappa : environment -> environment

Axel Simon's avatar
Axel Simon committed
96
   (*stack: [...,t] -> [...] and type of function f is set to t*)
97
   val popToFunction : VarInfo.symid * environment -> environment
Axel Simon's avatar
Axel Simon committed
98

99
100
101
   (*push the name of the function into the current context (the context
   determines in which function calls to unknown functions are recorded)*)
   val enterFunction : VarInfo.symid * environment -> environment
102

Axel Simon's avatar
Axel Simon committed
103
   (*pop the last function from the current context*)
104
105
   val leaveFunction : VarInfo.symid * environment -> environment
   
106
107
108
109
   (*unset the type of function f, if the function type was set, return an
   environment in which the function type was pushed*)
   val clearFunction : VarInfo.symid * environment ->
         environment option * environment
Axel Simon's avatar
Axel Simon committed
110
   
111
112
   val forceNoInputs : VarInfo.symid * VarInfo.symid list *
                     environment -> VarInfo.symid list
113
114
115
116

    (*apply the Boolean function*)
   val meetBoolean : (BooleanDomain.bfun -> BooleanDomain.bfun) *
         environment -> environment
117

Axel Simon's avatar
Axel Simon committed
118
119
120
121
   val meetSizeConstraint : (SizeConstraint.size_constraint_set ->
                             SizeConstraint.size_constraint_set) *
                             environment -> environment

Axel Simon's avatar
Axel Simon committed
122
123
   val meetFlow : environment * environment -> environment
   val meet : environment * environment -> environment
Axel Simon's avatar
Axel Simon committed
124

Axel Simon's avatar
Axel Simon committed
125
126
127
   (*returns the set of substitutions for the first environment, this is empty
   if the the first environment is more specific (smaller) than the second*)
   val subseteq : environment * environment -> Substitutions.Substs
Axel Simon's avatar
Axel Simon committed
128
129
130
131

   (*query all function symbols in binding groups that would be modified by
   the given substitutions*)
   val affectedFunctions : Substitutions.Substs * environment -> SymbolSet.set
Axel Simon's avatar
Axel Simon committed
132

Axel Simon's avatar
Axel Simon committed
133
   val toString : environment -> string
Axel Simon's avatar
Axel Simon committed
134
   val toStringSI : environment * TVar.varmap -> string * TVar.varmap
135
   val topToString : environment -> string
136
   val topToStringSI : environment * TVar.varmap -> string * TVar.varmap
Axel Simon's avatar
Axel Simon committed
137
   val kappaToString : environment -> string
Axel Simon's avatar
Axel Simon committed
138
   val kappaToStringSI : environment * TVar.varmap -> string * TVar.varmap
139
140
   val funTypeToStringSI  : environment * VarInfo.symid * TVar.varmap ->
                            string * TVar.varmap
141
142
143
end = struct
   structure ST = SymbolTable
   structure BD = BooleanDomain
Axel Simon's avatar
Axel Simon committed
144
   structure SC = SizeConstraint
145
   structure SpanMap = SpanMap
146
   open Types
Axel Simon's avatar
Axel Simon committed
147
   open Substitutions
148

Axel Simon's avatar
Axel Simon committed
149
   (*any error that is not due to unification*)
150
   exception InferenceBug
151
   
152
153
154
   datatype binding
      = KAPPA of {
         ty : texp
Axel Simon's avatar
Axel Simon committed
155
      } | SINGLE of {
156
157
         name : ST.symid,
         ty : texp
Axel Simon's avatar
Axel Simon committed
158
      } | GROUP of {
159
         name : ST.symid,
Axel Simon's avatar
Axel Simon committed
160
         (*the type of this function, NONE if not yet known*)
161
         ty : (texp * BD.bfun) option,
Axel Simon's avatar
Axel Simon committed
162
163
         (*this is SOME (CONST w) if this is a decode function with pattern width w*)
         width : texp option,
164
         uses : (ST.symid * texp) SpanMap.map,
Axel Simon's avatar
Axel Simon committed
165
166
         (*a tree of nested binding groups*)
         nested : binding list
167
168
      } list
   
169
170
171
172
   datatype bind_info
      = SIMPLE of { ty : texp }
      | COMPOUND of { ty : (texp * BD.bfun) option, width : texp option,
                      uses : (ST.symid * texp) SpanMap.map,
Axel Simon's avatar
Axel Simon committed
173
                      nested : binding list }
174

175
176
177
178
   (*a scope contains one of the bindings above and some additional
   information that make substitution and join cheaper*)
   structure Scope : sig
      type scope
Axel Simon's avatar
Axel Simon committed
179
180
181
182
183
184
      type constraints
      val getFlow : constraints -> BooleanDomain.bfun
      val setFlow : BooleanDomain.bfun -> constraints -> constraints
      val getSize : constraints -> SC.size_constraint_set
      val setSize : SC.size_constraint_set -> constraints -> constraints
      val getCtxt : constraints -> VarInfo.symid list
185
      val getCurFun : constraints -> VarInfo.symid
Axel Simon's avatar
Axel Simon committed
186
187
      val setCtxt : VarInfo.symid list -> constraints -> constraints

188
      type environment = scope list * constraints
Axel Simon's avatar
Axel Simon committed
189
190
      val initial : binding * SC.size_constraint_set -> environment
      val wrap : binding * environment -> environment
191
192
      val wrapWithVars : binding * TVar.set * environment ->
                         environment
193
      val unwrap : environment -> (binding * environment)
Axel Simon's avatar
Axel Simon committed
194
195
      val unwrapDifferent : environment * environment ->
            (binding * binding) option * environment * environment
Axel Simon's avatar
Axel Simon committed
196
      val getVars : environment -> TVar.set
197
      val getBVars : environment -> BD.bvarset
198
199
      val getVarsUses : ST.symid * environment -> TVar.set * BD.bvarset
      val getMonoVars : environment -> TVar.set * BD.bvarset
Axel Simon's avatar
Axel Simon committed
200
      val lookup : ST.symid * environment -> TVar.set * bind_info
201
      val update : ST.symid  *
202
                   (bind_info * constraints -> bind_info * constraints) *
203
                   environment-> environment
Axel Simon's avatar
Axel Simon committed
204
      val toString : scope * TVar.varmap -> string * TVar.varmap
205
206
207
208
   end = struct
      type scope = {
         bindInfo : binding,
         typeVars : TVar.set,
209
         boolVars : BD.bvarset,
210
211
         version : int
      }
Axel Simon's avatar
Axel Simon committed
212
213
214
215
216
217
218
219
220
221
222
223
224
      type constraints = {
         flowInfo : BD.bfun,
         sizeInfo : SC.size_constraint_set,
         context : VarInfo.symid list
      }
      
      fun getFlow { flowInfo = fi, sizeInfo, context } = fi
      fun setFlow fi { flowInfo = _, sizeInfo = si, context = ctxt } =
         { flowInfo = fi, sizeInfo = si, context = ctxt }
      fun getSize { flowInfo, sizeInfo = si, context } = si
      fun setSize si { flowInfo = fi, sizeInfo = _, context = ctxt } =
         { flowInfo = fi, sizeInfo = si, context = ctxt }
      fun getCtxt { flowInfo, sizeInfo, context = ctxt } = ctxt
225
226
227
      fun getCurFun { flowInfo, sizeInfo, context = ctxt } = case ctxt of
           (curFun :: _) => curFun
         | [] => raise InferenceBug
Axel Simon's avatar
Axel Simon committed
228
229
230
      fun setCtxt ctxt { flowInfo = fi, sizeInfo = si, context = _ } =
         { flowInfo = fi, sizeInfo = si, context = ctxt }

231
      type environment = scope list * constraints
Axel Simon's avatar
Axel Simon committed
232
   
Axel Simon's avatar
Axel Simon committed
233
      val verCounter = ref 1
234
235
236
237
238
239
      fun nextVersion () =  let
           val v = !verCounter
         in
           (verCounter := v+1; v)
         end             

Axel Simon's avatar
Axel Simon committed
240
      fun prevTVars [] = TVar.empty
Axel Simon's avatar
Axel Simon committed
241
        | prevTVars ({bindInfo, typeVars = tv, boolVars, version}::_) = tv
242

243
244
245
      fun varsOfBinding (KAPPA {ty=t}, set) = texpVarset (t,set)
        | varsOfBinding (SINGLE {name, ty=t}, set) = texpVarset (t,set)
        | varsOfBinding (GROUP bs, set) = let
246
247
           fun vsOpt (SOME t,set) = texpVarset (t,set)
             | vsOpt (NONE,set) = set
248
249
           fun bvsOpt (SOME (t,_),set) = texpVarset (t,set)
             | bvsOpt (NONE,set) = set
250
           fun getUsesVars ((ctxt',t),set) = texpVarset (t,set)
251
           fun getBindVars ({name=n, ty=t, width=w, uses, nested},set) =
252
               List.foldl getUsesVars
253
                  (bvsOpt (t, vsOpt (w,set)))
Axel Simon's avatar
Axel Simon committed
254
                  (SpanMap.listItems uses)
255
256
257
        in
           List.foldl getBindVars set bs
        end
258

259
      fun prevBVars [] = BD.emptySet
Axel Simon's avatar
Axel Simon committed
260
        | prevBVars ({bindInfo, typeVars, boolVars = bv, version}::_) = bv
261
262

      val texpBVarset = texpBVarset (fn ((_,v),vs) => BD.addToSet (v,vs))
Axel Simon's avatar
Axel Simon committed
263

264
265
266
      fun bvarsOfBinding (KAPPA {ty}, ctxt, set) = texpBVarset (ty,set)
        | bvarsOfBinding (SINGLE {name, ty}, ctxt, set) = texpBVarset (ty,set)
        | bvarsOfBinding (GROUP bs, ctxt, set) =
Axel Simon's avatar
Axel Simon committed
267
         let
268
269
            fun getUsesVars ((site,t),set) =
               if List.exists (fn sym => ST.eq_symid (sym,site)) ctxt then
Axel Simon's avatar
Axel Simon committed
270
271
272
                  texpBVarset (t,set)
               else
                  set
273
            fun getBindVars ({name=n, ty=tOpt, width, uses, nested},set) =
274
               List.foldl getUsesVars
275
276
                  (if List.exists (fn sym => ST.eq_symid (sym,n)) ctxt
                   then case tOpt of
277
278
279
                     NONE => set | SOME (t,_) => texpBVarset (t,set)
                   else set)
                  (SpanMap.listItems uses)
Axel Simon's avatar
Axel Simon committed
280
281
282
283

         in
            List.foldl getBindVars set bs
         end
284

285
286
287
288
289
290
291
292
293
294
      fun getMonoVars (bis,_) = List.foldl
        (fn ({bindInfo = bi, typeVars, boolVars, version},(vSet,bSet)) => 
         case bi of
              KAPPA { ty = t } => (texpVarset (t,vSet), texpBVarset (t,bSet))
            | SINGLE { ty = t,... } => (texpVarset (t,vSet), texpBVarset (t,bSet))
            | GROUP _ => (vSet,bSet))
        (TVar.empty, BD.emptySet) bis

      fun getVarsUses (sym, (scs,_)) =
         let
295
296
            fun getUsesVars ((site,t),(vSet,bSet)) =
               if ST.eq_symid (sym,site) then
297
298
299
300
301
                  (texpVarset (t,vSet), texpBVarset (t,bSet))
               else
                  (vSet,bSet)
            fun getWidthVars (NONE, set) = set
              | getWidthVars (SOME w, (vSet,bSet)) = (texpVarset (w,vSet),bSet)
302
            fun getBindVars ({name, ty, width = wOpt, uses, nested},set) =
303
304
305
306
307
308
309
310
311
312
313
               List.foldl getUsesVars (getWidthVars (wOpt, set))
                  (SpanMap.listItems uses)
            fun getGroupVars ({bindInfo = bi, typeVars, boolVars, version},set) =
               case bi of
                    KAPPA {ty} => set
                  | SINGLE {name, ty} => set
                  | GROUP bs => List.foldl getBindVars set bs
         in
            List.foldl getGroupVars (TVar.empty, BD.emptySet) scs
         end

Axel Simon's avatar
Axel Simon committed
314
      fun initial (b, scs) =
315
316
         ([{
            bindInfo = b,
317
            typeVars = varsOfBinding (b, TVar.empty),
Axel Simon's avatar
Axel Simon committed
318
            boolVars = BD.emptySet,
319
            version = 0
Axel Simon's avatar
Axel Simon committed
320
321
322
323
324
325
          }], {
            flowInfo = BD.empty,
            sizeInfo = scs,
            context = []
          })
      fun wrap (b, (scs, state)) =
326
327
         ({
            bindInfo = b,
328
329
            typeVars = varsOfBinding (b, prevTVars scs),
            boolVars = bvarsOfBinding (b, getCtxt state, prevBVars scs),
330
            version = nextVersion ()
Axel Simon's avatar
Axel Simon committed
331
         }::scs,state)
332
333
334
335
336
337
338
      fun wrapWithVars (b, tVars, (scs, state)) =
         ({
            bindInfo = b,
            typeVars = (*varsOfBinding (b, prevTVars scs)*)tVars,
            boolVars = bvarsOfBinding (b, getCtxt state, prevBVars scs),
            version = nextVersion ()
         }::scs,state)
Axel Simon's avatar
Axel Simon committed
339
340
341
      fun unwrap ({bindInfo = bi, typeVars, boolVars, version} :: scs, state) =
            (bi, (scs, state))
        | unwrap ([], state) = raise InferenceBug
Axel Simon's avatar
Axel Simon committed
342
      fun unwrapDifferent
Axel Simon's avatar
Axel Simon committed
343
            ((all1 as ({bindInfo = bi1, typeVars = _, boolVars = _, version = v1 : int}::scs1,
344
             cons1))
Axel Simon's avatar
Axel Simon committed
345
            ,(all2 as ({bindInfo = bi2, typeVars = _, boolVars = _, version = v2 : int}::scs2,
346
             cons2))) =
Axel Simon's avatar
Axel Simon committed
347
            if v1=v2 then (NONE, all1, all2)
348
            else (SOME (bi1,bi2),(scs1,cons1),(scs2,cons2))
Axel Simon's avatar
Axel Simon committed
349
350
351
        | unwrapDifferent (all1 as ([], _), all2 as ([], _)) =
            (NONE, all1, all2)
        | unwrapDifferent (_, _) = raise InferenceBug
352
      
353
      fun getVars (scs, state) = prevTVars scs
Axel Simon's avatar
Axel Simon committed
354

355
      fun getBVars (scs, state) = prevBVars scs
356
357

      fun lookup (sym, (scs, cons)) =
358
         let
mb0's avatar
mb0 committed
359
            fun l [] = (TextIO.print ("urk, tried to lookup non-existent symbol " ^ SymbolTable.getString(!SymbolTables.varTable, sym) ^ "\n")
Axel Simon's avatar
Axel Simon committed
360
                       ;raise InferenceBug)
Axel Simon's avatar
Axel Simon committed
361
362
              | l ({bindInfo = KAPPA _, typeVars, boolVars, version}::scs) = l scs
              | l ({bindInfo = SINGLE {name, ty}, typeVars, boolVars, version}::scs) =
Axel Simon's avatar
Axel Simon committed
363
                  if ST.eq_symid (sym,name) then
364
                     (prevTVars scs, SIMPLE { ty = ty})
Axel Simon's avatar
Axel Simon committed
365
                  else l scs
Axel Simon's avatar
Axel Simon committed
366
              | l ({bindInfo = GROUP bs, typeVars, boolVars, version}::scs) =
Axel Simon's avatar
Axel Simon committed
367
                  let fun lG other [] = l scs
368
                        | lG other ((b as {name, ty, width, uses, nested})::bs) =
369
                           if ST.eq_symid (sym,name) then
370
371
                              (prevTVars scs,
                              COMPOUND { ty = ty, width = width, uses = uses, nested = nested })
Axel Simon's avatar
Axel Simon committed
372
                           else lG (b :: other) bs
373
                  in
Axel Simon's avatar
Axel Simon committed
374
                     lG [] bs
375
376
377
378
                  end
         in
            l scs
         end
Axel Simon's avatar
Axel Simon committed
379

380
381
      fun update (sym, action, env) =
         let
382
383
            fun tryUpdate (KAPPA _, cons) = NONE
              | tryUpdate (SINGLE {name, ty}, cons) =
384
385
                if ST.eq_symid (sym,name) then
                  let
386
                     val (SIMPLE {ty}, cons) = action (SIMPLE {ty = ty}, cons)
387
                  in
388
                     SOME (SINGLE {name = name, ty = ty}, cons)
389
390
                  end
                else NONE
391
              | tryUpdate (GROUP bs, cons) =
392
               let fun upd (otherBs, []) = NONE
393
                     | upd (otherBs, (b as {name, ty, width, uses, nested})::bs) =
394
395
                        if ST.eq_symid (sym,name) then
                           let val (COMPOUND { ty = ty, width = width,
396
                                               uses = uses, nested = nested}, cons) =
397
                                   action (COMPOUND { ty = ty, width = width,
398
                                                      uses = uses, nested = nested}, cons)
399
400
401
                           in
                              SOME (GROUP (List.revAppend (otherBs,
                                          {name = name, ty = ty,
402
403
                                           width = width, uses = uses,
                                           nested = nested} :: bs))
404
                                   ,cons)
405
406
407
408
409
                           end
                        else upd (b::otherBs, bs)
               in
                  upd ([],bs)
               end
Axel Simon's avatar
Axel Simon committed
410
411
            fun unravel (bs, ([],_)) = raise InferenceBug
              | unravel (bs, env) = case unwrap env of
412
413
               (b, env as (scs, cons)) =>
                  (case tryUpdate (b, cons) of
414
                       NONE => unravel (b::bs, env)
415
                     | SOME (b,cons) => List.foldl wrap (scs, cons) (b::bs) )
416
417
418
         in
            unravel ([], env)
         end
Axel Simon's avatar
Axel Simon committed
419

Axel Simon's avatar
Axel Simon committed
420
      fun showVarsVer (typeVars,boolVars,ver,si) =
Axel Simon's avatar
Axel Simon committed
421
422
         let
            val (vsStr, si) = TVar.setToString (typeVars,si)
423
            val bsStr = BD.setToString boolVars
Axel Simon's avatar
Axel Simon committed
424
         in
425
            ("ver=" ^ Int.toString(ver) ^
426
             (*", bvars = " ^ bsStr ^  ", vars=" ^ vsStr ^ *)"\n", si)
Axel Simon's avatar
Axel Simon committed
427
428
         end

429
      fun toString ({bindInfo = bi, typeVars, boolVars, version}, si) =
Axel Simon's avatar
Axel Simon committed
430
            let
Axel Simon's avatar
Axel Simon committed
431
               val (scStr, si) = showVarsVer (typeVars, boolVars, version, si)
432
433
434
435
436
437
               val (biStr, si) = showBindInfoSI (bi,si)
            in
               (scStr ^ biStr, si)
            end
      and showBindInfoSI (KAPPA {ty}, si) =
            let
Axel Simon's avatar
Axel Simon committed
438
439
               val (tStr, si) = showTypeSI (ty,si)
            in
440
               ("KAPPA : " ^ tStr, si)
Axel Simon's avatar
Axel Simon committed
441
            end
442
        | showBindInfoSI (SINGLE {name, ty}, si) =
Axel Simon's avatar
Axel Simon committed
443
444
445
            let
               val (tStr, si) = showTypeSI (ty,si)
            in
446
               ("SYMBOL " ^ ST.getString(!SymbolTables.varTable, name) ^
447
                " : " ^ tStr, si)
Axel Simon's avatar
Axel Simon committed
448
            end
449
        | showBindInfoSI (GROUP bs, si) =
Axel Simon's avatar
Axel Simon committed
450
451
452
453
454
455
456
            let
               fun prTyOpt (NONE, str, si) = ("", si)
                 | prTyOpt (SOME t, str, si) = let
                    val (tStr, si) = showTypeSI (t, si)
                 in
                     (str ^ tStr, si)
                 end
457
458
459
               fun prBTyOpt (NONE, str, si) = ("", si)
                 | prBTyOpt (SOME (t,bFun), str, si) = let
                    val (tStr, si) = showTypeSI (t, si)
Axel Simon's avatar
Axel Simon committed
460
461
                    val bStr = if concisePrint then "" else
                               ", flow:" ^ BD.showBFun bFun
462
                 in
Axel Simon's avatar
Axel Simon committed
463
                     (str ^ tStr ^ bStr, si)
464
                 end
mb0's avatar
mb0 committed
465
               fun printU (({span=(p1,p2),file=_}, (ctxt, t)), (str, sep, si)) =
Axel Simon's avatar
Axel Simon committed
466
467
468
469
470
471
                  let
                     val (tStr, si) = showTypeSI (t, si)
                  in
                     (str ^
                      sep ^ Int.toString(Position.toInt p1) ^
                      "-" ^ Int.toString(Position.toInt p2) ^
472
                      "@" ^ ST.getString(!SymbolTables.varTable, ctxt) ^
Axel Simon's avatar
Axel Simon committed
473
                      ":" ^ tStr
Axel Simon's avatar
Axel Simon committed
474
                     ,"\n\tuse at ", si)
Axel Simon's avatar
Axel Simon committed
475
                  end
476
               fun printB ({name,ty,width,uses,nested}, (str, si)) =
Axel Simon's avatar
Axel Simon committed
477
                  let
478
                     val (tStr, si) = prBTyOpt (ty, " : ", si)
Axel Simon's avatar
Axel Simon committed
479
480
                     val (wStr, si) = prTyOpt (width, ", width = ", si)
                     val (uStr, _, si) = 
Axel Simon's avatar
Axel Simon committed
481
                           List.foldl printU ("", "\n\tuse at ", si)
Axel Simon's avatar
Axel Simon committed
482
                                      (SpanMap.listItemsi uses)
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
                     fun showBindInfosSI n (b :: bs,si) =
                        let
                           val (bStr, si) = showBindInfoSI (b,si)
                           fun spaces n = if n<=0 then "" else "  " ^ spaces (n-1)
                           val sStr = spaces n
                           val (bsStr, si) = showBindInfosSI (n+1) (bs, si)
                           val fs1 = Substring.fields (fn c => c= #"\n") (Substring.full bStr)
                           val fs2 = Substring.fields (fn c => c= #"\n") (Substring.full bsStr)
                        in
                           (List.foldl
                              (fn (f,str) => str ^ sStr ^ Substring.string f ^ "\n")
                              "\n" (fs1 @ fs2),
                            si)
                        end
                       | showBindInfosSI n ([], si) = ("", si)
Axel Simon's avatar
Axel Simon committed
498
                     val (nStr, si) = showBindInfosSI 1 (nested,si)
Axel Simon's avatar
Axel Simon committed
499
500
501
                  in
                    (str ^
                     "\n  " ^ ST.getString(!SymbolTables.varTable, name) ^
502
                     tStr ^ wStr ^ nStr ^ uStr
Axel Simon's avatar
Axel Simon committed
503
504
505
506
                    ,si)
                  end
                val (bsStr, si) = List.foldr printB ("", si) bs
            in
507
               ("GROUP" ^ bsStr, si)
Axel Simon's avatar
Axel Simon committed
508
509
            end
               
510
   end
Axel Simon's avatar
Axel Simon committed
511
   
512
   type environment = Scope.environment
Axel Simon's avatar
Axel Simon committed
513

Axel Simon's avatar
Axel Simon committed
514
   fun primitiveEnvironment (l,scs) = Scope.initial
515
516
      (GROUP (List.map (fn (s,t,bFunGen,ow) =>
         {name = s, ty = SOME (t,bFunGen BD.empty),
517
          width = ow, uses = SpanMap.empty, nested = []}) l),
Axel Simon's avatar
Axel Simon committed
518
       scs)
519
520
521
   
   fun pushSingle (sym, t, env) = Scope.wrap (SINGLE {name = sym, ty = t},env)
   
Axel Simon's avatar
Axel Simon committed
522
   structure SymbolSet = RedBlackSetFn (
Axel Simon's avatar
Axel Simon committed
523
524
525
      struct
         type ord_key = SymbolTable.symid
         val compare = SymbolTable.compare_symid
Axel Simon's avatar
Axel Simon committed
526
527
      end)
          
528
   fun pushGroup (syms, env) = 
Axel Simon's avatar
Axel Simon committed
529
530
531
      let
         val (funs, nonFuns) = List.partition (fn (s,dec) => not dec) syms
         val funDefs = List.map
532
533
            (fn (s,_) => {name = s, ty = NONE, width = NONE,
                          uses = SpanMap.empty, nested = []})
Axel Simon's avatar
Axel Simon committed
534
            funs
Axel Simon's avatar
Axel Simon committed
535
         val nonFunSyms =
Axel Simon's avatar
Axel Simon committed
536
            SymbolSet.listItems (SymbolSet.fromList (List.map (fn (s,_) => s) nonFuns))
Axel Simon's avatar
Axel Simon committed
537
538
539
         val nonFunDefs = List.map
            (fn s => {name = s, ty = NONE, width =
              SOME (VAR (TVar.freshTVar (), BD.freshBVar ())),
540
              uses = SpanMap.empty, nested = []}) nonFunSyms
Axel Simon's avatar
Axel Simon committed
541
      in                                                                    
542
         Scope.wrap (GROUP (funDefs @ nonFunDefs), env)
Axel Simon's avatar
Axel Simon committed
543
544
      end                                    

545
546
547
   fun popGroup (env, true) = (case Scope.unwrap env of
        (KAPPA {ty=t}, env) =>
         let
Axel Simon's avatar
Axel Simon committed
548
           val (badUses, env) = popGroup (env, false)
549
         in
Axel Simon's avatar
Axel Simon committed
550
            (badUses, Scope.wrap (KAPPA {ty=t}, env))
551
552
553
         end
       | _ => raise InferenceBug)
     | popGroup (env, false) = case Scope.unwrap env of
554
        (GROUP bs, env) =>
Axel Simon's avatar
Axel Simon committed
555
556
         let
            val remVars = Scope.getVars env
Axel Simon's avatar
Axel Simon committed
557
            val (scs, state) = env
558
559
            (*figure out if there are any function usages that have unresolved
            type variables that relate to sizes*)
Axel Simon's avatar
Axel Simon committed
560
            val curVars = SC.getVarset (Scope.getSize state)
Axel Simon's avatar
Axel Simon committed
561
            val unbounded = TVar.difference (curVars,remVars)
562
            (*val _ = TextIO.print ("unbounded vars: " ^ #1 (TVar.setToString (unbounded,TVar.emptyShowInfo)) ^ "\n")*)
Axel Simon's avatar
Axel Simon committed
563
            val siRef = ref TVar.emptyShowInfo
Axel Simon's avatar
Axel Simon committed
564
            fun showUse (n, (ctxt,t)) =
Axel Simon's avatar
Axel Simon committed
565
566
567
568
               let
                  val nStr = SymbolTable.getString(!SymbolTables.varTable, n)
                  val (tStr, si) = showTypeSI (t, !siRef)
                  val vs = texpVarset (t,TVar.empty)
Axel Simon's avatar
Axel Simon committed
569
                  val (cStr, si) = SC.toStringSI (Scope.getSize state, SOME vs, si)
Axel Simon's avatar
Axel Simon committed
570
571
               in
                  (siRef := si
Axel Simon's avatar
Axel Simon committed
572
                  ; nStr ^ " : call to " ^ tStr ^ " has ambiguous vector sizes" ^
Axel Simon's avatar
Axel Simon committed
573
574
                     (if String.size cStr=0 then "" else " where " ^ cStr))
               end
Axel Simon's avatar
Axel Simon committed
575
576
577
578
579
580
581
582
583
584
585
586
            fun remBoundVars ({name,ty=SOME (t,_),width,uses,nested=ns},vs) =
                  List.foldl remBoundVars 
                     (TVar.difference (vs, texpVarset (t,TVar.empty)))
                     (List.concat (List.map (fn g => case g of
                          GROUP bs => bs
                        | _ => raise InferenceBug) ns))
              | remBoundVars (_,vs) = vs
            val unbounded = List.foldl remBoundVars unbounded bs
            (*TODO: we should also descend into the nested definitions,
            since the letrec expression cannot report ambigueties since
            when letrec groups are popped, the fixpoint has not been
            calculated yet*)
Axel Simon's avatar
Axel Simon committed
587
            val badSizes = List.concat (
588
               List.map (fn {name = n,ty,width,uses = us,nested} =>
Axel Simon's avatar
Axel Simon committed
589
590
                  List.map (fn (sp,t) => (sp, showUse (n, t))) (
                     SpanMap.listItemsi (
Axel Simon's avatar
Axel Simon committed
591
                        SpanMap.filter (fn (_,t) =>
Axel Simon's avatar
Axel Simon committed
592
593
594
                           not (TVar.isEmpty (TVar.intersection
                              (texpVarset (t,TVar.empty), unbounded)))
                           ) us))) bs)
595
596
            (*project out variables from the size and Boolean domains that are
            no longer needed*)
Axel Simon's avatar
Axel Simon committed
597
            val sCons = SC.filter (remVars, Scope.getSize state)
598
599
600
601
602
603
604
605
606
607
            val env = (scs, Scope.setSize sCons state)
            
            (*in case we are inside a function, store this group in the nested
            field of the function entry*)
            val inScope = SymSet.fromList (Scope.getCtxt state)
            val bs = List.filter
                        (fn {name, ty, width, uses = us, nested} =>
                           List.exists (fn (f,_) => SymSet.member (inScope,f))
                              (SpanMap.listItems us)
                        ) bs
Axel Simon's avatar
Axel Simon committed
608
            fun action group (COMPOUND {ty, width, uses, nested},cons) =
609
               (COMPOUND {ty = ty, width = width,
Axel Simon's avatar
Axel Simon committed
610
                uses = uses, nested = group :: nested}, cons)
611
612
              | action ns _ = raise InferenceBug
            val env = if List.null bs then env else
Axel Simon's avatar
Axel Simon committed
613
               Scope.update (Scope.getCurFun state, action (GROUP bs), env)
Axel Simon's avatar
Axel Simon committed
614
         in
615
            (badSizes, env)
Axel Simon's avatar
Axel Simon committed
616
         end
617
618
      | _ => raise InferenceBug

mb0's avatar
Merge.    
mb0 committed
619
620
621
622
   fun getGroupSyms env = case Scope.unwrap env of
        (GROUP bs, env) => List.map #name bs
      | _ => raise InferenceBug

623
   fun pushTop env = 
Axel Simon's avatar
Axel Simon committed
624
625
626
627
      let
         val a = TVar.freshTVar ()
         val b = BD.freshBVar ()
      in
628
         Scope.wrap (KAPPA {ty = VAR (a,b)}, env)
Axel Simon's avatar
Axel Simon committed
629
      end
630

Axel Simon's avatar
Axel Simon committed
631
   fun pushType (true, t, (scs, state)) =
Axel Simon's avatar
Axel Simon committed
632
      let
Axel Simon's avatar
Axel Simon committed
633
634
635
         val (t,bFun,sCons) = instantiateType (TVar.empty,t,TVar.empty,
                                               Scope.getFlow state,
                                               Scope.getSize state)
Axel Simon's avatar
Axel Simon committed
636
      in
Axel Simon's avatar
Axel Simon committed
637
638
         (Scope.wrap (KAPPA {ty = t}, (scs, Scope.setSize sCons (
                                             Scope.setFlow bFun state))))
Axel Simon's avatar
Axel Simon committed
639
      end
640
     | pushType (false, t, env) = Scope.wrap (KAPPA {ty = t}, env)
Axel Simon's avatar
Axel Simon committed
641

Axel Simon's avatar
Axel Simon committed
642
   fun pushMonadType (t, (scs, state)) =
643
644
645
646
647
648
      let
         val tvar = TVar.freshTVar ()
         val fromBVar = BD.freshBVar ()
         val toBVar = BD.freshBVar ()
         val fromVar = VAR (tvar, fromBVar)
         val toVar = VAR (tvar, toBVar)
Axel Simon's avatar
Axel Simon committed
649
650
651
652
653
         val bFun = BD.meetVarImpliesVar (fromBVar, toBVar) (Scope.getFlow state)
         val (t,bFun,sCons) = instantiateType (texpVarset(t,TVar.empty),t,
                                               TVar.empty,
                                               bFun,
                                               Scope.getSize state)
654
      in
Axel Simon's avatar
Axel Simon committed
655
656
         Scope.wrap (KAPPA {ty = MONAD (t, fromVar, toVar)},
                     (scs, Scope.setSize sCons (Scope.setFlow bFun state)))
657
658
      end

Axel Simon's avatar
Axel Simon committed
659
660
   fun pushWidth (sym, env) =
      (case Scope.lookup (sym,env) of
661
          (_, COMPOUND {ty, width = SOME t, uses, nested}) =>
Axel Simon's avatar
Axel Simon committed
662
663
664
665
666
667
            Scope.wrap (KAPPA {ty = t}, env)
        | _ => raise (UnificationFailure (
            SymbolTable.getString(!SymbolTables.varTable, sym) ^
            " is not a decoder"))
      )

Axel Simon's avatar
Axel Simon committed
668
669
670
   exception LookupNeedsToAddUse

   fun eq_span ((p1s,p1e), (p2s,p2e)) =
671
672
673
      Position.toInt p1s=Position.toInt p2s andalso
      Position.toInt p1e=Position.toInt p2e

Axel Simon's avatar
Axel Simon committed
674
   fun toStringSI ((scs, state),si) = 
675
      let
676
         fun showCons (s, (str, si)) =
677
678
679
680
681
            let
               val (bStr, si) = Scope.toString (s, si)
            in
               (bStr ^ "\n" ^ str, si)
            end
Axel Simon's avatar
Axel Simon committed
682
         val (sStr, si) = SC.toStringSI (Scope.getSize state, NONE, si)
683
684
         val (envConsStr, si) =
            List.foldr showCons ("sizes: " ^ sStr ^ "\n", si) scs
Axel Simon's avatar
Axel Simon committed
685
686
687
         fun showCtxt [] = "top level"
           | showCtxt [f] = ST.getString(!SymbolTables.varTable, f)
           | showCtxt (f::fs) = showCtxt [f] ^ ";" ^ showCtxt fs
688
      in
Axel Simon's avatar
Axel Simon committed
689
690
         ("environment at " ^ showCtxt (Scope.getCtxt state) ^ "\n" ^
          envConsStr ^ BD.showBFun (Scope.getFlow state) ^ "\n", si)
691
692
      end

693
694
695
696
697
698
699
   fun toString env =
      let
         val (str, _) = toStringSI (env,TVar.emptyShowInfo)
      in
         str
      end
   
700
   fun topToStringSI (env, si) =
Axel Simon's avatar
Axel Simon committed
701
      let
Axel Simon's avatar
Axel Simon committed
702
703
         fun tts acc (sc :: scs, state) =
            (case Scope.unwrap (sc :: scs, state) of
704
                 (GROUP _, (_, state)) => toStringSI ((acc, state), si)
Axel Simon's avatar
Axel Simon committed
705
               | (_, env) => tts (acc @ [sc]) env) 
Axel Simon's avatar
Axel Simon committed
706
           | tts acc ([], state) = toStringSI ((acc, state), si)
Axel Simon's avatar
Axel Simon committed
707
708
709
      in
         tts [] env
      end
710

711
712
713
714
715
716
717
   fun topToString env =
      let
         val (str, _) = topToStringSI (env,TVar.emptyShowInfo)
      in
         str
      end

Axel Simon's avatar
Axel Simon committed
718
   fun kappaToStringSI (env, si) = (case Scope.unwrap env of
Axel Simon's avatar
Axel Simon committed
719
720
721
722
723
724
        (KAPPA {ty = t}, _) =>
         let
            val (tStr, si) = showTypeSI (t,si)
         in
            (tStr ^ "\n", si)
         end
Axel Simon's avatar
Axel Simon committed
725
726
      | _ => raise InferenceBug
   )
727

Axel Simon's avatar
Axel Simon committed
728
729
730
731
732
733
734
   fun kappaToString env =
      let
         val (str, _) = kappaToStringSI (env,TVar.emptyShowInfo)
      in
         str
      end

735
   fun funTypeToStringSI (env, f, si) = (case Scope.lookup (f,env) of
736
737
        (_, COMPOUND { ty = SOME (t,_), width, uses, nested }) =>
            showTypeSI (t,si)
738
739
      | _ => raise InferenceBug
   )
740

741
742
743
744
745
746
747
748
749
750
751
752
753
754
   fun reduceBooleanFormula (sym,t,setType,reduceToMono,env) =
      let
         (*we need to restrict the size of the Boolean formula in two
         ways: first, for the function we need all Boolean variables
         in its type, all lambda- and kappa-bound types in the
         environment as well as all the uses of other functions that
         occur in it; secondly, the analysis must continue with a
         Boolean formula that contians the Boolean variables of all
         lambda- and kappa-bound types in the environment. Since the
         latter is usually an empty environment (namely for all
         top-level functions), we first calculate the set of Boolean
         variables in kappa- and lambda-bound types and use that for
         the Boolean formula of the function; then we project onto
         the variables in kappa- and lambda-bound types*)
755
756
757
758
         val texpBVarset = texpBVarset (fn ((_,v),vs) => BD.addToSet (v,vs))

         val (monoTVars, monoBVars) = Scope.getMonoVars env
         val (usesTVars, usesBVars) = Scope.getVarsUses (sym, env)
759
760
         val funBVars = BD.union (texpBVarset (t,usesBVars),
                           BD.union (monoBVars, usesBVars))
761
                           
Axel Simon's avatar
Axel Simon committed
762
763
         val (scs, state) = env
         val bFun = BD.projectOnto (funBVars,Scope.getFlow state)
764
765
         val bFunRem = if reduceToMono then BD.projectOnto (monoBVars,bFun)
                       else bFun
766
         (*val _ = TextIO.print ("projecting for " ^ SymbolTable.getString(!SymbolTables.varTable, sym) ^ ": " ^ showType t ^ " onto " ^ BD.setToString funBVars ^ ", mono " ^ BD.setToString monoBVars ^"\n")*)
767
768
769
         val groupTVars = texpVarset (t,Scope.getVars env)
         val sCons = SC.filter (groupTVars, Scope.getSize state)
         val state = Scope.setSize sCons (Scope.setFlow bFunRem state)
Axel Simon's avatar
Axel Simon committed
770
         val env = Scope.update (sym, setType (t,bFun), (scs, state))
771
772
773
774
      in
         env
      end

Axel Simon's avatar
Axel Simon committed
775
776
   fun affectedFunctions (substs, env) =
      let
777
         fun aF (ss, substs, ([], _)) = ss
778
779
780
           | aF (ss, substs, env) =
               if isEmpty substs then ss else aFB ss (Scope.unwrap env)
         and aFB ss (GROUP l,env) =
Axel Simon's avatar
Axel Simon committed
781
            let
782
783
               fun aFL (ss, []) =
                   aF (ss, substsFilter (substs, Scope.getVars env), env)
784
785
786
                 | aFL (ss, {name = n, ty, width, uses = us, nested = ns} :: l) =
                     List.foldl (fn (b,ss) => aFB ss (b,env))
                     (if List.all (fn (_,t) => isEmpty
Axel Simon's avatar
Axel Simon committed
787
788
789
                              (substsFilter (substs, texpVarset (t,TVar.empty))))
                           (SpanMap.listItems us)
                     then aFL (ss, l)
Axel Simon's avatar
Axel Simon committed
790
                     else aFL (SymbolSet.add' (n, ss), l)
Axel Simon's avatar
Axel Simon committed
791
                     ) ns
Axel Simon's avatar
Axel Simon committed
792
793
794
            in
               aFL (ss, l)
            end
795
796
           | aFB ss (_, env) =
               aF (ss, substsFilter (substs, Scope.getVars env), env)
Axel Simon's avatar
Axel Simon committed
797
      in
798
         aF (SymbolSet.empty, substs, env)
Axel Simon's avatar
Axel Simon committed
799
800
      end

Axel Simon's avatar
Axel Simon committed
801
   fun affectedField (bVars, env as (scs,state)) =
802
803
      let
         fun aF (_, SOME f) = SOME f
Axel Simon's avatar
Axel Simon committed
804
           | aF (([],_), NONE) = NONE
805
           | aF (env, NONE) = case Scope.unwrap env of
806
              (KAPPA {ty = t}, env) =>
Axel Simon's avatar
Axel Simon committed
807
808
               aF (env, fieldOfBVar (bVars, t))
            | (SINGLE {name, ty = t}, env) => aF (env, fieldOfBVar (bVars, t))
809
810
            | (GROUP l, env) =>
            let
Axel Simon's avatar
Axel Simon committed
811
               fun findField ((_,t), SOME f) = SOME f
Axel Simon's avatar
Axel Simon committed
812
                 | findField ((_,t), NONE) = fieldOfBVar (bVars, t)
813
               fun aFL {name, ty = tOpt, width, uses, nested} =
814
815
816
                  List.foldl findField
                     (case tOpt of
                          NONE => NONE
Axel Simon's avatar
Axel Simon committed
817
                        | SOME (t,_) => fieldOfBVar (bVars, t))
818
819
820
821
822
823
824
825
826
827
                     (SpanMap.listItems uses)
            in
               aF (env, case List.mapPartial aFL l of
                       [] => NONE
                     | (f :: _) => SOME f)
            end
      in
         aF (env, NONE)
      end

Axel Simon's avatar
Axel Simon committed
828
   fun flowError (bVar, fOpt, envs) =
829
      let
Axel Simon's avatar
Axel Simon committed
830
831
832
         val fOpt = List.foldl (fn (env,res) => case res of
                       SOME f => SOME f
                     | NONE => affectedField (bVar, env)) fOpt envs
833
         val fStr = case fOpt of
Axel Simon's avatar
Axel Simon committed
834
                 NONE => "some field"
835
836
               | SOME f => "field " ^
                  SymbolTable.getString(!SymbolTables.fieldTable, f)
Axel Simon's avatar
Axel Simon committed
837
838
         val fStr = if Types.concisePrint then fStr else
                    fStr ^ " with vars " ^ BD.setToString bVar
839
840
841
842
      in
         raise UnificationFailure (fStr ^ " cannot flow here")
      end

Axel Simon's avatar
Axel Simon committed
843
   fun meetBoolean (update, env as (scs, state)) =
844
845
      (scs, Scope.setFlow (update (Scope.getFlow state)) state)
         handle (BD.Unsatisfiable bVar) => flowError (bVar, NONE, [env])
846

Axel Simon's avatar
Axel Simon committed
847
848
   fun meetSizeConstraint (update, (scs, state)) =
      (scs, Scope.setSize (update (Scope.getSize state)) state)
849

850
851
   fun genConstructorFlow (contra, env) = case Scope.unwrap env of
        (KAPPA {ty=FUN ([t], ALG (_,vs))}, _) =>
852
853
854
855
         let
            val dtVars = List.map (fn v => case v of
                             VAR p => p
                           | _ => raise InferenceBug) vs
856
857
            val flow = texpConstructorFlow dtVars contra t
            val env = meetBoolean (fn bFun => BD.meet (flow,bFun), env)
858
859
860
861
862
         in
            env
         end
      | _ => raise InferenceBug

Axel Simon's avatar
Axel Simon committed
863
   fun pushSymbol (sym, span, recordUsage, env) =
864
      (case Scope.lookup (sym,env) of
Axel Simon's avatar
Axel Simon committed
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
          (_, SIMPLE {ty = t}) =>
         let
            val tNew = setFlagsToTop t
            val env = Scope.wrap (KAPPA {ty = tNew}, env)
            val l1 = texpBVarset (op ::) (t, [])
            val l2 = texpBVarset (op ::) (tNew, [])
            fun genImpl ((contra1,f1),(contra2,f2),bf) =
               if contra1<>contra2 then raise InferenceBug else
               if contra1 then
                  BD.meetVarImpliesVar (f2,f1) bf
               else
                  BD.meetVarImpliesVar (f1,f2) bf
         in
            meetBoolean (fn bFun => ListPair.foldlEq genImpl bFun (l2, l1), env)
         end
880
        | (tvs, COMPOUND {ty = SOME (t,bFunFun), width = w, uses, nested}) =>
Axel Simon's avatar
Axel Simon committed
881
         let
Axel Simon's avatar
Axel Simon committed