Open JacquesCarette opened 2 years ago
Reminder to self: NamedArgument should likely be moved to drasil-code since it's "code-focused" and seemingly tightly bound to internal logic in drasil-code.
Related to #3307: We have a few code-related chunks in drasil-lang
that I started moving to drasil-code
, where I think they should belong. However, I'm blocked by a circular dependency when I try. I guess this is related to us previously having and then removing drasil-code-base
.
Path to finding the issue:
drasil-lang
's definition of a "document" language (another issue perhaps) that depends on CodeExpr
for code blocks. I don't think it should depend on CodeExpr
because CodeExpr
is only for expressions, not whole code blocks. Temporarily changing the dependency to Expr
should be fine, but a more appropriate input for code blocks is probably arbitrary text with a language tag or GOOL if we want to be restrictive to OO languages.drasil-lang
does not depend on CodeExpr
otherwise, so we can compile drasil-lang
just fine.CodeExpr
into drasil-code
, we run into a circular dependency with drasil-printers
because drasil-printers
carries a printer that converts CodeExpr
into its document language.Now the question is: should the printing code go inside drasil-code
or drasil-printers
(or something else)?
So, I searched for how drasil-code
relies on drasil-printers
:
> rg "import Language.Drasil.Printers" -ths drasil-code
drasil-code/lib/Language/Drasil/Chunk/Code.hs
15:import Language.Drasil.Printers (symbolDoc)
drasil-code/lib/Language/Drasil/Code/Imperative/Modules.hs
44:import Language.Drasil.Printers (SingleLine(OneLine), codeExprDoc)
drasil-code/lib/Language/Drasil/Code/Imperative/Generator.hs
33:import Language.Drasil.Printers (SingleLine(OneLine), sentenceDoc)
drasil-code/lib/Language/Drasil/Code/Imperative/Descriptions.hs
20:import Language.Drasil.Printers (SingleLine(OneLine), sentenceDoc)
drasil-code/lib/Language/Drasil/Code/Imperative/Comments.hs
10:import Language.Drasil.Printers (SingleLine(OneLine), sentenceDoc, unitDoc)
drasil-code/lib/Language/Drasil/Code/Imperative/WriteInput.hs
11:import Language.Drasil.Printers (SingleLine(OneLine), exprDoc, sentenceDoc,
drasil-code/lib/Language/Drasil/Code/Imperative/WriteReadMe.hs
6:import Language.Drasil.Printers (makeMd, introInfo, verInfo, unsupOS,
[added in post:] extLibSec, instDoc, endNote, whatInfo)
I think it's fair for drasil-code
to rely on drasil-printers
because drasil-code
houses code-generation code.
Looking at drasil-printers
, it contains...
Printing
: an AST (Document
) for documents we would commonly encounter, with features for tables, sections, equation blocks, code blocks, lists, figures, etc.,Printing.Import
: various printers for things in drasil-lang
to the AST mentioned above, Markdown
: a Markdown encoding of sorts largely focused on generating Markdown files related to the generated artifacts,JSON
: a specific kind of JSON
encoding, focused on JupyterLab notebooks (which are encoded as JSON files),Debug
: a chunk-dump tool which should be removed altogether ultimately with #2873 (one day),DOT
: a specific-ish kind of GraphViz/.dot
encoding largely focused on generating the .dot
diagrams we're interested in,HTML
: an HTML renderer for Document
with some goodies for things we're interested in,Plain
: a Document
renderer for plaintext variants of the SRS documents, andTeX
: a Document
renderer focused on building LaTeX documents, with some goodies for math and bibtex.Some 'aside' observations:
Document
is like our own pandoc of sorts! That's neat!Markdown
might be more appropriately placed elsewhere.State
in any of the printers here, but we do in GOOL. State
would allow us to do some nifty things, I believe, specifically for ID generation and such for HTML, footnote creation, traceability matrices from texts, etc. Have we ever discussed using State
in general for Drasil?The more important observation:
drasil-printers
and drasil-code
have different philosophies in regard to artifact generation. drasil-printers
carries things that are closer to our terminal chunks (/artifacts) while drasil-code
carriers 'higher level' knowledge. For printing-related matters, drasil-printers
'pulls in' the higher-level things from drasil-lang
, while drasil-code
exports lower-level things from drasil-printers
.Since we're largely dealing with 'synthetical' relationships, I think I tend towards the latter: 'higher level/problem knowledge' package carrying the information about how they should be rendered into the lower level/terminal chunk artifacts. I started work on that in 269b55f1d48a454022735fd9bb4a2c7c4f035d5e (looks larger than it is), but then I ran into another import issue. Namely, drasil-code
would need to rely on some new things from drasil-printers
:
import qualified Language.Drasil.Printing.AST as P
import Language.Drasil.Printing.PrintingInformation (PrintingInformation, ckdb, stg)
import Language.Drasil.Printing.Import.Helpers
(lookupC, parens)
import Language.Drasil.Printing.Import.Literal (literal)
import Language.Drasil.Printing.Import.Symbol (symbol)
I think that all of these things make sense -- printing to the Document
language (so, the Document
language itself), printing information, a chunk db, symbol stage, a chunk lookup function, a 'parenthesizing expressions' function for the document language, a literal renderer, and a symbol renderer. However, it looks like there was a design choice specifically made in the past to not export these.
So, it looks like there is a larger design decision to make, and I'm wondering: how shall we proceed?
Shallow answer to just the part about drasil-lang
's document language depending on CodeExpr
: maybe we could make that part polymorphic, i.e. the document language would have a type parameter that represents a to-be-filled type (i.e. CodeExpr
in practice). That way the document language is explicitly oblivious to the details of what 'code' is / will be.
I think the drasil-code
style is also more in-tune with the semantics paper/"describe syntax with a semantic domain in mind" style. Seeing this idea through, an alternative view of drasil-printers
might have:
drasil-artifacts
package, carrying various encodings for external things (HTML, Markdown, Makefile, etc.). Note that GOOL would not be included because it sits atop of the code.I'm not sure if the contents of drasil-printers
is generic enough either (there is a lot of implicit knowledge specific to the generators in Drasil), so it might also be good to split it up and move its pieces closer to the areas its most relevant to.
I don't think these kinds of changes are too huge, it's really just shifting things around to stabilize the dependency chain (or I guess come up with one that might fit the current story better).
(A lot of the analysis behind this issue is in #2883; specifically in the 'shallow analysis' for
drasil-lang
).The analysis there accurately describes how
drasil-lang
defines a whole slew of encodings. Some of these are inter-dependent, some are not. The type dependency graph and the module dependency graph both illustrate this.It would make a lot of sense to split this up into much smaller pieces. This can be done incrementally. The ones that are 'at the top' of the graph (in dependency order) can likely be hived off most easily. Also, I think there are things at the very bottom that can be split too.
To be precise, I think the following should be relatively easy to split:
There will remain dependencies between
The usefulness of doing this split is definitely going to be that some of the dependencies on
drasil-lang
will shift to being dependencies on much smaller bits.