11package edg .compiler
22
3- import scala .collection .mutable
4- import scala .collection .Set
3+ import edg .ExprBuilder
4+ import edg .compiler .CompilerError .ExprError
5+ import edg .util .DependencyGraph
6+ import edg .wir ._
57import edgir .expr .expr
68import edgir .init .init
7- import edg .wir ._
8- import edg .util .{DependencyGraph , MutableBiMap }
9- import edg .ExprBuilder
109import edgir .ref .ref .LocalPath
1110
12- case class AssignRecord ( target : IndirectDesignPath , root : DesignPath , value : expr. ValueExpr )
11+ import scala . collection .{ Set , mutable }
1312
14- case class OverassignRecord ( assigns : mutable. Set [( DesignPath , String , expr.ValueExpr )] = mutable. Set () )
13+ case class AssignRecord ( target : IndirectDesignPath , root : DesignPath , value : expr.ValueExpr )
1514
1615sealed trait ConnectedLinkRecord // a record in the connected link directed graph
1716object ConnectedLinkRecord {
@@ -53,21 +52,20 @@ class ConstProp() {
5352 // Params that have a forced/override value, so they arent over-assigned.
5453 private val forcedParams = mutable.Set [IndirectDesignPath ]()
5554
56- // Overassigns, for error tracking
57- // This only tracks overassigns that were discarded, not including assigns that took effect.
58- // Additional analysis is needed to get the full set of conflicting assigns.
59- private val discardOverassigns = mutable.HashMap [IndirectDesignPath , OverassignRecord ]()
55+ // Errors that were generated during the process of resolving parameters, including overassigns
56+ // A value may or may not exist (and may or not have been propagated) in the param dependency graph
57+ private val paramErrors = mutable.HashMap [IndirectDesignPath , mutable.ListBuffer [ErrorValue ]]()
6058
6159 def initFrom (that : ConstProp ): Unit = {
6260 require(paramAssign.isEmpty && paramSource.isEmpty && paramTypes.isEmpty && forcedParams.isEmpty
63- && discardOverassigns .isEmpty)
61+ && paramErrors .isEmpty)
6462 paramAssign.addAll(that.paramAssign)
6563 paramSource.addAll(that.paramSource)
6664 params.initFrom(that.params)
6765 paramTypes.addAll(that.paramTypes)
6866 connectedLink.initFrom(that.connectedLink)
6967 forcedParams.addAll(that.forcedParams)
70- discardOverassigns .addAll(that.discardOverassigns )
68+ paramErrors .addAll(that.paramErrors )
7169 }
7270
7371 //
@@ -120,9 +118,15 @@ class ConstProp() {
120118 }
121119 readyList.foreach { constrTarget =>
122120 val assign = paramAssign(constrTarget)
123- new ExprEvaluatePartial (this , assign.root).map(assign.value) match {
121+ new ExprEvaluatePartial (getValue , assign.root).map(assign.value) match {
124122 case ExprResult .Result (result) =>
125- params.setValue(constrTarget, result)
123+ result match {
124+ case result @ ErrorValue (_) =>
125+ paramErrors.getOrElseUpdate(constrTarget, mutable.ListBuffer ()).append(result)
126+ params.clearReadyNode(constrTarget)
127+ case result => params.setValue(constrTarget, result)
128+ }
129+
126130 onParamSolved(constrTarget, result)
127131 case ExprResult .Missing (missing) => // account for CONNECTED_LINK prefix
128132 val missingCorrected = missing.map { path =>
@@ -202,9 +206,11 @@ class ConstProp() {
202206 params.addNode(target, Seq (), overwrite = true ) // forced can overwrite other records
203207 } else {
204208 if (! forcedParams.contains(target)) {
205- if (params.nodeDefinedAt(target)) {
206- val record = discardOverassigns.getOrElseUpdate(target, OverassignRecord ())
207- record.assigns.add(paramSourceRecord)
209+ if (params.nodeDefinedAt(target)) { // TODO add propagated assign
210+ val (prevRoot, prevConstr, _) = paramSource.get(target).getOrElse(" ?" , " ?" , " " )
211+ paramErrors.getOrElseUpdate(target, mutable.ListBuffer ()).append(
212+ ErrorValue (s " over-assign from $root. $constrName, prev assigned from $prevRoot. $prevConstr" )
213+ )
208214 return // first set "wins"
209215 }
210216 params.addNode(target, Seq ())
@@ -254,7 +260,7 @@ class ConstProp() {
254260 }
255261
256262 /** Returns the value of a parameter, or None if it does not have a value (yet?). Can be used to check if parameters
257- * are resolved yet by testing against None.
263+ * are resolved yet by testing against None. Cannot return an ErrorValue
258264 */
259265 def getValue (param : IndirectDesignPath ): Option [ExprValue ] = {
260266 resolveConnectedLink(param) match {
@@ -264,7 +270,6 @@ class ConstProp() {
264270
265271 }
266272 def getValue (param : DesignPath ): Option [ExprValue ] = {
267- // TODO should this be an implicit conversion?
268273 getValue(param.asIndirect)
269274 }
270275
@@ -282,20 +287,14 @@ class ConstProp() {
282287 * references.
283288 */
284289 def getUnsolved : Set [IndirectDesignPath ] = {
285- paramTypes.keySet.toSet -- params.knownValueKeys
290+ paramTypes.keySet.toSet -- params.knownValueKeys -- paramErrors.keys
286291 }
287292
288293 def getAllSolved : Map [IndirectDesignPath , ExprValue ] = params.toMap
289294
290- def getErrors : Seq [CompilerError ] = {
291- discardOverassigns.map { case (target, record) =>
292- val propagatedAssign = paramSource.get(target).map { case (root, constrName, value) =>
293- CompilerError .OverAssignCause .Assign (target, root, constrName, value)
294- }.toSeq
295- val discardedAssigns = record.assigns.map { case (root, constrName, value) =>
296- CompilerError .OverAssignCause .Assign (target, root, constrName, value)
297- }
298- CompilerError .OverAssign (target, propagatedAssign ++ discardedAssigns)
295+ def getErrors : Seq [ExprError ] = {
296+ paramErrors.flatMap { case (target, errors) =>
297+ errors.map(error => ExprError (target, error.msg))
299298 }.toSeq
300299 }
301300}
0 commit comments