JacquesCarette / Drasil

Generate all the things (focusing on research software)
https://jacquescarette.github.io/Drasil
BSD 2-Clause "Simplified" License
142 stars 26 forks source link

Re-splitting drasil-lang #2885

Open JacquesCarette opened 2 years ago

JacquesCarette commented 2 years ago

(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.

balacij commented 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.

balacij commented 6 months ago

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:

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...

Some 'aside' observations:

The more important observation:

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?

JacquesCarette commented 6 months ago

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.

balacij commented 6 months ago

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:

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).