diff options
author | Martin Odersky <odersky@gmail.com> | 2012-12-25 14:05:35 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2012-12-25 14:05:35 +0100 |
commit | a6a4be703a516d4f970b5c8c131083cd981f20c4 (patch) | |
tree | 1c9ee00e51749e56c097eb11a7ce7d44a31398db /src/dotty/tools/dotc/core/Substituters.scala | |
parent | f1550a1a132a7a97d461afce1ea79453d78be5ea (diff) | |
download | dotty-a6a4be703a516d4f970b5c8c131083cd981f20c4.tar.gz dotty-a6a4be703a516d4f970b5c8c131083cd981f20c4.tar.bz2 dotty-a6a4be703a516d4f970b5c8c131083cd981f20c4.zip |
Added Substitution operations
Diffstat (limited to 'src/dotty/tools/dotc/core/Substituters.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/Substituters.scala | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/Substituters.scala b/src/dotty/tools/dotc/core/Substituters.scala new file mode 100644 index 000000000..55e3591a3 --- /dev/null +++ b/src/dotty/tools/dotc/core/Substituters.scala @@ -0,0 +1,153 @@ +package dotty.tools.dotc.core + +import Types._, Symbols._, Contexts._ + +object Substituters { + + class SubstOps(val tp: Type) extends AnyVal { + + def subst(from: PolyType, to: PolyType, map: SubstPolyMap = null)(implicit ctx: Context): Type = + tp match { + case tp @ PolyParam(pt, n) => + if (pt eq from) PolyParam(to, n) else tp + case tp: NamedType => + if (tp.symbol.isStatic) tp + else tp.derivedNamedType(tp.prefix.subst(from, to, map), tp.name) + case ThisType(_) + | MethodParam(_, _) + | NoPrefix => tp + case _ => + val substMap = if (map != null) map else new SubstPolyMap(from, to) + tp match { + case tp: AppliedType => + tp.derivedAppliedType( + substMap(tp.tycon), tp.typeArgs mapConserve substMap) + case _ => + substMap mapOver tp + } + } + + def subst(from: MethodType, to: MethodType, map: SubstMethodMap)(implicit ctx: Context): Type = + tp match { + case tp @ MethodParam(mt, n) => + if (mt eq from) MethodParam(to, n) else tp + case tp: NamedType => + if (tp.symbol.isStatic) tp + else tp.derivedNamedType(tp.prefix.subst(from, to, map), tp.name) + case ThisType(_) + | PolyParam(_, _) + | NoPrefix => tp + case _ => + val substMap = if (map != null) map else new SubstMethodMap(from, to) + tp match { + case tp: AppliedType => + tp.derivedAppliedType( + substMap(tp.tycon), tp.typeArgs mapConserve substMap) + case _ => + substMap mapOver tp + } + } + + def subst1(from: Symbol, to: Type, map: Subst1Map)(implicit ctx: Context): Type = { + tp match { + case tp: NamedType => + val sym = tp.symbol + if (tp.prefix eq NoPrefix) { + if (sym eq from) return to + } + if (sym.isStatic) tp + else tp.derivedNamedType(tp.prefix.subst1(from, to, map), tp.name) + case ThisType(_) + | MethodParam(_, _) + | PolyParam(_, _) + | NoPrefix => tp + case _ => + val substMap = if (map != null) map else new Subst1Map(from, to) + tp match { + case tp: AppliedType => + tp.derivedAppliedType( + substMap(tp.tycon), tp.typeArgs mapConserve substMap) + case _ => + substMap mapOver tp + } + } + } + + def subst2(from1: Symbol, to1: Type, from2: Symbol, to2: Type, map: Subst2Map)(implicit ctx: Context): Type = { + tp match { + case tp: NamedType => + val sym = tp.symbol + if (tp.prefix eq NoPrefix) { + if (sym eq from1) return to1 + if (sym eq from2) return to2 + } + if (sym.isStatic) tp + else tp.derivedNamedType(tp.prefix.subst2(from1, to1, from2, to2, map), tp.name) + case ThisType(_) + | MethodParam(_, _) + | PolyParam(_, _) + | NoPrefix => tp + case _ => + val substMap = if (map != null) map else new Subst2Map(from1, to1, from2, to2) + tp match { + case tp: AppliedType => + tp.derivedAppliedType( + substMap(tp.tycon), tp.typeArgs mapConserve substMap) + case _ => + substMap mapOver tp + } + } + } + + def subst(from: List[Symbol], to: List[Type], map: SubstMap)(implicit ctx: Context): Type = { + tp match { + case tp: NamedType => + val sym = tp.symbol + if (tp.prefix eq NoPrefix) { + var fs = from + var ts = to + while (fs.nonEmpty) { + if (fs.head eq sym) return ts.head + fs = fs.tail + ts = ts.tail + } + } + if (sym.isStatic) tp + else tp.derivedNamedType(tp.prefix.subst(from, to, map), tp.name) + case ThisType(_) + | MethodParam(_, _) + | PolyParam(_, _) + | NoPrefix => tp + case _ => + val substMap = if (map != null) map else new SubstMap(from, to) + tp match { + case tp: AppliedType => + tp.derivedAppliedType( + substMap(tp.tycon), tp.typeArgs mapConserve substMap) + case _ => + substMap mapOver tp + } + } + } + } + + class SubstPolyMap(from: PolyType, to: PolyType)(implicit ctx: Context) extends TypeMap { + def apply(tp: Type) = tp.subst(from, to, this) + } + + class SubstMethodMap(from: MethodType, to: MethodType)(implicit ctx: Context) extends TypeMap { + def apply(tp: Type) = tp.subst(from, to, this) + } + + class Subst1Map(from: Symbol, to: Type)(implicit ctx: Context) extends TypeMap { + def apply(tp: Type) = tp.subst1(from, to, this) + } + + class Subst2Map(from1: Symbol, to1: Type, from2: Symbol, to2: Type)(implicit ctx: Context) extends TypeMap { + def apply(tp: Type) = tp.subst2(from1, to1, from2, to2, this) + } + + class SubstMap(from: List[Symbol], to: List[Type])(implicit ctx: Context) extends TypeMap { + def apply(tp: Type): Type = tp.subst(from, to, this) + } +}
\ No newline at end of file |