melt-umn / silver

An attribute grammar-based programming language for composable language extensions
http://melt.cs.umn.edu/silver/
GNU Lesser General Public License v3.0
57 stars 7 forks source link

Separate [Message]s by an "analysis name" #782

Open remexre opened 1 year ago

remexre commented 1 year ago

If we want to filter the errors we're producing, we're currently (e.g. in the flow analysis) doing this by passing down some flags saying whether to produce an error or not. We could avoid all this flag-passing and simplify some logic by instead always producing those errors and filtering them out at the top.

To avoid running analyses that we don't want to run, for performance or circularity reasons, we need to be able to skip entire sublists; this suggests that maybe errors should be something like:

nonterminal Analysis;
annotation analysisName :: String occurs on Analysis;
annotation analysisMessages :: [Message] occurs on Analysis;

production analysis
top::Analysis ::=
{}

synthesized attribute errors :: [Analysis];

Each contribution to errors would probably look something like

top.errors <- [analysis(analysisName="tyck", analysisMessages=tyckErrors)];
monoid local tyckErrors :: [Message]; -- #781
tyckErrors <- ...;

Then, at the top, we can filter out analyses we didn't want to be run, and laziness should do the right thing for us.


I think it's a separate question as to how to use this for circularity; plausibly, we could bubble up a set of edges about which analyses are allowed to depend on which others? Honestly, having a helper like

function hasErrorsFrom
errors occurs on a =>
Boolean ::= tree::Decorated a  analysisName::String
{ return !null(concat(filter(\a -> a.analysisName == analysisName, tree.errors))); }

and using that locally might be enough.