1(* 2 Copyright (c) 2013-2015 David C.J. Matthews 3 4 This library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Lesser General Public 6 License version 2.1 as published by the Free Software Foundation. 7 8 This library is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 Lesser General Public License for more details. 12 13 You should have received a copy of the GNU Lesser General Public 14 License along with this library; if not, write to the Free Software 15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16*) 17 18(* 19 Derived from the original parse-tree 20 21 Copyright (c) 2000 22 Cambridge University Technical Services Limited 23 24 Further development: 25 Copyright (c) 2000-13 David C.J. Matthews 26 27 Title: Parse Tree Structure and Operations. 28 Author: Dave Matthews, Cambridge University Computer Laboratory 29 Copyright Cambridge University 1985 30 31*) 32 33 34functor TYPECHECK_PARSETREE ( 35 36structure BASEPARSETREE : BaseParseTreeSig 37structure PRINTTREE: PrintParsetreeSig 38structure EXPORTTREE: ExportParsetreeSig 39structure LEX : LEXSIG 40structure CODETREE : CODETREESIG 41structure STRUCTVALS : STRUCTVALSIG; 42structure TYPETREE : TYPETREESIG 43structure VALUEOPS : VALUEOPSSIG; 44structure PRETTY : PRETTYSIG 45structure COPIER: COPIERSIG 46structure DATATYPEREP: DATATYPEREPSIG 47 48structure UTILITIES : 49sig 50 type lexan; 51 type location = 52 { file: string, startLine: FixedInt.int, startPosition: FixedInt.int, 53 endLine: FixedInt.int, endPosition: FixedInt.int } 54 55 val noDuplicates: (string * 'a * 'a -> unit) -> 56 { apply: (string * 'a -> unit) -> unit, 57 enter: string * 'a -> unit, 58 lookup: string -> 'a option}; 59 60 val searchList: unit -> { apply: (string * 'a -> unit) -> unit, 61 enter: string * 'a -> unit, 62 lookup: string -> 'a option }; 63 64 val checkForDots: string * lexan * location -> unit; 65 66 val splitString: string -> { first:string,second:string } 67 68 structure Sharing: 69 sig 70 type lexan = lexan 71 end 72end 73 74structure PRINTTABLE : 75sig 76 type typeConstrs 77 type codetree 78 79 val getOverloads: string -> (typeConstrs * codetree) list 80 81 structure Sharing: 82 sig 83 type codetree = codetree 84 and typeConstrs = typeConstrs 85 end 86end; 87 88structure MISC : 89sig 90 exception InternalError of string; (* compiler error *) 91 92 val quickSort : ('a -> 'a -> bool) -> 'a list -> 'a list; 93 94 val lookupDefault : ('a -> 'b option) -> ('a -> 'b option) -> 'a -> 'b option 95end 96 97sharing LEX.Sharing = TYPETREE.Sharing = STRUCTVALS.Sharing = COPIER.Sharing 98 = VALUEOPS.Sharing = UTILITIES.Sharing = PRETTY.Sharing 99 = CODETREE.Sharing = PRINTTABLE.Sharing = DATATYPEREP.Sharing 100 = BASEPARSETREE.Sharing = PRINTTREE.Sharing = EXPORTTREE.Sharing 101 102): TypeCheckParsetreeSig = 103 104struct 105 open MISC 106 open LEX 107 open CODETREE 108 open STRUCTVALS 109 open TYPETREE 110 open VALUEOPS 111 open UTILITIES 112 open PRETTY 113 open PRINTTABLE 114 open DATATYPEREP 115 116 open BASEPARSETREE 117 open PRINTTREE 118 open EXPORTTREE 119 120 val emptyType = EmptyType 121 val badType = BadType 122 123 (* Second pass of ML parse tree. *) 124 125 (* This is pass 2 of the compiler. It walks over the parse tree 126 generated by pass 1 and looks up identifiers to match them to 127 declarations. It performs the type checking. "makeTypeId" is used 128 to construct unique identifiers for types depending on the context 129 (i.e. in a signature, structure or functor). *) 130 fun pass2 (v, makeTypeId, env, lex, sigTypeIdMap) = 131 let 132 (* Returns a function which can be passed to unify or apply to 133 print a bit of context info. *) 134 fun foundNear v () = 135 let 136 val errorDepth = errorDepth lex 137 in 138 displayParsetree (v, errorDepth) 139 end 140 141 (* A simpler error message routine for lookup_... where the message 142 does not involve pretty-printing anything. *) 143 fun giveError (v, lex, line) = 144 fn message => errorNear (lex, true, v, line, message); 145 146 fun checkForBuiltIn (name, v, lex, lineno, isConstr) = 147 (* ML97 does not allow the standard constructors to be rebound and does 148 not allow "it" to become a constructor. *) 149 if name = "true" orelse name = "false" orelse name = "nil" 150 orelse name = "::" orelse name = "ref" orelse (isConstr andalso name = "it") 151 then errorNear(lex, true, v, lineno, 152 "Rebinding or specifying \"" ^ name ^ "\" is illegal") 153 else () 154 155 (* Turn a result from unifyTypes into a pretty structure so that it 156 can be included in a message. *) 157 fun unifyErrorReport(lex, typeEnv) = unifyTypesErrorReport(lex, typeEnv, typeEnv, "unify") 158 159 (* Error message for incompatible types. Displays both expressions and their types. *) 160 fun typeMismatch (title, left, right, detail, lex : lexan, location, moreInfo) = 161 let 162 val message = 163 PrettyBlock(3, true, [], 164 [ 165 PrettyString title, 166 PrettyBreak(1, 0), left, 167 PrettyBreak(1, 0), right, 168 PrettyBreak(1, 0), 169 PrettyBlock(0, false, [], 170 [PrettyString "Reason:", PrettyBreak(1, 3), detail]) 171 ]) 172 in 173 reportError lex 174 { 175 location = location, 176 hard = true, 177 message = message, 178 context = SOME (moreInfo ()) 179 } 180 end; 181 182 (* Error message for single expressions with the wrong type. e.g. "if" not followed 183 by a "bool". *) 184 fun typeWrong (title, value, detail, lex : lexan, location, moreInfo) = 185 let 186 val message = 187 PrettyBlock(3, true, [], 188 [ 189 PrettyString title, 190 PrettyBreak(1, 0), value, 191 PrettyBreak(1, 0), 192 PrettyBlock(0, false, [], 193 [ PrettyString "Reason:", PrettyBreak(1, 3), detail]) 194 ]) 195 in 196 reportError lex 197 { 198 location = location, 199 hard = true, 200 message = message, 201 context = SOME (moreInfo ()) 202 } 203 end; 204 205 (* Display a value and its type as part of an error message. *) 206 fun valTypeMessage (lex, typeEnv) (title, value, valType) = 207 let 208 val errorDepth = errorDepth lex 209 in 210 PrettyBlock(3, false, [], 211 [ 212 PrettyString title, 213 PrettyBreak(1, 0), 214 displayParsetree (value, errorDepth), 215 PrettyBreak(1, 0), 216 PrettyString ":", 217 PrettyBreak(1, 0), 218 display(valType, 10000 (* All of it *), typeEnv) 219 ]) 220 end 221 222 fun matchTypeMessage (lex, typeEnv) (title, match, valType) = 223 let 224 val errorDepth = errorDepth lex 225 in 226 PrettyBlock(3, false, [], 227 [ 228 PrettyString title, 229 PrettyBreak(1, 0), 230 displayMatch (match, errorDepth), 231 PrettyBreak(1, 0), 232 PrettyString ":", 233 PrettyBreak(1, 0), 234 display(valType, 10000 (* All of it *), typeEnv) 235 ]) 236 end 237 238 (* Old error message and unification functions. These will eventually be 239 removed. *) 240 fun matchError 241 (error: matchResult, lex : lexan, location : LEX.location, moreInfo : unit -> pretty, typeEnv) : unit = 242 reportError lex 243 { 244 location = location, 245 hard = true, 246 message = unifyErrorReport(lex, typeEnv) error, 247 context = SOME (moreInfo ()) 248 } 249 250 fun unify (alpha, beta, lex, location, moreInfo, typeEnv) = 251 case unifyTypes (alpha, beta) of 252 NONE => () 253 | SOME error => 254 matchError (error, lex, location, moreInfo, typeEnv) 255 256 fun apply (f, arg, lex, location, moreInfo, typeEnv) = 257 case eventual f of 258 FunctionType {arg=farg, result} => 259 ( 260 unify (farg, arg, lex, location, moreInfo, typeEnv); 261 result 262 ) 263 | ef => (* Type variables etc. - Use general case. *) 264 let (* Make arg->'a, and unify with the function. *) 265 val resType = mkTypeVar (generalisable, false, false, false) 266 val fType = mkFunctionType (arg, resType) 267 268 (* This may involve more than just assigning the type to "ef". *) 269 val () = unify (ef, fType, lex, location, moreInfo, typeEnv); 270 in 271 resType (* The result is the type variable unified to the result. *) 272 end 273 274 (* These cases currently use the "apply" or "unify" and may need to be improved in 275 order to produce better messages. 276 apply: 277 Literals. The conversion functions are applied to the string literal. In effect this produces the set 278 of overloadings of the literal. This should never produce an error message. 279 Constructors in patterns to their args. 280 "case": the patterns are "applied" to the value to be tested. 281 282 unify: 283 Layered patterns, to set the variable. Also checks the pattern against any explicit type. 284 Handlers: the handling patterns are unified against a function from exn -> the result type of the 285 expression being handled. 286 *) 287 288 fun stringsOfSearchList { apply: (string * 'a -> unit) -> unit, ...} () = 289 let 290 val v = ref [] 291 val () = apply (fn (s, _) => v := s :: !v) 292 in 293 !v 294 end 295 296 fun assignValues (level, letDepth, env, near, v) = 297 let 298 val typeEnv = 299 { 300 lookupType = fn s => case #lookupType env s of NONE => NONE | SOME t => SOME(t, NONE), 301 lookupStruct = fn s => case #lookupStruct env s of NONE => NONE | SOME t => SOME(t, NONE) 302 } 303 (* Process each item of the sequence and return the type of the 304 last item. A default item is returned if the list is empty. *) 305 fun assignSeq(env, depth, l, isExp) = 306 let 307 fun applyList last [] = last 308 | applyList _ ((h, _) :: t) = 309 let 310 val expT = assignValues(level, depth, env, v, h) 311 val _ = 312 if isExp andalso not (null t) 313 then (* It's not the last value and we're going to discard it *) 314 case checkDiscard(expT, lex) of 315 NONE => () 316 | SOME s => errorNear (lex, false, h, getLocation h, s) 317 else () 318 in 319 applyList expT t 320 end 321 in 322 applyList badType l 323 end 324 325 (* Variables, constructors and fn are non-expansive. 326 [] is a derived form of "nil" so must be included. 327 Integer and string constants are also constructors but 328 cannot involve imperative type variables. Constrained 329 versions are also non-expansive. 330 This has been extended and made more explicit in ML 97. *) 331 fun nonExpansive (Fn _) = true 332 | nonExpansive (Ident _) = true 333 | nonExpansive (List{elements = [], ...}) = true 334 | nonExpansive (List{elements, ...}) = 335 List.foldl (fn (v, a) => a andalso nonExpansive v) true elements 336 | nonExpansive (Constraint {value, ...}) = nonExpansive value 337 | nonExpansive (Literal _) = true 338 | nonExpansive (Unit _) = true 339 | nonExpansive (TupleTree{fields, ...}) = 340 List.foldl (fn (v, a) => a andalso nonExpansive v) true fields 341 | nonExpansive (Labelled{recList, ...}) = 342 List.foldl (fn ({valOrPat, ...}, a) => a andalso nonExpansive valOrPat) 343 true recList (* Every element must be non-expansive *) 344 | nonExpansive (Applic{f, arg, ...}) = 345 isNonRefConstructor f andalso nonExpansive arg 346 | nonExpansive (Selector _) = true (* derived from fn {..} => ...*) 347 | nonExpansive (Parenthesised(p, _)) = nonExpansive p 348 | nonExpansive _ = false 349 350 (* An application is non-expansive only if it is a, possibly 351 constrained, constructor which is not ref. *) 352 and isNonRefConstructor (Ident {value=ref v, ...}) = 353 (* It is possible to rebind ref by way of datatype replication so we have 354 to check the type here. *) 355 let 356 fun isRefConstructor t = 357 case eventual t of 358 FunctionType{result, ...} => 359 (case eventual result of 360 TypeConstruction{constr, ...} => 361 sameTypeId (tcIdentifier constr, tcIdentifier refConstr) 362 | _ => false) 363 | _ => false 364 in 365 isConstructor v andalso not (isRefConstructor(valTypeOf v)) 366 end 367 | isNonRefConstructor (Constraint {value, ...}) = 368 isNonRefConstructor value 369 | isNonRefConstructor (Parenthesised(p, _)) = 370 isNonRefConstructor p 371 | isNonRefConstructor _ = false 372 373 (* Applies "assignValues" or "processPattern" to every element of a list and unifies the 374 types. Returns a type variable if the list is empty. 375 This is used for lists, function values (fn .. => ...), 376 handlers and case expressions. *) 377 fun assignList _ _ [] = mkTypeVar (generalisable, false, false, false) 378 | assignList (processValue: 'a->types, _, _) _ [single] = processValue single 379 380 | assignList (processValue: 'a->types, displayValue, typeMsg) 381 (errorMsg, itemName, separator, location, near) (tlist as hd :: tl) = 382 let 383 val firstType = processValue hd 384 385 fun printList (doPrint: 'a*FixedInt.int->pretty) (c: 'a list, separator, depth): pretty list = 386 if depth <= 0 then [PrettyString "..."] 387 else 388 case c of 389 [] => [] 390 | [v] => [doPrint (v, depth)] 391 | (v::vs) => 392 PrettyBlock (0, false, [], 393 [ 394 doPrint (v, depth), 395 PrettyBreak 396 (if separator = "," orelse separator = ";" orelse separator = "" then 0 else 1, 0), 397 PrettyString separator 398 ] 399 ) :: 400 PrettyBreak (1, 0) :: 401 printList doPrint (vs, separator, depth - 1) 402 403 fun applyList(ty, _, []) = ty 404 | applyList(ty, n, h::t) = 405 let 406 val typ = processValue h 407 in 408 case unifyTypes (ty, typ) of 409 NONE => applyList(ty, n+1, t) 410 | SOME report => 411 let 412 (* We have a type error but we don't know which is correct. 413 The previous items must have produced a consistent type 414 otherwise we'd already have reported an error but we 415 can't identify exactly where the error occurred. *) 416 val errorDepth = errorDepth lex 417 val previousValsAndType = 418 PrettyBlock(3, false, [], 419 [ 420 PrettyString ( 421 if n = 1 then itemName ^ " 1:" 422 else itemName ^ "s 1-" ^ Int.toString n ^ ":"), 423 PrettyBreak(1, 0), 424 PrettyBlock(0, false, [], 425 printList (*displayParsetree*)displayValue (List.take(tlist, n), 426 separator, errorDepth)), 427 PrettyBreak(1, 0), 428 PrettyString ":", 429 PrettyBreak(1, 0), 430 display(ty, 10000 (* All of it *), typeEnv) 431 ]) 432 in 433 typeMismatch(errorMsg, 434 previousValsAndType, 435 (*valTypeMessage*)typeMsg(lex, typeEnv) (concat[itemName, " ", Int.toString(n+1), ":"], h, typ), 436 unifyErrorReport(lex, typeEnv) report, lex, location, foundNear near); 437 (* Continue with "bad" which suppresses further error messages 438 and return "bad" as the result. *) 439 applyList(badType, n+1, t) 440 end 441 end 442 in 443 applyList(firstType, 1, tl) 444 end 445 446 fun ptAssignTypes (t, near) = 447 assignTypes 448 (t, 449 fn (s, line) => 450 lookupTyp 451 ({lookupType = #lookupType env, lookupStruct = #lookupStruct env}, 452 s, giveError (near, lex, line)), 453 lex); 454 455 (* Makes a type for an instance of an identifier. *) 456 457 (* Get the current overload set for the function and return a new 458 instance of the type containing the overload set. *) 459 fun overloadType(Value{typeOf, access = Overloaded TypeDep, name, ...}, isConv) = 460 #1 (generaliseOverload(typeOf, List.map #1 (getOverloads name), isConv)) 461 | overloadType(Value{typeOf, ...}, _) = #1 (generalise typeOf) 462 463 fun instanceType (v as Value{access=Overloaded TypeDep, ...}) = 464 (* Look up the current overloading for this function. *) 465 overloadType(v, false) 466 467 | instanceType(Value{typeOf, ...}) = #1 (generalise typeOf) 468 (* The types of constructors and variables are copied 469 to create new instances of type variables. *) 470 471 fun processPattern(pat, enterResult, level, notConst, mkVar, isRec) = 472 let 473 val mapProcessPattern = 474 map (fn x => processPattern(x, enterResult, level, notConst, mkVar, isRec)); 475 in 476 case pat of 477 Ident {name, value, expType, location, possible, ...} => (* Variable or nullary constructor. *) 478 let 479 (* Look up the name. If it is a constructor then use it, 480 otherwise return `undefined'. If it is a qualified name, 481 i.e. it contains a full-stop, we assume it is a constructor 482 and give an error message if it does not exist. *) 483 (* In ML 97 recursive declarations such as val rec f = ... 484 override constructor status. If this is a recursive declaration 485 we don't check for constructor status. *) 486 val names = splitString name; 487 val nameVal = 488 if isRec 489 then undefinedValue 490 else if #first names = "" 491 then (* Not qualified - may be a variable. *) 492 getOpt (#lookupVal env name, undefinedValue) 493 494 else (* Qualified - cannot be a variable. *) 495 lookupValue 496 ("Constructor", 497 {lookupVal= #lookupVal env, lookupStruct= #lookupStruct env}, 498 name, 499 giveError (pat, lex, location)) 500 501 (* Remember the possible names here. *) 502 val () = possible := #allValNames env 503 504 val instanceType = 505 (* If the result is a constructor use it. *) 506 if isConstructor nameVal (* exceptions. *) 507 then if notConst 508 then 509 ( 510 errorNear (lex, true, pat, location, 511 "Identifier before `as' must not be a constructor."); 512 badType 513 ) 514 else 515 (* Must be a nullary constructor otherwise it should 516 have been applied to something. *) 517 let 518 (* set this value in the record *) 519 val () = value := nameVal; 520 val isNullary = 521 case nameVal of 522 Value{class=Constructor{nullary, ...}, ...} => nullary 523 | Value{typeOf, ...} => (* exception *) not (isSome(getFnArgType typeOf)) 524 in 525 if isNullary then instanceType nameVal 526 else 527 ( 528 errorNear (lex, true, pat, location, 529 "Constructor must be applied to an argument pattern."); 530 badType 531 ) 532 end 533 534 (* If undefined or another variable, construct a new variable. *) 535 else 536 let 537 val props = [DeclaredAt location, SequenceNo (newBindingId lex)] 538 val var = mkVar(name, mkTypeVar (level, false, false, false), props) 539 in 540 checkForDots (name, lex, location); (* Must not be qualified *) 541 (* Must not be "true", "false" etc. *) 542 checkForBuiltIn (name, v, lex, location, false); 543 enterResult (name, var); 544 value := var; 545 valTypeOf var (* and return its type *) 546 end; 547 in 548 expType := instanceType; (* Record the instance type.*) 549 instanceType 550 end 551 552 | Literal{converter, expType, location, ...} => 553 let 554 (* Find out the overloadings on this converter and 555 construct an instance of it. The converters are 556 all functions from string to the result type. *) 557 val instanceType = overloadType(converter, true) 558 (* Apply the converter to string to get the type of the 559 literal. *) 560 val instance = 561 apply(instanceType, stringType, lex, location, foundNear pat, typeEnv) 562 in 563 expType := instance; (* Record the instance type.*) 564 instance 565 end 566 567 | Applic {f = con, arg, location, expType, ...} => 568 let 569 (* Apply the function to the argument and return the result. *) 570 (* Function must be a constructor. *) 571 val conType = 572 case con of 573 Ident {name, value, location, expType, possible, ...} => 574 let (* Look up the value and return the type. *) 575 576 (* Remember the possible names here. *) 577 val () = possible := #allValNames env 578 579 val constrVal = 580 lookupValue 581 ("Constructor", 582 {lookupVal = #lookupVal env, lookupStruct = #lookupStruct env}, 583 name, giveError (pat, lex, location)); 584 in 585 if isConstructor constrVal 586 then 587 let 588 val cType = instanceType constrVal 589 in 590 value := constrVal; 591 expType := cType; (* Record the instance type.*) 592 cType 593 end 594 else (* Undeclared or a variable. *) 595 ( 596 if isUndefinedValue constrVal then () 597 else errorNear (lex, true, pat, location, name ^ " is not a constructor"); 598 badType 599 ) 600 end 601 602 | _ => (* con is not an Ident *) 603 ( 604 errorNear (lex, true, pat, location, 605 "Constructor in a pattern was not an identifier"); 606 badType 607 ) 608 609 val patType = processPattern(arg, enterResult, level, notConst, mkVar, isRec); 610 (* Apply to the pattern type. *) 611 val resultType = apply (conType, patType, lex, location, foundNear pat, typeEnv) 612 in 613 expType := resultType; (* Record the instance type.*) 614 resultType 615 end (* Applic *) 616 617 | TupleTree{fields, expType, ...} => 618 let 619 (* Construct the type obtained by mapping "processPattern" 620 onto each element of the tuple. *) 621 val tupleType = mkProductType (mapProcessPattern fields) 622 in 623 expType := tupleType; 624 tupleType 625 end 626 627 | Labelled {recList, frozen, expType, ...} => 628 let (* Process each item in the list. *) 629 630 fun mapLabels [] = [] 631 | mapLabels ({name, valOrPat, expType, ...}::T) = 632 (* Type is a label entry with the label name 633 and the type of the pattern. *) 634 let 635 val ty = processPattern(valOrPat, enterResult, level, notConst, mkVar, isRec) 636 in 637 expType := ty; 638 mkLabelEntry(name, ty) :: mapLabels T 639 end; 640 val patType = mkLabelled (sortLabels(mapLabels recList), frozen); 641 in 642 expType := patType; 643 patType 644 end 645 646 | (aList as List{elements, location, expType}) => 647 let 648 (* Applies "processPattern" to every element of a list and 649 unifies the types. Returns a type variable if the list 650 is empty *) 651 fun processElement elem = 652 processPattern(elem, enterResult, level, notConst, mkVar, isRec) 653 val elementType = 654 assignList (processElement, displayParsetree, valTypeMessage) 655 ("Elements in a list have different types.", "Item", ",", location, aList) elements 656 val resType = 657 if isBadType elementType 658 then badType 659 else mkTypeConstruction ("list", tsConstr listConstr, [elementType], [DeclaredAt inBasis]) 660 in 661 expType := resType; 662 resType 663 end 664 665 | aConstraint as Constraint {value, given, location} => 666 let 667 val valType = processPattern(value, enterResult, level, notConst, mkVar, isRec); 668 val theType = ptAssignTypes(given, pat); 669 in 670 (* These must be unifiable. *) 671 case unifyTypes(valType, theType) of 672 NONE => () (* OK. *) 673 | SOME report => 674 typeMismatch("Type mismatch in type constraint.", 675 valTypeMessage (lex, typeEnv) ("Value:", value, valType), 676 PrettyBlock(0, false, [], 677 [ 678 PrettyString "Constraint:", 679 PrettyBreak(1, 0), 680 display(theType, 10000 (* All of it *), typeEnv) 681 ]), 682 unifyErrorReport (lex, typeEnv) report, 683 lex, location, foundNear aConstraint); 684 theType 685 end 686 687 | Layered {var, pattern, location} => 688 let 689 (* Unify the variable and the pattern - At this stage that simply 690 involves assigning the type of the pattern to the variable, 691 but it may result in more unification when the variable is 692 used *) 693 694 (* The "variable" must be either id or id: ty but we have to 695 check that the id is not a constructor. *) 696 val varType = processPattern(var, enterResult, level, true, mkVar, isRec); 697 val patType = processPattern(pattern, enterResult, level, notConst, mkVar, isRec) 698 val () = unify (varType, patType, lex, location, foundNear pat, typeEnv); 699 in 700 varType 701 end 702 703 | Unit _ => unitType 704 705 | WildCard _ => mkTypeVar (generalisable, false, false, false) 706 707 | Parenthesised(p, _) => 708 processPattern(p, enterResult, level, notConst, mkVar, isRec) 709 710 | _ => (* not a legal pattern *) 711 badType 712 713 end (* processPattern *) 714 715 (* val assValues = assignValues level line env; *) 716 and assValues near v = 717 case v of 718 Ident {name, value, expType, location, possible, ...} => 719 let 720 val expValue = 721 lookupValue 722 ("Value or constructor", 723 {lookupVal = #lookupVal env, lookupStruct = #lookupStruct env}, 724 name, giveError (near, lex, location)); 725 (* Set the value and type found. *) 726 val instanceType = instanceType expValue; 727 in 728 (* Include this reference in the list of local references. *) 729 case expValue of 730 Value { references=SOME{localRef, ...}, ...} => 731 localRef := location :: ! localRef 732 | _ => (); 733 (* Include this type in the list of instance types. *) 734 case expValue of 735 Value { instanceTypes=SOME instanceRef, ...} => 736 instanceRef := instanceType :: ! instanceRef 737 | _ => (); 738 expType := instanceType; 739 value := expValue; 740 possible := #allValNames env; 741 instanceType (* Result is the instance type. *) 742 end 743 744 | Literal{converter, expType, location, ...} => 745 let 746 (* Find out the overloadings on this converter and 747 construct an instance of it. The converters are 748 all functions from string to the result type. *) 749 val instanceType = overloadType(converter, true) 750 val instance = 751 apply(instanceType, stringType, lex, location, foundNear near, typeEnv) 752 in 753 expType := instance; 754 instance 755 end 756 757 | Applic {f, arg, location, expType, ...} => 758 let 759 (* Apply the function to the argument and return the result. *) 760 val funType = assValues near f; 761 val argType = assValues near arg; 762 (* If this is not a constructor the expression is expansive. We need to unify this 763 with a type-variable with local (non-generalisable) scope to force any type 764 variables to be monomorphic. The reason for this is that if there are polymorphic 765 type variables remaining in identifiers in the next pass we treat the identifier as 766 polymorphic and wrap a function round it. *) 767 val () = 768 if nonExpansive v 769 then () 770 else (unifyTypes (funType, mkTypeVar(level, false, false, false)); ()) 771 (* Test to see if we have a function. *) 772 val fType = 773 case eventual funType of 774 FunctionType {arg, result} => SOME(arg, result) 775 | _ => (* May be a simple type variable. *) 776 let 777 val funResType = mkTypeVar (generalisable, false, false, false) 778 val funArgType = mkTypeVar (generalisable, false, false, false) 779 val fType = mkFunctionType (funArgType, funResType) 780 in 781 case unifyTypes (fType, funType) of 782 NONE => SOME(funArgType, funResType) 783 | SOME _ => 784 ( 785 (* It's not a function. *) 786 typeMismatch("Type error in function application.", 787 valTypeMessage (lex, typeEnv) ("Function:", f, funType), 788 valTypeMessage (lex, typeEnv) ("Argument:", arg, argType), 789 PrettyString "Value being applied does not have a function type", 790 lex, location, foundNear near); 791 NONE 792 ) 793 end 794 795 in 796 case fType of 797 NONE => badType (* Not a function *) 798 | SOME (fArg, fResult) => 799 ( 800 case unifyTypes (fArg, argType) of 801 NONE => () 802 | SOME report => 803 typeMismatch("Type error in function application.", 804 valTypeMessage (lex, typeEnv) ("Function:", f, funType), 805 valTypeMessage (lex, typeEnv) ("Argument:", arg, argType), 806 unifyErrorReport (lex, typeEnv) report, lex, location, foundNear near); 807 expType := fResult; (* Preserve for browsing. *) 808 fResult 809 ) 810 end 811 812 | Cond {test, thenpt, elsept, location, ...} => 813 let 814 (* The test must be bool, and the then and else parts must be the 815 same. The result is either of these two once they have been 816 unified. *) 817 val testType = assValues v test; 818 val thenType = assValues v thenpt; 819 val elseType = assValues v elsept; 820 in 821 case unifyTypes(testType, boolType) of 822 NONE => () 823 | SOME report => 824 typeWrong("Condition in if-statement must have type bool.", 825 valTypeMessage (lex, typeEnv) ("If:", test, testType), 826 unifyErrorReport (lex, typeEnv) report, lex, location, foundNear v); 827 828 case unifyTypes(thenType, elseType) of 829 NONE => thenType (* or equally elseType *) 830 | SOME report => 831 ( 832 typeMismatch("Type mismatch between then-part and else-part.", 833 valTypeMessage (lex, typeEnv) ("Then:", thenpt, thenType), 834 valTypeMessage (lex, typeEnv) ("Else:", elsept, elseType), 835 unifyErrorReport (lex, typeEnv) report, lex, location, foundNear v); 836 badType 837 ) 838 end 839 840 | TupleTree{fields, expType, ...} => 841 let 842 (* Construct the type obtained by mapping "assignValue" onto 843 each element of the tuple. *) 844 val tupleType = mkProductType (map (assValues near) fields) 845 in 846 expType := tupleType; 847 tupleType 848 end 849 850 | Labelled {recList, frozen, expType, ...} => 851 let 852 (* Process each item in the list. *) 853 fun labEntryToLabType {name, valOrPat, expType, ...} = 854 let 855 val ty = assValues v valOrPat 856 in 857 expType := ty; 858 {name = name, typeof = ty } 859 end 860 861 val expressionType = 862 mkLabelled 863 (sortLabels (map labEntryToLabType recList), frozen) (* should always be true *); 864 in 865 expType := expressionType; 866 expressionType 867 end 868 869 | Selector {typeof, ...} => 870 typeof (* Already made. *) 871 872 | ValDeclaration {dec, explicit, implicit, ...} => 873 (assValDeclaration (dec, explicit, implicit); badType (* Should never be used. *)) 874 875 | FunDeclaration fund => 876 (assFunDeclaration fund; badType (* Should never be used. *)) 877 878 | OpenDec{decs=ptl, variables, structures, typeconstrs, ...} => 879 let 880 (* Go down the list of names opening the structures. *) 881 (* We have to be careful because open A B is not the same as 882 open A; open B if A contains a structure called B. *) 883 (* We accumulate the values so that we can produce debugging 884 information if we need to. Note: we have to be careful if 885 we have the same name in multiple structures. *) 886 val valTable = HashTable.hashMake 10 887 and typeTable = HashTable.hashMake 10 888 and structTable = HashTable.hashMake 10 889 890 (* First get the structures... *) 891 fun findStructure ({name, location, value, ...}: structureIdentForm) = 892 let 893 val foundStruct = 894 lookupStructure 895 ("Structure", {lookupStruct = #lookupStruct env}, name, 896 giveError (v, lex, location)) 897 val () = value := foundStruct (* Remember in case we export. *) 898 in 899 case foundStruct of 900 SOME str => SOME(str, location) 901 | NONE => NONE 902 end 903 904 val strs = List.mapPartial findStructure ptl 905 906 (* Value and substructure entries in a structure will generally have 907 "Formal" access which simply gives the offset of the entry within 908 the parent structure. We need to convert these into "Select" 909 entries to capture the address of the base structure. *) 910 fun copyEntries (str as Struct{locations, signat = sigTbl, name=strName, ...}, varLoc) = 911 let 912 val openLocs = 913 (* If we have a declaration location for the structure set this as the structure 914 location. Add in here as the "open location". *) 915 case List.find (fn DeclaredAt _ => true | _ => false) locations of 916 SOME (DeclaredAt loc) => [StructureAt loc, OpenedAt varLoc] 917 | _ => [OpenedAt varLoc] 918 919 (* Open the structure. Formal entries are turned into Selected entries. *) 920 val _ = 921 COPIER.openSignature 922 (sigTbl, 923 { 924 enterType = 925 fn (name, TypeConstrSet(ty, valConstrs)) => 926 let 927 (* We also have to turn the value constructors into 928 "selected" entries in case we use datatype 929 replication. Unlike with "include" in signatures, 930 there's no guarantee that the constructors will also 931 be part of the value environment. They could have 932 been redefined. *) 933 val newTypeSet = 934 TypeConstrSet(ty, 935 List.map (fn c => mkSelectedVar (c, str, openLocs)) valConstrs) 936 in 937 HashTable.hashSet(typeTable, name, newTypeSet); 938 #enterType env (name, newTypeSet) 939 end, 940 enterStruct = 941 fn (name, strVal) => 942 let 943 val selectedStruct = 944 makeSelectedStruct (strVal, str, openLocs); 945 in 946 HashTable.hashSet(structTable, name, selectedStruct); 947 #enterStruct env (name, selectedStruct) 948 end, 949 enterVal = 950 fn (name, value) => 951 let 952 val selectedVar = 953 mkSelectedVar (value, str, openLocs); 954 in 955 HashTable.hashSet(valTable, name, selectedVar); 956 #enterVal env (name, selectedVar) 957 end 958 }, 959 (* Add the structure we're opening here to the types of 960 the values. The name will be removed in messages if the type 961 constructor is in scope but if it has been redefined we can 962 get an identifiable name. *) 963 strName ^ "."); 964 in 965 () 966 end 967 968 (* ...then put them into the name space. *) 969 val () = List.app copyEntries strs; 970 in 971 variables := HashTable.fold (fn (_, v, t) => v :: t) [] valTable; 972 structures := HashTable.fold (fn (_, v, t) => v :: t) [] structTable; 973 typeconstrs := HashTable.fold (fn (_, v, t) => v :: t) [] typeTable; 974 badType (* Does not return a type *) 975 end 976 977 | TypeDeclaration(tlist, _) => 978 let (* This is either a type abbreviation in the core language, in a structure 979 or in a signature or it is a type specification in a signaure. *) 980 fun messFn(name, _, new) = 981 errorNear (lex, true, v, declaredAt(tcLocations new), 982 name ^ " has already been bound in this declaration"); 983 984 val newEnv = noDuplicates messFn; 985 986 (* First match all the types on the right-hand sides. *) 987 fun processTypeBody (TypeBind {decType = SOME decType, ...}) = ptAssignTypes(decType, v) 988 | processTypeBody _ = emptyType (* Specification. *) 989 990 val resTypes = List.map processTypeBody tlist; 991 992 (* Can now declare the new types. *) 993 fun processType (TypeBind {name, typeVars, isEqtype, nameLoc, tcon=tcRef, ...}, decType) = 994 let 995 (* Construct a type constructor which is an alias of the 996 right-hand side of the declaration. If we are effectively 997 giving a new name to a type constructor we use the same type 998 identifier. This is needed to check "well-formedness" in signatures. *) 999 val props = [DeclaredAt nameLoc, SequenceNo (newBindingId lex)] 1000 1001 val tcon = 1002 if isEmpty decType 1003 then (* Type specification *) 1004 let 1005 val description = { location = nameLoc, name = name, description = "" } 1006 in 1007 makeTypeConstructor (name, typeVars, 1008 makeTypeId(isEqtype, false, (typeVars, EmptyType), description), props) 1009 end 1010 else case typeNameRebinding(typeVars, decType) of 1011 SOME typeId => 1012 makeTypeConstructor (name, typeVars,typeId, props) 1013 | NONE => 1014 let 1015 val description = { location = nameLoc, name = name, description = "" } 1016 in 1017 makeTypeConstructor (name, typeVars, 1018 makeTypeId(isEqtype, false, (typeVars, decType), description), props) 1019 end 1020 in 1021 checkForDots (name, lex, nameLoc); (* Must not be qualified *) 1022 #enter newEnv (name, tcon); (* Check for duplicates. *) 1023 tcRef := TypeConstrSet(tcon, []); 1024 #enterType env (name, TypeConstrSet(tcon, [])) (* Put in the surrounding scope. *) 1025 end 1026 1027 val () = ListPair.app processType (tlist, resTypes); 1028 in 1029 badType (* Does not return a type *) 1030 end 1031 1032 | AbsDatatypeDeclaration absData => assAbsData absData 1033 1034 | DatatypeReplication{oldType, newType, oldLoc, newLoc, ...} => 1035 (* Adds both the type and the constructors to the 1036 current environment. *) 1037 let 1038 (* Look up the type constructor in the environment. *) 1039 val oldTypeCons: typeConstrSet = 1040 lookupTyp 1041 ({lookupType = #lookupType env, lookupStruct = #lookupStruct env}, 1042 oldType, 1043 giveError (near, lex, oldLoc)) 1044 1045 (* Copy the datatype, converting any Formal constructors to Selected. *) 1046 local 1047 (* If the type name was qualified (e.g. S.t) we need to find the 1048 value constructors from the same structure. *) 1049 val {first = namePrefix, ...} = splitString oldType; 1050 val baseStruct = 1051 if namePrefix = "" 1052 then NONE 1053 else lookupStructure("Structure", {lookupStruct = #lookupStruct env}, 1054 namePrefix, giveError (v, lex, oldLoc)) 1055 val TypeConstrSet(tcons, tcConstructors) = oldTypeCons 1056 val newName = newType 1057 val locations = [DeclaredAt newLoc, SequenceNo (newBindingId lex)] 1058 (* Create a new constructor with the same unique ID. *) 1059 val typeID = tcIdentifier tcons 1060 val newTypeCons = makeTypeConstructor(newName, tcTypeVars tcons, typeID, locations) 1061 1062 (* Copy the value constructors. *) 1063 fun copyAConstructor(Value{name=cName, typeOf, class, access, ...}) = 1064 let 1065 (* Copy the types of value constructors replacing 1066 occurrences of the old type with the new one. 1067 This is not strictly necessary but improves printing. 1068 e.g. local datatype X = A | B in datatype Y = datatype X end; 1069 A; prints A: Y rather than A: X *) 1070 fun copyTypeCons (tcon : typeConstrs) : typeConstrs = 1071 if sameTypeId(tcIdentifier tcon, typeID) 1072 then newTypeCons 1073 else tcon; 1074 fun copyTyp (t : types) : types = 1075 copyType (t, fn x => x, (* Don't bother with type variables. *) 1076 copyTypeCons); 1077 val newType = copyTyp typeOf; 1078 val newAccess = 1079 case (access, baseStruct) of 1080 (* If we are opening a structure we must have a base structure 1081 and we turn Formal entries into Selected. If we are replicating 1082 a datatype within a signature the original constructors will 1083 be Formal. *) 1084 (Formal addr, SOME(Struct{access, ...})) => Selected{base=access, addr=addr} 1085 | (Formal _, NONE) => access 1086 | _ => access; (* Probably already a global. *) 1087 in 1088 Value{name=cName, typeOf=newType, class=class, access=newAccess, locations=locations, 1089 references = NONE, instanceTypes=NONE} 1090 end 1091 1092 in 1093 val newValConstrs = map copyAConstructor tcConstructors 1094 val newTypeCons = TypeConstrSet(newTypeCons, newValConstrs) 1095 end 1096 in 1097 (* This previously checked that it was a datatype but that's 1098 not actually correct. *) 1099 (* Enter the value constrs in the environment. *) 1100 List.app (fn c => (#enterVal env) (valName c, c)) newValConstrs; 1101 (* Add this type constructor to the environment. *) 1102 (#enterType env) (newType, newTypeCons); 1103 badType (* Does not return a type *) 1104 end 1105 1106 | (aList as List{elements, location, expType, ...}) => 1107 let 1108 val elementType = 1109 assignList(assValues v, displayParsetree, valTypeMessage) 1110 ("Elements in a list have different types.", "Item", ",", location, aList) elements 1111 val resType = 1112 if isBadType elementType 1113 then badType 1114 else mkTypeConstruction ("list", tsConstr listConstr, [elementType], [DeclaredAt inBasis]) 1115 in 1116 expType := resType; 1117 resType 1118 end 1119 1120 | Constraint {value, given, location} => 1121 let 1122 val valType = assValues near value; 1123 val theType = ptAssignTypes(given, v) 1124 in 1125 (* These must be unifiable. *) 1126 case unifyTypes(valType, theType) of 1127 NONE => () (* OK. *) 1128 | SOME report => 1129 typeMismatch("Type mismatch in type constraint.", 1130 valTypeMessage (lex, typeEnv) ("Value:", value, valType), 1131 PrettyBlock(0, false, [], 1132 [ 1133 PrettyString "Constraint:", 1134 PrettyBreak(1, 0), 1135 display(theType, 10000 (* All of it *), typeEnv) 1136 ]), 1137 unifyErrorReport (lex, typeEnv) report, 1138 lex, location, foundNear v); 1139 theType 1140 end 1141 1142 | (aFun as Fn {matches, location, expType, ...}) => (* Must unify the types of each of the alternatives.*) 1143 let 1144 val resType = 1145 assignList(assMatchTree aFun, displayMatch, matchTypeMessage) 1146 ("Clauses in fn expression have different types.", "Clause", "|", location, aFun) matches 1147 in 1148 expType := resType; 1149 resType 1150 end 1151 1152 | Unit _ => 1153 unitType 1154 1155 | Localdec {decs, body, isLocal, varsInBody, ...} => 1156 let (* Local declarations or expressions. *) 1157 val newValEnv = searchList(); 1158 val newTypeEnv = searchList(); 1159 val newStrEnv = searchList(); 1160 val newLetDepth = if isLocal then letDepth else letDepth+1; 1161 (* The environment for the local declarations. *) 1162 val localEnv = 1163 { 1164 lookupVal = lookupDefault (#lookup newValEnv) (#lookupVal env), 1165 lookupType = lookupDefault (#lookup newTypeEnv) (#lookupType env), 1166 lookupFix = #lookupFix env, 1167 (* This environment is needed if we open a 1168 structure which has sub-structures. *) 1169 lookupStruct = lookupDefault (#lookup newStrEnv) (#lookupStruct env), 1170 lookupSig = #lookupSig env, 1171 lookupFunct = #lookupFunct env, 1172 lookupTvars = #lookupTvars env, 1173 enterVal = #enter newValEnv, 1174 enterType = #enter newTypeEnv, 1175 (* Fixity has already been dealt with in the parsing process. The only reason 1176 we deal with it here is to ensure that declarations are printed in the 1177 correct order. We simply need to make sure that local fixity declarations 1178 are ignored. *) 1179 enterFix = fn _ => (), 1180 enterStruct = #enter newStrEnv, 1181 enterSig = #enterSig env, 1182 enterFunct = #enterFunct env, 1183 allValNames = fn () => (stringsOfSearchList newValEnv () @ #allValNames env ()) 1184 }; 1185 1186 (* Process the local declarations and discard the result. *) 1187 val _ : types = assignSeq(localEnv, newLetDepth, decs, false) 1188 1189 (* This is the environment used for the body of the declaration. 1190 Declarations are added both to the local environment and to 1191 the surrounding scope. *) 1192 val bodyEnv = 1193 { 1194 (* Look-ups come from the local environment *) 1195 lookupVal = #lookupVal localEnv, 1196 lookupType = #lookupType localEnv, 1197 lookupFix = #lookupFix localEnv, 1198 lookupStruct = #lookupStruct localEnv, 1199 lookupSig = #lookupSig localEnv, 1200 lookupFunct = #lookupFunct localEnv, 1201 lookupTvars = #lookupTvars localEnv, 1202 enterVal = 1203 fn (pair as (_, v)) => 1204 (varsInBody := v :: ! varsInBody; 1205 #enter newValEnv pair; 1206 #enterVal env pair), 1207 enterType = 1208 fn pair => 1209 (#enter newTypeEnv pair; 1210 #enterType env pair), 1211 enterFix = #enterFix env, 1212 enterStruct = 1213 fn pair => 1214 (#enter newStrEnv pair; 1215 #enterStruct env pair), 1216 enterSig = #enterSig env, 1217 enterFunct = #enterFunct env, 1218 allValNames = #allValNames localEnv 1219 }; 1220 (* Now the body, returning its result if it is an expression. *) 1221 val resType = assignSeq(bodyEnv, newLetDepth, body, not isLocal) 1222 in 1223 resType 1224 end (* LocalDec *) 1225 1226 | ExpSeq (ptl, _) => 1227 (* A sequence of expressions separated by semicolons. 1228 Result is result of last expression. *) 1229 assignSeq (env, letDepth, ptl, true) 1230 1231 | ExDeclaration(tlist, _) => 1232 let 1233 fun messFn(name, _, line) = 1234 errorNear (lex, true, v, line, 1235 name ^ " has already been bound in this declaration"); 1236 1237 (* Construct an environment to check for duplicate declarations. 1238 Include the declaration location as the value. *) 1239 val dupEnv = noDuplicates messFn; 1240 1241 fun processException (ExBind {name, previous, ofType, value, nameLoc, ...}) = 1242 let 1243 (* Fill in any types. If there was no type given the exception has type exn 1244 otherwise it has type ty->exn. *) 1245 val oldType = 1246 case ofType of 1247 NONE => exnType 1248 | SOME typeof => mkFunctionType(ptAssignTypes(typeof, v), exnType) 1249 val locations = [DeclaredAt nameLoc, SequenceNo (newBindingId lex)] 1250 1251 val exValue = 1252 case previous of 1253 EmptyTree => mkEx (name, oldType, locations) (* Generative binding. *) 1254 1255 | Ident {name = prevName, value = prevValue, location, expType, possible, ...} => 1256 let 1257 (* ex = ex' i.e. a non-generative binding? *) 1258 (* Match up the previous exception. *) 1259 val prev = 1260 lookupValue 1261 ("Exception", 1262 {lookupVal= #lookupVal env, 1263 lookupStruct= #lookupStruct env}, 1264 prevName, 1265 giveError (v, lex, location)) 1266 val excType = valTypeOf prev 1267 in 1268 (* Check that it is an exception *) 1269 case prev of 1270 Value{class=Exception, ...} => () 1271 | _ => errorNear (lex, true, v, location, "(" ^ prevName ^ ") is not an exception."); 1272 prevValue := prev; (* Set the value of the looked-up identifier. *) 1273 expType := excType; (* And remember the type. *) 1274 possible := #allValNames env; 1275 (* The result is an exception with the same type. *) 1276 mkEx (name, excType, locations) 1277 end 1278 | _ => 1279 raise InternalError "processException: badly-formed parse-tree" 1280 in 1281 (* Save this value. *) 1282 value := exValue; 1283 1284 (* In the check environment *) 1285 #enter dupEnv (name, nameLoc); 1286 1287 (* Must not be qualified *) 1288 checkForDots (name, lex, nameLoc) : unit; 1289 (* Must not be "true", "false" etc. *) 1290 checkForBuiltIn (name, v, lex, nameLoc, true) : unit; 1291 1292 (* Put this exception into the env *) 1293 #enterVal env (name, exValue) 1294 end 1295 1296 val () = List.app processException tlist; 1297 in 1298 badType 1299 end (* ExDeclaration *) 1300 1301 | Raise (pt, line) => 1302 let 1303 val exType = assValues v pt 1304 in 1305 (* The exception value must have type exn. *) 1306 case unifyTypes(exType, exnType) of 1307 NONE => () 1308 | SOME report => 1309 typeWrong("Exception to be raised must have type exn.", 1310 valTypeMessage (lex, typeEnv) ("Raise:", pt, exType), 1311 unifyErrorReport (lex, typeEnv) report, lex, line, foundNear v); 1312 (* Matches anything *) 1313 mkTypeVar (generalisable, false, false, false) 1314 end 1315 1316 | (aHandler as HandleTree {exp, hrules, location, ...}) => 1317 let 1318 (* If the expression returns type E 1319 the handler must be exn -> E *) 1320 val expType = assValues aHandler exp; 1321 (* Unify the handler with a function from exn -> expType *) 1322 val clauses = 1323 assignList(assMatchTree aHandler, displayMatch, matchTypeMessage) 1324 ("Clauses in handler have different types.", "Clause", "|", location, aHandler) hrules 1325 (* The result type of the handlers must match the result type of the expression being 1326 handled and the arguments must all have type exn. *) 1327 val () = 1328 unify (clauses, mkFunctionType (exnType, expType), lex, location, foundNear v, typeEnv); 1329 in 1330 expType (* Result is expType. *) 1331 end 1332 1333 | While {test, body, location, ...} => 1334 let 1335 val testType = assValues v test 1336 in 1337 (* Test must be bool. Result is unit *) 1338 case unifyTypes(testType, boolType) of 1339 NONE => () 1340 | SOME report => 1341 typeWrong("Loop condition of while-expression must have type bool.", 1342 valTypeMessage (lex, typeEnv) ("While:", test, testType), 1343 unifyErrorReport (lex, typeEnv) report, lex, location, foundNear v); 1344 assValues v body; (* Result of body is discarded. *) 1345 unitType 1346 end 1347 1348 | aCase as Case {test, match, location, expType, ...} => 1349 let 1350 val funType = 1351 assignList(assMatchTree aCase, displayMatch, matchTypeMessage) 1352 ("Clauses in case have different types.", "Clause", "|", location, aCase) match; 1353 val argType = assValues aCase test; 1354 (* The matches constitute a function from the test type to 1355 the result of the case statement, so we apply the match type 1356 to the test. *) 1357 val resType = apply (funType, argType, lex, location, foundNear aCase, typeEnv) 1358 in 1359 expType := resType; 1360 resType 1361 end 1362 1363 | anAndAlso as Andalso {first, second, location} => 1364 let 1365 (* Both parts must be bool and the result is bool. *) 1366 fun mkTupleTree(fields, location) = TupleTree { fields=fields, location=location, expType = ref EmptyType } 1367 val pairArgs = mkTupleTree([first, second], location) 1368 val argTypes = assValues anAndAlso pairArgs; 1369 val boolStarBool = mkProductType[boolType, boolType] 1370 val () = 1371 case unifyTypes(argTypes, boolStarBool) of 1372 NONE => () 1373 | SOME report => 1374 typeWrong("Arguments of andalso must have type bool*bool.", 1375 valTypeMessage (lex, typeEnv) ("Arguments:", pairArgs, argTypes), 1376 unifyErrorReport (lex, typeEnv) report, lex, location, foundNear anAndAlso) 1377 in 1378 boolType 1379 end 1380 1381 | anOrElse as Orelse {first, second, location} => 1382 let 1383 (* Both parts must be bool and the result is bool. *) 1384 fun mkTupleTree(fields, location) = TupleTree { fields=fields, location=location, expType = ref EmptyType } 1385 val pairArgs = mkTupleTree([first, second], location) 1386 val argTypes = assValues anOrElse pairArgs; 1387 val boolStarBool = mkProductType[boolType, boolType] 1388 val () = 1389 case unifyTypes(argTypes, boolStarBool) of 1390 NONE => () 1391 | SOME report => 1392 typeWrong("Arguments of orelse must have type bool*bool.", 1393 valTypeMessage (lex, typeEnv) ("Arguments:", pairArgs, argTypes), 1394 unifyErrorReport (lex, typeEnv) report, lex, location, foundNear anOrElse) 1395 in 1396 boolType 1397 end 1398 1399 | Directive { tlist, fix, ... } => 1400 ( 1401 (* Infix declarations have already been processed by the parser. We include 1402 them here merely so that we get all declarations in the correct order. *) 1403 List.app (fn name => #enterFix env (name, FixStatus(name, fix))) tlist; 1404 badType 1405 ) 1406 1407 | WildCard _ => (* Should never occur in an expression. *) 1408 raise InternalError "assignTypes: wildcard found" 1409 1410 | Layered _ => 1411 raise InternalError "assignTypes: layered pattern found" 1412 1413 | EmptyTree => 1414 raise InternalError "assignTypes: emptytree found" 1415 1416 | Parenthesised(p, _) => assValues near p 1417 1418 (* end of assValues *) 1419 1420 and assMatchTree _ (MatchTree {vars, exp, resType, argType, ...}) = 1421 let 1422 (* A match is a function from the pattern to the expression *) 1423 1424 (* Process the pattern looking for variables. *) 1425 1426 (* Construct a new environment for the variables. *) 1427 fun messFn(name, _, Value{locations, ...}) = 1428 errorNear (lex, true, v, declaredAt locations, 1429 name ^ " has already been bound in this match"); 1430 1431 val newEnv = noDuplicates messFn; 1432 val newLevel = level + 1; 1433 val decs = processPattern(vars, #enter newEnv, newLevel, false, mkPattVar, false) 1434 1435 (* The identifiers declared in the pattern are available in the 1436 body of the function. *) 1437 val bodyEnv = 1438 { 1439 lookupVal = lookupDefault (#lookup newEnv) (#lookupVal env), 1440 lookupType = #lookupType env, 1441 lookupFix = #lookupFix env, 1442 lookupStruct = #lookupStruct env, 1443 lookupSig = #lookupSig env, 1444 lookupFunct = #lookupFunct env, 1445 lookupTvars = #lookupTvars env, 1446 enterVal = #enterVal env, 1447 enterType = #enterType env, 1448 enterFix = #enterFix env, 1449 enterStruct = #enterStruct env, 1450 enterSig = #enterSig env, 1451 enterFunct = #enterFunct env, 1452 allValNames = 1453 fn () => (stringsOfSearchList newEnv () @ #allValNames env ()) 1454 }; 1455 1456 (* Now the body. *) 1457 val expType = assignValues(newLevel, letDepth, bodyEnv, v, exp); 1458 in 1459 resType := expType; 1460 argType := decs; 1461 (* Result is a function from the type of the pattern to the type 1462 of the body. This previously generalised the resulting type. Why? *) 1463 mkFunctionType (decs, expType) 1464 end (* MatchTree *) 1465 1466 and assValDeclaration (valdecs: valbind list, explicit, implicit) = 1467 (* assignTypes for a val-declaration. *) 1468 let 1469 val newLevel = level + 1; 1470 1471 (* Set the scope of explicit type variables. *) 1472 val () = #apply explicit(fn (_, tv) => setTvarLevel (tv, newLevel)); 1473 1474 (* For each implicit type variable associated with this value declaration, 1475 link it to any type variable with the same name in an outer 1476 scope. *) 1477 val () = 1478 #apply implicit 1479 (fn (name, tv) => 1480 case #lookupTvars env name of SOME v => linkTypeVars(v, tv) | NONE => setTvarLevel (tv, newLevel)); 1481 (* If it isn't there set the level of the type variable. *) 1482 1483 (* Construct a new environment for the variables. *) 1484 val newEnv = 1485 noDuplicates 1486 (fn(name, _, Value{locations, ...}) => 1487 errorNear (lex, true, v, declaredAt locations, 1488 name ^ " has already been bound in this declaration")); 1489 1490 (* This environment is those identifiers declared by recursive bindings *) 1491 val recEnv = searchList (); 1492 1493 (* If this is a recursive declaration we will have to find all 1494 the variables declared by the patterns in each binding before 1495 we can look at the bodies of the bindings. For simplicity we 1496 process the patterns first even if this is not recursive but 1497 arrange for the variables to be added to the environment 1498 after rather than before processing the bodies. The result of 1499 processing the patterns is a list of their types. Each item 1500 in the list must be unified with the type of the 1501 corresponding body. *) 1502 1503 (* Process the patterns. *) 1504 local 1505 fun doVal (ValBind {dec, isRecursive, variables, ...}) = 1506 let 1507 fun enterVals(pair as (_, value)) = 1508 ( 1509 #enter newEnv pair; 1510 if isRecursive then #enter recEnv pair else (); 1511 variables := value :: ! variables 1512 ) 1513 1514 val patType = 1515 processPattern(dec, enterVals, newLevel, false, mkValVar, isRecursive); 1516 in 1517 patType 1518 end; 1519 1520 in 1521 val decs = List.map doVal (valdecs) 1522 end 1523 1524 (* Now the bodies. *) 1525 local 1526 (* Check that the types match by going down the list of value 1527 bindings and the list of types produced from the patterns, 1528 and matching corresponding types. *) 1529 fun checkTypes (patType, (ValBind {dec, exp, line, isRecursive, ...})) = 1530 let 1531 val newEnv = 1532 { (* If this is recursive we find the recursive names 1533 and others in the surrounding scope. *) 1534 lookupVal = 1535 if isRecursive 1536 then lookupDefault (#lookup recEnv) (#lookupVal env) 1537 else #lookupVal env, 1538 lookupType = #lookupType env, 1539 lookupFix = #lookupFix env, 1540 lookupStruct = #lookupStruct env, 1541 lookupSig = #lookupSig env, 1542 lookupFunct = #lookupFunct env, 1543 (* Extend the environment of type variables. *) 1544 lookupTvars = 1545 lookupDefault (#lookup explicit) 1546 (lookupDefault (#lookup implicit) (#lookupTvars env)), 1547 enterVal = #enterVal env, 1548 enterType = #enterType env, 1549 enterFix = #enterFix env, 1550 enterStruct = #enterStruct env, 1551 enterSig = #enterSig env, 1552 enterFunct = #enterFunct env, 1553 allValNames = 1554 if isRecursive 1555 then fn () => (stringsOfSearchList recEnv () @ #allValNames env ()) 1556 else #allValNames env 1557 } 1558 1559 val expType = assignValues(newLevel, letDepth, newEnv, exp, exp); 1560 1561 val () = 1562 case unifyTypes(patType, expType) of 1563 NONE => () (* OK*) 1564 | SOME report => 1565 typeMismatch("Pattern and expression have incompatible types.", 1566 valTypeMessage (lex, typeEnv) ("Pattern:", dec, patType), 1567 valTypeMessage (lex, typeEnv) ("Expression:", exp, expType), 1568 unifyErrorReport (lex, typeEnv) report, lex, line, foundNear v) 1569 1570 (* true if the expression is a possibly-constrained fn-expression. 1571 It isn't clear whether a parenthesised expression is allowed here. 1572 As often, the definition is informal. On p8 of the ML97 1573 definition it says "exp must be of the form fn match". In ML90 1574 it added "possibly constrained by one or more type expressions". 1575 This is such a mess that I'm allowing both contraints and parentheses 1576 here. *) 1577 fun isConstrainedFn (Constraint {value, ...}) = isConstrainedFn value 1578 | isConstrainedFn (Fn _) = true 1579 | isConstrainedFn (Parenthesised(p, _)) = isConstrainedFn p 1580 | isConstrainedFn _ = false; 1581 in 1582 (* Must check that the expression is of the form FN match. *) 1583 (* N.B. the code generator assumes this is true. *) 1584 if isRecursive andalso not (isConstrainedFn exp) 1585 then errorNear (lex, true, v, line, 1586 "Recursive declaration is not of the form `fn match'") 1587 else () 1588 end 1589 in 1590 val () = ListPair.app checkTypes (decs, valdecs) 1591 end 1592 1593 (* Now allow generalisation on the variables being declared. 1594 For imperative type variables we have to know whether the 1595 expression is expansive. *) 1596 fun allowGen (d, (ValBind {exp, line, ...})) = 1597 ( 1598 allowGeneralisation 1599 (d, newLevel, nonExpansive exp, lex, line, foundNear v, typeEnv) 1600 ) (* allowGen *) 1601 in 1602 ListPair.appEq allowGen (decs, valdecs); 1603 (* And declare the new names into the surrounding environment. *) 1604 let 1605 fun enterDec(s, v as Value{instanceTypes, ...}) = 1606 ( 1607 valOf instanceTypes := []; (* Remove any recursive references. *) 1608 #enterVal env (s, v) 1609 ) 1610 in 1611 #apply newEnv enterDec 1612 end 1613 end (* assValDeclaration *) 1614 1615 and assFunDeclaration {dec=tlist: fvalbind list, explicit, implicit, ...} = 1616 (* Assigntypes for a fun-declaration. *) 1617 let 1618 val funLevel = level + 1; (* Level for function names. *) 1619 1620 (* Set the scope of explicit type variables. *) 1621 val () = 1622 #apply explicit(fn (_, tv) => setTvarLevel (tv, funLevel)); 1623 1624 (* For each implicit type variable associated with this value declaration, 1625 link it to any type variable with the same name in an outer 1626 scope. *) 1627 val () = 1628 #apply implicit 1629 (fn (name, tv) => 1630 case #lookupTvars env name of SOME v => linkTypeVars(v, tv) | NONE => setTvarLevel (tv, funLevel)); 1631 (* If it isn't there set the level of the type variable. *) 1632 1633 (* Construct a new environment for the variables. *) 1634 fun msgFn(name, _, Value{locations, ...}) = 1635 errorNear (lex, true, v, declaredAt locations, 1636 name ^ " has already been bound in this declaration"); 1637 1638 val newEnv = noDuplicates msgFn; 1639 1640 (* Since this is a recursive declaration we must get the function 1641 names first. Because of the way they are parsed they are hidden 1642 as applications of the function to one or more patterns. There 1643 may be more than one clause in a function binding but each 1644 should declare the same function and have the same number of 1645 patterns. We need to know the number of patterns and the 1646 function name in the third pass so we save them in the 1647 function binding. *) 1648 1649 local 1650 fun findNameAndPatts (FValBind {clauses = (FValClause {dec, line, ...}::_), numOfPatts, functVar, ...}) = 1651 let 1652 (* Just look at the first clause for the moment. *) 1653 val { ident = { name, location, ... }, ... } = dec; 1654 (* Declare a new identifier with this name. *) 1655 val locations = [DeclaredAt location, SequenceNo (newBindingId lex)] 1656 val funVar = 1657 mkValVar (name, mkTypeVar (funLevel, false, false, false), locations) 1658 1659 val arity = case dec of { args, ...} => List.length args 1660 val () = numOfPatts := arity; 1661 val () = 1662 (* Put the results onto the function binding. *) 1663 if arity = 0 1664 then errorNear (lex, true, v, line, 1665 "Clausal function does not have any parameters.") 1666 else () 1667 in 1668 (* Must not be qualified *) 1669 checkForDots (name, lex, line); 1670 (* Must not be "true", "false" etc. but may be "it" *) 1671 checkForBuiltIn (name, v, lex, line, false); 1672 functVar := funVar; (* Save the variable. *) 1673 (* Enter it in the environment. *) 1674 #enter newEnv (name, funVar) 1675 end 1676 | findNameAndPatts _ = raise InternalError "findNameAndPatts: badly-formed parse-tree"; 1677 1678 in 1679 val () = List.app findNameAndPatts tlist 1680 end; 1681 1682 local 1683 (* Can now process the clausal functions in the environment 1684 of the function names and using the information about 1685 function name and number of patterns we have saved. *) 1686 fun processBinding 1687 (fvalBind as FValBind {clauses, functVar=ref functVar, argType, resultType, location, ...}) = 1688 let 1689 (* Each fun binding in the declaration may consist of several 1690 clauses. Each must have the same function name, the same 1691 number of patterns and a unifiable type. *) 1692 (* The type information is built up from the bottom so that if there are 1693 errors we can report them in the most appropriate place. 1694 Build a type to be used for the function. This will later be unified 1695 with the type that we've already created for the function variable. *) 1696 val funType = mkTypeVar(generalisable, false, false, false) 1697 1698 fun processClause (clause as FValClause {dec, exp, line, ...}) = 1699 let 1700 val { ident = ident, args, constraint, ... } = dec 1701 1702 fun mkClausal(clauses, location) : fvalbind = 1703 FValBind 1704 { 1705 clauses = clauses, 1706 numOfPatts = ref 0, 1707 functVar = ref undefinedValue, 1708 argType = ref badType, 1709 resultType = ref badType, 1710 location = location 1711 } 1712 1713 fun mkFunDeclaration (dec, explicit, implicit, location) : parsetree = 1714 FunDeclaration 1715 { 1716 dec=dec, 1717 explicit = explicit, 1718 implicit = implicit, 1719 location = location 1720 } 1721 1722 val clauseAsTree: parsetree = 1723 (* This clause as a parsetree object for error messages. *) 1724 mkFunDeclaration([mkClausal([clause], line)], explicit, implicit, line) 1725 1726 val () = (* Set the type. Only in case we look at the export tree. *) 1727 #expType ident := valTypeOf functVar 1728 1729 fun messFn (name, _, Value{locations, ...}) = 1730 errorNear (lex, true, clauseAsTree, declaredAt locations, 1731 name ^ " has already been bound in this clause."); 1732 (* Construct a new environment for the variables in the patts. *) 1733 val varEnv = noDuplicates messFn; 1734 val varLevel = funLevel + 1; (* Level for variables. *) 1735 1736 (* Process the patterns. *) 1737 val argTypeList = 1738 List.map (fn arg => 1739 processPattern(arg, #enter varEnv, varLevel, false, mkPattVar, false)) 1740 args 1741 (* This list is used for the type of the helper function. *) 1742 val () = argType := 1743 (case argTypeList of 1744 [] => badType (* error *) 1745 | [single] => single 1746 | multiple => mkProductType multiple) 1747 1748 (* The identifiers declared in the pattern are available in the 1749 body of the function. Since it is recursive the function 1750 names are also available. *) 1751 val bodyEnv = 1752 { 1753 lookupVal = 1754 lookupDefault (#lookup varEnv) 1755 (lookupDefault (#lookup newEnv) (#lookupVal env)), 1756 lookupType = #lookupType env, 1757 lookupFix = #lookupFix env, 1758 lookupStruct = #lookupStruct env, 1759 lookupSig = #lookupSig env, 1760 lookupFunct = #lookupFunct env, 1761 (* Extend the environment of type variables. *) 1762 lookupTvars = 1763 lookupDefault (#lookup explicit) 1764 (lookupDefault (#lookup implicit) (#lookupTvars env)), 1765 enterVal = #enterVal env, 1766 enterType = #enterType env, 1767 enterFix = #enterFix env, 1768 enterStruct = #enterStruct env, 1769 enterSig = #enterSig env, 1770 enterFunct = #enterFunct env, 1771 allValNames = 1772 fn () => (stringsOfSearchList varEnv () @ 1773 stringsOfSearchList newEnv () @ #allValNames env ()) 1774 }; 1775 1776 (* Now the body. *) 1777 val expTyp = assignValues(varLevel, letDepth, bodyEnv, exp, exp); 1778 (* Check the expression type against any explicit type constraint. *) 1779 (* Return the explicit constraint if possible. For the purposes of 1780 type checking this is identical to "expTyp" but if there is a 1781 type abbreviation this will be used when printing the result. 1782 .e.g type t = int * int; fun f ((x, y):t): t = (y, x); *) 1783 val typeOfBody = 1784 case constraint of 1785 NONE => expTyp 1786 | SOME given => 1787 let 1788 val theType = ptAssignTypes(given, v) 1789 in 1790 case unifyTypes(expTyp, theType) of 1791 NONE => () (* OK. *) 1792 | SOME report => 1793 typeMismatch("Body of fun binding does not match type constraint.", 1794 valTypeMessage (lex, typeEnv) ("Expression:", exp, expTyp), 1795 PrettyBlock(0, false, [], 1796 [ 1797 PrettyString "Constraint:", 1798 PrettyBreak(1, 0), 1799 display(theType, 10000 (* All *), typeEnv) 1800 ]), 1801 unifyErrorReport (lex, typeEnv) report, 1802 lex, line, foundNear clauseAsTree); 1803 theType 1804 end 1805 (* Remember the result type for the debugger. Actually this 1806 assigns the result type for each clause in the fun but 1807 they'll all be the same. *) 1808 val () = resultType := typeOfBody 1809 (* The type of this clause is a function type. *) 1810 val clauseType = List.foldr mkFunctionType typeOfBody argTypeList 1811 (* Unify this with the type we're using for the other clauses. *) 1812 val () = 1813 case unifyTypes(clauseType, funType) of 1814 NONE => () (* OK. *) 1815 | SOME report => 1816 typeMismatch("Type of clause does not match the type of previous clauses.", 1817 valTypeMessage (lex, typeEnv) ("Clause:", clauseAsTree, clauseType), 1818 PrettyBlock(0, false, [], 1819 [ 1820 PrettyString "Other clauses:", 1821 PrettyBreak(1, 0), 1822 display(funType, 10000 (* All *), typeEnv) 1823 ]), 1824 unifyErrorReport (lex, typeEnv) report, 1825 lex, line, foundNear clauseAsTree) 1826 in (* body of processClause *) 1827 () 1828 end 1829 in (* body of processFun *) 1830 List.app processClause clauses; 1831 (* If this function makes any recursive references move those references from the 1832 local list to the recursive list. In that way if we're looking for whether a 1833 function is actually referenced we'll only include it if it's referenced outside 1834 or from another referenced function. *) 1835 let 1836 fun moveRefs(FValBind{functVar=ref(Value{references,...}), ...}) = 1837 let 1838 val {localRef as ref locals, recursiveRef, ...} = valOf references 1839 val callerName = valName functVar (* Name of referring function. *) 1840 in 1841 recursiveRef := List.map (fn r => (r, callerName)) locals @ !recursiveRef; 1842 localRef := [] 1843 end 1844 in 1845 List.app moveRefs tlist 1846 end; 1847 (* Finally unify the function type with the type of the function variable. If the 1848 variable has not yet been used that will simply set its type but if it has been 1849 used recursively it may have been given an incompatible type. *) 1850 case unifyTypes(funType, valTypeOf functVar) of 1851 NONE => () (* OK. *) 1852 | SOME report => 1853 let 1854 fun mkFunDeclaration (dec, explicit, implicit, location) : parsetree = 1855 FunDeclaration 1856 { 1857 dec=dec, 1858 explicit = explicit, 1859 implicit = implicit, 1860 location = location 1861 } 1862 1863 fun mkIdent (name, loc) : parsetree = 1864 Ident 1865 { 1866 name = name, 1867 expType = ref EmptyType, 1868 value = ref undefinedValue, 1869 location = loc, 1870 possible = ref(fn () => []) 1871 } 1872 1873 val fvalAsTree = mkFunDeclaration([fvalBind], explicit, implicit, location) 1874 in 1875 typeMismatch("Type of function does not match type of recursive application.", 1876 valTypeMessage (lex, typeEnv) ("Function:", fvalAsTree, funType), 1877 valTypeMessage (lex, typeEnv) 1878 ("Variable:", mkIdent(valName functVar, location), valTypeOf functVar), 1879 unifyErrorReport (lex, typeEnv) report, 1880 lex, location, foundNear fvalAsTree) 1881 end 1882 end 1883 in 1884 val () = List.app processBinding tlist 1885 end; 1886 1887 in 1888 (* Now declare the new names into the surrounding environment, 1889 releasing the copy flags on the type variables. All fun 1890 bindings are non-expansive. *) 1891 List.app 1892 (fn(FValBind{ 1893 functVar as ref(var as Value{typeOf, locations, name, instanceTypes, ...}), ...}) => 1894 ( 1895 (* Generalise the types. allowGeneralisation side-effects the type variables, 1896 replaces any that can be generalised by general variables. *) 1897 allowGeneralisation(typeOf, funLevel, true, lex, declaredAt locations, foundNear v, typeEnv); 1898 (* Remove any recursive references. This really isn't right. *) 1899 valOf instanceTypes := []; 1900 #enterVal env (name, var); 1901 functVar := var 1902 )) tlist 1903 end (* assFunDeclaration *) 1904 1905 and assAbsData({typelist=typeList, withtypes, declist, equalityStatus, isAbsType=isAbs, ...}) = 1906 let 1907 (* A type declaration causes a type to be entered in the type 1908 environment, together with some constructors. *) 1909 fun messFn (name, _, TypeConstrSet(new, _)) = 1910 errorNear (lex, true, v, declaredAt(tcLocations new), 1911 name ^ " has already been bound in this declaration"); 1912 1913 val localTypeEnv = noDuplicates messFn; 1914 1915 (* datatype and abstype declarations are both recursive so we can 1916 enter the type names into the environment during a first pass, 1917 and then process the value constructors during a second. *) 1918 fun enterType(typeConstr, typeName) = 1919 ( 1920 checkForDots (typeName, lex, declaredAt(tcLocations(tsConstr typeConstr))); (* Must not be qualified *) 1921 #enter localTypeEnv (typeName, typeConstr) (* Check for duplicates. *) 1922 ); 1923 1924 (* Make the type constructors and put them in a list. *) 1925 fun enterTcon (DatatypeBind {name, tcon, typeVars, nameLoc, ...}) = 1926 let 1927 (* Make a new ID. If this is within a let declaration we always make 1928 a free ID because it is purely local and can't be exported. *) 1929 val description = { location = nameLoc, name = name, description = "" } 1930 val arity = length typeVars 1931 1932 val newId = 1933 if letDepth = 0 1934 then makeTypeId(false, true, (typeVars, EmptyType), description) 1935 else makeFreeIdEqUpdate (arity, Local{addr = ref ~1, level = ref baseLevel}, false, description) 1936 val locations = [DeclaredAt nameLoc, SequenceNo (newBindingId lex)] 1937 val tc = makeTypeConstructor(name, typeVars, newId, locations) 1938 in 1939 tcon := TypeConstrSet(tc, []); 1940 enterType(TypeConstrSet(tc, []), name); 1941 tc 1942 end 1943 1944 val listOfTypes = map enterTcon typeList; 1945 1946 local 1947 fun lookup(s, line) = 1948 lookupTyp 1949 ({lookupType = lookupDefault(#lookup localTypeEnv) (#lookupType env), 1950 lookupStruct = #lookupStruct env}, 1951 s, giveError (v, lex, line)) 1952 in 1953 fun localAssignTypes decType = assignTypes (decType, lookup, lex) 1954 end 1955 1956 (* First match all the types on the right-hand sides using the 1957 datatypes and the existing bindings. *) 1958 local 1959 fun processType (TypeBind {decType = SOME decType, ...}) = localAssignTypes decType 1960 | processType _ = emptyType 1961 in 1962 val decTypes = List.map processType withtypes 1963 end; 1964 1965 (* Can now enter the `withtypes'. *) 1966 fun enterWithType (TypeBind {name, typeVars, nameLoc, tcon=tcRef, ...}, decType) = 1967 let 1968 val description = { location = nameLoc, name = name, description = "" } 1969 (* Construct a type constructor which is an alias of the 1970 right-hand side of the declaration. *) 1971 val locations = [DeclaredAt nameLoc, SequenceNo (newBindingId lex)] 1972 val tcon = 1973 makeTypeConstructor (name, typeVars, 1974 makeTypeId(false, false, (typeVars, decType), description), locations) 1975 val tset = TypeConstrSet(tcon, []) 1976 in 1977 tcRef := tset; 1978 enterType(tset, name); (* Checks for duplicates. *) 1979 #enterType env (name, tset) (* Put in the global environment. *) 1980 end 1981 1982 val () = ListPair.app enterWithType (withtypes, decTypes); 1983 1984 (* For the constructors *) 1985 fun messFn (name, _, Value{locations, ...}) = 1986 errorNear (lex, true, v, declaredAt locations, 1987 name ^ " has already been used as a constructor in this type"); 1988 1989 val consEnv = noDuplicates messFn; 1990 val abstypeEnv = searchList (); 1991 1992 (* Now process the types and generate the constructors. *) 1993 fun genValueConstrs (DatatypeBind {name, typeVars, constrs, nameLoc, tcon, ...}, typ) = 1994 let 1995 val numOfConstrs = length constrs; 1996 val typeVarsAsTypes = List.map TypeVar typeVars 1997 1998 (* The new constructor applied to the type variables (if any) *) 1999 val locations = [DeclaredAt nameLoc, SequenceNo (newBindingId lex)] 2000 val resultType = mkTypeConstruction (name, typ, typeVarsAsTypes, locations) 2001 2002 (* Sort the constructors by name. This simplifies matching with 2003 datatypes in signatures. *) 2004 fun leq {constrName=xname: string, ...} {constrName=yname, ...} = xname < yname; 2005 val sortedConstrs = quickSort leq constrs; 2006 2007 fun processConstr ({constrName=name, constrArg, idLocn, constrVal, ...}) = 2008 let 2009 val (constrType, isNullary) = 2010 case constrArg of 2011 NONE => (resultType, true) 2012 | SOME argtype => 2013 (mkFunctionType (localAssignTypes argtype, resultType), false) 2014 val locations = [DeclaredAt idLocn, SequenceNo (newBindingId lex)] 2015 val cons = 2016 makeValueConstr (name, constrType, isNullary, numOfConstrs, Local{addr = ref ~1, level = ref baseLevel}, 2017 locations) 2018 2019 (* Name must not be qualified *) 2020 val () = checkForDots (name, lex, idLocn); 2021 (* Must not be "true", "false" etc. *) 2022 val () = checkForBuiltIn (name, v, lex, idLocn, true) : unit; 2023 2024 (* Put into the environment. *) 2025 val () = #enter consEnv (name, cons) 2026 2027 (* Link it in case we export the tree. *) 2028 val () = constrVal := cons 2029 in 2030 cons 2031 end (* processConstr *) 2032 val tset = TypeConstrSet (typ, List.map processConstr sortedConstrs) 2033 in 2034 (* If this is an abstype enter the version with the constructors into 2035 a local environment and a version without the constructors into the 2036 global environment. If it is a datatype enter the version with 2037 constructors in the global environment. *) 2038 if isAbs 2039 then (#enter abstypeEnv (name, tset); #enterType env (name, TypeConstrSet(typ, []))) 2040 else #enterType env (name, tset); 2041 tcon := tset; 2042 tset 2043 end (* genValueConstrs *) 2044 2045 val listOfTypeSets = ListPair.map genValueConstrs (typeList, listOfTypes); 2046 2047 (* Third pass - Check to see if equality testing is allowed for 2048 these types. *) 2049 val () = computeDatatypeEqualities(listOfTypeSets, sigTypeIdMap); 2050 2051 (* If this is a datatype declaration the value constructors should be 2052 entered in the surrounding scope, otherwise (abstract type 2053 declaration) we evaluate the declarations in an environment 2054 containing the value constructors, but the value constructors 2055 themselves do not appear in the surrounding scope. *) 2056 val () = 2057 if not isAbs 2058 then #apply consEnv (#enterVal env) 2059 else 2060 let (* Abstract type *) 2061 (* The declarations have to be evaluated in an environment in 2062 which the constructors have been declared. When an identifier 2063 is looked up it may: 2064 (a) be one of these new declarations, or else 2065 (b) be a constructor from the type declarations, or else 2066 (c) be outside the abstract type declaration. 2067 New declarations are entered in the local environment so that 2068 they can be found under (a) and in the surrounding environment 2069 where they will be available after this declaration. *) 2070 val decEnv = 2071 let 2072 val localEnv = searchList (); 2073 fun enterValFn pair = (#enter localEnv pair; #enterVal env pair); 2074 val lookupValFn = 2075 lookupDefault (#lookup localEnv) 2076 (lookupDefault (#lookup consEnv) (#lookupVal env)) 2077 fun allValNames () = (stringsOfSearchList localEnv () @ stringsOfSearchList consEnv () @ #allValNames env ()) 2078 (* We also have to do something similar with types. This is really 2079 only for perverse cases where there is a datatype replication 2080 inside the abstype. *) 2081 fun enterTypeFn pair = (#enter abstypeEnv pair; #enterType env pair); 2082 val lookupTypeFn = 2083 lookupDefault (#lookup abstypeEnv) (#lookupType env) 2084 in 2085 { 2086 lookupVal = lookupValFn, 2087 lookupType = lookupTypeFn, 2088 lookupFix = #lookupFix env, 2089 lookupStruct = #lookupStruct env, 2090 lookupSig = #lookupSig env, 2091 lookupFunct = #lookupFunct env, 2092 lookupTvars = #lookupTvars env, 2093 enterVal = enterValFn, 2094 enterType = enterTypeFn, 2095 enterFix = #enterFix env, 2096 enterStruct = #enterStruct env, 2097 enterSig = #enterSig env, 2098 enterFunct = #enterFunct env, 2099 allValNames = allValNames 2100 } 2101 end; 2102 2103 in 2104 (* Process the declarations, discarding the result. *) 2105 assignSeq (decEnv, letDepth, declist, false); 2106 (* Turn off equality outside the with..end block. This is required by the 2107 "Abs" function defined in section 4.9 of the ML Definition. 2108 We need to record the equality status, though, because we need 2109 to reinstate this for code-generation. *) 2110 equalityStatus := List.map tcEquality listOfTypes; 2111 List.app(fn tc => tcSetEquality (tc, false)) listOfTypes; 2112 () 2113 end; 2114 in 2115 badType (* Does not return a type *) 2116 end (* assAbsData *) 2117 in 2118 assValues near v 2119 end (* assignValues *); 2120 2121 val Env gEnv = env 2122 2123 val env = 2124 { 2125 lookupVal = #lookupVal gEnv, 2126 lookupType = #lookupType gEnv, 2127 lookupFix = #lookupFix gEnv, 2128 lookupStruct = #lookupStruct gEnv, 2129 lookupSig = #lookupSig gEnv, 2130 lookupFunct = #lookupFunct gEnv, 2131 lookupTvars = fn _ => NONE, 2132 enterVal = #enterVal gEnv, 2133 enterType = #enterType gEnv, 2134 enterFix = #enterFix gEnv, 2135 enterStruct = #enterStruct gEnv, 2136 enterSig = #enterSig gEnv, 2137 enterFunct = #enterFunct gEnv, 2138 allValNames = #allValNames gEnv 2139 }; 2140 in 2141 assignValues(1, 0, env, v, v) 2142 end (* pass2 *); 2143 2144 (* Before code-generation perform an extra pass through the tree to remove 2145 unnecessary polymorphism. The type-checking computes a most general 2146 type for a value, typically a function, but it is frequently used in 2147 situations where a less general type would suffice. *) 2148 (* Note: if the less general type involves a local datatype this isn't 2149 done to avoid a possible bug with datatypes defined after the 2150 function. *) 2151 fun setLeastGeneralTypes(p: parsetree, _: lexan) = 2152 let 2153 (* Because of mutual recursion we need to process the set of variables 2154 produced by a fun-declaration or a val rec declaration as a group. 2155 We also process no-recursive val bindings here for simplicity. *) 2156 fun processVariableSet(variables: values list) = 2157 let 2158 (* Two polymorphic values that are involved in mutual recursion will have 2159 the same type variable in both values. When we produce the least 2160 general type we have to consider all the types that may be used for 2161 those variables. Unfortunately, because of flexible records we need 2162 to repeat the unification we did in the previous pass. *) 2163 local 2164 fun getTypeVarsAndInstance (Value{typeOf, instanceTypes, ...}, vars) = 2165 let 2166 val instances = ! (valOf instanceTypes) 2167 fun getPolyVars typ = 2168 let 2169 val (copied, tyVars) = generalise typeOf 2170 (* Unify the types. If there's an error we return a fresh set of the type 2171 variables which gives the most general type. 2172 There shouldn't be an error but there is one 2173 circumstance at least where we can get an error here. If we have a functor 2174 declaration followed by an application of the functor in the same "program" 2175 we can set an entry in instanceTypes of a Value used in the functor declaration 2176 to an instance in the functor application because the instanceTypes value is 2177 inherited into the functor signature if there's no explicit signature. 2178 We really need to handle this properly and not inherit the instanceTypes 2179 value in that case. Test116 shows this. *) 2180 in 2181 if isSome(unifyTypes(copied, typ)) 2182 then #2 (generalise typeOf) 2183 else tyVars (* Return the type vars instantiated to the instance types. *) 2184 end 2185 (* This returns a list, one entry for each instance, of a list of the 2186 type variables for that instance. *) 2187 val instanceVarLists = List.map getPolyVars instances 2188 (* Transpose that list so we get a list, one entry for each type variable, 2189 of all the instance types that are possible. *) 2190 fun transpose ([]::_) = [] 2191 | transpose (args as _::_) = (List.map hd args) :: transpose (List.map tl args) 2192 | transpose [] = [] 2193 val instanceVars = transpose instanceVarLists 2194 (* Get the original type variables. *) 2195 val originalVars = getPolyTypeVars(typeOf, fn _ => NONE) 2196 (* Look to see if we already have some of the original vars in the list. 2197 If we have we use the same ref for each var and merge the instance types. *) 2198 fun mergeVars(ovar, iTypes) = 2199 case List.find (fn (tv, _) => sameTv(tv, ovar)) vars of 2200 NONE => (ovar, ref iTypes) 2201 | SOME(matched as (_, otherRef)) => 2202 ( otherRef := iTypes @ ! otherRef; matched) 2203 val mergedList = ListPair.map mergeVars (originalVars, instanceVars) @ vars 2204 in 2205 mergedList 2206 end 2207 in 2208 (* Get a list of the original type variables each with a reference containing 2209 the shared list of instance types. *) 2210 val typeVarMap = List.foldl getTypeVarsAndInstance [] variables 2211 end 2212 local 2213 fun reduceTypes(tv, ref types) = 2214 (* Although tv is a type variable it could occur as the least general type. 2215 Unify takes care of that. *) 2216 if isSome(unifyTypes(TypeVar tv, leastGeneral(List.map #value types))) 2217 then raise InternalError "reduceTypes: Unable to set type vars" 2218 else () 2219 in 2220 val () = List.app reduceTypes typeVarMap 2221 end 2222 in 2223 () 2224 end 2225 2226 fun leastGenExp(ValDeclaration{dec, ...}) = 2227 ( 2228 (* Val declarations may be recursive or non-recursive. In the case of 2229 recursive declarations we need to handle these in the same way as 2230 fun-declarations. *) 2231 (* Gather all the variables and process them as a group. There can't be 2232 any dependencies between them except for mutual recursion. *) 2233 processVariableSet 2234 (List.foldl (fn (ValBind{variables=ref variables, ...}, vars) => variables @ vars) [] dec); 2235 List.app (fn ValBind{exp, ...} => leastGenExp exp) dec 2236 ) 2237 2238 | leastGenExp(FunDeclaration{dec, ...}) = 2239 ( 2240 (* First process the outer declarations. *) 2241 processVariableSet(List.map(fn FValBind{functVar=ref var, ...} => var) dec); 2242 (* Then process the inner declarations. Setting the outer type may have set the 2243 instance types within the bodies. *) 2244 let 2245 fun processClause(FValClause{exp, ...}) = leastGenExp exp 2246 fun processBind(FValBind{clauses, ...}) = List.app processClause clauses 2247 in 2248 List.app processBind dec 2249 end 2250 ) 2251 2252 | leastGenExp(Localdec{decs, body, ...}) = 2253 ( 2254 (* Process the body expressions in order but the declarations must be done in 2255 reverse order after the body. *) 2256 List.app (leastGenExp o #1) body; 2257 List.foldr (fn ((p, _), ()) => leastGenExp p) () decs 2258 ) 2259 2260 | leastGenExp(AbsDatatypeDeclaration { declist, ... }) = 2261 (* Declarations in reverse order *) 2262 List.foldr (fn ((p, _), ()) => leastGenExp p) () declist 2263 2264 (* All the rest of these just involve processing sub-expressions. *) 2265 | leastGenExp(Applic{f, arg, ...}) = (leastGenExp f; leastGenExp arg) 2266 2267 | leastGenExp(Cond{test, thenpt, elsept, ...}) = 2268 (leastGenExp test; leastGenExp thenpt; leastGenExp elsept) 2269 2270 | leastGenExp(TupleTree{fields, ...}) = List.app leastGenExp fields 2271 2272 | leastGenExp(Constraint{value, ...}) = leastGenExp value 2273 2274 | leastGenExp(Fn {matches, ...}) = List.app (fn MatchTree{exp, ...} => leastGenExp exp) matches 2275 2276 | leastGenExp(ExpSeq(ptl, _)) = List.app (leastGenExp o #1) ptl 2277 2278 | leastGenExp(HandleTree{exp, hrules, ...}) = 2279 (leastGenExp exp; List.app (fn MatchTree{exp, ...} => leastGenExp exp) hrules) 2280 2281 | leastGenExp(While{test, body, ...}) = (leastGenExp test; leastGenExp body) 2282 2283 | leastGenExp(Case{test, match, ...}) = 2284 (leastGenExp test; List.app (fn MatchTree{exp, ...} => leastGenExp exp) match) 2285 2286 | leastGenExp(Andalso {first, second, ...}) = (leastGenExp first; leastGenExp second) 2287 2288 | leastGenExp(Orelse{first, second, ...}) = (leastGenExp first; leastGenExp second) 2289 2290 | leastGenExp(Labelled{recList, ...}) = List.app (leastGenExp o #valOrPat) recList 2291 2292 | leastGenExp(List{elements, ...}) = List.app leastGenExp elements 2293 2294 | leastGenExp(Parenthesised(p, _)) = leastGenExp p 2295 2296 | leastGenExp _ = () 2297 2298 in 2299 leastGenExp p 2300 end 2301 2302 (* Types that can be shared. *) 2303 structure Sharing = 2304 struct 2305 type lexan = lexan 2306 and pretty = pretty 2307 and codetree = codetree 2308 and codeBinding = codeBinding 2309 and types = types 2310 and values = values 2311 and typeId = typeId 2312 and structVals = structVals 2313 and typeConstrs= typeConstrs 2314 and typeVarForm=typeVarForm 2315 and env = env 2316 and fixStatus = fixStatus 2317 and structureIdentForm = structureIdentForm 2318 and typeParsetree = typeParsetree 2319 and parsetree = parsetree 2320 and valbind = valbind 2321 and fvalbind = fvalbind 2322 and fvalclause = fvalclause 2323 and typebind = typebind 2324 and datatypebind=datatypebind 2325 and exbind = exbind 2326 and labelRecEntry=labelRecEntry 2327 and ptProperties = ptProperties 2328 and matchtree = matchtree 2329 and typeVarMap = typeVarMap 2330 and level = level 2331 end 2332 2333end (* PARSETREE *); 2334