File: STRUCT_VALS.ML

package info (click to toggle)
polyml 5.6-8
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 31,892 kB
  • ctags: 34,453
  • sloc: cpp: 44,983; ansic: 24,520; asm: 14,850; sh: 11,730; makefile: 551; exp: 484; python: 253; awk: 91; sed: 9
file content (655 lines) | stat: -rw-r--r-- 27,283 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
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
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
(*
    Copyright (c) 2000
        Cambridge University Technical Services Limited

    Modified David C. J. Matthews 2009, 2012, 2015.

    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.
    
    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 GNU
    Lesser General Public License for more details.
    
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*)

(*
    Title:      Global and Local values.
    Author:     Dave Matthews,Cambridge University Computer Laboratory
    Copyright   Cambridge University 1985
*)

(* This type contains the basic structures of global and local declarations.
   Putting the global declarations in a separate type allows us to install a new
   compiler (particularly to fix bugs) and still be compatible with declarations
   made with the old compiler. It is also convenient to put local values in
   here as well.  *) 
  
functor STRUCT_VALS (

structure CODETREE : CODETREESIG where type machineWord = Address.machineWord

(*****************************************************************************)
(*                  UNIVERSALTABLE                                           *)
(*****************************************************************************)
structure UNIVERSALTABLE :
sig
  type 'a tag = 'a Universal.tag;
  type univTable
  type universal = Universal.universal
  
  val makeUnivTable: unit -> univTable;
  val univEnter:     univTable * 'a tag * string * 'a -> unit;
  val univLookup:    univTable * 'a tag * string -> 'a option;
  
  (* Freeze a mutable table so it is immutable. *)
  val univFreeze:       univTable -> univTable

    val fold: (string * universal * 'a -> 'a) -> 'a -> univTable -> 'a
end;

structure PRETTY: PRETTYSIG (* Temporary addition. *)

) :> STRUCTVALSIG where type codetree = CODETREE.codetree and type univTable = UNIVERSALTABLE.univTable and type level = CODETREE.level
=  

(*****************************************************************************)
(*                  STRUCTVALS functor body                                  *)
(*****************************************************************************)
struct
    open CODETREE;
  
    open Misc;
    open Universal;
    open UNIVERSALTABLE;
  
    (* Location for declarations. *)
    type location =
        { file: string, startLine: int, startPosition: int, endLine: int, endPosition: int }

    (* The idea of this is reduce the number of mutable objects. *)
    datatype 'a possRef = FrozenRef of 'a | VariableRef of 'a ref
    fun pling(FrozenRef x) = x | pling(VariableRef(ref x)) = x
    fun updatePR(VariableRef r, x) = r := x | updatePR(FrozenRef _, _) = raise Fail "Assignment to frozen ref"

    (* References to identifiers.  exportedRef is set to true if the identifier is exported to
       the global environment or to a structure.  localRef contains the list of local uses.
       recursiveRef contains a list of (mutually) recursive references together with the name
       of the function that refers to this.  It is used when computing whether a recursive
       function is actually refered to from elsewhere. 
       This is an option type because this is used only within local identifiers. *)
    type references =
    {
        exportedRef: bool ref,
        localRef: location list ref,
        recursiveRef: (location * string) list ref
    } option
    
    fun makeRef(): references =
        SOME { exportedRef = ref false, localRef = ref nil, recursiveRef=ref nil }
   
  (* typeIds are used to distinguish between concrete types.  Two
     types that share will have the same identifier.  If the identifiers are
     different they are different types.
     There are three classes of type identifier.  Free identifiers are used for
     types in the global environment. Bound identifiers occur in signatures,
     functors and while compiling structures.  Type functions arise from
     type bindings (type abbreviations) or from "where type" definitions
     in signatures.
     The type identifier also contains the equality attribute.
     In ML97 only types have these identifiers.  In ML90 these were also
     needed for structures.
     Free and Bound IDs contain information to find the equality and
     value-printing functions. *)
    type typeIdDescription = { location: location, name: string, description: string }

    datatype typeId =
        TypeId of { access: valAccess, description: typeIdDescription, idKind: typeIdKind }

    and typeIdKind =
        Free of { uid: uniqueId, allowUpdate: bool, arity: int  }
    |   Bound of { offset: int, eqType: bool possRef, isDatatype: bool, arity: int }
    |   TypeFn of typeVarForm list * types

    (* A type is the union of these different cases. *)
    and types = 
        TypeVar          of typeVarForm

    |   TypeConstruction of
        {
            name:  string,
            constr: typeConstrs,
            args:  types list,
            locations: locationProp list
        }

    |   FunctionType of
        { 
            arg:    types,
            result: types
        }

    |   LabelledType  of labelledRec

    |   OverloadSet   of
        {
            typeset: typeConstrs list
        }

    |   BadType

    |   EmptyType

    and typeConstrs = 
        TypeConstrs of
        {
            name:       string,
            identifier: typeId,
            locations:  locationProp list (* Location of declaration *)
        }

    and typeConstrSet = (* A type constructor with its, possible, value constructors. *)
        TypeConstrSet of typeConstrs * values list

    and labelFieldList =
        FieldList of string list * bool (* True if this is frozen *)
    |   FlexibleList of labelFieldList ref

    (* Access to a value, structure or functor. *)
    and valAccess =
        Global   of codetree
    |   Local    of { addr: int ref, level: level ref }
    |   Selected of { addr: int,     base:  structVals }
    |   Formal   of int
    |   Overloaded of typeDependent (* Values only. *)

    (* Structures. *)
    and structVals = 
       Struct of
        {
            name:   string,
            signat: signatures,
            access: valAccess,
            locations: locationProp list
        }

    (* Signatures.  The representation of a signature deserves a bit of explanation.
       A signature is an environment: a set of values, type constructors and sub-structures.
       Behind the types associated with the type constructors and values
       are what the semantics calls "type names" but are referred to in the Poly/ML
       code as type-ids to avoid confusion with the text name of a type constructor.
       The same signature may be bound to a signature identifier, used as an argument
       to a functor, the result of a functor or the signature of a structure.  The
       environment is the same in each case; what is different is the type names.
       To avoid rebuilding the environment for each case the same environment is
       used but with different sets of typeIdMap, firstBoundIndex and boundIds.
       typeIdMap maps the "offset" of any bound id found in the environment to a
       type-id.  For structures the result will always be a free id and boundIds
       will be empty.  In other cases it may map to either a free id, perhaps as
       the result of "where type" constraint, or to a bound id.  Sharing constraints
       will cause different bound ids in the environment to map to the same resulting
       bound id.  Normally, firstBoundIndex will be zero and boundIds will be the
       set of bound ids that can be produced by typeIdMap.  The exception is the
       result signature of a functor.  In that case typeIdMap may return bound Ids
       in the set of the boundIds for the argument to the functor, which will have
       offsets >= 0 and < firstBoundIndex or in the set for the result of the functor
       with offsets >= firstBoundIndex and < firstBoundIndex+length boundIds.  When
       the functor is applied the typeIdMap for the structure that is produced
       maps the first set to the free ids of the actual argument and the maps the
       second set to new, unique free ids. *)
    and signatures =
        Signatures of
        { 
            name:               string,
            tab:                univTable,
            typeIdMap:          int -> typeId,
            firstBoundIndex:    int,
            boundIds:           typeId list,
            locations:          locationProp list
        }

    and functors =
        Functor of
        {
            name:       string,
            arg:        structVals,
            result:     signatures,
            access:     valAccess,
            locations:  locationProp list
        }

    (* Values. *)
    (* The overloaded functions divide up into basically two groups: Those =, 
       <>, print and makestring  which are infinitely overloaded and those 
       *, + etc  which are overloaded on a limited range of types. *)  
    and typeDependent =
        Print
    |   GetPretty
    |   MakeString
    |   AddPretty
    |   Equal
    |   NotEqual
    |   AddOverload
    |   TypeDep
    |   GetLocation

    and values =
        Value of
        {
            name: string,
            typeOf: types,
            access: valAccess,
            class: valueClass,
            locations: locationProp list, (* Location of declaration *)
            references: references,
            instanceTypes: types list ref option (* Instance types for local variables. *)
        }

    (* Classes of values. *)
    and valueClass =
        ValBound
    |   PattBound
    |   Exception
    |   Constructor of
        {
            nullary: bool, (* True if this is a single value (e.g. "nil") rather than a function. *)
            ofConstrs: int (* Total number of constructors in the datatype. *)
        }

    and locationProp =
        DeclaredAt of location
    |   OpenedAt of location
    |   StructureAt of location
    |   SequenceNo of int
  
    withtype uniqueId = bool ref
        (* We use a ref here both because we can then set equality if we
           need but also because it allows us to create a unique Id. *)
      
    and typeVarForm = 
    {
        value:    types ref,
        encoding: Word.word
    }

    and labelledRec =
    {
        (* Fields actually present in this record.  If this was flexible at some
           stage there may be extra fields listed in the full field list. *)
        recList: { name: string, typeof: types } list,
        (* The names of all the fields including extra fields. *)
        fullList: labelFieldList
    }

    
  (* A set of type contructors.  This is used only during the
     compilation process and represents the set of possible types
     which may occur. It functions in much the same way as a type
     variable.  Because we only allow overloading on monomorphic
     type constructors such as "int" and "word" we can restrict the
     set to containing only type constructors rather than general types.
     This overload set was added for ML 97 because ML 97, unlike ML 90,
     defaults overloaded operators and constants if unification does
     not result in a single type being found.  
     The overload set is used in a similar way to a flexible record
     and will always be pointed at by a type variable so that the
     set can be replaced by a single type construction if the unification
     reduces to a single type. *)
    and overloadSetForm =
    {
        typeset: typeConstrs list
    }

    (* Identifiers *)
    fun makeFreeId(arity, access, eq, desc) =
        TypeId { access=access, description = desc,
            idKind = Free {uid = ref eq, allowUpdate=false, arity=arity}}
    (* At the moment the only reason for distinguishing makeFreeId and makeFreeIdEqUpdate
       is that it allows us to check that we're actually permitting update when needed. *)
    fun makeFreeIdEqUpdate(arity, access, eq, desc) =
        TypeId { access=access, description = desc,
            idKind = Free {uid = ref eq, allowUpdate=true, arity=arity}}

    fun makeBoundId (arity, access, n, eq, isdt, desc) =
        TypeId { access=access, description = desc,
            idKind = Bound{offset=n, eqType=FrozenRef eq, isDatatype = isdt, arity=arity}}

    (* Within the body of a functor we make bound stamps but may need to
       set the equality attribute. *)
    fun makeBoundIdWithEqUpdate (arity, access, n, eq, isdt, desc) =
        TypeId { access=access, description = desc,
            idKind = Bound{offset=n, eqType=VariableRef(ref eq), isDatatype = isdt, arity=arity}}

    (* Type functions currently always have Free ids. *)
    fun makeTypeFunction(desc, typeFn) =
        TypeId { access=Global CodeZero, description = desc, idKind = TypeFn typeFn};
            
    (* Find the number - assuming it is bound. *)
    fun offsetId (TypeId{idKind=Bound {offset, ...}, ...}) = offset
    |   offsetId _       = raise InternalError "offsetId: not a Bound";

    (* Are two type constructors the same? *)
    fun sameTypeId (TypeId{idKind=Free{uid = a, ...}, ...}, TypeId{idKind=Free {uid = b, ...}, ...}) = a = b
    |   sameTypeId (TypeId{idKind=Bound{offset=a, ...}, ...}, TypeId{idKind=Bound{offset=b, ...}, ...}) = a = b
    |   sameTypeId _ = false (* Includes type functions. *)

    fun idAccess (TypeId { access, ...}) = access

    fun isEquality (TypeId { idKind = Free{uid = ref eq, ...}, ...}) = eq
    |   isEquality (TypeId { idKind = Bound{eqType, ...}, ...}) = pling eqType
    |   isEquality (TypeId { idKind = TypeFn _, ...}) = raise InternalError "isEquality: TypeFn"

    (* Set the equality property.   Currently, free IDs are used for abstypes and
       datatypes that are local to a function as well as the usual case of using them
       for top-level types. *)
    fun setEquality(TypeId{idKind = Free{uid, allowUpdate=true, ...}, ...}, eq) = uid := eq
    |   setEquality(TypeId{idKind = Bound{eqType=VariableRef id, ...}, ...}, eq) = id := eq
    |   setEquality _ = raise InternalError "setEquality: can't set equality attribute"

    (* Signatures: Used for both signatures of local structures and for global structures 
       (name spaces). Strictly signatures do not contain fix-status functors
       or signatures but as we use these structures for top-level name-spaces
       we have to have tables for these. *)
    val makeSignatureTable = makeUnivTable

    (* Make a signature, freezing the table. *)
    fun makeSignature (name, table, fbi, locations, typeIdMap, boundIds) =
        Signatures { name = name,
               tab        = univFreeze table,
               typeIdMap  = typeIdMap,
               firstBoundIndex   = fbi,
               boundIds   = boundIds,
               locations = locations  }
    
  (* Types. *)

  (* Level at which type is generalisable. *)

  val generalisable = 9999; 
    
    
  (* Destructors, constructors and predicates for types *)
  val emptyType            = EmptyType;
  val badType              = BadType;

  fun isEmpty             EmptyType           = true | isEmpty            _ = false;
  fun isBad               BadType             = true | isBad              _ = false;
  
  fun makeValueConstr (name, typeOf, nullary, constrs, access, locations) : values =
    Value
    { 
      name    = name,
      typeOf  = typeOf,
      access  = access,
      class   = Constructor { nullary = nullary, ofConstrs = constrs },
      locations = locations,
      references = NONE,
      instanceTypes = NONE
    };

  
  (* A type variable is implemented as a true variable i.e. it can
     be assigned a particular type when it is unified. Initially it is
     set to EmptyType which represents an unset type variable.
     When it is unified with a type it is set to point to the type it
     has been unified with.  Type variables associated with variables
     have level set to the nesting level, others have level set to
     "generalisable". If two type variables are united their levels are 
     set to the lower of the two. If level is not "generalisable" the type
     variable is not generalisable. This is needed to deal with cases like
       fn a => let val x = a in x end      and
       fn a => let val x = hd a in x end
     The level is set to "generalisable" at the end of the block with that
     level. Actually ``level'' is not actually changed - instead the type
     variable is assigned to a new variable with the correct level, since
     only the last variable in a sequence is looked at.
     ``equality'' is true if this is an equality variable e.g. ''a.
     ``nonunifiable'' is true for type variables introduced explicitly
     or type variables in signatures. Such type variables can have their
     level changed but cannot be unified with other types, with other
     nonunifiable type variables or with equality variables (unless it
     is already an equality variable). 
     ``weak'' is true if this is an imperative type variable e.g. '_a *)

    fun sameTv (a : typeVarForm, b : typeVarForm) : bool = 
        #value a = #value b; (* If the same ref it must be the same *)
        
    local
        open Word
        infix 8 >> <<
        infix 7 andb
        infix 6 orb
    in
        fun makeTv {value : types, level, equality, nonunifiable, printable} : typeVarForm =
            { value    = ref value, (* REF HOTSPOT - 400 *)
              encoding = (fromInt level << 0w3)
                           orb (if equality     then 0w4 else 0w0)
                           orb (if nonunifiable then 0w2 else 0w0)
                           orb (if printable    then 0w1 else 0w0)}
        
        fun tvSetValue ({ value, ...} : typeVarForm, t : types) = value := t
        fun tvValue ({value = ref v, ...} : typeVarForm) : types = v
        fun tvLevel ({encoding, ...} : typeVarForm) : int  = Word.toInt(encoding >> 0w3)
        fun tvEquality ({encoding, ...} : typeVarForm)     = encoding andb 0w4 <> 0w0
        fun tvNonUnifiable ({encoding, ...} : typeVarForm) = encoding andb 0w2 <> 0w0
        fun tvPrintity ({encoding, ...} : typeVarForm)     = encoding andb 0w1 <> 0w0
    end

    local
        fun follow (FlexibleList(ref r)) = follow r
        |   follow (FieldList c) = c
    in
        fun recordIsFrozen { fullList, ...} =
            #2 (follow fullList)
        and recordFields {fullList, ...} =
            #1 (follow fullList)
    end

  (* Type constructors are identifiers which take zero or more types and yield a
     type as result. Their main property is that two type constructors can be 
     unified iff they are the same constructor. Another use for
     constructors is for aliasing types. In this case "typeVars" points to a list 
     of type variables which are used in the "equivalent" type. ``equality'' is a 
     flag indicating if the values can be tested for equality. *)
      
    fun tcName       (TypeConstrs {name,...})       = name
    fun tcIdentifier (TypeConstrs {identifier,...}) = identifier
    fun tcLocations  (TypeConstrs {locations, ...}) = locations

    (* Is this a type function?  N.B. It is possible, though unlikely, that it
       is a datatype as well i.e. has value constructors. *)
    fun tcIsAbbreviation (TypeConstrs {identifier = TypeId{idKind = TypeFn _, ...},...}) = true
    |   tcIsAbbreviation _ = false

    fun tcArity(TypeConstrs {identifier=TypeId{idKind=TypeFn(args, _),...}, ...}) = length args
    |   tcArity(TypeConstrs {identifier=TypeId{idKind=Bound{arity, ...},...}, ...}) = arity
    |   tcArity(TypeConstrs {identifier=TypeId{idKind=Free{arity, ...},...}, ...}) = arity

    (* Equality and "equivalence" are now properties of the type id.  Retain these functions for the moment. *)

    val tcEquality = isEquality o tcIdentifier;
    fun tcSetEquality(tc, eq) = setEquality(tcIdentifier tc, eq)

    (* Construct a type constructor. *)
    fun makeTypeConstructor (name, uid, locations) =
        TypeConstrs
        {
            name       = name,
            identifier = uid,
            locations = locations
        }

    fun tsConstr(TypeConstrSet(ts, _)) = ts
    and tsConstructors(TypeConstrSet(_, tvs)) = tvs

    val inBasis =
        { file = "Standard Basis", startLine = 0, startPosition = 0, endLine = 0, endPosition = 0}
    fun basisDescription name = { location = inBasis, description = "In Basis", name = name }


    (* Infix status. *)
    datatype infixity = 
        Infix of int
    |   InfixR of int
    |   Nonfix

    datatype fixStatus = FixStatus of string * infixity
      
    fun isGlobal   (Global   _) = true | isGlobal   _ = false;
    fun isLocal    (Local    _) = true | isLocal    _ = false;
    fun isSelected (Selected _) = true | isSelected _ = false;
    fun isFormal   (Formal   _) = true | isFormal   _ = false;
    
    fun vaGlobal   (Global   x) = x | vaGlobal   _ = raise Match;
    fun vaLocal    (Local    x) = x | vaLocal    _ = raise Match;
    fun vaSelected (Selected x) = x | vaSelected _ = raise Match;
    fun vaFormal   (Formal   x) = x | vaFormal   _ = raise Match;
    
    val makeGlobal = Global;
    val makeFormal = Formal;
  
    fun makeLocal () = Local { addr = ref ~1 (* Invalid addr - catch errors *), level = ref baseLevel }
       
    fun makeSelected (addr, base) =
        Selected { addr = addr, base = base };

    fun makeStruct (name, signat, access, locations) = 
        Struct { name = name, signat = signat, access = access, locations = locations }
    
    (* Global structure *)
    fun makeGlobalStruct (name, signat, code, locations) =
        makeStruct (name, signat, makeGlobal code, locations)

    (* These are used in INITIALISE so must be mutable. *)
    fun makeEmptyGlobal name =
        makeStruct (name,
            Signatures { name = "",
                   tab        = makeUnivTable(),
                   typeIdMap  = fn _ => raise Subscript,
                   firstBoundIndex   = 0, 
                   boundIds   = [],
                   locations =  [DeclaredAt inBasis] },
            makeGlobal CodeZero, [DeclaredAt inBasis])
     
    (* Local structure. *)
    fun makeLocalStruct (name, signat, location) = 
        makeStruct (name, signat, makeLocal (), location);
     
    (* Structure in a local structure or a functor argument. *)
    fun makeSelectedStruct (selected as Struct{access, name, signat, locations, ...}, base, openLocs) =
    case access of 
        Formal sel =>
           makeStruct(name, signat, makeSelected (sel, base), openLocs @ locations)
      | Global code => (* Need to add the locations. *)
           makeStruct(name, signat, Global code, openLocs @ locations)
      | _          => selected
  
    fun makeFormalStruct (name, signat, addr, location) =
      makeStruct (name, signat, makeFormal addr, location);
     
    (* Values. *)  
    fun makeOverloaded (name, typeOf, operation) : values =
    Value{ name = name, typeOf = typeOf, access = Overloaded operation, class = ValBound,
           locations = [DeclaredAt inBasis], references = NONE, instanceTypes = NONE};

    val undefinedValue    =
    Value{ name = "<undefined>", typeOf = BadType, access = Global CodeZero, class = ValBound,
           locations = [DeclaredAt inBasis], references = NONE, instanceTypes = NONE };

    fun isUndefinedValue(Value{name = "<undefined>", ...}) = true | isUndefinedValue _ = false

    fun valName (Value{name, ...}) = name
    fun valTypeOf (Value{typeOf, ...}) = typeOf

    fun isConstructor (Value{class=Constructor _, ...}) = true
    | isConstructor (Value{class=Exception, ...})     = true
    | isConstructor _                                  = false;

    fun isValueConstructor (Value{class=Constructor _, ...}) = true
    | isValueConstructor _                                 = false;


    (* Functor value. *)
    fun makeFunctor (name, arg, result, access, locations) = 
        Functor 
        {
            name = name,
            arg = arg,
            result = result,
            access = access,
            locations = locations
        }

    val valueVar:      values      tag = tag();
    val typeConstrVar: typeConstrSet tag = tag();
    val fixVar:        fixStatus   tag = tag();
    val structVar:     structVals  tag = tag();
    val signatureVar:  signatures  tag = tag();
    val functorVar:    functors    tag = tag();

    fun makeLook (t:'a tag) table n = univLookup (table, t, n)
    and makeEnter (t:'a tag) table (n, v) = univEnter (table, t, n, v)
    and makeAllNames (t:'a tag) table () =
        UNIVERSALTABLE.fold (fn (s, u, l) => if Universal.tagIs t u then s :: l else l) [] table

    datatype env = 
    Env of 
    { 
        lookupVal:    string -> values option,
        lookupType:   string -> typeConstrSet option,
        lookupFix:    string -> fixStatus option,
        lookupStruct: string -> structVals option,
        lookupSig:    string -> signatures option,
        lookupFunct:  string -> functors option,
        enterVal:     string * values      -> unit,
        enterType:    string * typeConstrSet -> unit,
        enterFix:     string * fixStatus   -> unit,
        enterStruct:  string * structVals  -> unit,
        enterSig:     string * signatures  -> unit,
        enterFunct:   string * functors    -> unit,
        allValNames:  unit -> string list
    }

    (* This creates functions for entering and looking up names. *)
    fun makeEnv tab =
        Env { lookupVal    = makeLook  valueVar      tab,
          lookupType   = makeLook  typeConstrVar tab,
          lookupFix    = makeLook  fixVar        tab,
          lookupStruct = makeLook  structVar     tab,
          lookupSig    = makeLook  signatureVar  tab,
          lookupFunct  = makeLook  functorVar    tab,
          enterVal     = makeEnter valueVar      tab,
          enterType    = makeEnter typeConstrVar tab,
          enterFix     = makeEnter fixVar        tab,
          enterStruct  = makeEnter structVar     tab,
          enterSig     = makeEnter signatureVar  tab,
          enterFunct   = makeEnter functorVar    tab,
          allValNames  = makeAllNames valueVar   tab
        }

    structure Sharing =
    struct
        type codetree   = codetree
        and  signatures = signatures
        and  types      = types
        and  values     = values
        and  typeId     = typeId
        and  structVals = structVals
        and  valAccess  = valAccess
        and  typeConstrs= typeConstrs
        and  typeConstrSet=typeConstrSet
        and  env        = env
        and  univTable  = univTable
        and  fixStatus  = fixStatus
        and  infixity   = infixity
        and  functors   = functors
        and  locationProp = locationProp
        and  typeVarForm = typeVarForm
        and  level      = level
    end
end (* STRUCTVALS *);