File:  [Research Unix] / researchv10no / cmd / sml / src / typing / overload.sml
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:34 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Norman

(* Copyright 1989 by AT&T Bell Laboratories *)
(* overload.sml *)

structure Overload : OVERLOAD = struct

structure Basics = Basics

local open Basics TypesUtil PrintUtil ErrorMsg BasicTypes
   PrintType
 in

type subst = (tyvar * tvkind) list

exception SoftUnify

fun copyScheme (tyfun as TYFUN{arity,...}) : ty * ty =
    let val tvs = typeArgs arity
     in (applyTyfun(tyfun,tvs),
	 if arity>1 then tupleTy tvs else hd tvs)
    end

fun rollBack subst =
    let fun loop (nil,trace) = trace
	  | loop (((tv as ref kind),oldkind)::subst,trace) =
	       (tv := oldkind;
		loop(subst,(tv,kind)::trace))
     in loop(subst,nil)
    end

fun redoSubst nil = ()
  | redoSubst ((tv,INSTANTIATED ty)::rest) =
      (instantiate(tv, ty); redoSubst rest)
  | redoSubst (_) = impossible "Overload--redoSubst"

fun softUnify(ty1: ty, ty2: ty): subst =
    let val subst: subst ref = ref nil
	fun softInst(tv as ref kind: tyvar, ty: ty) : unit =
	    let fun scan(ty: ty) : unit =  (* simple occurrence check *)
		   case ty
		     of VARty(tv') => 
		          if eqTyvar(tv, tv') then raise SoftUnify else ()
		      | CONty(_, args) => app scan args
		      | FLEXRECORDty(ref(OPEN fields)) =>
		          app (fn (_,ty') => scan ty') fields
		      | ty => ()  (* propagate error *)
	     in case kind
		  of META _ => ()
		   | _ => raise SoftUnify;
 	        scan ty;
		subst := (tv, kind)::(!subst);
		tv := INSTANTIATED ty
	    end
	
	fun unify(ty1: ty, ty2: ty): unit =
	    let val ty1 = prune ty1
		and ty2 = prune ty2
	     in case (ty1,ty2)
		  of (VARty(tv1),VARty(tv2)) =>
		       if eqTyvar(tv1,tv2) then () else softInst(tv1,ty2)
		   | (VARty(tv1),_) => softInst(tv1,ty2)
		   | (_,VARty(tv2)) => softInst(tv2,ty1)
		   | (CONty(ref tycon1, args1), CONty(ref tycon2, args2)) =>
		       if eqTycon(tycon1, tycon2)
		       then unifyLists(args1, args2)
		       else (unify(reduceType ty1, ty2)
			     handle ReduceType => 
			       unify(ty1, reduceType ty2)
			       handle ReduceType => raise SoftUnify)
		   | (ERRORty, _) => ()  (* propagate error *)
		   | (_, ERRORty) => ()  (* propagate error *)
		   | _ => raise SoftUnify
	    end
	
	and unifyLists([],[]) = ()
	  | unifyLists(ty1::rest1, ty2::rest2) = 
	      (unify(ty1,ty2); unifyLists(rest1,rest2))
	  | unifyLists(_) = raise SoftUnify

     in unify(ty1,ty2)
	  handle SoftUnify => (rollBack(!subst); raise SoftUnify);
	!subst
    end


exception Overld

datatype stack
  = EMPTY
  | PUSH of var ref * ty * stack
  | MARK of stack

val overloaded = ref EMPTY  (* stack of currently unresolved overloaded vars *)

fun resetOverloaded () = overloaded := EMPTY

fun markOverloaded () = overloaded := MARK(!overloaded)

fun pushOverloaded (refvar as ref(OVLDvar{options,scheme,...}) : var ref) = 
	   let val (scheme',ty) = copyScheme(scheme)
	    in overloaded := PUSH(refvar,ty,!overloaded);
	       scheme'
	   end
  | pushOverloaded _ = impossible "overload.1"

fun resolveOVLDvar(rv as ref(OVLDvar{name,options,...}),context) =
   (let fun findFirst({indicator, variant}::rest) =
	    ((softUnify(applyPoly(indicator,0,infinity), context), variant, rest)
	      handle SoftUnify => findFirst(rest))
	  | findFirst(nil) = 
	      (complain("overloaded variable \"" ^ Symbol.name(name) ^
	                "\" not defined at type:");
	       print "   ";
	       resetPrintType(); printType(context); newline();
	       raise Overld)
	fun findSecond({indicator, variant}::rest) =
	    ((rollBack(softUnify(applyPoly(indicator,0,infinity), context));
	      complain("overloaded variable \"" ^ Symbol.name(name) ^
			"\" cannot be resolved");
	      raise Overld)
	     handle SoftUnify => findSecond(rest))
	  | findSecond(nil) = ()
        val (subst,var,restOptions) = findFirst(!options)
	val subst = rollBack subst
     in findSecond(restOptions);
	redoSubst subst;
	rv := var
    end handle Overld => ())
  | resolveOVLDvar _ = impossible "overload.2"

fun resolveOverloaded () =
    let fun loop EMPTY = ()
	  | loop(MARK(s)) = (overloaded := s)
	  | loop(PUSH(refvar,context,s)) = 
	      (resolveOVLDvar(refvar,context); loop(s))
     in loop(!overloaded)
    end

end (* local *)

end (* structure Overload *)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.