1(* 2 Original Poly version: 3 Title: Operations on type structures. 4 Author: Dave Matthews, Cambridge University Computer Laboratory 5 Copyright Cambridge University 1985 6 7 ML translation and other changes: 8 Copyright (c) 2000 9 Cambridge University Technical Services Limited 10 11 Further development: 12 Copyright (c) 2000-9, 2012-2018, 2020 David C.J. Matthews 13 14 This library is free software; you can redistribute it and/or 15 modify it under the terms of the GNU Lesser General Public 16 License version 2.1 as published by the Free Software Foundation. 17 18 This library is distributed in the hope that it will be useful, 19 but WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 Lesser General Public License for more details. 22 23 You should have received a copy of the GNU Lesser General Public 24 License along with this library; if not, write to the Free Software 25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 26*) 27 28functor TYPE_TREE ( 29 structure LEX : LEXSIG 30 structure STRUCTVALS : STRUCTVALSIG; 31 structure PRETTY : PRETTYSIG 32 structure CODETREE : CODETREESIG where type machineWord = Address.machineWord 33 structure EXPORTTREE: EXPORTTREESIG; 34 structure DEBUG: DEBUG 35 36 structure UTILITIES : 37 sig 38 val mapTable: ('a * 'a -> bool) -> 39 {enter: 'a * 'b -> unit, lookup: 'a -> 'b option} 40 val splitString: string -> { first:string, second:string } 41 end; 42 43 structure MISC : 44 sig 45 exception InternalError of string; 46 47 val lookupDefault : ('a -> 'b option) -> ('a -> 'b option) -> 'a -> 'b option 48 end; 49 50 sharing LEX.Sharing = PRETTY.Sharing = EXPORTTREE.Sharing = STRUCTVALS.Sharing 51 = CODETREE.Sharing 52 53) : TYPETREESIG = 54 55(*****************************************************************************) 56(* TYPETREE functor body *) 57(*****************************************************************************) 58struct 59 open MISC; 60 open PRETTY; 61 62 open STRUCTVALS; 63 open LEX; 64 open UTILITIES; 65 open CODETREE; 66 open EXPORTTREE 67 68 (* added 16/4/96 SPF *) 69 fun sameTypeVar (TypeVar x, TypeVar y) = sameTv (x, y) 70 | sameTypeVar _ = false; 71 72 73 fun isTypeVar (TypeVar _) = true 74 | isTypeVar _ = false; 75 76 fun isFunctionType (FunctionType _) = true 77 | isFunctionType _ = false; 78 79 fun isEmpty EmptyType = true 80 | isEmpty _ = false; 81 82 fun isBadType BadType = true 83 | isBadType _ = false; 84 85 val emptyType = EmptyType; 86 87 fun typesTypeVar (TypeVar x) = x 88 | typesTypeVar _ = raise Match; 89 90 fun typesFunctionType (FunctionType x) = x 91 | typesFunctionType _ = raise Match; 92 93 (* This is really left over from an old definition. *) 94 fun tcEquivalent(TypeConstrs{identifier = TypeId {idKind = TypeFn(_, result), ...}, ...}) = result 95 | tcEquivalent _ = raise InternalError "tcEquivalent: Not a type function" 96 97 (* A type construction is the application of a type constructor to 98 a sequence of types to yield a type. A construction may have a nil 99 list if it is a single type identifier such as ``int''. *) 100 101 (* When a type constructor is encountered in the first pass this entry 102 is put in. Subsequently a type constructor entry will be assigned to 103 it so that the types can be checked. *) 104 105(*************) 106 107 fun mkTypeVar (level, equality, nonunifiable, printable) = 108 TypeVar (makeTv {value=emptyType, level=level, equality=equality, 109 nonunifiable=nonunifiable, printable=printable}); 110 111 fun mkTypeConstruction (name, typc, args, locations) = 112 TypeConstruction {name = name, constr = typc, 113 args = args, locations = locations} 114 115 local 116 (* Turn a tuple into a record of the form {1=.., 2=... }*) 117 fun maptoRecord ([], _) = [] 118 | maptoRecord (H::T, i) = 119 {name=Int.toString i, typeof=H} :: maptoRecord (T,i+1) 120 in 121 fun mkProductType (typel: types list) = 122 let 123 val fields = maptoRecord (typel, 1) 124 in 125 LabelledType {recList = fields, fullList = FieldList(List.map #name fields, true)} 126 end 127 end 128 129 fun mkFunctionType (arg, result) = 130 FunctionType {arg = arg, result = result}; 131 132 fun mkOverloadSet [constr] = 133 (* If there is just a single constructor in the set we make 134 a type construction from it. *) 135 mkTypeConstruction(tcName constr, constr, nil, []) 136 | mkOverloadSet constrs = 137 let 138 (* Make a type variable and point this at the overload set 139 so we can narrow down the overloading. *) 140 val var = mkTypeVar (generalisable, false, false, false) 141 val set = OverloadSet {typeset=constrs}; 142 in 143 tvSetValue (typesTypeVar var, set); 144 var 145 end 146 147 fun mkLabelled (l, frozen) = 148 let 149 val final = FieldList(map #name l, frozen) 150 val lab = 151 LabelledType {recList = l, 152 fullList = if frozen then final else FlexibleList(ref final) } 153 in 154 if frozen 155 then lab 156 else 157 let 158 (* Use a type variable so that the record can be expanded. 159 This also provides a model (equality etc). for any fields that 160 are added later. *) 161 val var = mkTypeVar (generalisable, false, false, false) 162 val () = 163 if isTypeVar var 164 then tvSetValue (typesTypeVar var, lab) 165 else (); 166 in 167 var 168 end 169 end 170 171 (* Must remove leading zeros because the labels are compared by 172 string comparison. *) 173 fun mkLabelEntry (name, t) = 174 let 175 fun stripZeros s = 176 if size s <= 1 orelse String.str(String.sub(s, 0)) <> "0" 177 then s 178 else stripZeros (String.substring(s, 1, size s-1)); 179 in 180 {name = stripZeros name, typeof = t} 181 end; 182 183 (* Functions to construct the run-time representations of type constructor values, 184 type values and value constructors. These are all tuples and centralising the 185 code here avoids having the offsets as integers at various places. 186 Monotype constructor and type values are almost the same except that 187 type values have the printer entry as the function whereas monotype 188 constructors have the print entry as a ref pointing to the function, 189 allowing addPrettyPrint to set a printer for the type. The entries 190 for polytypes are functions that take the type values as arguments 191 and return the corresponding values. *) 192 structure TypeValue = 193 struct 194 val equalityOffset = 0 195 and printerOffset = 1 196 and boxnessOffset = 2 197 and sizeOffset = 3 198 199 local 200 (* Values used to represent boxness. *) 201 val boxedRepNever = 0w1 (* Never boxed, always tagged e.g. bool *) 202 and boxedRepAlways = 0w2 (* Always boxed, never tagged e.g. function types *) 203 and boxedRepEither = 0w3 (* Either boxed or tagged e.g. (arbitrary precision) int *) 204 fun make n = mkConst(Address.toMachineWord n) 205 fun isCode n = 206 mkInlproc(mkEqualTaggedWord(mkLoadArgument 0, make n), 1, "test-box", [], 0) 207 in 208 val boxedNever = make boxedRepNever 209 and boxedAlways = make boxedRepAlways 210 and boxedEither = make boxedRepEither 211 (* Test for boxedness. This must be applied to the value extracted from 212 the "boxedness" field after applying to any base type arguments in 213 the case of a polytype constructor. *) 214 val isBoxedNever = isCode boxedRepNever 215 and isBoxedAlways = isCode boxedRepAlways 216 and isBoxedEither = isCode boxedRepEither 217 end 218 219 (* Sizes are always a single word. *) 220 val singleWord = mkConst(Address.toMachineWord 0w1) 221 222 fun extractEquality idCode = mkInd(equalityOffset, idCode) 223 and extractPrinter idCode = mkInd(printerOffset, idCode) 224 and extractBoxed idCode = mkInd(boxnessOffset, idCode) 225 and extractSize idCode = mkInd(sizeOffset, idCode) 226 227 fun createTypeValue{eqCode, printCode, boxedCode, sizeCode} = 228 mkTuple[eqCode, printCode, boxedCode, sizeCode] 229 end 230 231 (* Value constructors are represented by tuples, either pairs for nullary constructors 232 or triples for constructors with arguments. For nullary functions the "injection" 233 function is actually the value itself. If this is a polytype all the entries are 234 functions that take the type values for the base types as arguments. *) 235 structure ValueConstructor = 236 struct 237 val testerOffset = 0 238 val injectorOffset = 1 239 val projectorOffset = 2 240 241 fun extractTest constrCode = mkInd(testerOffset, constrCode) 242 and extractInjection constrCode = mkInd(injectorOffset, constrCode) 243 and extractProjection constrCode = mkInd(projectorOffset, constrCode) 244 245 fun createValueConstr{testMatch, injectValue, projectValue} = mkTuple[testMatch, injectValue, projectValue] 246 fun createNullaryConstr{ testMatch, constrValue } = mkTuple[testMatch, constrValue] 247 end 248 249 (* Eqtypes with built-in equality functions. The printer functions are all replaced in the basis. *) 250 local 251 open Address PRETTY TypeValue 252 fun defaultMonoTypePrinter _ = PrettyString "?" 253 fun defaultPolyTypePrinter _ _ = PrettyString "?" 254 255 fun eqAndPrintCode (eqCode, nArgs, boxed) = 256 let 257 val code = 258 if nArgs = 0 259 then createTypeValue{ 260 eqCode=eqCode, 261 printCode=mkConst (toMachineWord (ref defaultMonoTypePrinter)), 262 boxedCode = boxed, 263 sizeCode = singleWord 264 } 265 else createTypeValue{ 266 eqCode=mkInlproc(eqCode, nArgs, "eq-helper()", [], 0), 267 printCode=mkConst (toMachineWord (ref defaultPolyTypePrinter)), 268 boxedCode = mkInlproc(boxed, nArgs, "boxed-helper()", [], 0), 269 sizeCode = mkInlproc(singleWord, nArgs, "size-helper()", [], 0) 270 } 271 in 272 Global (genCode(code, [], 0) ()) 273 end 274 275 fun makeConstr(name, fullName, eqFun, boxed) = 276 makeTypeConstructor (name, [], 277 makeFreeId(0, eqAndPrintCode(eqFun, 0, boxed), true, basisDescription fullName), 278 [DeclaredAt inBasis]) 279 280 (* since code generator relies on these representations, 281 we may as well export them *) 282 283 (* Strings are now always vectors whose first word is the length. 284 The old special case for single-character strings has been removed. *) 285 local 286 val stringEquality = 287 mkInlproc( 288 (* This previously checked for pointer equality first. That has 289 been removed. 290 Test the lengths first and only do the byte comparison if 291 they are the same. This seems to save more time than including 292 the length word in the byte comparison. *) 293 mkCand( 294 mkEqualPointerOrWord( (* Because we're not actually tagging these we use pointerEq here. *) 295 mkLoadOperation(LoadStoreUntaggedUnsigned, mkLoadArgument 0, CodeZero), 296 mkLoadOperation(LoadStoreUntaggedUnsigned, mkLoadArgument 1, CodeZero)), 297 mkBlockOperation{kind=BlockOpEqualByte, leftBase=mkLoadArgument 0, rightBase=mkLoadArgument 1, 298 leftIndex=mkConst(toMachineWord wordSize), rightIndex=mkConst(toMachineWord wordSize), 299 (* Use argument 1 here rather than 0. We could use either but this works 300 better when we're using equality for pattern matching since it 301 gets the length of the constant string. It also works better 302 for the, to me, more natural ordering of variable=constant. *) 303 length=mkLoadOperation(LoadStoreUntaggedUnsigned, mkLoadArgument 1, CodeZero) 304 } 305 ), 306 2, "stringEquality", [], 0) 307 in 308 val stringEquality = stringEquality 309 end 310 311 local 312 (* Arbitrary precision values are normalised so if a value can be represented 313 as a tagged fixed precision value it will be. 314 Unlike strings it is much more likely that the value will be short so we 315 generate equality as a test that handles the short case as inline code and 316 the long case as a function call. If either argument is a short constant 317 this will be optimised away so the test will reduce to a test on whether 318 the value equals the constant. *) 319 val intEquality = 320 mkEnv( 321 [mkDec(0, 322 (* Long-form equality - should not be inlined. *) 323 mkProc( 324 (* Equal if signs are the same ... *) 325 mkCand( 326 mkEqualTaggedWord( 327 mkUnary(BuiltIns.MemoryCellFlags, mkLoadArgument 0), 328 mkUnary(BuiltIns.MemoryCellFlags, mkLoadArgument 1) 329 ), 330 mkEnv( 331 [mkDec(0, mkUnary(BuiltIns.MemoryCellLength, mkLoadArgument 1))], 332 mkCand( 333 (* ... and the lengths are equal ... *) 334 mkEqualTaggedWord( 335 mkUnary(BuiltIns.MemoryCellLength, mkLoadArgument 0), 336 mkLoadLocal 0 337 ), 338 (* ... and they're byte-wise equal .*) 339 mkBlockOperation{kind=BlockOpEqualByte, leftBase=mkLoadArgument 0, rightBase=mkLoadArgument 1, 340 leftIndex=CodeZero, rightIndex=CodeZero, 341 length=mkBinary(BuiltIns.WordArith BuiltIns.ArithMult, 342 mkConst(toMachineWord RunCall.bytesPerWord), mkLoadLocal 0)} 343 ) 344 ) 345 ), 346 2, "arbitraryPrecisionEquality", [], 1) 347 ) 348 ], 349 mkInlproc( 350 mkCor( (* Either they're equal... *) 351 (* N.B. The values could be short or long. That's particularly important 352 if we have a series of tests against short constants. If we convert it to 353 an indexed case we MUST check that the value is short before computing 354 the index. *) 355 mkEqualPointerOrWord(mkLoadArgument 0, mkLoadArgument 1), 356 (* .. or if either is short the result is false ... *) 357 mkCand( 358 mkCand( 359 mkNot(mkIsShort(mkLoadArgument 0)), 360 mkNot(mkIsShort(mkLoadArgument 1)) 361 ), 362 (* ... otherwise we have to test the vectors. *) 363 mkEval(mkLoadClosure 0, [mkLoadArgument 0, mkLoadArgument 1]) 364 ) 365 ), 366 2, "intInfEquality", [mkLoadLocal 0], 0) 367 ) 368 in 369 (* Code-generate the function and return the inline part. 370 We need to set the maximum inline size here to ensure the long form 371 code is not inlined. It would be better to have a way of turning off 372 inlining for specific functions. *) 373 val intEquality = genCode(intEquality, [Universal.tagInject DEBUG.maxInlineSizeTag 5], 1) () 374 end 375 in 376 val fixedIntConstr = makeConstr("int", "FixedInt.int", equalTaggedWordFn, boxedNever) (* Fixed precision is always short *) 377 val intInfConstr = makeConstr("int", "IntInf.int", intEquality, boxedEither) 378 val charConstr = makeConstr("char", "char", equalTaggedWordFn, boxedNever) (* Always short *) 379 val stringConstr = makeConstr("string", "string", stringEquality, boxedEither (* Single chars are unboxed. *)) 380 val wordConstr = makeConstr("word", "word", equalTaggedWordFn, boxedNever) 381 382 (* Ref is a datatype with a single constructor. The constructor is added in INITIALISE. 383 Equality is special for "'a ref", "'a array" and "'a Array2.array". They permit equality 384 even if the 'a is not an eqType. *) 385 val refConstr = 386 makeTypeConstructor 387 ("ref", 388 [makeTv {value=EmptyType, level=generalisable, equality=false, nonunifiable=false, printable=false}], 389 makeFreeId(1, eqAndPrintCode(equalPointerOrWordFn, 1, boxedAlways), true, basisDescription "ref"), 390 [DeclaredAt inBasis]); 391 val arrayConstr = 392 makeTypeConstructor 393 ("array", 394 [makeTv {value=EmptyType, level=generalisable, equality=false, nonunifiable=false, printable=false}], 395 makeFreeId(1, eqAndPrintCode(equalPointerOrWordFn, 1, boxedAlways), true, basisDescription "Array.array"), 396 [DeclaredAt inBasis]); 397 val array2Constr = 398 makeTypeConstructor 399 ("array", 400 [makeTv {value=EmptyType, level=generalisable, equality=false, nonunifiable=false, printable=false}], 401 makeFreeId(1, eqAndPrintCode(equalPointerOrWordFn, 1, boxedAlways), true, basisDescription "Array2.array"), 402 [DeclaredAt inBasis]); 403 val byteArrayConstr = 404 makeTypeConstructor 405 ("byteArray", [], 406 makeFreeId(0, eqAndPrintCode(equalPointerOrWordFn, 0, boxedAlways), true, basisDescription "byteArray"), 407 [DeclaredAt inBasis]); 408 (* Bool is a datatype. The constructors are added in INITIALISE. *) 409 val boolConstr = 410 makeTypeConstructor 411 ("bool", [], makeFreeId(0, eqAndPrintCode(equalTaggedWordFn, 0, boxedNever), true, basisDescription "bool"), 412 [DeclaredAt inBasis]); 413 end 414 415 (* These polytypes allow equality even if the type argument is not an equality type. *) 416 fun isPointerEqType id = 417 sameTypeId (id, tcIdentifier refConstr) orelse 418 sameTypeId (id, tcIdentifier arrayConstr) orelse 419 sameTypeId (id, tcIdentifier array2Constr) orelse 420 sameTypeId (id, tcIdentifier byteArrayConstr) 421 422 (* Non-eqtypes *) 423 local 424 open Address PRETTY TypeValue 425 426 fun makeType(name, descr, boxed) = 427 let 428 fun defaultPrinter _ = PrettyString "?" 429 val code = 430 createTypeValue{ 431 eqCode=CodeZero (* No equality. *), 432 printCode=mkConst (toMachineWord (ref defaultPrinter)), 433 boxedCode=boxed, 434 sizeCode=singleWord 435 } 436 in 437 makeTypeConstructor ( 438 name, [], makeFreeId(0, Global (genCode(code, [], 0) ()), false, descr), 439 [DeclaredAt inBasis]) 440 end 441 in 442 val realConstr = makeType("real", basisDescription "real", boxedAlways(* Currently*)) (* Not an eqtype in ML97. *) 443 (* Short real: Real32.real *) 444 val floatConstr = 445 makeType("real", basisDescription "real", 446 if RunCall.bytesPerWord <= 0w4 then boxedAlways else boxedNever) 447 val exnConstr = makeType("exn", basisDescription "exn", boxedAlways); 448 (* "undefConstr" is used as a place-holder during parsing for the actual type constructor. 449 If the type constructor is not found this may appear in an error message. *) 450 val undefConstr = 451 makeType("undefined", { location = inBasis, description = "Undefined", name = "undefined" }, boxedEither); 452 end 453 454 (* The unit type is equivalent to the empty record. *) 455 val unitConstr = 456 makeTypeConstructor ("unit", [], 457 makeTypeFunction({ location = inBasis, description = "unit", name = "unit" }, 458 ([], LabelledType {recList = [], fullList = FieldList([], true)})), 459 [DeclaredAt inBasis]); 460 461 462 (* Type identifiers bound to standard type constructors. *) 463 464 val unitType = mkTypeConstruction ("unit", unitConstr, [], []) 465 466 val fixedIntType = mkTypeConstruction ("int", fixedIntConstr, [], []) 467 val stringType = mkTypeConstruction ("string", stringConstr, [], []) 468 val boolType = mkTypeConstruction ("bool", boolConstr, [], []) 469 val exnType = mkTypeConstruction ("exn", exnConstr, [], []) 470 471 fun isUndefined cons = sameTypeId (tcIdentifier cons, tcIdentifier undefConstr); 472 val isUndefinedTypeConstr = isUndefined 473 474 (* Test if a type is the undefined constructor. *) 475 fun isUndefinedType(TypeConstruction{constr, ...}) = isUndefined constr 476 | isUndefinedType _ = false 477 478 (* Similar to alphabetic ordering except that shorter labels come before longer ones. 479 This has the advantage that numerical labels are compared by their numerical order 480 i.e. 1 < 2 < 10 whereas alphabetic ordering puts "1" < "10" < "2". *) 481 fun compareLabels (a : string, b : string) : int = 482 if size a = size b 483 then if a = b then 0 else if a < b then ~1 else 1 484 else if size a < size b then ~1 else 1; 485 486 (* Sort using the label ordering. 487 A simple sort routine - particularly if the list is already sorted. *) 488 fun sortLabels [] = [] 489 | sortLabels (s::rest) = 490 let 491 fun enter s _ [] = [s] 492 | enter s name (l as ( (h as {name=hname, ...}) :: t)) = 493 let 494 val comp = compareLabels (name, hname); 495 in 496 if comp <= 0 then s :: l else h :: enter s name t 497 end; 498 in 499 enter s (#name s) (sortLabels rest) 500 end 501 502 (* Chains down a list of type variables returning the type they are 503 bound to. As a side-effect it also points all the type variables 504 at this type to reduce the need for future chaining and to free 505 unused type variables. Normally a type variable points to at most 506 one other, which then points to "empty". However if we have unified 507 two type variables by pointing one at the other, there may be type 508 variables which pointed to the first and which cannot be found and 509 redirected at the second until they themselves are examined. *) 510 511 fun eventual (t as (TypeVar tv)) : types = 512 let 513 (* Note - don't change the level/copy information - the only type 514 variable with this correct is the one at the end of the list. *) 515 val oldVal = tvValue tv 516 val newVal = eventual oldVal; (* Search that *) 517 in 518 (* Update the type variable to point to the last in the chain. 519 We don't do this if the value hasn't changed. The reason for 520 that was that assignment to refs in the database in the old 521 persistent store system was very expensive and we wanted to avoid 522 unnecessary assignments. This special case could probably be removed. *) 523 if PolyML.pointerEq(oldVal, newVal) 524 then () 525 else tvSetValue (tv, newVal); (* Put it on *) 526 case newVal of 527 EmptyType => t (* Not bound to anything - return the type variable *) 528 | LabelledType (r as { recList, fullList }) => 529 if List.length recList = List.length(recordFields r) 530 then (* All the generic fields are present so we don't need to do anything. *) 531 if recordIsFrozen r then newVal else t 532 else (* We need to add fields from the generic. *) 533 let 534 (* Add any fields from the generic that aren't present in this instance. *) 535 fun createNewField name = 536 { name = name, 537 (* The new type variable has to be created with the same properties 538 as if we had first generalised it from the generic and then 539 unified with this instance. 540 The level is inherited from the instance since the generic 541 will always have level = generalisable. Nonunifiable must be false. *) 542 typeof = mkTypeVar (tvLevel tv, tvEquality tv, false, tvPrintity tv)} 543 544 fun addToInstance([], []) = [] 545 | addToInstance(generic :: geRest, []) = createNewField generic :: addToInstance(geRest, []) 546 | addToInstance([], instance) = instance 547 (* This case can occur if we are producing an error message because of 548 a type-incorrect program so we just ignore it. *) 549 | addToInstance(generic :: geRest, inst as instance :: iRest) = 550 let 551 val order = compareLabels (generic, #name instance); 552 in 553 if order = 0 (* Equal *) 554 then instance :: addToInstance(geRest, iRest) 555 else if order < 0 (* generic name < instance name *) 556 then createNewField generic :: addToInstance(geRest, inst) 557 else (* This is another case that can occur with type-incorrect code. *) 558 instance :: addToInstance(generic :: geRest, iRest) 559 end 560 561 val newList = addToInstance(recordFields r, recList) 562 val newRecord = 563 LabelledType {recList = newList, fullList = fullList} 564 in 565 tvSetValue(tv, newRecord); 566 if recordIsFrozen r then newRecord else t 567 end 568 569 | OverloadSet _ => t (* Return the set of types. *) 570 571 | _ => newVal (* Return the type it is bound to *) 572 end 573 574 | eventual t (* not a type variable *) = t; 575 576 577 (* Apply a function to every element of a type. *) 578 fun foldType f = 579 let 580 fun foldT typ v = 581 let 582 val t = eventual typ; 583 val res = f t v; (* Process this entry. *) 584 in 585 case t of 586 TypeVar tv => foldT (tvValue tv) res 587 588 | TypeConstruction {args, ...} => (* Then process the arguments. *) 589 List.foldr (fn (t, v) => foldT t v) res args 590 591 | FunctionType {arg, result} => foldT arg (foldT result res) 592 593 | LabelledType {recList,...} => 594 List.foldr (fn ({ typeof, ... }, v) => foldT typeof v) res recList 595 596 | BadType => res 597 598 | EmptyType => res 599 600 | OverloadSet _ => res 601 end 602 in 603 foldT 604 end; 605 606 (* Checks to see whether a labelled record is in the form of 607 a product i.e. 1=, 2= We only need this for prettyprinting. 608 Zero-length records (i.e. unit) and singleton records are not 609 considered as tuples. *) 610 fun isProductType(LabelledType(r as {recList=recList as _::_::_, ...})) = 611 let 612 fun isRec [] _ = true 613 | isRec ({name, ...} :: l) n = 614 name = Int.toString n andalso isRec l (n+1) 615 in 616 recordIsFrozen r andalso isRec recList 1 617 end 618 | isProductType _ = false; 619 620 621 (* Test to see is a type constructor is in an overload set. *) 622 fun isInSet(tcons: typeConstrs, (H::T): typeConstrs list) = 623 sameTypeId (tcIdentifier tcons, tcIdentifier H) orelse isInSet(tcons, T) 624 | isInSet(_, []: typeConstrs list) = false 625 626 val prefInt = ref fixedIntConstr 627 628 (* Returns the preferred overload if there is one. *) 629 fun preferredOverload typeset = 630 if isInSet(!prefInt, typeset) 631 then SOME(!prefInt) 632 else if isInSet(realConstr, typeset) 633 then SOME realConstr 634 else if isInSet(wordConstr, typeset) 635 then SOME wordConstr 636 else if isInSet(charConstr, typeset) 637 then SOME charConstr 638 else if isInSet(stringConstr, typeset) 639 then SOME stringConstr 640 else NONE 641 642 fun setPreferredInt c = prefInt := c 643 644 fun equalTypeIds(x, y) = 645 let 646 (* True if two types are equal. *) 647 fun equalTypes (TypeConstruction{constr=xVal, args=xArgs, ...}, 648 TypeConstruction{constr=yVal, args=yArgs, ...}) = 649 equalTypeIds(tcIdentifier xVal, tcIdentifier yVal) 650 andalso equalTypeLists (xArgs, yArgs) 651 652 | equalTypes (FunctionType x, FunctionType y) = 653 equalTypes (#arg x, #arg y) andalso 654 equalTypes (#result x, #result y) 655 656 | equalTypes (LabelledType x, LabelledType y) = 657 recordIsFrozen x andalso recordIsFrozen y andalso 658 equalRecordLists (#recList x, #recList y) 659 660 | equalTypes (TypeVar x, TypeVar y) = sameTv (x, y) 661 662 | equalTypes (EmptyType, EmptyType) = true 663 664 | equalTypes _ = false 665 666 and equalTypeLists ([], []) = true 667 | equalTypeLists (x::xs, y::ys) = 668 equalTypes(x, y) andalso equalTypeLists (xs, ys) 669 | equalTypeLists _ = false 670 671 and equalRecordLists ([], []) = true 672 | equalRecordLists (x::xs, y::ys) = 673 #name x = #name y andalso 674 equalTypes(#typeof x, #typeof y) andalso equalRecordLists (xs, ys) 675 | equalRecordLists _ = false 676 in 677 case (x, y) of 678 (TypeId{idKind=TypeFn(_, xEquiv), ...}, TypeId{idKind=TypeFn(_, yEquiv), ...}) => 679 equalTypes(xEquiv, yEquiv) 680 | _ => sameTypeId(x, y) 681 end 682 683 (* See if the types are the same. This is a bit of a fudge, but saves carrying 684 around a flag saying whether the structures were copied. This is only an 685 optimisation. If the values are different it will not go wrong. *) 686 val identical : types * types -> bool = PolyML.pointerEq 687 and identicalConstr : typeConstrs * typeConstrs -> bool = PolyML.pointerEq 688 and identicalList : 'a list * 'a list -> bool = PolyML.pointerEq 689 690 (* Copy a type, avoiding copying type structures unnecessarily. 691 Used to make new type variables for all distinct type variables when 692 generalising polymorphic functions, and to make new type stamps for 693 type constructors when generalising signatures. *) 694 fun copyType (at, copyTypeVar, copyTypeConstr) = 695 let 696 fun copyList [] = [] 697 | copyList (l as (h :: t)) = 698 let 699 val h' = copyType (h, copyTypeVar, copyTypeConstr); 700 val t' = copyList t; 701 in 702 if identical (h', h) andalso identicalList (t', t) 703 then l 704 else h' :: t' 705 end (* copyList *); 706 707 fun copyRecordList [] = [] 708 | copyRecordList (l as ({name, typeof} :: t)) = 709 let 710 val typeof' = copyType (typeof, copyTypeVar, copyTypeConstr); 711 val t' = copyRecordList t; 712 in 713 if identical (typeof', typeof) andalso identicalList (t', t) 714 then l 715 else {name=name, typeof=typeof'} :: t' 716 end (* copyList *); 717 718 val atyp = eventual at; 719 in 720 case atyp of 721 TypeVar _ => (* Unbound type variable, flexible record or overloading. *) 722 copyTypeVar atyp 723 724 | TypeConstruction {constr, args, locations, ...} => 725 let 726 val copiedArgs = copyList args; 727 val copiedConstr = copyTypeConstr constr; 728 (* Use the name from the copied constructor. This will normally 729 be the same as the original EXCEPT in the case where we are 730 using copyType to generate copies of the value constructors of 731 replicated datatypes. *) 732 val copiedName = tcName copiedConstr 733 in 734 if identicalList (copiedArgs, args) andalso 735 identicalConstr (copiedConstr, constr) 736 then atyp 737 else (* Must copy it. *) 738 mkTypeConstruction (copiedName, copiedConstr, copiedArgs, locations) 739 end 740 741 | FunctionType {arg, result} => 742 let 743 val copiedArg = copyType (arg, copyTypeVar, copyTypeConstr); 744 val copiedRes = copyType (result, copyTypeVar, copyTypeConstr); 745 in 746 if identical (copiedArg, arg) andalso 747 identical (copiedRes, result) 748 then atyp 749 else FunctionType {arg = copiedArg, result = copiedRes} 750 end 751 752 | LabelledType {recList, fullList} => 753 (* Rigid labelled records only. Flexible ones are treated as type vars. *) 754 let 755 val copiedList = copyRecordList recList 756 in 757 if identicalList (copiedList, recList) 758 then atyp 759 else LabelledType {recList = copiedList, fullList = fullList} 760 end 761 762 | EmptyType => 763 EmptyType 764 765 | BadType => 766 BadType 767 768 | OverloadSet _ => 769 raise InternalError "copyType: OverloadSet found" 770 771 end (* copyType *); 772 773 (* Copy a type constructor if it is Bound and in the required range. If this refers to a type 774 function copies that as well. Does not copy value constructors. *) 775 fun copyTypeConstrWithCache (tcon, typeMap, _, mungeName, cache) = 776 case tcIdentifier tcon of 777 TypeId{idKind = TypeFn(args, equiv), description, access, ...} => 778 let 779 val copiedEquiv = 780 copyType(equiv, fn x => x, 781 fn tcon => 782 copyTypeConstrWithCache (tcon, typeMap, fn x => x, mungeName, cache)) 783 in 784 if identical (equiv, copiedEquiv) 785 then tcon (* Type is identical and we don't want to change the name. *) 786 else (* How do we find a type function? *) 787 makeTypeConstructor (mungeName(tcName tcon), args, 788 TypeId { 789 access = access, description = description, idKind = TypeFn(args, copiedEquiv)}, 790 tcLocations tcon) 791 792 end 793 794 | id => 795 ( 796 case typeMap id of 797 NONE => 798 ( 799 (*print(concat[tcName tcon, " not copied\n"]);*) 800 tcon (* No change *) 801 ) 802 | SOME newId => 803 let 804 val name = #second(splitString (tcName tcon)) 805 (* We must only match here if they're really the same. *) 806 fun cacheMatch tc = 807 equalTypeIds(tcIdentifier tc, newId) 808 andalso #second(splitString(tcName tc)) = name 809 in 810 case List.find cacheMatch cache of 811 SOME tc => 812 ( 813 (*print(concat[tcName tcon, " copied as ", tcName tc, "\n"]);*) 814 tc (* Use the entry from the cache. *) 815 ) 816 | NONE => 817 (* Either a hidden identifier or alternatively this can happen as part of 818 the matching process. 819 When matching a structure to a signature we first match up the type 820 constructors then copy the type of each value replacing bound type IDs 821 with the actual IDs as part of the checking process. 822 We will return SOME newId but we don't have a 823 cache so return NONE for List.find. *) 824 let 825 val newName = mungeName(tcName tcon) 826 in 827 (*print(concat[tcName tcon, " not cached\n"]);*) 828 makeTypeConstructor(newName, tcTypeVars tcon, newId, tcLocations tcon) 829 end 830 end 831 ) 832 833 (* Exported version. *) 834 fun copyTypeConstr (tcon, typeMap, copyTypeVar, mungeName) = 835 copyTypeConstrWithCache(tcon, typeMap, copyTypeVar, mungeName, []) 836 837 (* Compose typeID maps. If the first map returns a Bound id we apply the second otherwise 838 just return the result of the first. *) 839 fun composeMaps(m1, m2) n = 840 let 841 fun map2 (TypeId{idKind=Bound{ offset, ...}, ...}) = m2 offset 842 843 | map2 (id as TypeId{idKind=Free _, ...}) = id 844 845 | map2 (TypeId{idKind=TypeFn(args, equiv), access, description, ...}) = 846 let 847 fun copyId(TypeId{idKind=Free _, ...}) = NONE 848 | copyId id = SOME(map2 id) 849 (* If it's a type function e.g. this was a "where type" we have to apply the 850 map to any type identifiers in the type. *) 851 val copiedEquiv = 852 copyType(equiv, fn x => x, 853 fn tcon => copyTypeConstr (tcon, copyId, fn x => x, fn y => y)) 854 in 855 TypeId{idKind = TypeFn(args, copiedEquiv), access=access, description=description} 856 end 857 in 858 map2(m1 n) 859 end 860 861 (* Basic procedure to print a type structure. *) 862 type printTypeEnv = 863 { lookupType: string -> (typeConstrSet * (int->typeId) option) option, 864 lookupStruct: string -> (structVals * (int->typeId) option) option} 865 866 val emptyTypeEnv = { lookupType = fn _ => NONE, lookupStruct = fn _ => NONE } 867 868 (* Test whether two type constructors are the same after mapping. 869 This is used to try to find the correct "path" to a type constructor 870 when printing. *) 871 fun eqTypeConstrs(xTypeCons, xMap, yTypeCons, yMap) = 872 let 873 fun id x = x 874 fun copyId (SOME mapTypeId) (TypeId{idKind=Bound{ offset, ...}, ...}) = SOME(mapTypeId offset) 875 | copyId _ _ = NONE 876 val mappedX = copyTypeConstr(xTypeCons, copyId xMap, id, id) 877 and mappedY = copyTypeConstr(yTypeCons, copyId yMap, id, id) 878 in 879 equalTypeIds(tcIdentifier mappedX, tcIdentifier mappedY) 880 end 881 882 (* prints a block of items *) 883 fun tDisp (t : types, depth : FixedInt.int, typeVarName : typeVarForm -> string, env: printTypeEnv, 884 sigMap: (int->typeId)option) : pretty = 885 let 886 (* prints a block of items *) 887 fun dispP (t : types, depth : FixedInt.int) : pretty = 888 let 889 (* prints a block of items *) 890 fun parenthesise depth t = 891 if depth <= 1 892 then PrettyString "..." 893 else 894 PrettyBlock (0, false, [], 895 [ 896 PrettyString "(", 897 dispP (t, depth - 1), 898 PrettyString ")" 899 ]); 900 901 (* prints a sequence of items *) 902 fun prettyList [] _ _: pretty list = [] 903 904 | prettyList [H] depth separator = 905 let 906 val v = eventual H; 907 in 908 if separator = "*" andalso 909 (isFunctionType v orelse isProductType v) 910 then (* Must bracket the expression *) [parenthesise depth v] 911 else [dispP (v, depth)] 912 end 913 914 | prettyList (H :: T) depth separator = 915 if depth <= 0 916 then [PrettyString "..."] 917 else 918 let 919 val v = eventual H; 920 in 921 PrettyBlock (0, false, [], 922 [(if separator = "*" andalso 923 (isFunctionType v orelse isProductType v) 924 then (* Must bracket the expression *) parenthesise depth v 925 else dispP (v, depth)), 926 PrettyBreak (if separator = "," then 0 else 1, 0), 927 PrettyString separator 928 ]) :: 929 PrettyBreak (1, 0) :: 930 prettyList T (depth - 1) separator 931 end; 932 933 val typ = eventual t; (* Find the real type structure *) 934 in 935 case typ of 936 TypeVar tyVar => 937 let 938 val tyVal : types = tvValue tyVar; 939 in 940 case tyVal of 941 EmptyType => PrettyString (typeVarName tyVar) 942 | _ => dispP (tyVal, depth) 943 end 944 945 (* Type construction. *) 946 | TypeConstruction {args, name, constr=typeConstructor, ...} => 947 let 948 val constrName = (* Use the type constructor name unless we're had an error. *) 949 if isUndefined typeConstructor then name else tcName typeConstructor 950 951 (* There are three possible cases: we may not find any type with the 952 name, we may look up the name and find the type or we may look up the 953 name and find a different type. *) 954 datatype isFound = NotFound | FoundMatch | FoundNotMatch 955 956 (* If we're printing a value that refers to a type constructor we 957 want to print the correct amount of any structure prefix for the 958 current context. *) 959 fun findType (_, []) = NotFound 960 | findType ({ lookupType, ... }, [typeName]) = 961 ( 962 (* This must be the name of a type. *) 963 case lookupType typeName of 964 SOME (t, map) => 965 if eqTypeConstrs(typeConstructor, sigMap, tsConstr t, map) 966 then FoundMatch else FoundNotMatch 967 | NONE => NotFound 968 ) 969 | findType ({ lookupStruct, ... }, structName :: tail) = 970 ( 971 (* This must be the name of a structure. Does it contain our type? *) 972 case lookupStruct structName of 973 SOME(Struct { signat, ...}, map) => 974 let 975 val Signatures { tab, typeIdMap, ...} = signat 976 val Env { lookupType, lookupStruct, ...} = makeEnv tab 977 val newMap = 978 case map of 979 SOME map => composeMaps(typeIdMap, map) 980 | NONE => typeIdMap 981 fun subLookupType s = 982 case lookupType s of NONE => NONE | SOME t => SOME(t, SOME newMap) 983 fun subLookupStruct s = 984 case lookupStruct s of NONE => NONE | SOME t => SOME(t, SOME newMap) 985 in 986 findType({lookupType=subLookupType, lookupStruct=subLookupStruct}, tail) 987 end 988 | NONE => NotFound 989 ) 990 991 (* See if we have this type in the current environment or in some structure in 992 the current environment. The name we have may be a full structure path. *) 993 fun nameToList ("", l) = (l, NotFound) (* Not there. *) 994 | nameToList (s, l) = 995 let 996 val { first, second } = splitString s 997 val currentList = second :: l 998 in 999 case findType(env, currentList) of 1000 FoundMatch => (currentList, FoundMatch) 1001 | FoundNotMatch => 1002 ( 1003 case nameToList(first, currentList) of 1004 result as (_, FoundMatch) => result 1005 | (l, _) => (l, FoundNotMatch) 1006 ) 1007 | NotFound => nameToList(first, currentList) 1008 end 1009 (* Try the type constructor name first. This is usually accurate. If not 1010 fall back to the type identifier. This may be needed in rarer cases. *) 1011 val names = 1012 case nameToList(constrName, []) of 1013 (names, FoundMatch) => names (* Found the type constructor name. *) 1014 | (names, f) => 1015 let 1016 (* Try the type identifier name. *) 1017 val TypeId { description = { name=idName, ...}, ...} = 1018 case (sigMap, tcIdentifier typeConstructor) of 1019 (SOME map, TypeId{idKind=Bound{offset, ...}, ...}) => map offset 1020 | (_, id) => id 1021 (* Only add "?" if we actually found a type with the required 1022 name but it wasn't the right one. This allows us to print a 1023 sensible result where the type has been shadowed but doesn't 1024 affect situations such as where we create a unique type name 1025 for a free type variable. *) 1026 fun addQuery n = 1027 case f of FoundNotMatch => "?" :: n | _ => n 1028 in 1029 if idName = "" then addQuery names 1030 else 1031 case nameToList(idName, []) of 1032 (idNames, FoundMatch) => idNames 1033 | (_, _) => addQuery names (* Print it as "?.t". This isn't ideal but will help in 1034 situations where we have redefined "t". *) 1035 end 1036 val newName = String.concatWith "." names 1037 (* Get the declaration position for the type constructor. *) 1038 val constrContext = 1039 if isUndefined typeConstructor then [] 1040 else 1041 ( 1042 case List.find(fn DeclaredAt _ => true | _ => false) (tcLocations typeConstructor) of 1043 SOME(DeclaredAt loc) => [ContextLocation loc] 1044 | _ => [] 1045 ) 1046 val constructorEntry = 1047 PrettyBlock(0, false, constrContext, [PrettyString newName(*constrName*)]) 1048 in 1049 case args of 1050 [] => constructorEntry 1051 | args as hd :: tl => 1052 let 1053 val argVal = eventual hd; 1054 in 1055 PrettyBlock (0, false, [], 1056 [ 1057 (* If we have just a single argument and it's just a type constructor 1058 or a construction we don't need to parenthesise it. *) 1059 if null tl andalso not (isProductType argVal orelse isFunctionType argVal) 1060 then dispP (argVal, depth - 1) 1061 else if depth <= 1 1062 then PrettyString "..." 1063 else PrettyBlock(0, false, [], 1064 [PrettyString "(", PrettyBreak (0, 0)] 1065 @ prettyList args (depth - 1) "," 1066 @ [PrettyBreak (0, 0), PrettyString ")"] 1067 ), 1068 PrettyBreak(1, 0), 1069 constructorEntry (* The constructor. *) 1070 ]) 1071 end 1072 end 1073 1074 | FunctionType {arg, result} => 1075 if depth <= 0 1076 then PrettyString "..." 1077 else (* print out in infix notation *) 1078 let 1079 val evArg = eventual arg; 1080 in 1081 PrettyBlock (0, false, [], 1082 [ 1083 (* If the argument is a function it must be printed as (a-> b)->.. *) 1084 if isFunctionType evArg 1085 then parenthesise depth evArg 1086 else dispP (evArg, depth - 1), 1087 PrettyBreak(1, 2), 1088 PrettyString "->", 1089 PrettyBreak (1, 2), 1090 dispP (result, depth - 1) 1091 ]) 1092 end 1093 1094 | LabelledType (r as {recList, ...}) => 1095 if depth <= 0 1096 then PrettyString "..." 1097 else if isProductType typ 1098 then (* Print as a product *) 1099 PrettyBlock (0, false, [], (* Print them as t1 * t2 * t3 .... *) 1100 prettyList (map (fn {typeof, ...} => typeof) recList) depth "*") 1101 else (* Print as a record *) 1102 let 1103 (* The ordering on fields is designed to allow mixing of tuples and 1104 records (e.g. #1). It puts shorter names before longer so that 1105 #11 comes after #2 and before #100. For named records it does 1106 not make for easy reading so we sort those alphabetically when 1107 printing. *) 1108 val sortedRecList = 1109 Misc.quickSort(fn {name = a, ...} => fn {name = b, ...} => a <= b) recList 1110 in 1111 PrettyBlock (2, false, [], 1112 PrettyString "{" :: 1113 (let 1114 fun pRec [] _ = [] 1115 | pRec ({name, typeof} :: T) depth = 1116 if depth <= 0 then [PrettyString "..."] 1117 else 1118 [ 1119 PrettyBlock(0, false, [], 1120 [ 1121 PrettyBlock(0, false, [], 1122 [ 1123 PrettyString (name ^ ":"), 1124 PrettyBreak(1, 0), 1125 dispP(typeof, depth - 1) 1126 ] @ 1127 (if null T then [] else [PrettyBreak (0, 0), PrettyString ","]) 1128 ) 1129 ]@ 1130 (if null T then [] else PrettyBreak (1, 0) :: pRec T (depth-1)) 1131 ) 1132 ] 1133 in 1134 pRec sortedRecList (depth - 1) 1135 end) @ 1136 [ PrettyString (if recordIsFrozen r then "}" else case recList of [] => "...}" | _ => ", ...}")] 1137 ) 1138 end 1139 1140 | OverloadSet {typeset = []} => PrettyString "no type" 1141 1142 | OverloadSet {typeset = tconslist} => 1143 (* This typically arises when printing error messages in the second pass because 1144 the third pass will select a single type e.g. int where possible. To 1145 simplify the messages select a single type if possible. *) 1146 ( 1147 case preferredOverload tconslist of 1148 SOME tcons => dispP(mkTypeConstruction (tcName tcons, tcons,[], []), depth) 1149 | NONE => 1150 (* Just print the type constructors separated by / *) 1151 let 1152 fun constrLocation tcons = 1153 case List.find(fn DeclaredAt _ => true | _ => false) (tcLocations tcons) of 1154 SOME(DeclaredAt loc) => [ContextLocation loc] 1155 | _ => [] 1156 (* Type constructor with context. *) 1157 fun tconsItem tcons = 1158 PrettyBlock(0, false, constrLocation tcons, [PrettyString(tcName tcons)]) 1159 1160 fun printTCcons [] = [] 1161 | printTCcons [tcons] = [tconsItem tcons] 1162 | printTCcons (tcons::rest) = 1163 tconsItem tcons :: PrettyBreak (0, 0) :: 1164 PrettyString "/" :: printTCcons rest 1165 in 1166 PrettyBlock (0, false, [], printTCcons tconslist) 1167 end 1168 ) 1169 1170 | EmptyType => PrettyString "no type" 1171 1172 | BadType => PrettyString "bad" 1173 end (* dispP *) 1174 in 1175 dispP (t, depth) 1176 end (* tDisp *); 1177 1178 (* Generate unique type-variable names. *) 1179 1180 fun varNameSequence () : typeVarForm -> string = 1181 (* We need to ensure that every distinct type variable has a distinct name. 1182 Each new type variable is given a name starting at "'a" and going on 1183 through the alphabet. *) 1184 let 1185 datatype names = Names of {name: string, entry: typeVarForm} 1186 val nameNum = ref ~1 1187 val gNameList = ref [] (* List of names *) 1188 in 1189 (* If the type is already there return the name we have given it 1190 otherwise make a new name and put it in the list. *) 1191 fn var => 1192 case List.find (fn (Names {entry,...}) => sameTv (entry, var)) (!gNameList) of 1193 NONE => (* Not on the list - make a new name *) 1194 let 1195 fun name num = (if num >= 26 then name (num div 26 - 1) else "") 1196 ^ String.str (Char.chr (num mod 26 + Char.ord #"a")) 1197 val () = nameNum := !nameNum + 1 1198 val n = (if tvEquality var then "''" else "'") ^ name(!nameNum) 1199 (* Should explicit type variables be distinguished? *) 1200 in 1201 gNameList := Names{name=n, entry=var} :: !gNameList; 1202 n 1203 end 1204 | SOME (Names {name,...}) => name 1205 end (* varNameSequence *) 1206 1207 (* Print a type (as a block of items) *) 1208 fun displayWithMap (t : types, depth : FixedInt.int, env, sigMap) = 1209 tDisp (t, depth, varNameSequence (), env, sigMap) 1210 and display (t : types, depth : FixedInt.int, env) = 1211 tDisp (t, depth, varNameSequence (), env, NONE) 1212 1213 (* Print out zero, one or more type variables (unblocked) *) 1214 fun printTypeVars([], _, _) = [] (* No type vars i.e. monotype *) 1215 1216 | printTypeVars([oneVar], depth, typeV) = (* Single type var. *) 1217 [ 1218 tDisp (TypeVar oneVar, depth, typeV, emptyTypeEnv, NONE), 1219 PrettyBreak (1, 0) 1220 ] 1221 1222 | printTypeVars(vars, depth, typeV) = 1223 (* Must parenthesise them. *) 1224 if depth <= 1 then [PrettyString "..."] 1225 else 1226 [ 1227 PrettyBlock(0, false, [], 1228 PrettyString "(" :: 1229 PrettyBreak(0, 0) :: 1230 (let 1231 fun pVars vars depth: pretty list = 1232 if depth <= 0 then [PrettyString "..."] 1233 else if null vars then [] 1234 else 1235 [ 1236 tDisp (TypeVar(hd vars), depth, typeV, emptyTypeEnv, NONE), 1237 PrettyBreak (0, 0) 1238 ] @ 1239 (if null (tl vars) then [] 1240 else PrettyString "," :: PrettyBreak (1, 0) :: pVars (tl vars) (depth - 1) 1241 ) 1242 in 1243 pVars vars depth 1244 end) @ [PrettyString ")"] 1245 ), 1246 PrettyBreak (1, 0) 1247 ] 1248 1249 1250 (* Version used in parsetree. *) 1251 fun displayTypeVariables (vars : typeVarForm list, depth : FixedInt.int) = 1252 printTypeVars (vars, depth, varNameSequence ()) 1253 1254 1255 (* Parse tree for types. This is used to represent types in the source. *) 1256 datatype typeParsetree = 1257 ParseTypeConstruction of 1258 { name: string, args: typeParsetree list, 1259 location: location, nameLoc: location, argLoc: location, 1260 (* foundConstructor is set to the constructor when it has been 1261 looked up. This allows us to get the location where it was 1262 declared if we export the parse-tree. *) 1263 foundConstructor: typeConstrs ref } 1264 | ParseTypeProduct of 1265 { fields: typeParsetree list, location: location } 1266 | ParseTypeFunction of 1267 { argType: typeParsetree, resultType: typeParsetree, location: location } 1268 | ParseTypeLabelled of 1269 { fields: ((string * location) * typeParsetree * location) list, 1270 frozen: bool, location: location } 1271 | ParseTypeId of { types: typeVarForm, location: location } 1272 | ParseTypeBad (* Place holder for errors. *) 1273 1274 fun typeFromTypeParse( 1275 ParseTypeConstruction{ args, name, location, foundConstructor = ref constr, ...}) = 1276 let 1277 val argTypes = List.map typeFromTypeParse args 1278 in 1279 TypeConstruction {name = name, constr = constr, 1280 args = argTypes, locations = [DeclaredAt location]} 1281 end 1282 1283 | typeFromTypeParse(ParseTypeProduct{ fields, ...}) = 1284 mkProductType(List.map typeFromTypeParse fields) 1285 1286 | typeFromTypeParse(ParseTypeFunction{ argType, resultType, ...}) = 1287 mkFunctionType(typeFromTypeParse argType, typeFromTypeParse resultType) 1288 1289 | typeFromTypeParse(ParseTypeLabelled{ fields, frozen, ...}) = 1290 let 1291 fun makeField((name, _), t, _) = mkLabelEntry(name, typeFromTypeParse t) 1292 in 1293 mkLabelled(sortLabels(List.map makeField fields), frozen) 1294 end 1295 1296 | typeFromTypeParse(ParseTypeId{ types, ...}) = TypeVar types 1297 1298 | typeFromTypeParse(ParseTypeBad) = BadType 1299 1300 fun makeParseTypeConstruction((constrName, nameLoc), (args, argLoc), location) = 1301 ParseTypeConstruction{ 1302 name = constrName, nameLoc = nameLoc, args = args, argLoc = argLoc, 1303 location = location, foundConstructor = ref undefConstr } 1304 1305 fun makeParseTypeProduct(recList, location) = 1306 ParseTypeProduct{ fields = recList, location = location } 1307 1308 fun makeParseTypeFunction(arg, result, location) = 1309 ParseTypeFunction{ argType = arg, resultType = result, location = location } 1310 1311 fun makeParseTypeLabelled(recList, frozen, location) = 1312 ParseTypeLabelled{ fields = recList, frozen = frozen, location = location } 1313 1314 fun makeParseTypeId(types, location) = 1315 ParseTypeId{ types = types, location = location } 1316 1317 fun unitTree location = ParseTypeLabelled{ fields = [], frozen = true, location = location } 1318 1319 (* Build an export tree from the parse tree. *) 1320 fun typeExportTree(navigation, p: typeParsetree) = 1321 let 1322 val typeof = typeFromTypeParse p 1323 1324 (* Common properties for navigation and printing. *) 1325 val commonProps = 1326 PTprint(fn d => display(typeof, d, emptyTypeEnv)) :: 1327 PTtype typeof :: 1328 exportNavigationProps navigation 1329 1330 fun asParent () = typeExportTree(navigation, p) 1331 1332 in 1333 case p of 1334 ParseTypeConstruction{ location, nameLoc, args, argLoc, ...} => 1335 let 1336 (* If the constructor has been bound return the declaration location. 1337 We have to attach the declaration location in the right place if 1338 this is a polytype e.g. if we have "int list" here we will have 1339 the location for "list" which is the second item not the first. *) 1340 val (name, decLoc) = 1341 case typeof of 1342 TypeConstruction { constr, name, ...} => 1343 if isUndefined constr 1344 then (name, []) 1345 else (name, mapLocationProps(tcLocations constr)) 1346 | _ => ("", []) (* Error? *) 1347 val navNameAndArgs = 1348 (* Separate cases for nullary, unary and higher type constructions. *) 1349 case args of 1350 [] => decLoc (* Singleton e.g. int *) 1351 | [oneArg] => 1352 let (* Single arg e.g. int list. *) 1353 (* Navigate between the type constructor and the argument. 1354 Since the arguments come before the constructor we go there first. *) 1355 fun getArg () = 1356 typeExportTree({parent=SOME asParent, previous=NONE, next=SOME getName}, oneArg) 1357 and getName () = 1358 getStringAsTree({parent=SOME asParent, previous=SOME getArg, next=NONE}, 1359 name, nameLoc, decLoc) 1360 in 1361 [PTfirstChild getArg] 1362 end 1363 | args => 1364 let (* Multiple arguments e.g. (int, string) pair *) 1365 fun getArgs () = 1366 (argLoc, 1367 exportList(typeExportTree, SOME getArgs) args @ 1368 exportNavigationProps{parent=SOME asParent, previous=NONE, next=SOME getName}) 1369 and getName () = 1370 getStringAsTree({parent=SOME asParent, previous=SOME getArgs, next=NONE}, 1371 name, nameLoc, decLoc) 1372 in 1373 [PTfirstChild getArgs] 1374 end 1375 in 1376 (location, navNameAndArgs @ commonProps) 1377 end 1378 1379 | ParseTypeProduct{ location, fields, ...} => 1380 (location, exportList(typeExportTree, SOME asParent) fields @ commonProps) 1381 1382 | ParseTypeFunction{ location, argType, resultType, ...} => 1383 (location, exportList(typeExportTree, SOME asParent) [argType, resultType] @ commonProps) 1384 1385 | ParseTypeLabelled{ location, fields, ...} => 1386 let 1387 fun exportField(navigation, label as ((name, nameLoc), t, fullLoc)) = 1388 let 1389 (* The first position is the label, the second the type *) 1390 fun asParent () = exportField (navigation, label) 1391 fun getLab () = 1392 getStringAsTree({parent=SOME asParent, next=SOME getType, previous=NONE}, 1393 name, nameLoc, [PTtype(typeFromTypeParse t)]) 1394 and getType () = 1395 typeExportTree({parent=SOME asParent, previous=SOME getLab, next=NONE}, t) 1396 in 1397 (fullLoc, PTfirstChild getLab :: exportNavigationProps navigation) 1398 end 1399 in 1400 (location, exportList(exportField, SOME asParent) fields @ commonProps) 1401 end 1402 1403 | ParseTypeId{ location, ...} => 1404 (location, commonProps) 1405 1406 | ParseTypeBad => 1407 (nullLocation, commonProps) 1408 end 1409 1410 fun displayTypeParse(types, depth, env) = display(typeFromTypeParse types, depth, env) 1411 1412 (* Associates type constructors from the environment with type identifiers 1413 (NOT type variables) *) 1414 fun assignTypes (tp : typeParsetree, lookupType : string * location -> typeConstrSet, lex : lexan) = 1415 let 1416 fun typeFromTypeParse(ParseTypeConstruction{ args, name, location, foundConstructor, ...}) = 1417 let 1418 (* Assign constructor, then the parameters. *) 1419 val TypeConstrSet(constructor, _) = lookupType (name, location) 1420 val () = 1421 (* Check that it has the correct arity. *) 1422 if not (isUndefined constructor) 1423 then 1424 let 1425 val arity : int = tcArity constructor; 1426 val num : int = length args; 1427 in 1428 if arity <> num 1429 then (* Give an error message *) 1430 errorMessage (lex, location, 1431 String.concat["Type constructor (", tcName constructor, 1432 ") requires ", Int.toString arity, " type(s) not ", 1433 Int.toString num]) 1434 else foundConstructor := constructor 1435 end 1436 else () 1437 val argTypes = List.map typeFromTypeParse args 1438 in 1439 TypeConstruction {name = name, constr = constructor, 1440 args = argTypes, locations = [DeclaredAt location]} 1441 end 1442 1443 | typeFromTypeParse(ParseTypeProduct{ fields, ...}) = 1444 mkProductType(List.map typeFromTypeParse fields) 1445 1446 | typeFromTypeParse(ParseTypeFunction{ argType, resultType, ...}) = 1447 mkFunctionType(typeFromTypeParse argType, typeFromTypeParse resultType) 1448 1449 | typeFromTypeParse(ParseTypeLabelled{ fields, frozen, ...}) = 1450 let 1451 fun makeField((name, _), t, _) = mkLabelEntry(name, typeFromTypeParse t) 1452 in 1453 mkLabelled(sortLabels(List.map makeField fields), frozen) 1454 end 1455 1456 | typeFromTypeParse(ParseTypeId{ types, ...}) = TypeVar types 1457 1458 | typeFromTypeParse(ParseTypeBad) = BadType 1459 in 1460 typeFromTypeParse tp 1461 end; 1462 1463 (* When we have finished processing a list of patterns we need to check 1464 that the record is now frozen. *) 1465 fun recordNotFrozen (TypeVar t) : bool = (* Follow the chain *) recordNotFrozen (tvValue t) 1466 | recordNotFrozen (LabelledType r) = not(recordIsFrozen r) 1467 | recordNotFrozen _ = false (* record or type alias *); 1468 1469 datatype generalMatch = Matched of {old: typeVarForm, new: types}; 1470 1471 fun generaliseTypes (atyp : types, checkTv: typeVarForm->types option) = 1472 let 1473 val madeList = ref [] (* List of tyVars. *); 1474 1475 fun tvs atyp = 1476 let 1477 val tyVar = typesTypeVar atyp; 1478 in 1479 case List.find(fn Matched{old, ...} => sameTv (old, tyVar)) (!madeList) of 1480 SOME(Matched{new, ...}) => new 1481 | NONE => 1482 ( 1483 case checkTv tyVar of 1484 SOME found => found 1485 | NONE => 1486 let (* Not on the list - make a new name *) 1487 (* Make a unifiable type variable even if the original 1488 is nonunifiable. *) 1489 val n : types = 1490 mkTypeVar (generalisable, tvEquality tyVar, false, tvPrintity tyVar) 1491 in 1492 (* Set the new variable to have the same value as the 1493 existing. That is only really needed if we have an 1494 overload set. *) 1495 tvSetValue (typesTypeVar n, tvValue tyVar); 1496 madeList := Matched {old = tyVar, new = n} :: !madeList; 1497 n 1498 end 1499 ) 1500 end 1501 1502 fun copyTypeVar (atyp as TypeVar tyVar) = 1503 if tvLevel tyVar <> generalisable 1504 then atyp (* Not generalisable. *) 1505 else (* Unbound, overload set or flexible record *) 1506 let 1507 val newTv = tvs atyp 1508 in 1509 (* If we have a type variable pointing to a flexible record we have to 1510 copy the type pointed at by the variable. *) 1511 case tvValue tyVar of 1512 valu as LabelledType _ => 1513 tvSetValue (typesTypeVar newTv, copyType (valu, copyTypeVar, fn t => t)) 1514 | _ => (); 1515 newTv 1516 end 1517 | copyTypeVar atyp = atyp 1518 1519 val copied = 1520 (* Only process type variables. Return type constructors unchanged. *) 1521 copyType (atyp, copyTypeVar, fn t => t (*copyTCons*)) 1522 in 1523 (copied, ! madeList) 1524 end (* generaliseTypes *); 1525 1526 (* Exported wrapper for generaliseTypes. *) 1527 fun generalise atyp = 1528 let 1529 val (t, newMatch) = generaliseTypes (atyp, fn _ => NONE) 1530 fun makeResult(Matched{new, old}) = 1531 {value=new, equality=tvEquality old, printity=tvPrintity old} 1532 in 1533 (t, List.map makeResult newMatch) 1534 end; 1535 1536 (* Return the original polymorphic type variables. *) 1537 fun getPolyTypeVars(atyp, map) = 1538 let 1539 val (_, newMatch) = generaliseTypes (atyp, map) 1540 in 1541 List.map (fn(Matched{old, ...}) => old) newMatch 1542 end; 1543 1544 fun generaliseWithMap(atyp, map) = 1545 let 1546 val (t, newMatch) = generaliseTypes (atyp, map) 1547 fun makeResult(Matched{new, old}) = 1548 {value=new, equality=tvEquality old, printity=tvPrintity old} 1549 in 1550 (t, List.map makeResult newMatch) 1551 end 1552 1553 (* Find the argument type which gives this result when the constructor 1554 is applied. If we have, for example, a value of type int list and 1555 we have discovered that this is a "::" node we have to work back by 1556 comparing the type of "::" ('a * 'a list -> 'a list) to find the 1557 argument of the constructor (int * int list) and hence how to print it. 1558 (Actually "list" is treated specially). *) 1559 fun constructorResult (FunctionType{arg, result=TypeConstruction{args, ...}}, typeArgs) = 1560 let 1561 val matches = ListPair.zip(List.map typesTypeVar args, typeArgs) 1562 fun getArg tv = 1563 case List.find(fn (atv, _) => sameTv(tv, atv)) matches of 1564 SOME (_, ty) => SOME ty 1565 | NONE => NONE 1566 in 1567 #1 (generaliseTypes(arg, getArg)) 1568 end 1569 | constructorResult _ = raise InternalError "Not a function type" 1570 1571 (* If we have a type construction which is an alias for another type 1572 we construct the alias by first instantiating all the type variables 1573 and then copying the type. *) 1574 fun makeEquivalent (atyp, args) = 1575 case tcIdentifier atyp of 1576 TypeId{idKind=TypeFn(typeArgs, typeResult), ...} => 1577 let 1578 val matches = ListPair.zip(typeArgs, args) 1579 fun getArg tv = 1580 case List.find(fn (atv, _) => sameTv(tv, atv)) matches of 1581 SOME (_, ty) => SOME ty 1582 | NONE => NONE 1583 in 1584 #1 (generaliseTypes(typeResult, getArg)) 1585 end 1586 1587 | TypeId _ => raise InternalError "makeEquivalent: Not a type function" 1588 1589 (* Look for the occurrence of locally declared datatypes in the type of a value. *) 1590 fun checkForEscapingDatatypes(ty: types, errorFn: string->unit) : unit = 1591 let 1592 fun checkTypes (typ: types) (ok: bool) : bool = 1593 case typ of 1594 TypeConstruction {constr, args, ...} => 1595 if tcIsAbbreviation constr 1596 then (* May be an alias for a type that contains a local datatype. *) 1597 foldType checkTypes (makeEquivalent (constr, args)) ok 1598 else if ok 1599 then 1600 ( 1601 case tcIdentifier constr of 1602 TypeId{access=Local{addr, ...}, ...} => 1603 if !addr < 0 1604 then 1605 ( 1606 errorFn("Type of expression contains local datatype (" ^ tcName constr 1607 ^") outside its definition."); 1608 false 1609 ) 1610 else true 1611 | _ => true (* Could we have a "selected" entry with a local datatype? *) 1612 ) 1613 else false 1614 | _ => ok 1615 in 1616 foldType checkTypes ty true; 1617 () 1618 end 1619 1620 (* This 3-valued logic is used because in a few cases we may not be sure 1621 if equality testing is allowed. If we have 2 mutually recursive datatypes 1622 t = x of s | ... and s = z of t we would first examine "t", find that 1623 it uses "s", look at "s", find that refers back to "t". To avoid 1624 infinite recursion we return the result that equality "maybe" 1625 allowed for "t" and hence for "s". However we may find that the 1626 other constructors for "t" do not allow equality and so equality 1627 will not be allowed for "s" either. *) 1628 1629 datatype tri = Yes (* 3-valued logic *) 1630 | No 1631 | Maybe; 1632 1633 1634 (* Returns a flag saying if equality testing is allowed for values of 1635 the given type. "equality" is used both to generate the code for 1636 a specific call of equality e.g. (a, b, c) = f(x), and to generate 1637 the equality operation for a type when it is declared. In the latter 1638 case type variables may be parameters which will be filled in later e.g. 1639 type 'a list = nil | op :: of ('a * 'a list). "search" 1640 is a function which looks up constructors in mutually recursive type 1641 declarations. "lookupTypeVar" deals with type variables. If they 1642 represent parameters to a type declaration equality 1643 checking will be allowed. If we are unifying this type to an equality 1644 type variable they will be unified to new equality type variables. 1645 Otherwise equality is not allowed. *) 1646 1647 fun equality (ty, search, lookupTypeVar) : tri = 1648 let 1649 (* Can't use foldT because it is not monotonic 1650 (equality on ref 'a is allowed). *) 1651 (* Returns Yes only if equality testing is allowed for all types 1652 in the list. *) 1653 fun eqForList ([], soFar) = soFar 1654 | eqForList (x::xs, soFar) = 1655 case equality (x, search, lookupTypeVar) of 1656 No => No 1657 | Maybe => eqForList (xs, Maybe) 1658 | Yes => eqForList (xs, soFar); 1659 in 1660 case eventual ty of 1661 TypeVar tyVar => (* The type variable may point to a flexible record or 1662 an overload set or it may be the end of the chain. 1663 If this is a labelled record we have to make sure that 1664 any fields we add also admit equality. 1665 lookupTypeVar makes the type variable an equality type 1666 so that any new fields are checked for equality but 1667 we also have to call "equality" to check the existing 1668 fields. *) 1669 if tvEquality tyVar then Yes 1670 else 1671 ( 1672 case tvValue tyVar of 1673 lab as LabelledType _ => 1674 ( 1675 case lookupTypeVar tyVar of 1676 No => No 1677 | _ => equality (lab, search, lookupTypeVar) 1678 ) 1679 | _ => lookupTypeVar tyVar 1680 ) 1681 1682 | FunctionType {...} => No (* No equality on function types! *) 1683 1684 | TypeConstruction {constr, args, ...} => 1685 if isUndefined constr 1686 then No 1687 1688 else if tcIsAbbreviation constr 1689 then (* May be an alias for a type that allows equality. *) 1690 equality (makeEquivalent (constr, args), search, lookupTypeVar) 1691 1692 (* ref - Equality is permitted on refs of all types *) 1693 (* The Definition of Standard ML says that ref is the ONLY type 1694 constructor which is treated in this way. The standard basis 1695 library says that other mutable types such as array should 1696 also work this way. *) 1697 else if isPointerEqType(tcIdentifier constr) 1698 then Yes 1699 1700 (* Others apart from ref and real *) 1701 else if tcEquality constr (* Equality allowed. *) 1702 then eqForList (args, Yes) (* Must be allowed for all the args *) 1703 1704 else 1705 let (* Not an alias. - Look it up. *) 1706 val s = search (tcIdentifier constr); 1707 in 1708 if s = No then No else eqForList (args, s) 1709 end (* TypeConstruction *) 1710 1711 | LabelledType {recList, ...} => (* Record equality if all subtypes are (ignore frozen!) *) 1712 (* TODO: Avoid copying the list? *) 1713 eqForList (map (fn{typeof, ...}=>typeof) recList, Yes) 1714 1715 | OverloadSet _ => 1716 (* This should not happen because all overload sets should be pointed 1717 to by type variables and so should be handled in the TypeVar case. *) 1718 raise InternalError "equality - Overloadset found" 1719 1720 | BadType => No 1721 1722 | EmptyType => No (* shouldn't occur *) 1723 end 1724 1725 (* When a datatype is declared we test to see if equality is allowed. The 1726 types are mutually recursive so value constructors of one type may 1727 take arguments involving values of any of the others. *) 1728 1729 fun computeDatatypeEqualities(types: typeConstrSet list, boundIdEq) = 1730 let 1731 datatype state = 1732 Processed of tri (* Already processed or processing. *) 1733 | NotSeen of typeConstrSet list (* Value is list of constrs. *); 1734 1735 (* This table tells us, for each type constructor, whether it definitely 1736 admits equality, definitely does not or whether we have yet to look 1737 at it. *) 1738 1739 fun isProcessed (Processed _) = true | isProcessed _ = false; 1740 1741 fun stateProcessed (Processed x) = x | stateProcessed _ = raise Match; 1742 fun stateNotSeen (NotSeen x) = x | stateNotSeen _ = raise Match; 1743 1744 val {enter:typeId * state -> unit,lookup} = mapTable sameTypeId; 1745 1746 (* Look at each of the constructors in the list. Equality testing is 1747 only allowed if it is allowed for each of the alternatives. *) 1748 fun constrEq _ [] soFar = soFar (* end of list - all o.k. *) 1749 | constrEq constructor (h :: t) soFar = 1750 (* The constructor may be a constant e.g. 1751 datatype 'a list = nil | ... or a function e.g. 1752 datatype 'a list = ... cons of 'a * 'a list. *) 1753 if not (isFunctionType (valTypeOf h)) (* Constant *) 1754 then constrEq constructor t soFar (* Go on to the next. *) 1755 1756 else 1757 let 1758 (* Function - look at the argument type. *) 1759 (* Equality is allowed for any type-variable. The only type variables 1760 allowed are parameters to the datatype so if we have a type variable 1761 then equality is allowed for this datatype. *) 1762 val eq = 1763 equality (#arg (typesFunctionType (valTypeOf h)), 1764 genEquality, fn _ => Yes); 1765 in 1766 if eq = No 1767 then (* Not allowed. *) No 1768 else (* O.k. - go on to the next. *) 1769 constrEq constructor t (if eq = Maybe then Maybe else soFar) 1770 end (* constrEq *) 1771 1772 (* This procedure checks to see if equality is allowed for this datatype. *) 1773 and genEquality constructorId = 1774 let 1775 (* Look it up to see if we have already done it. It may fail because 1776 we may have constructors that do not admit equality. *) 1777 val thisState = 1778 case (lookup constructorId, constructorId) of 1779 (SOME inList, _) => inList 1780 | (NONE, TypeId{idKind = Bound{offset, ...}, ...}) => 1781 Processed(if boundIdEq offset then Yes else No) 1782 | _ => Processed No 1783 in 1784 if isProcessed thisState 1785 then stateProcessed thisState (* Have either done it already or are currently doing it. *) 1786 else (* notSeen - look at it now. *) 1787 let 1788 (* Equality is allowed for this datatype only if all of them admit it. 1789 There are various other alternatives but this is what the standard says. 1790 If the "name" is rigid (free) we must not grant equality if it is not 1791 already there although that is not an error. *) 1792 (* Set the state to "Maybe". This prevents infinite recursion. *) 1793 val () = enter (constructorId, Processed Maybe); 1794 val eq = 1795 List.foldl 1796 (fn (cons, t) => 1797 if t = No 1798 then No 1799 else constrEq cons (tsConstructors cons) t) 1800 Yes 1801 (stateNotSeen thisState); 1802 in 1803 (* Set the state we have found if it is "yes" or "no". If it is 1804 maybe we have a recursive reference which appears to admit 1805 equality, but may not. E.g. if we have 1806 datatype t = A of s | B of int->int and s = C of t 1807 if we start processing "t" we will go on to "s" and do that 1808 before returning to "t". It is only later we find that "t" does 1809 not admit equality. If we get "Maybe" as the final result when 1810 all the recursion has been unwound we can set the result to 1811 "yes", but any intermediate "Maybe"s have to be done again. *) 1812 enter (constructorId, if eq = Maybe then thisState else Processed eq); 1813 eq 1814 end 1815 end (* genEquality *); 1816 in 1817 (* If we have an eqtype we set it to true, otherwise we set all of them 1818 to "notSeen" with the constructor as value. *) 1819 List.app 1820 (fn dec as TypeConstrSet(decCons, _) => 1821 let (* If we have two datatypes which share we may already have 1822 one in the table. We have to link them together. *) 1823 val tclist = 1824 case lookup (tcIdentifier decCons) of 1825 NONE => [dec] 1826 | SOME l => 1827 let 1828 val others = stateNotSeen l 1829 val newList = dec :: others; 1830 in 1831 (* If any of these are already equality types (i.e. share with an eqtype) 1832 then they all must be. *) 1833 if tcEquality decCons orelse tcEquality (tsConstr(hd others)) 1834 then List.app (fn d => tcSetEquality (tsConstr d, true)) newList 1835 else (); 1836 newList 1837 end 1838 in 1839 enter (tcIdentifier decCons, NotSeen tclist) 1840 end) types; 1841 1842 (* Apply genEquality to each element of the list. *) 1843 List.app 1844 (fn TypeConstrSet(constructor, _) => 1845 let 1846 val constructorId = tcIdentifier constructor; 1847 val eqForCons = genEquality constructorId; 1848 in 1849 (* If the result is "Maybe" it involves a recursive reference, but 1850 the rest of the type allows equality. The type admits equality. *) 1851 if eqForCons = No 1852 then () (* Equality not allowed *) 1853 else 1854 ( (* Turn on equality. *) 1855 enter (constructorId, Processed Yes); 1856 tcSetEquality (constructor, true) 1857 ) 1858 end) types 1859 end (* computeDatatypeEqualities *); 1860 1861 datatype matchResult = 1862 SimpleError of types * types * string 1863 | TypeConstructorError of types * types * typeConstrs * typeConstrs 1864 1865 (* Type matching algorithm for both unification and signature matching. *) 1866 (* The mapping has now been moved out of here. Instead when signature matching the 1867 target signature is copied before this is called which means that this 1868 process is now symmetric. There may be some redundant tests left in here. *) 1869 fun unifyTypes(Atype : types, Btype : types) : matchResult option = 1870 let 1871 (* Get the result in here. This isn't very ML-like but it greatly 1872 simplifies converting the code. *) 1873 val matchResult: matchResult option ref = ref NONE 1874 fun matchError error = (* Only report one error. *) 1875 case matchResult of ref (SOME _) => () | r => r := SOME error 1876 fun cantMatch(alpha, beta, text) = matchError(SimpleError(alpha, beta, text)) 1877 1878 fun match (Atype : types, Btype : types) : unit = 1879 let (* Check two records/tuples and return the combined type. *) 1880 fun unifyRecords (rA as {recList=typAlist, fullList = gA}, 1881 rB as {recList=typBlist, fullList = gB}, 1882 typA : types, typB : types) : types = 1883 let 1884 val typAFrozen = recordIsFrozen rA 1885 and typBFrozen = recordIsFrozen rB 1886 1887 fun matchLabelled ([], []) = [] 1888 1889 (* Something left in bList - this is fine if typeA is not frozen. 1890 e.g. (a: s, b: t) will match (a: s, ...) but not just (a:s). *) 1891 | matchLabelled ([], bList as {name=bName, ...} :: _) = 1892 ( 1893 if typAFrozen 1894 then cantMatch (typA, typB, "(Field " ^ bName ^ " missing)") 1895 else (); 1896 bList (* return the remainder of the list *) 1897 ) 1898 1899 | matchLabelled (aList as {name=aName, ...} :: _, []) = (* Something left in bList *) 1900 ( 1901 if typBFrozen 1902 then cantMatch (typA, typB, "(Field " ^ aName ^ " missing)") 1903 else (); 1904 aList (* the rest of aList *) 1905 ) 1906 1907 | matchLabelled (aList as ((aVal as {name=aName,typeof=aType})::aRest), 1908 bList as ((bVal as {name=bName,typeof=bType})::bRest)) = 1909 (* both not nil - look at the names. *) 1910 let 1911 val order = compareLabels (aName, bName); 1912 in 1913 if order = 0 (* equal *) 1914 then (* same name - must be unifiable types *) 1915 ( (* The result is (either) one of these with the rest of the list. *) 1916 match (aType, bType); 1917 aVal :: matchLabelled (aRest, bRest) 1918 ) 1919 else if order < 0 (* aName < bName *) 1920 then (* The entries in each list are in order so this means that this 1921 entry is not in bList. If the typeB is frozen this is an error. *) 1922 if typBFrozen (* Continue with the entry removed. *) 1923 then (cantMatch (typA, typB, "(Field " ^ aName ^ " missing)"); aList) 1924 else aVal :: matchLabelled (aRest, bList) 1925 else (* aName > bName *) 1926 if typAFrozen 1927 then (cantMatch (typA, typB, "(Field " ^ bName ^ " missing)"); bList) 1928 else bVal :: matchLabelled (aList, bRest) 1929 end (* not nil *); 1930 1931 (* Return the combined list. Only actually used if both are flexible. *) 1932 val result = 1933 if typAFrozen andalso typBFrozen andalso List.length typAlist <> List.length typBlist 1934 then (* Don't attempt to unify the fields if we have the wrong number of items. 1935 If we've added or removed an item from a tuple e.g. a function with 1936 multiple arguments, it's more useful to know this than to get unification 1937 errors on fields that don't match. *) 1938 (cantMatch (typA, typB, "(Different number of fields)"); []) 1939 else matchLabelled (typAlist, typBlist) 1940 1941 fun lastFlex(FlexibleList(ref(r as FlexibleList _))) = lastFlex r 1942 | lastFlex(FlexibleList r) = SOME r 1943 | lastFlex(FieldList _) = NONE 1944 1945 in 1946 if typAFrozen 1947 then (if typBFrozen then () else valOf(lastFlex gB) := gA; typA) 1948 else if typBFrozen 1949 then (valOf(lastFlex gA) := gB; typB) 1950 else 1951 let 1952 (* We may have these linked already in which case we shouldn't do anything. *) 1953 val lastA = valOf(lastFlex gA) and lastB = valOf(lastFlex gB) 1954 in 1955 if lastA = lastB 1956 then () 1957 else 1958 let 1959 val genericFields = FieldList(map #name result, false) 1960 in 1961 (* If these are both flexible we have link all the generics together 1962 so that if we freeze any one of them they all get frozen. *) 1963 lastA := genericFields; 1964 lastB := FlexibleList lastA 1965 end; 1966 LabelledType {recList = result, fullList = gA} 1967 end 1968 end (* unifyRecords *); 1969 1970 (* Sets a type variable to a value. - Checks that the type variable 1971 we are assigning does not occur in the expression we are about to 1972 assign to it. Such cases can occur if we have infinitely-typed 1973 expressions such as fun a. a::a where a has type 'a list list ... 1974 Also propagates the level information of the type variable. 1975 Now also deals with flexible records. *) 1976 fun assign (var, t) = 1977 let 1978 (* Mapped over the type to be assigned. *) 1979 (* Returns "false" if it is safe to make the assignment. Sorts out 1980 imperative type variables and propagates level information. 1981 N.B. It does not propagate equality status. The reason is that 1982 if we are unifying ''a with 'b ref, the 'b does NOT become 1983 an equality type var. In all other cases it would. *) 1984 fun occursCheckFails _ true = true 1985 1986 | occursCheckFails ty false = 1987 let 1988 val t = eventual ty 1989 in 1990 case t of 1991 TypeVar tvar => 1992 let 1993 (* The level is the minimum of the two, and if we are unifying with 1994 an equality type variable we must make this into one. *) 1995 val minLev = Int.min (tvLevel var, tvLevel tvar) 1996 val oldValue = tvValue tvar 1997 in 1998 if tvLevel tvar <> minLev 1999 then (* If it is nonunifiable we cannot make its level larger. *) 2000 if tvNonUnifiable tvar 2001 then cantMatch (Atype, Btype, "(Type variable is free in surrounding scope)") 2002 else 2003 let 2004 (* Must make a new type var with the right properties *) 2005 (* This type variable may be a flexible record, in which 2006 case we have to save the record and put it on the new 2007 type variable. We have to do this for the record itself so that new 2008 fields inherit the correct status and also for any existing fields. *) 2009 val newTv = mkTypeVar (minLev, tvEquality tvar, false, tvPrintity tvar) 2010 in 2011 tvSetValue (typesTypeVar newTv, oldValue); 2012 tvSetValue (tvar, newTv) 2013 end 2014 else (); 2015 (* Safe if vars are different but we also have to check any flexible records. *) 2016 occursCheckFails oldValue (sameTv (tvar, var)) 2017 end 2018 2019 | TypeConstruction {args, constr, ...} => 2020 (* If this is a type abbreviation we have to expand this before processing 2021 any arguments. We mustn't process arguments that are not actually used. *) 2022 if tcIsAbbreviation constr 2023 then occursCheckFails(makeEquivalent (constr, args)) false 2024 else List.foldr (fn (t, v) => occursCheckFails t v) false args 2025 2026 | FunctionType {arg, result} => 2027 occursCheckFails arg false orelse occursCheckFails result false 2028 2029 | LabelledType {recList,...} => 2030 List.foldr (fn ({ typeof, ... }, v) => occursCheckFails typeof v) false recList 2031 2032 | _ => false 2033 2034 end 2035 2036 val varVal = tvValue var (* Current value of the variable to be set. *) 2037 2038 local 2039 (* We need to process any type abbreviations before applying the occurs check. 2040 The type we're assigning could boil down to the same type variable we're 2041 trying to assign. This doesn't breach the occurs check. *) 2042 fun followVarsAndTypeFunctions t = 2043 case eventual t of 2044 ev as TypeConstruction{constr, args, ...} => 2045 if tcIsAbbreviation constr 2046 then followVarsAndTypeFunctions(makeEquivalent (constr, args)) 2047 else ev 2048 | ev => ev 2049 in 2050 val finalType = followVarsAndTypeFunctions t 2051 end 2052 2053 (* We may actually have the same type variable after any type abbreviations 2054 have been followed. *) 2055 val reallyTheSame = 2056 case finalType of 2057 TypeVar tv => sameTv (tv, var) 2058 | _ => false 2059 2060 in (* start of "assign" *) 2061 case varVal of 2062 LabelledType _ => 2063 (* Flexible record. Check that the records are compatible. *) 2064 match (varVal, t) 2065 | OverloadSet _ => 2066 (* OverloadSet. Check that the sets match. This is only in the 2067 case where t is something other than an overload set since 2068 we remove the overload set from a variable when unifying two 2069 sets. *) 2070 match (varVal, t) 2071 | _ => (); 2072 2073 if reallyTheSame 2074 then () (* Don't apply the occurs check or check for non-unifiable. *) 2075 2076 (* If this type variable was put in explicitly then it can't be 2077 assigned to something else. (We have already checked for the 2078 type variables being the same). *) 2079 else if tvNonUnifiable var 2080 then cantMatch (Atype, Btype, "(Cannot unify with explicit type variable)") 2081 2082 else if occursCheckFails finalType false 2083 then cantMatch (Atype, Btype, "(Type variable to be unified occurs in type)") 2084 2085 else 2086 let (* Occurs check succeeded. *) 2087 fun canMkEqTv (tvar : typeVarForm) : tri = 2088 (* Turn it into an equality type var. *) 2089 if tvEquality tvar then Yes 2090 (* If it is nonunifiable we cannot make it into an equality type var. *) 2091 else if tvNonUnifiable tvar then No 2092 else (* Must make a new type var with the right properties *) 2093 let (* This type variable may be a flexible record or an overload set, 2094 in which case we have to save the record and put it on the 2095 new type variable. 2096 We have to do both because we have to ensure that the existing 2097 fields in the flexible record admit equality and ALSO that any 2098 additional fields we may add by unification with other records 2099 also admit equality. *) 2100 val newTv = mkTypeVar (tvLevel tvar, true, false, tvPrintity tvar) 2101 val oldValue = tvValue tvar 2102 in 2103 tvSetValue (tvar, newTv); 2104 (* If this is an overloaded type we must remove any types that 2105 don't admit equality. *) 2106 case oldValue of 2107 OverloadSet{typeset} => 2108 let 2109 (* Remove any types which do not admit equality. *) 2110 fun filter [] = [] 2111 | filter (h::t) = 2112 if tcEquality h then h :: filter t else filter t 2113 in 2114 case filter typeset of 2115 [] => No 2116 | [constr] => 2117 ( (* Turn a singleton into a type construction. *) 2118 tvSetValue (typesTypeVar newTv, 2119 mkTypeConstruction(tcName constr, constr, nil, [])); 2120 Yes 2121 ) 2122 | newset => 2123 ( 2124 tvSetValue (typesTypeVar newTv, OverloadSet{typeset=newset}); 2125 Yes 2126 ) 2127 end 2128 | _ => (* Labelled record or unbound variable. *) 2129 ( 2130 tvSetValue (typesTypeVar newTv, oldValue); 2131 Yes 2132 ) 2133 end 2134 2135 in 2136 (* If we are unifying a type with an equality type variable 2137 we must ensure that equality is allowed for that type. This 2138 will turn most type variables into equality type vars. *) 2139 if tvEquality var andalso equality (t, fn _ => No, canMkEqTv) = No 2140 then cantMatch (Atype, Btype, "(Requires equality type)") 2141 (* TODO: This can result in an unhelpful message if var is bound 2142 to a flexible record since there is no indication in the 2143 printed type that the flexible record is an equality type. 2144 It would be improved if we set the value to be EmptyType. 2145 At least then the type variable would be printed which would 2146 be an equality type. 2147 --- Adding the "Requires equality type" should improve things. *) 2148 else (); 2149 (* Propagate the "printity" status. This is probably not complete 2150 but doesn't matter too much since this is a Poly extension. *) 2151 if tvPrintity var 2152 then 2153 let 2154 fun makePrintity(TypeVar tv) _ = 2155 ( 2156 if tvPrintity tv then () 2157 else case tvValue tv of 2158 (* If it's an overload set we don't need to do anything. This will 2159 eventually be a monotype. *) 2160 OverloadSet _ => () 2161 | oldValue => 2162 let (* Labelled record or unbound variable. *) 2163 val newTv = mkTypeVar (tvLevel tv, tvEquality tv, tvNonUnifiable tv, true) 2164 in 2165 tvSetValue(tv, newTv); 2166 (* Put this on the chain if it's a labelled record. *) 2167 tvSetValue (typesTypeVar newTv, oldValue) 2168 end 2169 ) 2170 2171 | makePrintity _ _ = () 2172 in 2173 foldType makePrintity t () 2174 end 2175 else (); 2176 (* Actually make the assignment. It doesn't matter if var is 2177 a labelled record, because t will be either a fixed record 2178 or a combination of the fields of var and t. Likewise if 2179 var was previously an overload set this may replace the set 2180 by a single type construction. *) 2181 (* If we have had an error don't make the assignment. At the very least 2182 it could prevent us producing useful error information and it could 2183 also result in unnecessary consequential errors. *) 2184 case !matchResult of 2185 NONE => tvSetValue (var, t) 2186 | SOME _ => () 2187 end 2188 end (* assign *); 2189 2190 (* First find see if typeA and typeB are unified to anything 2191 already, and get the end of a list of "flexibles". *) 2192 2193 val tA = eventual Atype 2194 and tB = eventual Btype 2195 2196 in (* start of "match" *) 2197 if isUndefinedType tA orelse isUndefinedType tB 2198 then () (* If either of these was an undefined type constructor don't try to match. 2199 TODO: There are further tests below for this which are now redundant. *) 2200 else 2201 case (tA, tB) of 2202 (BadType, _) => () (* If either is an error don't try to match *) 2203 | (_, BadType) => () 2204 2205 | (TypeVar typeAVar, TypeVar typeBVar) => 2206 (* Unbound type variable, flexible record or overload set. *) 2207 let 2208 (* Even if this is a one-way match we can allow type variables 2209 in the typeA to be instantiated to anything in the typeB. *) 2210 val typeAVal = tvValue typeAVar; 2211 (* We have two unbound type variables or flex. records. *) 2212 in 2213 if sameTv (typeAVar, typeBVar) (* same type variable? *) 2214 then () 2215 else (* no - assign one to the other *) 2216 if tvNonUnifiable typeAVar 2217 (* If we have a nonunifiable type variable we want to assign 2218 the typeB to it. If the typeB is nonunifiable as well we 2219 will get an error message. *) 2220 then assign (typeBVar, tA) 2221 else 2222 let 2223 (* If they are both flexible records we first set the typeB 2224 to the union of the records, and then set the typeA to 2225 that. In that way we propagate properties such as 2226 equality and level between the two variables. *) 2227 val typBVal = tvValue typeBVar 2228 in 2229 case (typeAVal, typBVal) of 2230 (LabelledType recA, LabelledType recB) => 2231 ( 2232 (* Turn these back into simple type variables to save 2233 checking the combined record against the originals 2234 when we make the assignment. 2235 (Would be safe but redundant). *) 2236 tvSetValue (typeBVar, emptyType); 2237 tvSetValue (typeAVar, emptyType); 2238 assign (typeBVar, 2239 unifyRecords (recA, recB, typeAVal, typBVal)); 2240 assign (typeAVar, tB) 2241 ) 2242 | (OverloadSet{typeset=setA}, OverloadSet{typeset=setB}) => 2243 let 2244 (* The lists aren't ordered so we just have to go 2245 through by hand. *) 2246 fun intersect(_, []) = [] 2247 | intersect(a, H::T) = 2248 if isInSet(H, a) then H::intersect(a, T) else intersect(a, T) 2249 val newSet = intersect(setA, setB) 2250 in 2251 case newSet of 2252 [] => cantMatch (Atype, Btype, "(Incompatible overloadings)") 2253 | _ => 2254 ( 2255 tvSetValue (typeBVar, emptyType); 2256 tvSetValue (typeAVar, emptyType); 2257 (* I've changed this from OverloadSet{typeset=newset} 2258 to use mkOverloadSet. The main reason was that it 2259 fixed a bug which resulted from a violation of the 2260 assumption that "equality" would not be passed an 2261 overload set except when pointed to by a type variable. 2262 It also removed the need for a separate test for 2263 singleton sets since mkOverloadSet deals with them. 2264 DCJM 1/9/00. *) 2265 assign (typeBVar, mkOverloadSet newSet); 2266 assign (typeAVar, tB) 2267 ) 2268 end 2269 | (EmptyType, _) => (* A is not a record or an overload set. *) 2270 assign (typeAVar, tB) 2271 | (_, EmptyType) => (* A is a record but B isn't *) 2272 assign (typeBVar, tA) (* typeB is ordinary type var. *) 2273 | _ => (* Bad combination of labelled record and overload set *) 2274 cantMatch (Atype, Btype, "(Incompatible types)") 2275 end 2276 end 2277 2278 | (TypeVar typeAVar, _) => 2279 (* typeB is not a type variable so set typeA to typeB.*) 2280 (* Be careful if this is a non-unifiable type variable being matched to 2281 the special case of the identity type-construction. *) 2282 ( 2283 if tvNonUnifiable typeAVar orelse (case tvValue typeAVar of OverloadSet _ => true | _ => false) 2284 then 2285 ( 2286 case tB of 2287 TypeConstruction {constr, args, ...} => 2288 if isUndefined constr orelse not (tcIsAbbreviation constr) 2289 then 2290 ( 2291 case tB of 2292 TypeConstruction {constr, args, ...} => 2293 if isUndefined constr orelse not (tcIsAbbreviation constr) 2294 then assign (typeAVar, tB) 2295 else match(tA, eventual (makeEquivalent (constr, args))) 2296 | _ => assign (typeAVar, tB) 2297 ) 2298 else match(tA, eventual (makeEquivalent (constr, args))) 2299 2300 | _ => assign (typeAVar, tB) 2301 ) 2302 else assign (typeAVar, tB) 2303 ) 2304 2305 | (_, TypeVar typeBVar) => (* and typeA is not *) 2306 ( 2307 (* We have to check for the special case of the identity type-construction. *) 2308 if tvNonUnifiable typeBVar orelse (case tvValue typeBVar of OverloadSet _ => true | _ => false) 2309 then 2310 ( 2311 case tA of 2312 TypeConstruction {constr, args, ...} => 2313 if isUndefined constr orelse not (tcIsAbbreviation constr) 2314 then 2315 ( 2316 case tB of 2317 TypeVar tv => 2318 (* This will fail if we are matching a signature because the 2319 typeB will be non-unifiable. *) 2320 assign (tv, tA) (* set typeB to typeA *) 2321 | typB => match (tA, typB) 2322 ) 2323 else match(eventual (makeEquivalent (constr, args)), tB) 2324 | _ => 2325 ( 2326 case tB of 2327 TypeVar tv => 2328 (* This will fail if we are matching a signature because the 2329 typeB will be non-unifiable. *) 2330 assign (tv, tA) (* set typeB to typeA *) 2331 | typB => match (tA, typB) 2332 ) 2333 ) 2334 else 2335 ( 2336 case tB of 2337 TypeVar tv => 2338 (* This will fail if we are matching a signature because the 2339 typeB will be non-unifiable. *) 2340 assign (tv, tA) (* set typeB to typeA *) 2341 | typB => match (tA, typB) 2342 ) 2343 ) 2344 2345 | (TypeConstruction({constr = tACons, args=tAargs, ...}), 2346 TypeConstruction ({constr = tBCons, args=tBargs, ...})) => 2347 ( 2348 (* We may have a number of possibilities here. 2349 a) If tA is an alias we simply expand it out and recurse (even 2350 if tB is the same alias). e.g. if we have string t where 2351 type 'a t = int*'a we expand string t into int*string and 2352 try to unify that. 2353 b) map it and see if the result is an alias. -- NOW REMOVED 2354 c) If tB is a type construction and it is an alias we expand 2355 that e.g. unifying "int list" and "int t" where type 2356 'a t = 'a list (particularly common in signature/structure 2357 matching.) 2358 d) Finally we try to unify the stamps and the arguments. *) 2359 if isUndefined tACons orelse isUndefined tBCons 2360 then () (* If we've had an undefined type constructor don't try to check further. *) 2361 else if tcIsAbbreviation tACons 2362 (* Candidate is an alias - expand it. *) 2363 then match (makeEquivalent (tACons, tAargs), tB) 2364 else if tcIsAbbreviation tBCons 2365 then match (tA, makeEquivalent (tBCons, tBargs)) 2366 else if tcIsAbbreviation tBCons (* If the typeB is an alias it must be expanded. *) 2367 then match (tA, makeEquivalent (tBCons, tBargs)) 2368 else if sameTypeId (tcIdentifier tACons, tcIdentifier tBCons) 2369 then 2370 let (* Same type constructor - do the arguments match? *) 2371 fun matchLists [] [] = () 2372 | matchLists (a::al) (b::bl) = 2373 ( 2374 match (a, b); 2375 matchLists al bl 2376 ) 2377 | matchLists _ _ = (* This should only happen as a result of 2378 a different error. *) 2379 cantMatch (Atype, Btype, "(Different numbers of arguments)") 2380 in 2381 matchLists tAargs tBargs 2382 end 2383 2384 (* When we have different type constructors, especially two with the same name, 2385 we try to produce more information. *) 2386 else matchError(TypeConstructorError(tA, tB, tACons, tBCons)) 2387 ) 2388 2389 | (OverloadSet {typeset}, TypeConstruction {constr=tBCons, args=tBargs, ...}) => 2390 (* The candidate is an overloaded type and the target is a type 2391 construction. *) 2392 ( 2393 if not (isUndefined tBCons orelse not (tcIsAbbreviation tBCons)) 2394 then match (tA, makeEquivalent (tBCons, tBargs)) 2395 else if isUndefined tBCons 2396 then () 2397 else if tcIsAbbreviation tBCons 2398 then match (tA, makeEquivalent (tBCons, tBargs)) 2399 else (* See if the target type is among those in the overload set. *) 2400 if null tBargs (* Must be a nullary type constructor. *) 2401 andalso isInSet(tBCons, typeset) 2402 then () (* ok. *) 2403 (* Overload sets arise primarily with literals such as "1" and it's 2404 most likely that the error is a mismatch between int and another 2405 type rather than that the user assumed that the literal was 2406 overloaded on a type it actually wasn't. *) 2407 else 2408 case preferredOverload typeset of 2409 NONE => cantMatch (tA, tB, "(Different type constructors)") 2410 | SOME prefType => 2411 matchError( 2412 TypeConstructorError( 2413 mkTypeConstruction (tcName prefType, prefType,[], []), 2414 tB, prefType, tBCons)) 2415 ) 2416 2417 | (TypeConstruction {constr=tACons, args=tAargs, ...}, OverloadSet {typeset}) => 2418 ( 2419 if not (isUndefined tACons orelse not (tcIsAbbreviation tACons)) 2420 then match (makeEquivalent (tACons, tAargs), tB) 2421 (* We should never find an overload set as the target for a signature 2422 match but it is perfectly possible for tB to be an overload set 2423 when unifying two types. *) 2424 else if null tAargs andalso isInSet(tACons, typeset) 2425 then () (* ok. *) 2426 else 2427 case preferredOverload typeset of 2428 NONE => cantMatch (tA, tB, "(Different type constructors)") 2429 | SOME prefType => 2430 matchError( 2431 TypeConstructorError( 2432 tA, mkTypeConstruction (tcName prefType, prefType,[], []), 2433 tACons, prefType)) 2434 ) 2435 2436 | (OverloadSet _ , OverloadSet _) => raise InternalError "Unification: OverloadSet/OverloadSet" 2437 (* (OverloadSet , OverloadSet) should not occur because that should be 2438 handled in the (TypeVar, TypeVar) case. *) 2439 2440 | (TypeConstruction({constr = tACons, args=tAargs, ...}), _) => 2441 if not (isUndefined tACons orelse not (tcIsAbbreviation tACons)) 2442 (* Candidate is an alias - expand it. *) 2443 then match (makeEquivalent (tACons, tAargs), tB) 2444 else (* typB not a construction (but typeA is) *) 2445 cantMatch (tA, tB, "(Incompatible types)") 2446 2447 | (_, TypeConstruction {constr=tBCons, args=tBargs, ...}) => (* and typeA is not. *) 2448 (* May have a type equivalence e.g. "string t" matches int*string if type 2449 'a t = int * 'a . Alternatively we may be matching a structure to a signature 2450 where the signature says "type t" and the structure contains "type 2451 t = int->int" (say). We need to set the type in the signature to int->int. *) 2452 if not (isUndefined tBCons orelse not (tcIsAbbreviation tBCons)) 2453 then match (tA, makeEquivalent (tBCons, tBargs)) 2454 else if isUndefined tBCons 2455 then () 2456 else if tcIsAbbreviation tBCons 2457 then match (tA, makeEquivalent (tBCons, tBargs)) 2458 else cantMatch (tB, tA, "(Incompatible types)") 2459 2460 2461 | (FunctionType {arg=typAarg, result=typAres, ...}, 2462 FunctionType {arg=typBarg, result=typBres, ...}) => 2463 ( (* must be unifiable functions *) 2464 (* In principle it doesn't matter whether we unify arguments or 2465 results first but it could affect the error messages. Is this 2466 the best way to do it? *) 2467 match (typAarg, typBarg); 2468 match (typAres, typBres) 2469 ) 2470 2471 | (EmptyType, EmptyType) => () 2472 (* This occurs only with exceptions - empty means no argument *) 2473 2474 | (LabelledType recA, LabelledType recB) => 2475 (* Unify the records, but discard the result because at least one of the 2476 records is frozen. *) 2477 (unifyRecords (recA, recB, tA, tB); ()) 2478 2479 | _ => cantMatch (tA, tB, "(Incompatible types)") 2480 2481 end (* match *) 2482 2483 in 2484 match (Atype, Btype); 2485 ! matchResult 2486 end (* unifyTypes *) 2487 2488 (* Turn a result from matchTypes into a pretty structure so that it 2489 can be included in a message. *) 2490 fun unifyTypesErrorReport (_, alphaTypeEnv, betaTypeEnv, what) = 2491 let 2492 fun reportError(SimpleError(alpha: types, beta: types, reason)) = 2493 (* This previously used a single type variable sequence for 2494 both types. It may be that this is needed to make 2495 sensible error messages. *) 2496 PrettyBlock(3, false, [], 2497 [ 2498 PrettyString ("Can't " ^ what (* "match" if a signature, "unify" if core lang. *)), 2499 PrettyBreak (1, 0), 2500 display (alpha, 1000 (* As deep as necessary *), alphaTypeEnv), 2501 PrettyBreak (1, 0), 2502 PrettyString "to", 2503 PrettyBreak (1, 0), 2504 display (beta, 1000 (* As deep as necessary *), betaTypeEnv), 2505 PrettyBreak (1, 0), 2506 PrettyString reason 2507 ]) 2508 2509 | reportError(TypeConstructorError(alpha: types, beta: types, alphaCons, betaCons)) = 2510 let 2511 fun expandedTypeConstr(ty, tyEnv, tyCons) = 2512 let 2513 fun lastPart name = #second(splitString name) 2514 2515 (* Print the type which includes the type constructor name with as 2516 much additional information as we can. *) 2517 fun printWithDesc{ location, name, description } = 2518 PrettyBlock(3, false, [], 2519 [ display (ty, 1000, tyEnv) ] 2520 @ (if lastPart name = lastPart(tcName tyCons) then [] 2521 else 2522 [ 2523 PrettyBreak(1, 0), 2524 PrettyString "=", 2525 PrettyBreak(1, 0), 2526 PrettyBlock(0, false, [ContextLocation location], [PrettyString name]) 2527 ] 2528 ) 2529 @ (if description = "" then [] 2530 else 2531 [ 2532 PrettyBreak(1, 0), 2533 PrettyBlock(0, false, [ContextLocation location], 2534 [PrettyString ("(*" ^ description ^ "*)")]) 2535 ] 2536 ) 2537 ) 2538 in 2539 case tcIdentifier tyCons of 2540 TypeId { description, ...} => printWithDesc description 2541 end 2542 in 2543 PrettyBlock(3, false, [], 2544 [ 2545 PrettyString ("Can't " ^ what (* "match" if a signature, "unify" if core lang. *)), 2546 PrettyBreak (1, 0), 2547 expandedTypeConstr(alpha, alphaTypeEnv, alphaCons), 2548 PrettyBreak (1, 0), 2549 PrettyString (if what = "unify" then "with" else "to"), 2550 PrettyBreak (1, 0), 2551 expandedTypeConstr(beta, betaTypeEnv, betaCons), 2552 PrettyBreak (1, 0), 2553 PrettyString "(Different type constructors)" 2554 ]) 2555 end 2556 2557 in 2558 reportError 2559 end 2560 2561 (* Given a function type returns the first argument if the 2562 function takes a tuple otherwise returns the only argument. 2563 Extended to include the case where the argument is not a function 2564 in order to work properly for overloaded literals. *) 2565 fun firstArg(FunctionType{arg= 2566 LabelledType { recList = {typeof, ...} ::_, ...}, ...}) = 2567 eventual typeof 2568 | firstArg(FunctionType{arg, ...}) = eventual arg 2569 | firstArg t = t 2570 2571 (* Returns an instance of an overloaded function using the supplied 2572 list of type constructors for the overloading. *) 2573 fun generaliseOverload(t, constrs, isConverter) = 2574 let 2575 (* Returns the result type of a function. *) 2576 fun getResult(FunctionType{result, ...}) = eventual result 2577 | getResult _ = raise InternalError "getResult - not a function"; 2578 2579 val arg = if isConverter then getResult t else firstArg t 2580 in 2581 case arg of 2582 TypeVar tv => 2583 let 2584 (* The argument should be a type variable, possibly set to 2585 an empty overload set. This should be replaced by 2586 the current overload set in the copied function type. *) 2587 val newSet = mkOverloadSet constrs 2588 val (t, _) = generaliseTypes(t, fn old => if sameTv(old, tv) then SOME newSet else NONE) 2589 in 2590 (t, [newSet]) 2591 end 2592 | _ => raise InternalError "generaliseOverload - arg is not a type var" 2593 end 2594 (* Prints out a type constructor e.g. type 'a fred = 'a * 'a 2595 or datatype 'a joe = bill of 'a list | mary of 'a * int or 2596 simply type 'a abs if the type is abstract. *) 2597 fun displayTypeConstrsWithMap ( 2598 TypeConstrSet( 2599 TypeConstrs{identifier=TypeId{idKind=TypeFn(args, result), ...}, name, ...}, []), depth, typeEnv, sigMap) = 2600 (* Type function *) 2601 if depth <= 0 2602 then PrettyString "..." 2603 else 2604 let 2605 val typeV = varNameSequence () (* Local sequence for this binding. *) 2606 in 2607 PrettyBlock (3, false, [], 2608 PrettyString "type" :: 2609 PrettyBreak (1, 0) :: 2610 printTypeVars (args, depth, typeV) @ 2611 [ 2612 PrettyString (#second(splitString name)), 2613 PrettyBreak(1, 0), 2614 PrettyString "=", 2615 PrettyBreak(1, 0), 2616 tDisp(result, depth-1, typeV, typeEnv, sigMap) 2617 ] 2618 ) 2619 end 2620 2621 | displayTypeConstrsWithMap (TypeConstrSet(tCons, [] (* No constructors *)), depth, _, _) = 2622 (* Abstract type or type in a signature. *) 2623 if depth <= 0 2624 then PrettyString "..." 2625 else PrettyBlock (3, false, [], 2626 PrettyString ( 2627 if tcEquality tCons then "eqtype" else "type") :: 2628 PrettyBreak (1, 0) :: 2629 printTypeVars (tcTypeVars tCons, depth, varNameSequence ()) @ 2630 [PrettyString (#second(splitString(tcName tCons)))] 2631 ) 2632 2633 | displayTypeConstrsWithMap (TypeConstrSet(tCons as TypeConstrs{name, locations, ...}, tcConstructors), depth, typeEnv, sigMap) = 2634 (* It has constructors - datatype declaration *) 2635 if depth <= 0 2636 then PrettyString "..." 2637 else 2638 let 2639 val typeV = varNameSequence () 2640 (* Construct a ('a, 'b, 'c) tyCons construction for the result types 2641 of each of the constructors. N.B. We use the original type 2642 constructors because they have the appropriate equality type properties. 2643 datatype 'a t = A of 'a is not the same as ''a t = A of ''a. *) 2644 val typeVars = tcTypeVars tCons 2645 val typeResult = mkTypeConstruction(name, tCons, map TypeVar typeVars, locations) 2646 2647 (* Print a single constructor (blocked) *) 2648 fun pValConstr (first, name, typeOf, depth) = 2649 let 2650 val (t, _) = generalise typeOf 2651 val firstBreak = PrettyBreak (1, if first then 2 else 0) 2652 in 2653 case t of 2654 FunctionType { arg, result} => 2655 let 2656 (* Constructor with an argument. The constructor "type" is the argument. 2657 We have to unify the result type of the function with the 2658 ('a, 'b, 'c) tyCons type so that we get the correct type variables 2659 in the argument. We just print the argument of the function. *) 2660 val _ = unifyTypes(result, typeResult) 2661 in 2662 [ 2663 firstBreak, 2664 PrettyBlock (0, false, [], 2665 PrettyBlock (0, false, [], 2666 (if first then PrettyBreak (0, 2) 2667 else PrettyBlock (0, false, [], [PrettyString "|", PrettyBreak(1, 2)]) 2668 ) :: 2669 (if depth <= 0 then [PrettyString "..."] 2670 else [ PrettyString name, PrettyBreak (1, 4), PrettyString "of"]) 2671 ) :: 2672 (if depth > 0 2673 then 2674 [ 2675 PrettyBreak (1, 4), 2676 (* print the type as a single block of output *) 2677 tDisp (arg, depth - 1, typeV, typeEnv, sigMap) 2678 ] 2679 else []) 2680 ) 2681 ] 2682 end 2683 2684 | _ => 2685 [ 2686 firstBreak, 2687 PrettyBlock (0, false, [], 2688 [if first then PrettyBreak (0, 2) 2689 else PrettyBlock (0, false, [], [PrettyString "|", PrettyBreak(1, 2)]), 2690 PrettyString (if depth <= 0 then "..." else name)] 2691 ) 2692 ] 2693 end 2694 2695 (* Print a sequence of constructors (unblocked) *) 2696 fun pValConstrRest ([], _ ): pretty list = [] 2697 | pValConstrRest (H :: T, depth): pretty list = 2698 if depth < 0 then [] 2699 else pValConstr (false, valName H, valTypeOf H, depth) @ 2700 pValConstrRest (T, depth - 1) 2701 2702 fun pValConstrList ([], _ ) = PrettyString "" (* shouldn't occur *) 2703 | pValConstrList (H :: T, depth) = 2704 PrettyBlock (2, true, [], 2705 pValConstr (true, valName H, valTypeOf H, depth) @ 2706 pValConstrRest (T, depth - 1) 2707 ) 2708 2709 in 2710 PrettyBlock(0, false, [], 2711 [ 2712 PrettyBlock(0, false, [], 2713 PrettyString "datatype" :: 2714 PrettyBreak (1, 2) :: 2715 printTypeVars (typeVars, depth, typeV) @ 2716 [ PrettyString(#second(splitString(tcName tCons))), PrettyBreak(1, 0), PrettyString "=" ] 2717 ), 2718 pValConstrList (tcConstructors, depth - 1) 2719 ] 2720 ) 2721 end (* displayTypeConstrsWithMap *) 2722 2723 fun displayTypeConstrs (tCons : typeConstrSet, depth : FixedInt.int, typeEnv) : pretty = 2724 displayTypeConstrsWithMap(tCons, depth, typeEnv, NONE) 2725 2726 (* Return a type constructor from an overload. If there are 2727 several (i.e. the overloading has not resolved to a single type) 2728 it returns the "best". This is called in the third pass so it 2729 should never be called if there is not at least one type that 2730 is possible. *) 2731 fun typeConstrFromOverload(f, _) = 2732 let 2733 fun prefType(TypeVar tvar) = 2734 ( (* If we still have an overload set that's because it has 2735 not reduced to a single type. In ML 97 we default to 2736 int, real, word, char or string in that order. This 2737 works correctly for overloading literals so long as 2738 the literal conversion functions are correctly installed. *) 2739 case tvValue tvar of 2740 OverloadSet{typeset} => 2741 let 2742 (* If we accept this type we have to freeze the 2743 overloading to this type. 2744 I'm not happy about doing this here but it 2745 seems the easiest solution. *) 2746 fun freezeType tcons = 2747 ( 2748 tvSetValue(tvar, 2749 mkTypeConstruction(tcName tcons, tcons, [], [])); 2750 tcons 2751 ) 2752 in 2753 case preferredOverload typeset of 2754 SOME tycons => freezeType tycons 2755 | NONE => raise InternalError "typeConstrFromOverload: No matching type" 2756 end 2757 | _ => raise InternalError "typeConstrFromOverload: No matching type" (* Unbound or flexible record. *) 2758 ) 2759 | prefType(TypeConstruction{constr, args, ...}) = 2760 if not (tcIsAbbreviation constr) 2761 then constr (* Generally args will be nil in this case but 2762 in the special case of looking for an equality 2763 function for 'a ref or 'a array it may not be. *) 2764 else prefType (makeEquivalent (constr, args)) 2765 | prefType _ = raise InternalError "typeConstrFromOverload: No matching type" 2766 in 2767 prefType(firstArg(eventual f)) 2768 end; 2769 2770 (* Return the result type of a function. Also used to test if the value is 2771 a function type. *) 2772 fun getFnArgType t = 2773 case eventual t of 2774 FunctionType {arg, ... } => SOME arg 2775 | _ => NONE 2776 2777 2778 (* Assigns type variables to variables with generalisation permitted 2779 if their level is at least that of the current level. 2780 In ML90 mode this produced an error message for any top-level 2781 free imperative type variables. We don't do that in ML97 because 2782 it is possible that another declaration may "freeze" the type variable 2783 before the composite expression reaches the top level. *) 2784 fun allowGeneralisation (t, level, nonExpansive, lex, location, moreInfo, typeEnv) = 2785 let 2786 fun giveError(s1: string, s2: string) = 2787 let 2788 (* Use a single sequence. *) 2789 val vars : typeVarForm -> string = varNameSequence (); 2790 open DEBUG 2791 val parameters = debugParams lex 2792 val errorDepth = getParameter errorDepthTag parameters 2793 in 2794 reportError lex 2795 { 2796 hard = true, 2797 location = location, 2798 message = 2799 PrettyBlock (3, false, [], 2800 [ 2801 PrettyString s1, 2802 PrettyBreak (1, 0), 2803 tDisp (t, errorDepth, vars, typeEnv, NONE), 2804 PrettyBreak (1, 0), 2805 PrettyString s2 2806 ] 2807 ), 2808 context = SOME(moreInfo ()) 2809 } 2810 end 2811 2812 local 2813 open DEBUG 2814 val parameters = debugParams lex 2815 in 2816 val checkOverloadFlex = getParameter narrowOverloadFlexRecordTag parameters 2817 end 2818 2819 fun general t (genArgs as (showError, nonExpansive)) = 2820 case eventual t of 2821 TypeVar tvar => 2822 let 2823 val argSet = 2824 if tvLevel tvar >= level andalso tvLevel tvar <> generalisable 2825 andalso (case tvValue tvar of OverloadSet _ => false | _ => true) 2826 then 2827 let 2828 (* Make a new generisable type variable, except that type 2829 variables in an expansive context cannot be generalised. 2830 We also don't generalise if this is an overload set. 2831 The reason for that is that it allows us to get overloading 2832 information from the surrounding context. 2833 e.g. let fun f x y = x+y in f 2.0 end. An alternative 2834 would be take the default type (in this case int). 2835 DCJM 1/9/00. *) 2836 val nonCopiable = not nonExpansive 2837 val newLevel = 2838 if nonCopiable then level-1 else generalisable (* copiable *); 2839 2840 val isOk = 2841 (* If the type variable has top-level scope then we have 2842 a free type variable. We only want to generate this 2843 message once even if we have multiple type variables.*) 2844 (* If the type variable is non-unifiable and the expression is 2845 expansive then we have an error since this will have to 2846 be a monotype. *) 2847 if tvNonUnifiable tvar andalso nonCopiable andalso showError 2848 then 2849 ( 2850 giveError("Type", "includes a free type variable"); 2851 false 2852 ) 2853 else showError; 2854 (* It may be a flexible record so we have to transfer the 2855 record to the new variable. *) 2856 val newTypeVar = 2857 makeTv {value=tvValue tvar, level=newLevel, equality=tvEquality tvar, 2858 nonunifiable=if nonCopiable then (tvNonUnifiable tvar) else false, 2859 printable=tvPrintity tvar} 2860 in 2861 tvSetValue (tvar, TypeVar newTypeVar); 2862 (* If we are using the "narrow" context for overloading and 2863 flexible records we should apply this here. Otherwise it is 2864 dealt with in the next pass when we have the full program context. *) 2865 case (checkOverloadFlex, tvValue tvar) of 2866 (true, LabelledType _) => giveError("Type", "is an unresolved flexible record") 2867 | (true, OverloadSet {typeset, ...}) => 2868 ( (* Set this to the "preferred" type. Typically this is "int" but for overloaded literals 2869 (e.g. 0w0) it could be something else. *) 2870 case preferredOverload typeset of 2871 SOME tycons => 2872 tvSetValue(tvar, 2873 mkTypeConstruction(tcName tycons, tycons, [], [])) 2874 | NONE => raise InternalError "general: No matching type" 2875 ) 2876 | _ => (); 2877 (isOk, nonExpansive) 2878 end 2879 else genArgs 2880 in 2881 general (tvValue tvar) argSet (* Process any flexible record. *) 2882 end 2883 2884 | TypeConstruction {args, constr, ...} => 2885 (* There is a pathological case here. If we have a type equivalence 2886 which contains type variables that do not occur on the RHS 2887 (e.g. type 'a t = int) then we generalise over them even with an 2888 expansive expression. This is because the semantics treats type 2889 abbreviations as type functions and so any type variables that 2890 are eliminated by the function application do not appear in the 2891 "type" that the semantics applies to the expression. *) 2892 if tcIsAbbreviation constr 2893 then 2894 let 2895 val (r1, _) = general(makeEquivalent (constr, args)) genArgs 2896 (* Process any arguments that have not been processed in the equivalent. *) 2897 val (r2, _) = List.foldr (fn (t, v) => general t v) (r1, true) args 2898 in 2899 (r2, nonExpansive) 2900 end 2901 else List.foldr (fn (t, v) => general t v) genArgs args 2902 2903 | FunctionType {arg, result} => general arg (general result genArgs) 2904 2905 | LabelledType {recList,...} => 2906 List.foldr (fn ({ typeof, ... }, v) => general typeof v) genArgs recList 2907 2908 | _ => genArgs 2909 in 2910 general t (true, nonExpansive); 2911 () 2912 end (* end allowGeneralisation *); 2913 2914 (* Check for free type variables at the top level. Added for ML97. This replaces the 2915 test in allowGeneralisation above and is applied to all top-level 2916 values including those in structures and functors. *) 2917 (* I've changed this from giving an error message, which prevented the 2918 code from evaluating, to giving a warning and setting the type 2919 variables to unique type variables. That allows, for example, 2920 fun f x = raise x; f Subscript; to work. DCJM 8/3/01. *) 2921 fun checkForFreeTypeVariables(valName: string, ty: types, lex: lexan, printAndEqCode) : unit = 2922 let 2923 (* Generate new names for the type constructors. *) 2924 val count = ref 0 2925 fun genName num = 2926 (if num >= 26 then genName (num div 26 - 1) else "") 2927 ^ String.str (Char.chr (num mod 26 + Char.ord #"a")); 2928 2929 fun checkTypes (TypeVar tvar) () = 2930 if isEmpty(tvValue tvar) andalso tvLevel tvar = 1 2931 then (* The type variable is unbound (specifically, not 2932 an overload set) and it is not generic i.e. it 2933 must have come from an expansive expression. *) 2934 let 2935 val name = "_" ^ genName(!count) 2936 val _ = count := !count + 1; 2937 val declLoc = location lex (* Not correct but OK for the moment. *) 2938 val declDescription = 2939 { location = declLoc, name = name, description = "Constructed from a free type variable." } 2940 val tCons = 2941 makeTypeConstructor (name, [], 2942 makeFreeId(0, Global(printAndEqCode()), tvEquality tvar, declDescription), 2943 [DeclaredAt declLoc]); 2944 val newVal = mkTypeConstruction(name, tCons, [], []) 2945 in 2946 warningMessage(lex, location lex, 2947 concat["The type of (", valName, 2948 ") contains a free type variable. Setting it to a unique monotype."]); 2949 tvSetValue (tvar, newVal) 2950 end 2951 else () 2952 | checkTypes _ () = () 2953 2954 in 2955 foldType checkTypes ty (); 2956 () 2957 end 2958 2959 (* Returns true if a type constructor permits equality. *) 2960 2961 fun permitsEquality constr = 2962 if tcIsAbbreviation constr 2963 then typePermitsEquality( 2964 mkTypeConstruction (tcName constr, constr, List.map TypeVar (tcTypeVars constr), [])) 2965 else tcEquality constr 2966 2967 and typePermitsEquality ty = equality (ty, fn _ => No, fn _ => Yes) <> No 2968 2969 (* See if a type abbreviation or "where type" has the form type t = s or 2970 type 'a t = 'a s etc and so is simply giving a new name to the type 2971 constructor. If it is it then checks that the type constructor used 2972 (s in this example) is just a simple type name. *) 2973 fun typeNameRebinding(typeArgs, typeResult): typeId option = 2974 let 2975 fun eqTypeVar(TypeVar ta, tb) = sameTv (ta, tb) 2976 | eqTypeVar _ = false 2977 in 2978 case typeResult of 2979 TypeConstruction {constr, args, ... } => 2980 if not (ListPair.allEq eqTypeVar(args, typeArgs)) 2981 then NONE 2982 else 2983 ( 2984 case tcIdentifier constr of 2985 TypeId{idKind=TypeFn _, ...} => NONE 2986 | tId => SOME tId 2987 2988 ) 2989 | _ => NONE 2990 end 2991 2992 (* Returns the number of the entry in the list. Used to find out the 2993 location of fields in a labelled record for expressions and pattern 2994 matching. Assumes that the label appears in the list somewhere. *) 2995 2996 fun entryNumber (label, LabelledType{recList, ...}) = 2997 let (* Count up the list. *) 2998 fun entry ({name, ...}::l) n = 2999 if name = label then n else entry l (n + 1) 3000 | entry [] _ = raise Match 3001 in 3002 entry recList 0 3003 end 3004 3005 | entryNumber (label, TypeVar tvar) = 3006 entryNumber (label, tvValue tvar) 3007 3008 | entryNumber (label, TypeConstruction{constr, ...}) = (* Type alias *) 3009 entryNumber (label, tcEquivalent constr) 3010 3011 | entryNumber _ = 3012 raise InternalError "entryNumber - not a record" 3013 3014 (* Size of a labelled record. *) 3015 3016 fun recordWidth (LabelledType{recList, ...}) = 3017 length recList 3018 3019 | recordWidth (TypeVar tvar) = 3020 recordWidth (tvValue tvar) 3021 3022 | recordWidth (TypeConstruction{constr, ...}) = (* Type alias *) 3023 recordWidth (tcEquivalent constr) 3024 3025 | recordWidth _ = 3026 raise InternalError "entryNumber - not a record" 3027 3028 fun recordFieldMap f (LabelledType{recList, ...}) = List.map (f o (fn {typeof, ...} => typeof)) recList 3029 | recordFieldMap f (TypeVar tvar) = recordFieldMap f (tvValue tvar) 3030 | recordFieldMap f (TypeConstruction{constr, ...}) = recordFieldMap f (tcEquivalent constr) 3031 | recordFieldMap _ _ = raise InternalError "entryNumber - not a record" 3032 3033 (* Unify two type variables which would otherwise be non-unifiable. 3034 Used when we have found a local type variable with the same name 3035 as a global one. *) 3036 fun linkTypeVars (a, b) = 3037 let 3038 val ta = typesTypeVar (eventual(TypeVar a)); (* Must both be type vars. *) 3039 val tb = typesTypeVar (eventual(TypeVar b)); 3040 in (* Set the one with the higher level to point to the one with the 3041 lower, so that the effective level is the lower. *) 3042 if (tvLevel ta) > (tvLevel tb) 3043 then tvSetValue (ta, TypeVar b) 3044 else tvSetValue (tb, TypeVar a) 3045 end; 3046 3047 (* Set its level by setting it to a new type variable. *) 3048 fun setTvarLevel (typ, level) = 3049 let 3050 val tv = typesTypeVar (eventual(TypeVar typ)); (* Must be type var. *) 3051 in 3052 tvSetValue (tv, mkTypeVar (level, tvEquality tv, true, tvPrintity tv)) 3053 end; 3054 3055 (* Construct the least general type from a list of types. This is used after 3056 type checking to try to remove polymorphism from local values. It takes 3057 the list of actual uses of the value, usually a function, and removes 3058 any unnecessary polymorphism. This is particularly the case if the 3059 function involves a flexible record, where the unspecified fields are 3060 treated as polymorphic, but where the function is actually applied 3061 to a records which are monomorphic. *) 3062 fun leastGeneral [] = EmptyType (* Never used? *) 3063 3064 (* Don't use this at the moment - see the comment on TypeVar below. 3065 Also the comment on TypeConstruction for local datatypes. *) 3066(* | leastGeneral [oneType] = oneType *)(* Just one - this is it. *) 3067 3068 | leastGeneral(firstType::otherTypes): types = 3069 let 3070 fun canonical (typ as TypeVar tyVar) = 3071 ( 3072 case tvValue tyVar of 3073 EmptyType => typ 3074 | OverloadSet _ => 3075 let 3076 val constr = typeConstrFromOverload(typ, false) 3077 in 3078 mkTypeConstruction(tcName constr, constr, [], []) 3079 end 3080 | t => canonical t 3081 ) 3082 | canonical (typ as TypeConstruction { constr, args, ...}) = 3083 if tcIsAbbreviation constr (* Handle type abbreviations directly *) 3084 then canonical(makeEquivalent (constr, args)) 3085 else typ 3086 | canonical typ = typ 3087 3088 (* Take the head of the each argument list and extract the least general. 3089 Then process the tail. It's an error if each element of the list 3090 does not contain the same number of items. *) 3091 fun leastArgs ([]::_) = [] 3092 | leastArgs (args as _::_) = 3093 leastGeneral(List.map hd args) :: leastArgs (List.map tl args) 3094 | leastArgs _ = raise Empty 3095 3096 in 3097 case canonical firstType of 3098 (*typ as *)TypeVar _(*tv*) => 3099 let 3100 (*fun sameTypeVar(TypeVar tv1) = sameTv(tv, tv1) | sameTypeVar _ = false*) 3101 in 3102 (* If they are all the same type variable return that otherwise return 3103 a new generalisable type variable. They may all be equal if we always 3104 apply this function to a value whose type is a polymorphic type in the 3105 function that contains all these uses. *) 3106 (* Temporarily, at least, create a new type var in this case. If we have a polymorphic 3107 function that is only used inside another polymorphic function but isn't declared 3108 inside it, if we use the caller's type variable here the call won't be recognised 3109 as polymorphic. *) 3110 (*if List.all sameTypeVar otherTypes then typ else*) mkTypeVar(generalisable, false, false, false) 3111 end 3112 3113 | TypeConstruction{ constr, args, name, locations, ...} => 3114 ( 3115 (* There is a potential problem if the datatype is local including if it was 3116 constructed in a functor. Almost always it will have been declared after 3117 the polymorphic function but if it happens not to have been we could set 3118 a polymorphic function to a type that doesn't exist yet. To avoid this 3119 we don't allow a local datatype here and instead fall back to the 3120 polymorphic case. *) 3121 case tcIdentifier constr of 3122 thisConstrId as TypeId{access=Global _, ...} => 3123 let 3124 val argLength = List.length args 3125 (* This matches if it is an application of the same type constructor. *) 3126 fun getTypeConstrs(TypeConstruction{constr, args, ...}) = 3127 if sameTypeId(thisConstrId, tcIdentifier constr) andalso 3128 List.length args = argLength 3129 then SOME args else NONE 3130 | getTypeConstrs _ = NONE 3131 val allArgs = List.mapPartial (getTypeConstrs o canonical) otherTypes 3132 in 3133 if List.length allArgs = List.length otherTypes 3134 then TypeConstruction{constr=constr, name=name, locations=locations, 3135 args = leastArgs(args :: allArgs)} 3136 else (* At least one of these wasn't the same type constructor. *) 3137 mkTypeVar(generalisable, false, false, false) 3138 end 3139 | _ => mkTypeVar(generalisable, false, false, false) 3140 ) 3141 3142 | FunctionType{ arg, result } => 3143 let 3144 fun getFuns(FunctionType{arg, result}) = SOME(arg, result) 3145 | getFuns _ = NONE 3146 val argResults = List.mapPartial (getFuns o canonical) otherTypes 3147 in 3148 if List.length argResults = List.length otherTypes 3149 then 3150 let 3151 val (args, results) = ListPair.unzip argResults 3152 in 3153 FunctionType{arg=leastGeneral(arg::args), result = leastGeneral(result::results)} 3154 end 3155 else (* At least one of these wasn't a function. *) 3156 mkTypeVar(generalisable, false, false, false) 3157 end 3158 3159 | LabelledType (r as {recList=firstRec, fullList}) => 3160 if recordIsFrozen r 3161 then 3162 let 3163 (* This matches if all the field names are the same. Extract the types. *) 3164 fun nameMatch({name=name1: string, ...}, {name=name2, ...}) = name1 = name2 3165 fun getRecords(LabelledType{recList, ...}) = 3166 if ListPair.allEq nameMatch (firstRec, recList) 3167 then SOME(List.map #typeof recList) else NONE 3168 | getRecords _ = NONE 3169 val argResults = List.mapPartial (getRecords o canonical) otherTypes 3170 in 3171 if List.length argResults = List.length otherTypes 3172 then 3173 let 3174 (* Use the names from the first record (they all are the same) to 3175 build a new record. *) 3176 val argTypes = leastArgs(List.map #typeof firstRec :: argResults) 3177 fun recreateRecord({name, ...}, types) = {name=name, typeof=types} 3178 val newList = ListPair.map recreateRecord(firstRec, argTypes) 3179 in 3180 LabelledType{recList=newList, fullList=fullList } 3181 end 3182 else (* At least one of these wasn't a record. *) 3183 mkTypeVar(generalisable, false, false, false) 3184 end 3185 else (* At this stage the record should be frozen if the program is 3186 correct but if it isn't we could have a flexible record which 3187 we report elsewhere. *) 3188 mkTypeVar(generalisable, false, false, false) 3189 3190 | _ => (* May arise if there's been an error. *) mkTypeVar(generalisable, false, false, false) 3191 end 3192 3193 (* Test if this is floating point i.e. the "real" type. We could include 3194 abbreviations of real as well but it's probably not worth it. *) 3195 datatype floatKind = FloatDouble | FloatSingle 3196 3197 local 3198 val realId = tcIdentifier realConstr and floatId = tcIdentifier floatConstr 3199 3200 fun isFloatId constr = 3201 let 3202 val id = tcIdentifier constr 3203 in 3204 if sameTypeId(id, realId) then SOME FloatDouble 3205 else if sameTypeId(id, floatId) then SOME FloatSingle 3206 else NONE 3207 end 3208 in 3209 fun isFloatingPt(TypeConstruction{args=[], constr, ...}) = isFloatId constr 3210 | isFloatingPt(OverloadSet {typeset, ...}) = 3211 ( 3212 case preferredOverload typeset of 3213 SOME t => isFloatId t (* real only. float is never preferred. *) 3214 | NONE => NONE 3215 ) 3216 | isFloatingPt(TypeVar tv) = isFloatingPt (tvValue tv) 3217 | isFloatingPt _ = NONE 3218 end 3219 3220 fun checkDiscard(t: types, lex: lexan): string option = 3221 let 3222 open DEBUG 3223 val checkLevel = getParameter reportDiscardedValuesTag (debugParams lex) 3224 3225 fun isUnit(LabelledType{recList=[], ...}) = true (* Unit is actually an empty record *) 3226 | isUnit(TypeConstruction{ 3227 constr as TypeConstrs{identifier=TypeId{idKind=TypeFn _, ...}, ...}, 3228 args, ...}) = 3229 isUnit(makeEquivalent(constr, args)) 3230 | isUnit(TypeVar _) = true (* Allow unbound type vars *) 3231 | isUnit _ = false 3232 3233 fun isAFunction(FunctionType _) = true 3234 | isAFunction(TypeConstruction{ 3235 constr as TypeConstrs{identifier=TypeId{idKind=TypeFn _, ...}, ...}, 3236 args, ...}) = 3237 isAFunction(makeEquivalent(constr, args)) 3238 | isAFunction _ = false 3239 in 3240 case checkLevel of 3241 1 => if isAFunction (eventual t) then SOME "A function value is being discarded." else NONE 3242 | 2 => if isUnit (eventual t) then NONE else SOME "A non unit value is being discarded." 3243 | _ => NONE 3244 end 3245 3246 structure Sharing = 3247 struct 3248 type types = types 3249 and values = values 3250 and typeId = typeId 3251 and structVals = structVals 3252 and typeConstrs= typeConstrs 3253 and typeConstrSet=typeConstrSet 3254 and typeParsetree = typeParsetree 3255 and locationProp = locationProp 3256 and pretty = pretty 3257 and lexan = lexan 3258 and ptProperties = ptProperties 3259 and typeVarForm = typeVarForm 3260 and codetree = codetree 3261 and matchResult = matchResult 3262 and generalMatch = generalMatch 3263 end 3264end (* TYPETREE *); 3265