(* types.rml *)
module Types:
  type Level		= int
  type TyName		= string
  type AlphaTag		= int
  type AlphaEq		= bool
  type AlphaOvld	= TyName list option
  datatype Type		= VAR of Alpha
			| CONS of Type list * TyName
  and Alpha		= ALPHA of AlphaTag * Level * AlphaEq * AlphaOvld * Type lvar
  relation mkAlpha	: (Level, bool, TyName list option) => Alpha
  relation mkFreeAlpha	: Level => Alpha
  relation mkEqAlpha	: Level => Alpha
  relation mkOvldAlpha	: (TyName list, Level) => Alpha
  relation alpha_ovld	: Alpha => TyName list option
  relation deref	: Type => Type
end

relation mkAlpha =
  rule	tick => tag & lvar_new => subst
	----------------
	mkAlpha(lev, eq, ovld) => ALPHA(tag,lev,eq,ovld,subst)
end

relation mkFreeAlpha =
  rule	mkAlpha(lev, false, NONE) => alpha
	----------------
	mkFreeAlpha lev => alpha
end

relation mkEqAlpha =
  rule	mkAlpha(lev, true, NONE) => alpha
	----------------
	mkEqAlpha lev => alpha
end

relation mkOvldAlpha =
  rule	mkAlpha(lev, false, SOME ovld) => alpha
	----------------
	mkOvldAlpha(ovld, lev) => alpha
end

relation alpha_ovld =
  axiom	alpha_ovld(ALPHA(_,_,_,ovld,_)) => ovld
end

relation deref =
  rule	lvar_get subst => NONE
	----------------
	deref(ty as VAR(ALPHA(_,_,_,_,subst))) => ty

  rule	lvar_get subst => SOME ty' & deref ty' => ty
	----------------
	deref(VAR(ALPHA(_,_,_,_,subst))) => ty

  axiom deref(ty as CONS(_,_)) => ty
end
