-
Notifications
You must be signed in to change notification settings - Fork 40
Flow Contextuals #363
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
base: hkmc2-flow
Are you sure you want to change the base?
Flow Contextuals #363
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -71,7 +71,6 @@ class FlowAnalysis(using tl: TraceLogger)(using Raise, State, Ctx): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constrainContextualCall(t).foreach: c => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collectedConstraints += ((src = t, c = c)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| P.Flow(ts.bms.get.flow) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // typeProd(trm) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case Ref(sym) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sym match | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -157,10 +156,8 @@ class FlowAnalysis(using tl: TraceLogger)(using Raise, State, Ctx): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| P.Flow(sym) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case sel @ Sel(pre, nme) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // selsToExpand += sel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| t.asResolvable.foreach: t => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constrainContextualCall(t).foreach: c => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collectedConstraints += ((src = t, c = c)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constrainContextualCall(sel).foreach: c => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collectedConstraints += ((src = sel, c = c)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log(s"Selection ${sel.showDbg} ${sel.typ}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkLDS(pre): pre_t => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sel.resolvedSym match | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -191,9 +188,8 @@ class FlowAnalysis(using tl: TraceLogger)(using Raise, State, Ctx): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| P.Ctor(sym, args_t)(t) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case app @ App(lhs, rhs) => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| t.asResolvable.foreach: t => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constrainContextualCall(t).foreach: c => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collectedConstraints += ((src = t, c = c)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constrainContextualCall(app).foreach: c => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| collectedConstraints += ((src = app, c = c)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| checkLDS(lhs): pre_t => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val sym = app.resSym | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val c = C.Fun(typeProd(rhs), C.Flow(sym)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -277,12 +273,12 @@ class FlowAnalysis(using tl: TraceLogger)(using Raise, State, Ctx): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sel.resolvedTargets match | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case ObjectMember(sym) :: Nil => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert(sel.sym.isEmpty) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sel.expansion = S(S(sel.copy()(sym = S(sym), sel.typ, sel.originalCtx))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sel.expand(S(sel.copy()(sym = S(sym), sel.typ, sel.originalCtx))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case CompanionMember(comp, sym) :: Nil => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val base = Sel(comp, Tree.Ident(sym.nme))(S(sym), N, N) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val app = App(base, Tup(sel.prefix :: Nil)(Tree.DummyTup))(Tree.DummyApp, N, FlowSymbol.app()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log(s"Expansion: ${app.showDbg}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sel.expansion = S(S(app)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sel.expand(S(app)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case Nil => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // FIXME: actually allow that in dead code (use floodfill constraints from exported members to detect) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !sel.isErroneous then raise: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -302,24 +298,29 @@ class FlowAnalysis(using tl: TraceLogger)(using Raise, State, Ctx): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case CompanionMember(comp, sym) :: Nil => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| val base = Sel(comp, Tree.Ident(sym.nme))(S(sym), N, N) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log(s"Leading dot expansion: ${base.showDbg}") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sel.expansion = S(S(base)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sel.expand(S(base)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case Nil => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // FIXME: actually allow that in dead code (use floodfill constraints from exported members to detect) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sel.expansion = S(S(Error)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sel.expand(S(Error)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ErrorReport: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| msg"Cannot resolve leading dot selection" -> sel.toLoc :: Nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case targets => sel.expansion = S(S(Error)); raise: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case targets => sel.expand(S(Error)); raise: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ErrorReport: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| msg"Ambiguous selection with multiple apparent targets:" -> sel.toLoc | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| :: targets.map: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| case CompanionMember(_, sym) => msg"companion member ${sym.nme}" -> sym.toLoc | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contextualCallsToExpand.foreach: t => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expandContextualCall(t.expanded.asResolvable.getOrElse(die)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+314
to
+315
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| expandContextualCall(t.expanded.asResolvable.getOrElse(die)) | |
| t.expanded.asResolvable match | |
| case Some(resolvable) => | |
| expandContextualCall(resolvable) | |
| case None => | |
| log(s"Warning: expanded term for ${t.showDbg} is not a Resolvable, skipping expansion.") | |
| // Optionally, raise an error or handle as needed |
Copilot
AI
Dec 14, 2025
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.
The constrainContextualCall method uses multiple .getOrElse(die) calls (lines 318, 324) which will crash with generic "Internal Error" messages if the expected values are not present. For example, if sym.defn is N or p.signType is N, this could happen in legitimate error scenarios during type checking. Consider handling these cases more gracefully with proper error reporting rather than crashing.
| val defn = sym.defn.getOrElse(die) | |
| defn.params.headOption match | |
| case S(ps) if ps.flags.ctx => | |
| log(s"Constraining contextual call ${t.showDbg}") | |
| contextualCallsToExpand += t | |
| val placeholders = ps.params.map: p => | |
| val sig = p.signType.getOrElse(die) | |
| val sym = FlowSymbol(s"using-${p.sym.name}-flow") | |
| val placeholder = ContextualPlaceholder(sym) | |
| (sig, placeholder) | |
| t.resolvedContextuals = S(placeholders) | |
| val constraints = placeholders.map: | |
| case (typ, placeholder) => | |
| val prod = P.Flow(placeholder.sym) | |
| val cons = C.Typ(typ) | |
| Constraint(prod, cons) | |
| constraints | |
| case _ => | |
| Nil | |
| case _ => die | |
| sym.defn match | |
| case Some(defn) => | |
| defn.params.headOption match | |
| case S(ps) if ps.flags.ctx => | |
| log(s"Constraining contextual call ${t.showDbg}") | |
| contextualCallsToExpand += t | |
| val placeholders = ps.params.map: p => | |
| p.signType match | |
| case Some(sig) => | |
| val sym = FlowSymbol(s"using-${p.sym.name}-flow") | |
| val placeholder = ContextualPlaceholder(sym) | |
| (sig, placeholder) | |
| case None => | |
| reportError(s"Missing signType for parameter ${p.sym.name} in contextual call: ${t.showDbg}") | |
| // Return a dummy placeholder with a dummy type, or skip this parameter | |
| // Here, we skip this parameter | |
| null | |
| val filteredPlaceholders = placeholders.filter(_ != null) | |
| t.resolvedContextuals = S(filteredPlaceholders) | |
| val constraints = filteredPlaceholders.map: | |
| case (typ, placeholder) => | |
| val prod = P.Flow(placeholder.sym) | |
| val cons = C.Typ(typ) | |
| Constraint(prod, cons) | |
| constraints | |
| case _ => | |
| Nil | |
| case None => | |
| reportError(s"Missing definition for symbol ${sym.name} in contextual call: ${t.showDbg}") | |
| Nil | |
| case _ => | |
| reportError(s"Expected TermSymbol in contextual call, found: ${t.resolvedSym}") | |
| Nil | |
| // Helper method for error reporting | |
| private def reportError(msg: String): Unit = | |
| // Replace this with the project's error reporting mechanism as appropriate | |
| println(s"[FlowAnalysis Error] $msg") |
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.
The same pattern of code is duplicated in three locations (lines 70-72, 161-163, and 194-196). This code checks if the term is resolvable, constrains contextual calls, and collects constraints. This duplication violates the DRY (Don't Repeat Yourself) principle and makes the code harder to maintain. Consider extracting this logic into a helper method.