diff --git a/src/main/resources/manuals/types b/src/main/resources/manuals/types index e5194d4da1..86fb735b31 100644 --- a/src/main/resources/manuals/types +++ b/src/main/resources/manuals/types @@ -736,7 +736,7 @@ type SharedArrayBuffer extends Object { // https://tc39.es/ecma262/#sec-properties-of-dataview-instances type DataView extends OrdinaryObject { - DataView: Bot; + DataView: Undefined; ViewedArrayBuffer: ESValue; ByteLength: NonNegInt | Enum[~auto~]; ByteOffset: NonNegInt; diff --git a/src/main/scala/esmeta/analyzer/TypeAnalyzer.scala b/src/main/scala/esmeta/analyzer/TypeAnalyzer.scala index 279a1a4468..dba72336e4 100644 --- a/src/main/scala/esmeta/analyzer/TypeAnalyzer.scala +++ b/src/main/scala/esmeta/analyzer/TypeAnalyzer.scala @@ -7,7 +7,6 @@ import esmeta.es.* import esmeta.ir.{Func => IRFunc, *} import esmeta.ty.* import esmeta.ty.util.{Stringifier => TyStringifier} -import esmeta.ty.FieldMap.{Elem => FMElem} import esmeta.util.* import esmeta.util.Appender.* import esmeta.state.* @@ -601,7 +600,7 @@ class TypeAnalyzer( rv <- transfer(expr) lty = lv.ty rty = rv.ty - relem = FMElem(rty) + relem = Binding(rty) elem = if (positive) relem else lty.record(field) -- relem refinedTy = ValueTy( ast = lty.ast, @@ -622,7 +621,7 @@ class TypeAnalyzer( record = ty.record refinedTy = ValueTy( ast = ty.ast, - record = if (positive) record.update(field, FMElem.Exist) else record, + record = if (positive) record.update(field, Binding.Exist) else record, ) _ <- modify(_.update(l, AbsValue(refinedTy))) } yield () diff --git a/src/main/scala/esmeta/ty/Binding.scala b/src/main/scala/esmeta/ty/Binding.scala new file mode 100644 index 0000000000..b16734cd07 --- /dev/null +++ b/src/main/scala/esmeta/ty/Binding.scala @@ -0,0 +1,79 @@ +package esmeta.ty + +import esmeta.state.* +import esmeta.ty.util.Parser +import esmeta.util.* + +/** field binding types */ +case class Binding( + value: ValueTy, + uninit: Boolean = false, + absent: Boolean = false, +) extends TyElem + with Lattice[Binding] { + + /** top check */ + def isTop: Boolean = value.isTop && uninit.isTop && absent.isTop + + /** bottom check */ + def isBottom: Boolean = value.isBottom && uninit.isBottom && absent.isBottom + + /** Absent check */ + def isAbsent: Boolean = value.isBottom && !uninit && absent + + /** partial order/subset operator */ + def <=(that: => Binding): Boolean = (this eq that) || { + this.value <= that.value && + this.uninit <= that.uninit && + this.absent <= that.absent + } + + /** union type */ + def ||(that: => Binding): Binding = + if (this eq that) this + else + Binding( + this.value || that.value, + this.uninit || that.uninit, + this.absent || that.absent, + ) + + /** intersection type */ + def &&(that: => Binding): Binding = + if (this eq that) this + else + Binding( + this.value && that.value, + this.uninit && that.uninit, + this.absent && that.absent, + ) + + /** prune type */ + def --(that: => Binding): Binding = + if (that.isBottom) this + else + Binding( + this.value -- that.value, + this.uninit -- that.uninit, + this.absent -- that.absent, + ) + + /** existence check */ + def exists: Set[Boolean] = + (if (!value.isBottom || uninit) Set(true) else Set()) ++ + (if (absent) Set(false) else Set()) + + /** containment check */ + def contains(v: Option[Value | Uninit], heap: Heap): Boolean = v match + case Some(value: Value) => this.value.contains(value, heap) + case Some(Uninit) => this.uninit + case None => this.absent +} +object Binding extends Parser.From(Parser.binding) { + lazy val Top: Binding = Binding(AnyT, true, true) + lazy val Exist: Binding = Binding(AnyT, true, false) + lazy val Init: Binding = Binding(AnyT, false, false) + lazy val Uninit: Binding = Binding(BotT, true, false) + lazy val Absent: Binding = Binding(BotT, false, true) + lazy val Bot: Binding = Binding(BotT, false, false) +} diff --git a/src/main/scala/esmeta/ty/FieldMap.scala b/src/main/scala/esmeta/ty/FieldMap.scala index 093beb1c85..70a2983f46 100644 --- a/src/main/scala/esmeta/ty/FieldMap.scala +++ b/src/main/scala/esmeta/ty/FieldMap.scala @@ -4,8 +4,8 @@ import esmeta.state.* import esmeta.ty.util.Parser import esmeta.util.* -/** field type map */ -case class FieldMap(map: Map[String, FieldMap.Elem]) +/** field refinement map */ +case class FieldMap(map: Map[String, Binding]) extends TyElem with Lattice[FieldMap] { @@ -30,9 +30,9 @@ case class FieldMap(map: Map[String, FieldMap.Elem]) FieldMap( (for { field <- (this.fields ++ that.fields) - elem = this(field) || that(field) - if !elem.isTop - } yield field -> elem).toMap, + binding = this(field) || that(field) + if !binding.isTop + } yield field -> binding).toMap, ) /** intersection type */ @@ -44,20 +44,20 @@ case class FieldMap(map: Map[String, FieldMap.Elem]) FieldMap( (for { field <- (this.fields ++ that.fields) - elem = this(field) && that(field) - if !elem.isTop - } yield field -> elem).toMap, + binding = this(field) && that(field) + if !binding.isTop + } yield field -> binding).toMap, ) /** TODO prune type */ def --(that: => FieldMap): FieldMap = this /** field accessor */ - def apply(field: String): Elem = map.getOrElse(field, Elem.Top) + def apply(field: String): Binding = map.getOrElse(field, Binding.Top) /** field update */ - def update(field: String, elem: Elem): FieldMap = - FieldMap(map + (field -> elem)) + def update(field: String, binding: Binding): FieldMap = + FieldMap(map + (field -> binding)) /** fields */ def fields: Set[String] = map.keySet @@ -70,80 +70,5 @@ case class FieldMap(map: Map[String, FieldMap.Elem]) object FieldMap extends Parser.From(Parser.fieldMap) { lazy val Top: FieldMap = FieldMap() - - def apply(fields: (String, Elem)*): FieldMap = FieldMap(fields.toMap) - - /** optinoal value types */ - case class Elem( - value: ValueTy, - uninit: Boolean = false, - absent: Boolean = false, - ) extends TyElem - with Lattice[Elem] { - - /** top check */ - def isTop: Boolean = value.isTop && uninit.isTop && absent.isTop - - /** bottom check */ - def isBottom: Boolean = value.isBottom && uninit.isBottom && absent.isBottom - - /** Absent check */ - def isAbsent: Boolean = value.isBottom && !uninit && absent - - /** partial order/subset operator */ - def <=(that: => Elem): Boolean = (this eq that) || { - this.value <= that.value && - this.uninit <= that.uninit && - this.absent <= that.absent - } - - /** union type */ - def ||(that: => Elem): Elem = - if (this eq that) this - else - Elem( - this.value || that.value, - this.uninit || that.uninit, - this.absent || that.absent, - ) - - /** intersection type */ - def &&(that: => Elem): Elem = - if (this eq that) this - else - Elem( - this.value && that.value, - this.uninit && that.uninit, - this.absent && that.absent, - ) - - /** prune type */ - def --(that: => Elem): Elem = - if (that.isBottom) this - else - Elem( - this.value -- that.value, - this.uninit -- that.uninit, - this.absent -- that.absent, - ) - - /** existence check */ - def exists: Set[Boolean] = - (if (!value.isBottom || uninit) Set(true) else Set()) ++ - (if (absent) Set(false) else Set()) - - /** containment check */ - def contains(v: Option[Value | Uninit], heap: Heap): Boolean = v match - case Some(value: Value) => this.value.contains(value, heap) - case Some(Uninit) => this.uninit - case None => this.absent - } - object Elem extends Parser.From(Parser.fieldMapElem) { - lazy val Top: Elem = Elem(AnyT, true, true) - lazy val Exist: Elem = Elem(AnyT, true, false) - lazy val Init: Elem = Elem(AnyT, false, false) - lazy val Uninit: Elem = Elem(BotT, true, false) - lazy val Absent: Elem = Elem(BotT, false, true) - lazy val Bot: Elem = Elem(BotT, false, false) - } + def apply(fields: (String, Binding)*): FieldMap = FieldMap(fields.toMap) } diff --git a/src/main/scala/esmeta/ty/RecordTy.scala b/src/main/scala/esmeta/ty/RecordTy.scala index 9921c1def5..44aaa3e327 100644 --- a/src/main/scala/esmeta/ty/RecordTy.scala +++ b/src/main/scala/esmeta/ty/RecordTy.scala @@ -3,7 +3,6 @@ package esmeta.ty import esmeta.util.* import esmeta.state.{Value, RecordObj, Heap} import esmeta.ty.util.Parser -import FieldMap.{Elem => FMElem} /** record types */ enum RecordTy extends TyElem with Lattice[RecordTy] { @@ -53,17 +52,14 @@ enum RecordTy extends TyElem with Lattice[RecordTy] { val rs = rmap.keySet Elem( (for { - t <- - ls.filter(isSubTy(_, rs)) ++ - rs.filter(isSubTy(_, ls)) - fm = - lmap.getOrElse(t, FieldMap.Top) && - rmap.getOrElse(t, FieldMap.Top) + t <- ls.filter(isSubTy(_, rs)) ++ rs.filter(isSubTy(_, ls)) + lfm = lmap.getOrElse(t, FieldMap.Top) + rfm = rmap.getOrElse(t, FieldMap.Top) + fm = lfm && rfm pair <- update(t, fm) } yield pair) .groupBy(_._1) - .view - .mapValues(_.map(_._2).reduce(_ || _)) + .map { case (t, pairs) => t -> pairs.map(_._2).reduce(_ && _) } .toMap, ) @@ -84,14 +80,9 @@ enum RecordTy extends TyElem with Lattice[RecordTy] { case Elem(map) => StrT((for { (name, fm) <- map.toList - f <- fm.map.keySet ++ fieldMapOf(name).map.keySet + f <- fm.map.keySet ++ fieldsOf(name).keySet } yield f).toSet) - /** field type map */ - def fieldMap: Option[FieldMap] = this match - case Top => Some(FieldMap.Top) - case Elem(map) => map.map(fieldMapOf(_) && _).reduceOption(_ || _) - /** base type names */ def bases: BSet[String] = this match case Top => Inf @@ -103,22 +94,22 @@ enum RecordTy extends TyElem with Lattice[RecordTy] { case Elem(map) => Fin(map.keySet) /** field accessor */ - def apply(f: String): FMElem = this match - case Top => FMElem.Top + def apply(f: String): Binding = this match + case Top => Binding.Top case Elem(map) => - map.map(getField(_, f) && _(f)).foldLeft(FMElem.Bot)(_ || _) + map.map(getField(_, f) && _(f)).foldLeft(Binding.Bot)(_ || _) /** field accessor for specific record type */ - def apply(name: String, f: String): FMElem = this match - case Top => FMElem.Top + def apply(name: String, f: String): Binding = this match + case Top => Binding.Top case Elem(map) => - map.get(name).fold(FMElem.Bot)(getField(name, f) && _(f)) + map.get(name).fold(Binding.Bot)(getField(name, f) && _(f)) /** field update */ - def update(field: String, ty: ValueTy): RecordTy = update(field, FMElem(ty)) + def update(field: String, ty: ValueTy): RecordTy = update(field, Binding(ty)) /** field update */ - def update(field: String, elem: FMElem): RecordTy = this match + def update(field: String, elem: Binding): RecordTy = this match case Top => Top case Elem(map) => Elem(map.foldLeft(Map[String, FieldMap]()) { @@ -139,15 +130,15 @@ enum RecordTy extends TyElem with Lattice[RecordTy] { private def update( pair: (String, FieldMap), field: String, - elem: FMElem, + elem: Binding, ): Option[(String, FieldMap)] = val (t, fm) = pair val x = (for { map <- refinerOf(t).get(field) (_, u) <- map.find { case (e, _) => elem <= e } } yield u).getOrElse(t) - val xfm = fieldMapOf(x) - if (!xfm.map.contains(field) || (elem && xfm(field)).isBottom) None + val xfm = fieldsOf(x) + if (!xfm.contains(field) || (elem && xfm(field)).isBottom) None else Some(normalize(x -> fm.update(field, elem))) /** record containment check */ @@ -172,11 +163,7 @@ enum RecordTy extends TyElem with Lattice[RecordTy] { /** normalized type */ private def normalize(pair: (String, FieldMap)): (String, FieldMap) = val (t, fm) = pair - t -> FieldMap(fm.map.filter { (f, elem) => isValidField(t, f, elem) }) - - /** normalized type */ - private def isValidField(t: String, field: String, elem: FMElem): Boolean = - !(getField(t, field) <= elem) + t -> FieldMap(fm.map.filter { (f, elem) => !(getField(t, f) <= elem) }) } object RecordTy extends Parser.From(Parser.recordTy) { @@ -193,7 +180,7 @@ object RecordTy extends Parser.From(Parser.recordTy) { name -> FieldMap( (for { (field, ty) <- fields - elem = FMElem(ty, false, false) + elem = Binding(ty, false, false) } yield field -> elem).toMap, ), ), diff --git a/src/main/scala/esmeta/ty/TyModel.scala b/src/main/scala/esmeta/ty/TyModel.scala index 69171ff0bb..078f00335b 100644 --- a/src/main/scala/esmeta/ty/TyModel.scala +++ b/src/main/scala/esmeta/ty/TyModel.scala @@ -8,7 +8,6 @@ import esmeta.util.BaseUtils.* case class TyModel(decls: List[TyDecl] = Nil) extends TyElem { import TyDecl.Elem.* - import FieldMap.{Elem => FMElem} /** type declaration map */ lazy val declMap: Map[String, TyDecl] = (for { @@ -18,9 +17,9 @@ case class TyModel(decls: List[TyDecl] = Nil) extends TyElem { /** get method map */ lazy val methodOf: String => Map[String, String] = cached { tname => for { - (f, elem) <- upperFieldsOf(tname) - ty = elem.value - if ty <= CloT && !elem.absent + (f, binding) <- upperFieldsOf(tname) + ty = binding.value + if ty <= CloT && !binding.absent method <- ty.clo.getSingle match case One(method) => Some(method) case _ => None @@ -28,7 +27,7 @@ case class TyModel(decls: List[TyDecl] = Nil) extends TyElem { } /** refiner map */ - type Refiner = Map[String, Vector[(FMElem, String)]] + type Refiner = Map[String, Vector[(Binding, String)]] /** get refiner map */ lazy val refinerOf: String => Refiner = cached { tname => @@ -37,7 +36,7 @@ case class TyModel(decls: List[TyDecl] = Nil) extends TyElem { .map(x => x -> refinerOf(x)) .foldLeft[Refiner](Map()) { case (lref, (rt, rref)) => - lref ++ (fieldsOf(rt).map((f, e) => f -> Vector(e -> rt)) ++ rref) + lref ++ (ownFieldsOf(rt).map((f, e) => f -> Vector(e -> rt)) ++ rref) .map { (f, rm) => f -> lref.get(f).fold(rm) { lm => lm.filter((l, _) => rm.forall((r, _) => (l && r).isBottom)) ++ @@ -49,35 +48,8 @@ case class TyModel(decls: List[TyDecl] = Nil) extends TyElem { } /** get field type */ - def getField(tname: String, f: String): FMElem = fieldMapOf(tname)(f) - - /** get all field type map */ - lazy val fieldMapOf: String => FieldMap = cached { t => - FieldMap( - declMap.get(t).fold(Map()) { decl => - decl.parent.fold(lowerFieldsOf(t)) { (parent, extended) => - if (extended) upperFieldsOf(parent) ++ lowerFieldsOf(t) - else - fieldsOf(t).foldLeft(fieldMapOf(parent).map) { - case (map, (f, e)) => map + (f -> (map.get(f).fold(e)(_ && e))) - } - } - }, - ) - } - - /** get direct field types */ - lazy val fieldsOf: String => Map[String, FMElem] = cached { tname => - declMap - .get(tname) - .fold(Map())(_.elems.collect { - case AbsMethod(m) => m -> FMElem.Bot - case ConMethod(m, opt, tgt) => - m -> FMElem(CloT(tgt.getOrElse(s"Record[$tname].$m")), opt, opt) - case Field(f, opt, typeStr) => - f -> FMElem(ValueTy.from(typeStr), opt, opt) - }) - .toMap + lazy val getField: ((String, String)) => Binding = cached { (t, f) => + fieldsOf(t).getOrElse(f, Binding.Absent) } /** get diff field type map */ @@ -86,7 +58,7 @@ case class TyModel(decls: List[TyDecl] = Nil) extends TyElem { else if (isStrictSubTy(l, u)) val parent = parentOf(l).get val upper = diffOf(u, parent).get.map - Some(FieldMap(upper ++ fieldsOf(l))) + Some(FieldMap(upper ++ ownFieldsOf(l))) else None } @@ -99,6 +71,10 @@ case class TyModel(decls: List[TyDecl] = Nil) extends TyElem { lpair: (String, FieldMap), rmap: Map[String, FieldMap], ): Boolean = rmap.exists(isStrictSubTy(lpair, _)) + def isStrictSubTy( + lmap: Map[String, FieldMap], + rpair: (String, FieldMap), + ): Boolean = lmap.forall(isStrictSubTy(_, rpair)) def isStrictSubTy( lpair: (String, FieldMap), rpair: (String, FieldMap), @@ -122,7 +98,7 @@ case class TyModel(decls: List[TyDecl] = Nil) extends TyElem { def isSubTy(lpair: (String, FieldMap), rpair: (String, FieldMap)): Boolean = val (l, lfm) = lpair val (r, rfm) = rpair - def check = (for { + isStrictSubTy(l, r) || (for { lca <- lcaOf(l, r) ldfm <- diffOf(lca, l) rdfm <- diffOf(lca, r) @@ -132,7 +108,6 @@ case class TyModel(decls: List[TyDecl] = Nil) extends TyElem { rfm.fields.forall { case f => (ldfm(f) && lfm(f)) <= rfm(f) } aux }).getOrElse(false) - isStrictSubTy(l, r) || check def isSubTy(l: String, r: String): Boolean = l == r || isStrictSubTy(l, r) def isSubTy(l: String, rs: Set[String]): Boolean = @@ -154,6 +129,52 @@ case class TyModel(decls: List[TyDecl] = Nil) extends TyElem { childrenOf(tname).map(_.name).toSet } + /** get all field type map */ + lazy val fieldsOf: String => Map[String, Binding] = cached { t => + declMap.get(t).fold(Map()) { decl => + decl.parent.fold(lowerFieldsOf(t)) { (parent, extended) => + if (extended) upperFieldsOf(parent) ++ lowerFieldsOf(t) + else + ownFieldsOf(t).foldLeft(fieldsOf(parent)) { + case (map, (f, e)) => map + (f -> (map.get(f).fold(e)(_ && e))) + } + } + } + } + + /** get direct field types */ + lazy val ownFieldsOf: String => Map[String, Binding] = cached { t => + declMap + .get(t) + .fold(Map())(_.elems.collect { + case AbsMethod(m) => m -> Binding.Bot + case ConMethod(m, opt, tgt) => + m -> Binding(CloT(tgt.getOrElse(s"Record[$t].$m")), opt, opt) + case Field(f, opt, typeStr) => + f -> Binding(ValueTy.from(typeStr), opt, opt) + }) + .toMap + } + + /** get upper field types */ + lazy val upperFieldsOf: String => Map[String, Binding] = cached { tname => + parentOf(tname).fold(Map())(upperFieldsOf) ++ ownFieldsOf(tname) + } + + /** get lower field types */ + lazy val lowerFieldsOf: String => Map[String, Binding] = cached { tname => + val pairs = for { + decl <- childrenOf(tname) + if decl.isExtended + x = decl.name + pair <- lowerFieldsOf(x) + } yield pair + pairs.foldLeft(ownFieldsOf(tname)) { + case (fs, (f, e)) => + fs + (f -> (fs.getOrElse(f, Binding.Absent) || e)) + } + } + /** get base type name */ lazy val baseOf: String => String = cached(ancestorsOf(_).last) @@ -199,25 +220,5 @@ case class TyModel(decls: List[TyDecl] = Nil) extends TyElem { list = children.getOrElse(parent, Nil) } yield children += parent -> (decl :: list) children.map { case (k, v) => k -> v.reverse } - - /** get upper field types */ - private lazy val upperFieldsOf: String => Map[String, FMElem] = cached { - tname => parentOf(tname).fold(Map())(upperFieldsOf) ++ fieldsOf(tname) - } - - /** get lower field types */ - private lazy val lowerFieldsOf: String => Map[String, FMElem] = cached { - tname => - val pairs = for { - decl <- childrenOf(tname) - if decl.isExtended - x = decl.name - pair <- lowerFieldsOf(x) - } yield pair - pairs.foldLeft(fieldsOf(tname)) { - case (fs, (f, e)) => - fs + (f -> (fs.getOrElse(f, FMElem.Absent) || e)) - } - } } object TyModel extends Parser.From(Parser.tyModel) diff --git a/src/main/scala/esmeta/ty/util/JsonProtocol.scala b/src/main/scala/esmeta/ty/util/JsonProtocol.scala index dba99a6830..1679a14381 100644 --- a/src/main/scala/esmeta/ty/util/JsonProtocol.scala +++ b/src/main/scala/esmeta/ty/util/JsonProtocol.scala @@ -35,6 +35,6 @@ object JsonProtocol extends BasicJsonProtocol { given Encoder[TyDecl.Elem] = encoderWithStringifier(stringify) given Decoder[FieldMap] = decoderWithParser(FieldMap.from) given Encoder[FieldMap] = encoderWithStringifier(stringify) - given fmeDec: Decoder[FieldMap.Elem] = decoderWithParser(FieldMap.Elem.from) - given fmeEnc: Encoder[FieldMap.Elem] = encoderWithStringifier(stringify) + given fmeDec: Decoder[Binding] = decoderWithParser(Binding.from) + given fmeEnc: Encoder[Binding] = encoderWithStringifier(stringify) } diff --git a/src/main/scala/esmeta/ty/util/Parser.scala b/src/main/scala/esmeta/ty/util/Parser.scala index ac409e7c7a..d2c8b2065d 100644 --- a/src/main/scala/esmeta/ty/util/Parser.scala +++ b/src/main/scala/esmeta/ty/util/Parser.scala @@ -43,22 +43,21 @@ trait Parsers extends BasicParsers { // field type map given fieldMap: Parser[FieldMap] = { - import FieldMap.Elem - lazy val field = word ~ opt(":" ~> fieldMapElem) ^^ { - case f ~ v => f -> v.getOrElse(FieldMap.Elem.Init) + lazy val field = word ~ opt(":" ~> binding) ^^ { + case f ~ v => f -> v.getOrElse(Binding.Init) } "{" ~> rep(field <~ opt(",")) <~ "}" ^^ { case ts => FieldMap(ts.toMap) } }.named("ty.FieldMap") - // field type map element - given fieldMapElem: Parser[FieldMap.Elem] = { + // field bindings + given binding: Parser[Binding] = { val uninit = "U" ^^^ true | "" ^^^ false val absent = "A" ^^^ true | "" ^^^ false opt("[" ~> uninit ~ absent <~ "]") ~ valueTy ^^ { - case None ~ v => FieldMap.Elem(v, false, false) - case Some(u ~ a) ~ v => FieldMap.Elem(v, u, a) + case None ~ v => Binding(v, false, false) + case Some(u ~ a) ~ v => Binding(v, u, a) } - }.named("ty.FieldMap.Elem") + }.named("ty.Binding") // types given ty: Parser[Ty] = { diff --git a/src/main/scala/esmeta/ty/util/Stringifier.scala b/src/main/scala/esmeta/ty/util/Stringifier.scala index eb91dc4a1b..21a6ecf16e 100644 --- a/src/main/scala/esmeta/ty/util/Stringifier.scala +++ b/src/main/scala/esmeta/ty/util/Stringifier.scala @@ -13,20 +13,20 @@ object Stringifier { /** type elements */ given elemRule: Rule[TyElem] = (app, elem) => elem match - case elem: TyModel => tyModelRule(app, elem) - case elem: TyDecl => tyDeclRule(app, elem) - case elem: TyDecl.Elem => tyDeclElemRule(app, elem) - case elem: FieldMap => fieldMapRule(using false)(app, elem) - case elem: FieldMap.Elem => fieldMapElemRule(app, elem) - case elem: Ty => tyRule(app, elem) - case elem: RecordTy => recordTyRule(app, elem) - case elem: ListTy => listTyRule(app, elem) - case elem: AstTy => astTyRule(app, elem) - case elem: MapTy => mapTyRule(app, elem) - case elem: MathTy => mathTyRule(app, elem) - case elem: InfinityTy => infinityTyRule(app, elem) - case elem: NumberTy => numberTyRule(app, elem) - case elem: BoolTy => boolTyRule(app, elem) + case elem: TyModel => tyModelRule(app, elem) + case elem: TyDecl => tyDeclRule(app, elem) + case elem: TyDecl.Elem => tyDeclElemRule(app, elem) + case elem: FieldMap => fieldMapRule(using false)(app, elem) + case elem: Binding => bindingRule(app, elem) + case elem: Ty => tyRule(app, elem) + case elem: RecordTy => recordTyRule(app, elem) + case elem: ListTy => listTyRule(app, elem) + case elem: AstTy => astTyRule(app, elem) + case elem: MapTy => mapTyRule(app, elem) + case elem: MathTy => mathTyRule(app, elem) + case elem: InfinityTy => infinityTyRule(app, elem) + case elem: NumberTy => numberTyRule(app, elem) + case elem: BoolTy => boolTyRule(app, elem) /** type models */ given tyModelRule: Rule[TyModel] = (app, model) => @@ -64,23 +64,23 @@ object Stringifier { given fieldMapRule(using inline: Boolean): Rule[FieldMap] = (app, fieldMap) => val COLON = " : " val FieldMap(map) = fieldMap - given Rule[(String, FieldMap.Elem)] = { - case (app, (field, elem)) => + given Rule[(String, Binding)] = { + case (app, (field, binding)) => app >> field - if (elem != FieldMap.Elem.Init) app >> COLON >> elem + if (binding != Binding.Init) app >> COLON >> binding app } if (fieldMap.isTop) app >> "{}" else if (inline) val SEP = ", " - given Rule[List[(String, FieldMap.Elem)]] = iterableRule(sep = SEP) + given Rule[List[(String, Binding)]] = iterableRule(sep = SEP) app >> "{ " >> map.toList.sortBy(_._1) >> " }" else app.wrap("{", "}") { for (pair <- map.toList.sortBy(_._1)) app :> pair } - /** field type map element */ - given fieldMapElemRule: Rule[FieldMap.Elem] = (app, ty) => - val FieldMap.Elem(value, uninit, absent) = ty + /** field binding */ + given bindingRule: Rule[Binding] = (app, ty) => + val Binding(value, uninit, absent) = ty var tags = "" if (uninit) tags += "U" if (absent) tags += "A" diff --git a/src/main/scala/esmeta/ty/util/UnitWalker.scala b/src/main/scala/esmeta/ty/util/UnitWalker.scala index c0318c6cd3..de154da135 100644 --- a/src/main/scala/esmeta/ty/util/UnitWalker.scala +++ b/src/main/scala/esmeta/ty/util/UnitWalker.scala @@ -9,20 +9,20 @@ trait UnitWalker extends BasicUnitWalker { /** type elements */ def walk(ty: TyElem): Unit = ty match - case elem: TyModel => walk(elem) - case elem: TyDecl => walk(elem) - case elem: TyDecl.Elem => walk(elem) - case elem: FieldMap => walk(elem) - case elem: FieldMap.Elem => walk(elem) - case elem: Ty => walk(elem) - case elem: RecordTy => walk(elem) - case elem: ListTy => walk(elem) - case elem: AstTy => walk(elem) - case elem: MapTy => walk(elem) - case elem: MathTy => walk(elem) - case elem: InfinityTy => walk(elem) - case elem: NumberTy => walk(elem) - case elem: BoolTy => walk(elem) + case elem: TyModel => walk(elem) + case elem: TyDecl => walk(elem) + case elem: TyDecl.Elem => walk(elem) + case elem: FieldMap => walk(elem) + case elem: Binding => walk(elem) + case elem: Ty => walk(elem) + case elem: RecordTy => walk(elem) + case elem: ListTy => walk(elem) + case elem: AstTy => walk(elem) + case elem: MapTy => walk(elem) + case elem: MathTy => walk(elem) + case elem: InfinityTy => walk(elem) + case elem: NumberTy => walk(elem) + case elem: BoolTy => walk(elem) /** type models */ def walk(ty: TyModel): Unit = walkList(ty.decls, walk) @@ -54,11 +54,11 @@ trait UnitWalker extends BasicUnitWalker { def walk(fieldMap: FieldMap): Unit = walkMap(fieldMap.map, walk, walk) - /** field type map element */ - def walk(ty: FieldMap.Elem): Unit = - walk(ty.value) - walk(ty.uninit) - walk(ty.absent) + /** field binding */ + def walk(binding: Binding): Unit = + walk(binding.value) + walk(binding.uninit) + walk(binding.absent) /** types */ def walk(ty: Ty): Unit = ty match diff --git a/src/main/scala/esmeta/ty/util/Walker.scala b/src/main/scala/esmeta/ty/util/Walker.scala index f06b54d775..9301346a53 100644 --- a/src/main/scala/esmeta/ty/util/Walker.scala +++ b/src/main/scala/esmeta/ty/util/Walker.scala @@ -9,20 +9,20 @@ trait Walker extends BasicWalker { /** type elements */ def walk(ty: TyElem): TyElem = ty match - case elem: TyModel => walk(elem) - case elem: TyDecl => walk(elem) - case elem: TyDecl.Elem => walk(elem) - case elem: FieldMap => walk(elem) - case elem: FieldMap.Elem => walk(elem) - case elem: Ty => walk(elem) - case elem: RecordTy => walk(elem) - case elem: ListTy => walk(elem) - case elem: AstTy => walk(elem) - case elem: MapTy => walk(elem) - case elem: MathTy => walk(elem) - case elem: InfinityTy => walk(elem) - case elem: NumberTy => walk(elem) - case elem: BoolTy => walk(elem) + case elem: TyModel => walk(elem) + case elem: TyDecl => walk(elem) + case elem: TyDecl.Elem => walk(elem) + case elem: FieldMap => walk(elem) + case elem: Binding => walk(elem) + case elem: Ty => walk(elem) + case elem: RecordTy => walk(elem) + case elem: ListTy => walk(elem) + case elem: AstTy => walk(elem) + case elem: MapTy => walk(elem) + case elem: MathTy => walk(elem) + case elem: InfinityTy => walk(elem) + case elem: NumberTy => walk(elem) + case elem: BoolTy => walk(elem) /** type models */ def walk(ty: TyModel): TyModel = TyModel(walkList(ty.decls, walk)) @@ -54,11 +54,11 @@ trait Walker extends BasicWalker { def walk(fieldMap: FieldMap): FieldMap = FieldMap(walkMap(fieldMap.map, walk, walk)) - /** field type map element */ - def walk(ty: FieldMap.Elem): FieldMap.Elem = FieldMap.Elem( - walk(ty.value), - walk(ty.uninit), - walk(ty.absent), + /** field binding */ + def walk(binding: Binding): Binding = Binding( + walk(binding.value), + walk(binding.uninit), + walk(binding.absent), ) /** types */