Drasil icon indicating copy to clipboard operation
Drasil copied to clipboard

Re-splitting drasil-lang

Open JacquesCarette opened this issue 4 years ago • 4 comments

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

  • components of a notebook/document
  • natural language
  • people
  • references & citations
  • URIs

There will remain dependencies between

  • mathematical languages
  • constructs
  • derivations

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.

JacquesCarette avatar Nov 10 '21 21:11 JacquesCarette

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 avatar Jan 19 '22 17:01 balacij

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.
  • Other than the above issue, drasil-lang does not depend on CodeExpr otherwise, so we can compile drasil-lang just fine.
  • However, when we move 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, and
  • TeX: 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!
  • The Markdown might be more appropriately placed elsewhere.
  • We might want to build actual JSON, Markdown, GraphViz, and HTML encodings too.
  • We don't use 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?

balacij avatar Feb 22 '24 02:02 balacij

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.

JacquesCarette avatar Feb 22 '24 04:02 JacquesCarette

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:

  • The creation of a 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.
  • A shift of all the renderers closer to their syntax definitions.

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

balacij avatar Feb 22 '24 04:02 balacij