@@ -5,8 +5,6 @@ import effekt.context.Context
5
5
import effekt .lexer .TokenKind
6
6
import effekt .context .assertions .asDataType
7
7
8
- // import scala.collection.mutable
9
-
10
8
object Mono extends Phase [CoreTransformed , CoreTransformed ] {
11
9
12
10
override val phaseName : String = " mono"
@@ -27,31 +25,32 @@ object Mono extends Phase[CoreTransformed, CoreTransformed] {
27
25
}
28
26
}
29
27
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
35
28
// TODO: After solving the constraints it would be helpful to know
36
29
// which functions have which tparams
37
30
// 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 ])
40
31
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 =
42
41
val currentFlow = map.getOrElse(sym, Set ())
43
42
tpe match {
44
43
// 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)))
47
46
// TODO: What do we do with boxed types?
48
47
case o@ ValueType .Boxed (tpe, capt) =>
49
48
println(" Hit boxed type: " + o)
50
49
(sym -> currentFlow)
51
50
case _ => (sym -> currentFlow) // self cycling flow
52
51
}
53
52
54
- def findConstraintRec (value : Val , typeFlow : PolyConstraint ): PolyConstraint =
53
+ def findConstraintRec (value : Val , typeFlow : PolyConstraints ): PolyConstraints =
55
54
var newTypeFlow = typeFlow
56
55
value.binding match {
57
56
case App (callee, targ :: targs, vargs, bargs) =>
@@ -71,8 +70,8 @@ def findConstraintRec(value: Val, typeFlow: PolyConstraint): PolyConstraint =
71
70
case _ => newTypeFlow
72
71
}
73
72
74
- def findConstraints (definitions : List [Toplevel ]): PolyConstraint =
75
- var typeFlow : PolyConstraint = Map ()
73
+ def findConstraints (definitions : List [Toplevel ]): PolyConstraints =
74
+ var typeFlow : PolyConstraints = Map ()
76
75
definitions.foreach {
77
76
case Toplevel .Def (id, block) =>
78
77
block match
@@ -93,4 +92,31 @@ def findConstraints(definitions: List[Toplevel]): PolyConstraint =
93
92
case _ =>
94
93
case _ =>
95
94
}
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