Skip to content

Commit 239336f

Browse files
committed
Detect cycles in PolyConstraints
1 parent c3cd7de commit 239336f

File tree

1 file changed

+42
-16
lines changed
  • effekt/shared/src/main/scala/effekt/core

1 file changed

+42
-16
lines changed

effekt/shared/src/main/scala/effekt/core/Mono.scala

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import effekt.context.Context
55
import effekt.lexer.TokenKind
66
import effekt.context.assertions.asDataType
77

8-
// import scala.collection.mutable
9-
108
object Mono extends Phase[CoreTransformed, CoreTransformed] {
119

1210
override val phaseName: String = "mono"
@@ -27,31 +25,32 @@ object Mono extends Phase[CoreTransformed, CoreTransformed] {
2725
}
2826
}
2927

30-
// TODO: We probably want some kind of graph data structure instead of the map, for better performance in cycle detection later.
31-
// This works for now
32-
// TODO: Consider using unique IDs instead of Symbol for keys.
33-
// This works, but might give weird output when debugging
34-
// if the same symbol name is used twice
3528
// TODO: After solving the constraints it would be helpful to know
3629
// which functions have which tparams
3730
// so we can generate the required monomorphic functions
38-
type PolyConstraint = Map[symbols.Symbol, Set[symbols.Symbol]]
39-
type PolyConstraintEntry = (symbols.Symbol, Set[symbols.Symbol])
4031

41-
def appendConstraint(map: PolyConstraint, sym: symbols.Symbol, tpe: ValueType): PolyConstraintEntry =
32+
enum PolyType {
33+
case Var(val sym: symbols.Symbol)
34+
case Base(val tpe: symbols.Symbol)
35+
}
36+
37+
type PolyConstraints = Map[symbols.Symbol, Set[PolyType]]
38+
type PolyConstraintEntry = (symbols.Symbol, Set[PolyType])
39+
40+
def appendConstraint(map: PolyConstraints, sym: symbols.Symbol, tpe: ValueType): PolyConstraintEntry =
4241
val currentFlow = map.getOrElse(sym, Set())
4342
tpe match {
4443
// Ignore self cycling types A -> A
45-
case ValueType.Data(name, targs) if name != sym => (sym -> currentFlow.incl(name))
46-
case ValueType.Var(name) if name != sym => (sym -> (currentFlow.incl(name)))
44+
case ValueType.Data(name, targs) if name != sym => (sym -> (currentFlow + PolyType.Base(name)))
45+
case ValueType.Var(name) if name != sym => (sym -> (currentFlow + PolyType.Var(name)))
4746
// TODO: What do we do with boxed types?
4847
case o@ValueType.Boxed(tpe, capt) =>
4948
println("Hit boxed type: " + o)
5049
(sym -> currentFlow)
5150
case _ => (sym -> currentFlow) // self cycling flow
5251
}
5352

54-
def findConstraintRec(value: Val, typeFlow: PolyConstraint): PolyConstraint =
53+
def findConstraintRec(value: Val, typeFlow: PolyConstraints): PolyConstraints =
5554
var newTypeFlow = typeFlow
5655
value.binding match {
5756
case App(callee, targ :: targs, vargs, bargs) =>
@@ -71,8 +70,8 @@ def findConstraintRec(value: Val, typeFlow: PolyConstraint): PolyConstraint =
7170
case _ => newTypeFlow
7271
}
7372

74-
def findConstraints(definitions: List[Toplevel]): PolyConstraint =
75-
var typeFlow: PolyConstraint = Map()
73+
def findConstraints(definitions: List[Toplevel]): PolyConstraints =
74+
var typeFlow: PolyConstraints = Map()
7675
definitions.foreach {
7776
case Toplevel.Def(id, block) =>
7877
block match
@@ -93,4 +92,31 @@ def findConstraints(definitions: List[Toplevel]): PolyConstraint =
9392
case _ =>
9493
case _ =>
9594
}
96-
typeFlow
95+
typeFlow
96+
97+
object PolyGraphCalc {
98+
var visited: Set[symbols.Symbol] = Set()
99+
var recStack: Set[symbols.Symbol] = Set()
100+
101+
def hasCycle(vertex: symbols.Symbol, adjacency: PolyConstraints): Boolean =
102+
if (recStack.contains(vertex)) return true
103+
104+
if (visited.contains(vertex)) return false
105+
106+
visited += vertex
107+
recStack += vertex
108+
109+
adjacency.foreach((v, edges) => if (hasCycle(v, adjacency)) return true)
110+
111+
recStack -= vertex
112+
false
113+
114+
def hasCycle(constraints: PolyConstraints): Boolean =
115+
visited = Set()
116+
recStack = Set()
117+
118+
constraints.keys.foreach(v => if (hasCycle(v, constraints)) return true)
119+
120+
false
121+
}
122+

0 commit comments

Comments
 (0)