-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for GADTs #195
Support for GADTs #195
Changes from 79 commits
c4aa6d1
261f9e0
816ea20
e7025e2
6b2334e
5f18602
b7e1bc7
55eaa2a
270a859
e201914
9566694
957b966
88b1af4
ce83f9b
cdf0f04
37a9de7
570f3d7
cb89a08
5150f53
28a831c
aecd07e
1e5b030
1e87c13
3293b58
a30e27d
a6c5451
fa04070
ecfde50
13a0e85
9f5d9b9
53e1352
ac25d4e
6bfad52
3104598
6c5975d
fbd709f
b77b47b
e7b2c4c
9c5e2c5
2f193c8
f52774b
1bb4b2d
a017daa
61e8319
e0c09ca
7868b3d
2a633d2
17e8491
f0b84c0
9b73514
4f72058
80476ef
bb437ea
e4bff8c
dce34e4
462804a
c6491bd
db7f38a
8ee5a84
4b129aa
79e3f0f
8defef6
05b68c0
73d970a
f8784ac
0f9e788
7a0353f
cf228b0
4f24921
6e6b9a1
a7e3b94
625fafe
3c05aee
e13bff7
71d9232
0b766ce
e667617
2b27281
2bc5cf8
d268965
031f611
95f4cb7
60c4b74
ab4b456
27c2354
ab2fe6b
03044b8
2f636e5
7b89780
95a3620
54ba6ad
db2fb45
e24d01e
064f004
9ef9425
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -646,6 +646,9 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo | |
case (KEYWORD("super"), l0) :: _ => | ||
consume | ||
exprCont(Super().withLoc(S(l0)), prec, allowNewlines = false) | ||
case (IDENT("?", true), l0) :: _ => | ||
consume | ||
exprCont(Var("?").withLoc(S(l0)), prec, allowNewlines = false) | ||
case (IDENT("~", _), l0) :: _ => | ||
consume | ||
val rest = expr(prec, allowSpace = true) | ||
|
@@ -910,7 +913,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo | |
else App(App(v, PlainTup(acc)), PlainTup(rhs)) | ||
}, prec, allowNewlines) | ||
} | ||
case (KEYWORD(":"), l0) :: _ if prec <= NewParser.prec(':') => | ||
case (KEYWORD("as" | ":"), l0) :: _ if prec <= NewParser.prec(':') => | ||
consume | ||
R(Asc(acc, typ(0))) | ||
case (KEYWORD("where"), l0) :: _ if prec <= 1 => | ||
|
@@ -1108,35 +1111,59 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo | |
} | ||
|
||
// TODO support line-broken param lists; share logic with args/argsOrIf | ||
def typeParams(implicit fe: FoundErr, et: ExpectThen): Ls[(Opt[VarianceInfo], TypeName)] = { | ||
def typeParams(implicit fe: FoundErr, et: ExpectThen): Ls[(TypeParamInfo, TypeName)] = { | ||
val visinfo = yeetSpaces match { | ||
case (KEYWORD("type"), l0) :: _ => | ||
consume | ||
S(l0) | ||
case _ => N | ||
} | ||
val vinfo = yeetSpaces match { | ||
Meowcolm024 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
case (KEYWORD("in"), l0) :: (KEYWORD("out"), l1) :: _ => | ||
consume | ||
S(VarianceInfo.in, l0 ++ l1) | ||
S(VarianceInfo.in -> (l0++l1)) | ||
case (KEYWORD("in"), l0) :: _ => | ||
consume | ||
S(VarianceInfo.contra, l0) | ||
S(VarianceInfo.contra -> l0) | ||
case (KEYWORD("out"), l0) :: _ => | ||
consume | ||
S(VarianceInfo.co, l0) | ||
case _ => N | ||
S(VarianceInfo.co -> l0) | ||
case _ => | ||
N | ||
} | ||
yeetSpaces match { | ||
case (IDENT(nme, false), l0) :: _ => | ||
consume | ||
val tyNme = TypeName(nme).withLoc(S(l0)) | ||
|
||
@inline def getTypeName(kw: String) = yeetSpaces match { | ||
case (KEYWORD(k), l0) :: _ if k === kw => consume | ||
yeetSpaces match { | ||
case (IDENT(nme, false), l1) :: _ => | ||
consume; S(TypeName(nme).withLoc(S(l1))) | ||
case _ => err(msg"dangling $kw keyword" -> S(l0) :: Nil); N | ||
} | ||
case _ => N | ||
} | ||
val lb = getTypeName("restricts") | ||
val ub = getTypeName("extends") | ||
// TODO update `TypeParamInfo` to use lb and ub | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO |
||
yeetSpaces match { | ||
case (COMMA, l0) :: _ => | ||
consume | ||
vinfo.map(_._1) -> tyNme :: typeParams | ||
TypeParamInfo(vinfo.map(_._1), visinfo.isDefined, lb, ub) -> tyNme :: typeParams | ||
case _ => | ||
vinfo.map(_._1) -> tyNme :: Nil | ||
TypeParamInfo(vinfo.map(_._1), visinfo.isDefined, lb, ub) -> tyNme :: Nil | ||
} | ||
case _ => | ||
vinfo match { | ||
case S((_, loc)) => | ||
(visinfo, vinfo) match { | ||
case (S(l1), S(_ -> l2)) => | ||
err(msg"dangling type member and variance information" -> S(l1 ++ l2) :: Nil) | ||
case (_, S(_ -> loc)) => | ||
err(msg"dangling variance information" -> S(loc) :: Nil) | ||
case N => | ||
case (S(loc), _) => | ||
err(msg"dangling visible type member" -> S(loc) :: Nil) | ||
Meowcolm024 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
case (N, N) => | ||
} | ||
Nil | ||
} | ||
|
@@ -1203,7 +1230,7 @@ abstract class NewParser(origin: Origin, tokens: Ls[Stroken -> Loc], newDefs: Bo | |
case (NEWLINE, _) :: _ => // TODO: | ... | ||
assert(seqAcc.isEmpty) | ||
acc.reverse | ||
case (IDENT(nme, true), _) :: _ if nme =/= "-" => // TODO: | ... | ||
case (IDENT(nme, true), _) :: _ if nme =/= "-" && nme =/= "?" => // TODO: | ... | ||
assert(seqAcc.isEmpty) | ||
acc.reverse | ||
case _ => | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,9 +22,13 @@ class NormalForms extends TyperDatatypes { self: Typer => | |
mergeSortedMap(trs1, trs2) { (tr1, tr2) => | ||
assert(tr1.defn === tr2.defn) | ||
assert(tr1.targs.size === tr2.targs.size) | ||
TypeRef(tr1.defn, (tr1.targs lazyZip tr2.targs).map((ta1, ta2) => | ||
if (pol) TypeBounds.mk(ta1 & ta2, ta1 | ta2) else TypeBounds.mk(ta1 | ta2, ta1 & ta2) | ||
))(noProv) | ||
TypeRef(tr1.defn, (tr1.targs lazyZip tr2.targs).map { | ||
case (l: WildcardArg, r: WildcardArg) => | ||
if (pol) WildcardArg.mk(l.lb | r.lb, l.ub & r.ub) else WildcardArg.mk(l.lb & r.lb, l.ub | r.ub) | ||
case (l: WildcardArg, r: ST) => if (pol) WildcardArg.mk(l.lb | r, l.ub & r) else WildcardArg.mk(l.lb & r, l.ub | r) | ||
case (l: ST, r: WildcardArg) => if (pol) WildcardArg.mk(l | r.lb, l & r.ub) else WildcardArg.mk(l & r.lb, l | r.ub) | ||
case (l: ST, r: ST) => if (pol) WildcardArg.mk(l | r, l & r) else WildcardArg.mk(l & r, l | r) | ||
})(noProv) | ||
} | ||
|
||
|
||
|
@@ -196,11 +200,25 @@ class NormalForms extends TyperDatatypes { self: Typer => | |
val thatTarg = thatTargs.head | ||
thatTargs = thatTargs.tail | ||
vce match { | ||
case S(true) => otherTarg & thatTarg | ||
case S(false) => otherTarg | thatTarg | ||
case N => | ||
if (pol) TypeBounds.mk(otherTarg | thatTarg, otherTarg & thatTarg) | ||
else TypeBounds.mk(otherTarg & thatTarg, otherTarg | thatTarg) | ||
case S(true) => (otherTarg, thatTarg) match { | ||
case (l: WildcardArg, r: WildcardArg) => WildcardArg.mk(l.lb | r.lb, l.ub & r.ub) | ||
case (l: WildcardArg, r: ST) => l.ub & r | ||
case (l: ST, r: WildcardArg) => l & r.ub | ||
case (l: ST, r: ST) => l & r | ||
} | ||
case S(false) => (otherTarg, thatTarg) match { | ||
case (l: WildcardArg, r: WildcardArg) => WildcardArg.mk(l.lb & r.lb, l.ub | r.ub) | ||
case (l: WildcardArg, r: ST) => l.lb | r | ||
case (l: ST, r: WildcardArg) => l | r.lb | ||
case (l: ST, r: ST) => l | r | ||
} | ||
case N => (otherTarg, thatTarg) match { | ||
case (l: WildcardArg, r: WildcardArg) => | ||
if (pol) WildcardArg.mk(l.lb | r.lb, l.ub & r.ub) else WildcardArg.mk(l.lb & r.lb, l.ub | r.ub) | ||
case (l: WildcardArg, r: ST) => if (pol) WildcardArg.mk(l.lb | r, l.ub & r) else WildcardArg.mk(l.lb & r, l.ub | r) | ||
case (l: ST, r: WildcardArg) => if (pol) WildcardArg.mk(l | r.lb, l & r.ub) else WildcardArg.mk(l & r.lb, l | r.ub) | ||
case (l: ST, r: ST) => if (pol) WildcardArg.mk(l | r, l & r) else WildcardArg.mk(l & r, l | r) | ||
} | ||
} | ||
} | ||
TypeRef(that.defn, newTargs)(that.prov) | ||
|
@@ -241,7 +259,14 @@ class NormalForms extends TyperDatatypes { self: Typer => | |
case (LhsTop, _) => false | ||
case (LhsRefined(b1, ts1, rt1, trs1), LhsRefined(b2, ts2, rt2, trs2)) => | ||
b2.forall(b2 => b1.exists(_ <:< b2)) && | ||
ts2.forall(ts1) && rt1 <:< rt2 && | ||
ts2.forall { | ||
case sk: SkolemTag => ts1(sk) | ||
case tt: TraitTag => ts1(tt) | ||
case Extruded(pol, sk) => !pol || ts1.exists { // find ? <: bot | ||
case Extruded(true, _) => true | ||
case _ => false | ||
} | ||
} && rt1 <:< rt2 && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This thing looks very fishy. What is going on here? Why don't we use the normal set functions? |
||
trs2.valuesIterator.forall(tr2 => trs1.valuesIterator.exists(_ <:< tr2)) | ||
} | ||
def isTop: Bool = isInstanceOf[LhsTop.type] | ||
|
@@ -294,11 +319,25 @@ class NormalForms extends TyperDatatypes { self: Typer => | |
val thatTarg = thatTargs.head | ||
thatTargs = thatTargs.tail | ||
vce match { | ||
case S(true) => otherTarg | thatTarg | ||
case S(false) => otherTarg & thatTarg | ||
case N => | ||
if (pol) TypeBounds.mk(otherTarg & thatTarg, otherTarg | thatTarg) | ||
else TypeBounds.mk(otherTarg | thatTarg, otherTarg & thatTarg) | ||
case S(true) => (otherTarg, thatTarg) match { | ||
case (l: WildcardArg, r: WildcardArg) => WildcardArg.mk(l.lb & r.lb, l.ub | r.ub) | ||
case (l: WildcardArg, r: ST) => l.lb | r | ||
case (l: ST, r: WildcardArg) => l | r.lb | ||
case (l: ST, r: ST) => l | r | ||
} | ||
case S(false) => (otherTarg, thatTarg) match { | ||
case (l: WildcardArg, r: WildcardArg) => WildcardArg.mk(l.lb | r.lb, l.ub & r.ub) | ||
case (l: WildcardArg, r: ST) => l.ub & r | ||
case (l: ST, r: WildcardArg) => l & r.ub | ||
case (l: ST, r: ST) => l & r | ||
} | ||
case N => (otherTarg, thatTarg) match { | ||
case (l: WildcardArg, r: WildcardArg) => | ||
if (pol) WildcardArg.mk(l.lb & r.lb, l.ub | r.ub) else WildcardArg.mk(l.lb | r.lb, l.ub & r.ub) | ||
case (l: WildcardArg, r: ST) => if (pol) WildcardArg.mk(l.lb & r, l.ub | r) else WildcardArg.mk(l.lb | r, l.ub & r) | ||
case (l: ST, r: WildcardArg) => if (pol) WildcardArg.mk(l & r.lb, l | r.ub) else WildcardArg.mk(l | r.lb, l & r.ub) | ||
case (l: ST, r: ST) => if (pol) WildcardArg.mk(l & r, l | r) else WildcardArg.mk(l | r, l & r) | ||
} | ||
} | ||
} | ||
TypeRef(that.defn, newTargs)(that.prov) | ||
|
@@ -760,7 +799,7 @@ class NormalForms extends TyperDatatypes { self: Typer => | |
// * TODO later: when proper TypeRef-based simplif. is implemented, can remove this special case | ||
if (preserveTypeRefs && !primitiveTypes.contains(defn.name) || !tr.canExpand) { | ||
of(polymLvl, cons, LhsRefined(tr.mkClsTag, ssEmp, RecordType.empty, SortedMap(defn -> tr))) | ||
} else mk(polymLvl, cons, tr.expandOrCrash, pol) | ||
} else mk(polymLvl, cons, tr.expandOrCrash(pol), pol) | ||
case TypeBounds(lb, ub) => mk(polymLvl, cons, if (pol) ub else lb, pol) | ||
case PolymorphicType(lvl, bod) => mk(lvl, cons, bod, pol) | ||
case ConstrainedType(cs, bod) => mk(polymLvl, cs ::: cons, bod, pol) | ||
|
@@ -804,7 +843,7 @@ class NormalForms extends TyperDatatypes { self: Typer => | |
case tr @ TypeRef(defn, targs) => | ||
if (preserveTypeRefs && !primitiveTypes.contains(defn.name) || !tr.canExpand) { | ||
CNF(Disjunct(RhsBases(Nil, N, SortedMap.single(defn -> tr)), ssEmp, LhsTop, ssEmp) :: Nil) | ||
} else mk(polymLvl, cons, tr.expandOrCrash, pol) | ||
} else mk(polymLvl, cons, tr.expandOrCrash(pol), pol) | ||
case TypeBounds(lb, ub) => mk(polymLvl, cons, if (pol) ub else lb, pol) | ||
case PolymorphicType(lvl, bod) => mk(lvl, cons, bod, pol) | ||
case ConstrainedType(cs, bod) => mk(lvl, cs ::: cons, bod, pol) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need a special case for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removing it will cause unexpected operator in parsing