Creating Your Project in Drasil - JacquesCarette/Drasil GitHub Wiki

Warning: Wiki should not be edited directly. Edit the files in the ./wiki/ folder instead and make a PR.

Contents

  1. Tips to Get Started
  2. Creating Your Project in Drasil
  3. Adding Sections to SRS Body
  4. Code Generation

Tips to Get Started

  1. You will be working mainly in the code folder.
  2. There are several sub-packages that you will require to create your software in Drasil.
  3. Many scientific theories, concepts, quantities and units commonly used in scientific problems are already coded in Drasil, you can reuse them as required. E.g Newton’s law of motion theory, units like meters, seconds, and so on. Drasil also contains concepts like gravitational acceleration, kinetic energy, velocity, and so on.
  4. You will be using branches and pull requests for your project. See the Contributor's Guide for more details
  5. In addition to this manual, you can use example projects as your cheat sheet to build your own project.
  6. Refer to the Haddock documentation for Drasil. A variant with fully exposed modules is also available.
  7. We would like to keep improving this user guide based on your feedback. Please create issue(s) on GitHub with what you think is missing, unclear, or should be included as you follow this guide. You can assign issues to @JacquesCarette or @smiths.

Getting Started:

  • Follow the New Workspace Setup for setting up your machine for working with Drasil.
  • For more information on the contents of a Software Requirements Specification (SRS), see Dr. Smith's template
  • To create your project in Drasil, you will generally want to fork the repo and make your changes on your fork. Check out this pull request for more information on setting up your own bot for GitHub Actions.
  • Setting up your workspace

Sub-packages in Drasil:

See Folder Layout for a more in-depth discussion. There are three sub-packages that you will primarily be working with:

  • drasil-gen defines the entry point for artifact generation.
  • drasil-lang contains language primitives focused on mathematical knowledge capture. This package also includes a language for symbols (Symbol) and a language for mathematical expressions embedding symbols (Expr). It describes the layout of a document and much more.
  • drasil-theory contains chunk types for describing refinements of mathematical theories and instantiation of definitions.

There are several other sub-packages that you will need to work with on a smaller scale:

  • drasil-code and drasil-docLang: for generating code and documentation, respectively. You will mainly need them for Choices and SRSDecl.
  • drasil-database and drasil-system: for gathering pieces of information and bundling them together.
  • drasil-example and drasil-website: good reference material if you need it.
  • drasil-data: for knowing what things you can reuse (e.g. mathematical concepts and documentation concepts), and adding new things that others can reuse.

Creating Your Project in Drasil

Note: The instructions of this tutorial were last updated for a commit on 29 Oct 2022.

After all installation tasks and forking is completed and you are able to run existing example projects in Drasil, you are ready to create your own. You can use Visual Studio Code or any other editor that you are familiar with.

Adding a New User and Project Sub-Folder

  1. If you are a new user, add your information Peoples.hs in code/drasil-data/lib/Data/Drasil/People.hs. Create a new row and follow the same format to add your name, using the different person functions as needed.

  2. Now, you will need to create a new sub-folder for your project. Navigate to /code/drasil-example/ and create your new folder.

  3. Make a copy of template folder into the new folder and rename the new folder to your project name. Make sure you give your project an intuitive name. For example, Double Pendulum can be represented as DblPendulum, Projectile is Projectile, Solar Water Heating System is SWHS, etc. (note – project name should be one word, no spaces).

  4. Import module Data.Drasil.People into Body.hs. This is the file where you added your name. This will be used to include your name as an author on your generated SRS document. E.g. import Data.Drasil.People (brenda)

  5. Decide a name for your software system and define it as a Common Idea (CI) in a new file named Concepts.hs. For example, gamePhysics would be represented with:

gamePhysics :: CI
gamePhysics = commonIdeaWithDict "gamePhysics" (pn "game physics library") "Game Physics" [physics]

For more information, please see the documentation for commonIdeaWithDict.

  1. In Body.hs, start constructing your chunk database (ChunkDB) in the symbMap function by adding your program name (e.g nw “your software name”). Make sure the parameter you are adding here tallies with the value of the _sys record in defined in si in Body.hs. si holds all of your system's information as a System record type.

  2. Now you are ready to start constructing your SRS.

Create a Blank SRS Template for Your Project:

  1. In your newly created project folder, open Body.hs. Modify the file to reflect your project name by replacing all instances of the word 'Template' with your project name. You can perform a find and replace operation to complete this.

  2. Go to the si (System) section of the code in Body.hs and populate the following fields with your own functions:

_sys         = example --(will become the name of your software system e.g. dblpendulum)
_authors     = [authorName] --(will become the same name you added to People.hs)

For reference, the si data is used to hold global information about a system.

si :: System
si = SI {
  _sys         = example,
  _kind        = Doc.srs,
  _authors     = [authorName],
  _purpose     = [],
  _quants      = [] :: [QuantityDict],
  _concepts    = [] :: [DefinedQuantityDict],
  _instModels  = [] :: [InstanceModel],
  _datadefs    = [] :: [DataDefinition],
  _configFiles = [],
  _inputs      = [] :: [QuantityDict],
  _outputs     = [] :: [QuantityDict],
  _defSequence = [] :: [Block QDefinition],
  _constraints = [] :: [ConstrainedChunk],
  _constants   = [] :: [QDefinition],
  _sysinfodb   = symbMap,
  _usedinfodb  = usedDB,
   refdb       = refDB
}
  1. Remember to import your software system name from Concepts.hs into Body.hs as well as all other relevant modules. Once you have done this, you may totally remove the example and authorName functions from Body.hs. There should be no need for these functions anymore as the second step renders them unneeded. If there are, just replace them with the ones you created.

Modifying Main.hs for Your Software

  1. Update your Main.hs file: Your main module will load all the other modules in your project to build and generate your SRS.
  2. Open the Main.hs file in the current folder and replace all instances of template with your project name, save and close.

Update yaml and cabal Files

The package.yaml file contains some information about your project, including all the modules used in your project. From there, the compiler will generate a .cabal file for you. The information in the .cabal is then needed to actually build your project and connect all the packages included. As you add more modules to you project folder, you will need to update package.yaml (which will automatically update the .cabal file). You should almost never have to manually update the .cabal file.

  1. Navigate to ../code/drasil-example/**{your-new-example-folder}**/package.yaml
  2. At the bottom, update the file using the other examples as a guide. It should look something like this:
...
library:
  source-dirs: lib
  when:
  - condition: false
    other-modules: Paths_{your-example-name}

executables:
  yourExampleName:
      main: Main
      source-dirs: app
      ...
      dependencies: 
      - {your-example-name}
      when:
      - condition: false
        other-modules: Paths_{your-example-name}

Build Your Project – Run make

  1. Navigate to code/Makefile, add your project to the list of other example projects and modify as applicable.
  2. Navigate to the code folder from your terminal to build your project.
  3. Run make to build your project.
  4. Navigate to your project folder in build to view your output files.
  5. When you build your project, any artifacts that Drasil was able to generate (e.g. .tex and .html versions of the SRS, executable code) will be auto-generated in appropriate sub-folders of the build folder.
  6. After the build operation is completed, check the output of your SRS in the .html file. A cascading style sheet is also autogenerated in the same folder.

Updating Stable folder in code/stable/

You might have to update stable for all the other examples if you get the following error for any of the other examples. The one shown below is from the Template project:

-------------------------------------------
- logs/Template_log.log IS NOT EMPTY -- DIFFERENCE
- BETWEEN GENERATED AND STABLE OUTPUT FOUND
-------------------------------------------
-------------------------------------------
- ERROR IN GENERATED OUTPUT SEE ABOVE FOR -
-             MORE DETAILS                -
-------------------------------------------

Subsequently, you need to update stable for your new project whenever you make any changes. This can most easily be done by running make stabilize. Alternatively, you can follow these instructions manually:

  1. Make a copy of your project folder from /Drasil/code/build/yourProjectName.
  2. Paste in Drasil/code/stable to create a folder for your project. Ensure that the version in stable matches the version in build when pushing your project to your remote repository.
  3. Rename your folder with the name you used for _sys from the si variable in Body.hs. This should be the same as what appeared in the build folder.
  4. Update .html and .tex files (copy and replace) only.
  5. When you build your project, and it says GENERATED OUTPUT MATCHES STABLE VERSION, then stable is up to date, no need to update. Here is what a stabilized output will look like:
----------------------------
Make complete, checking logs
----------------------------
-------------------------------------------
- GENERATED OUTPUT MATCHES STABLE VERSION -
-------------------------------------------

GitHub Actions / Builds & Tests

If you'd like to test your new project against the existing build scripts, please include [workflow-trigger] in a commit message when pushing your work. This will force our Drasil build workflow to run on your branch, and you will be able to view logs of the run under the "Actions" tab. Alternatively, if you are working in a branch that already has a PR attached to it, it will automatically build and test without the [workflow-trigger] in your commit message. You may then view the logs related to your test run by finding the Action run linked to your commit/PR, or by visiting the "Actions" page and looking for your triggered test run.

For more information about our automated tests, please see our Workflow documentation.

Logging

A log file will be auto-generated in a logs folder for your project after every build: An example file path for this is: /code/logs/yourProjectName_log.log. The logs are generated by using diff between the build and stable folders to find any differences between the two folders.

Adding Sections to SRS Body

  1. After creating a blank SRS, you will be able to add sections to it and populate with information.
  2. The Body.hs module of your project will be used to gather the sections of your SRS.
  3. We will now begin to fill in the function mkSRS. The value of mkSRS will include all the sections required in your SRS document. Visit the different examples for more information on this. A list of potential sections and their constructors can be found in the Haddock documentation.
  4. You will find all the sections that can be created in ../code/drasil-docLang/lib/Drasil/DocLang/SRS.hs
  5. Begin adding sections using the excerpt below:
mkSRS = [ TableOfContents -- Adds a Table of Contents section
    RefSec $       -- Adds the reference material section
      RefProg intro  -- Add the introduction blob
        [TUnits         -- Adds table of units subsection
        , tsymb [TSPurpose, TypogConvention [Vector Bold], SymbOrder, VectorUnits] 
       -- The above adds table of symbols with contents and specified rules e.g ordering content of table, bold vector symbols, adds purpose of document, etc.
        , TAandA -- Adds table of abbreviation and acronym subsection
        ],
  1. Ensure that your import list contains DocLang's SRS:
import qualified Drasil.DocLang.SRS as SRS
  1. At this point build your code (by running make) and see what you generate. You should see the sections in step 5 displayed in your SRS. Depending on what you have added to mkSRS you may need to update the ChunkDB first, which will be explained below.

  2. The remainder of the tutorial will go over adding a subset of potential sections to your project. A complete list of potential sections can be found in the Haddock documentation. Not all sections need to be included in your project. See Dr. Smith's template for more information on each section.

Adding Introduction Section

You can add the ‘Introduction’ section and related sub-sections into Body.hs. The SRS section builder is defined in this module:

/code/drasil-docLang/lib/Drasil/DocLang/SRS.hs

Introduction constructors can be found in the IntroSec Haddock documentation.

  1. Start a new section in mkSRS after the block you created in step 5 above.
  2. Add the introduction section information to your project. An example Introduction will look something like:
IntroSec $
    IntroProg justification (phrase dblpendulum) -- This line introduces the system you want to build. 'justification' is a function that needs to be defined in `Body.hs` to hold the content of an introduction preamble.
      [IScope scope], -- This line adds the Scope of Requirements section to SRS. You will need to define a constructor for scope in Body.hs with type 'Sentence'. 
  1. Define a scope constructor (example below). This will hold the content of the introduction preamble and must be a Sentence.
scope :: Sentence
scope = foldlSent [S "dblpendulum is the subject" +:+. S "dblpendulum is the focus", phrase dblpendulum]
  1. Define a justification constructor. It introduces the system you want to build.
justification :: Sentence
justification = foldlSent [ atStartNP (a_ pendulum), S "consists" `S.of_` phrase mass, ...]
  1. Other sub-sections similar to scope in step 3 can also be included e.g. Purpose. Just make sure that you add to the imports and symbMap as required. Here is a sample of the first few sections added for the Projectile project:
mkSRS :: SRSDecl
mkSRS = [
  RefSec $
    RefProg intro
      [ TUnits
      , tsymb [TSPurpose, TypogConvention [Vector Bold], SymbOrder, VectorUnits]
      , TAandA
      ],
  IntroSec $
    IntroProg justification (phrase projectileTitle)
      [ IScope scope ],
  SSDSec $
    SSDProg
      [ SSDProblem $ PDProg prob []
        [ TermsAndDefs Nothing terms
        , PhySysDesc projectileTitle physSystParts figLaunch []
        , Goals [(phrase iVel +:+ S "vector") `S.the_ofThe` phrase projectile]]
  1. Since we added a scope section, you will need to include the constructor name in the chunk database. scope is defined in the doccon constructor in ../drasil-data/lib/Data/Drasil/Concepts/Documentation. The process of updating the chunk database may need to be repeated for other constructors that are created in other parts of the SRS.
doccon :: [NamedChunk]
doccon = [abbAcc, abbreviation, acronym, analysis, appendix, aspect, body,
  caseProb, charOfIR, characteristic, class_, client, code, column, company,
  component, concept, condition, connection, consVals, constant, constraint,
  -- ...
  safety, safetyReq, scenario, {-Here!-} scope, scpOfReq,
  -- ...
  validation, value, variable, vav, vavPlan, verification, video, year]
  1. In the 3rd argument of symbMap, add the doccon and doccon' functions. The third argument should now look like:
(nw yourSoftwarePackageName : [nw program] ++ map nw doccon ++ map nw doccon')

You must also import Data.Drasil.Concepts.Documentation as Doc (doccon, doccon') at the top of Body.hs.

symbMap maps references the the chunk database. Please review the GlassBR, NoPCM, and Projectile examples to understand how to populate it.

  1. You may choose to build your program every so often to keep track of errors easily.

Adding Goal Statements section

  1. Add a new subsection to mkSRS after PhySysDesc so that the SSD section looks like this:
SSDSec $ 
    SSDProg
      [ SSDProblem $ PDProg prob []
        [ TermsAndDefs Nothing terms
      , PhySysDesc pendulumTitle physSystParts figMotion []
      , Goals goalsInputs] -- This adds a goals section and goals input is defined for the preamble of the goal.
  1. The goalsInputs function defines the preamble of your goal statement. You can define goalsInputs in Body.hs or in a new Goals.hs file. For this guide, we will use a new Goals module.
  2. Create a new module Goals.hs in your working folder.
  3. Define your goal statement using 'ConceptInstance' type.
  4. You will require the goalStmtDom concept from Data.Drasil.Concepts.Documentation to be added to your import list in your Goals.hs module. You will use this function in defining your actual goal statement. Your Goals.hs file should look something like this simplified excerpt from the Pendulum example:
module Drasil.DblPendulum.Goals (goals, goalsInputs, goalRefs) where

import Language.Drasil
import Data.Drasil.Concepts.Documentation (goalStmtDom)

goals :: [ConceptInstance]
goals = [motionMass]

goalsInputs :: [Sentence]
goalsInputs = [S "the mass and length of the rod, initial angle of the mass and the gravitational constant"]

motionMass :: ConceptInstance
motionMass = cic "motionMass" 
  (S "Calculate the motion of the mass")
  "Motion-of-the-mass" goalStmtDom -- Here is where we apply goalStmtDom
  1. Add your module to the import list in Body.hs to display your Goal statement section and update symbMap as required.
  2. Add goals to your symbMap or to concIns (which will be created in step 10 of the next section).
  3. Add all other required parameters to your import list.

Adding Instance Models Section

Note: Instance Models are added with the Ims constructor under the SSDSolChSpec constructor in the Specific System Description section.

  1. Add the Instance Model section to mkSRS function in Body.hs. It should look similar to this:
        , TMs [] (Label : stdFields)
        , GDs [] ([Label, Units] ++ stdFields) ShowDerivation
        , DDs [] ([Label, Symbol, Units] ++ stdFields) ShowDerivation
        , IMs [] ([Label, Input, Output, InConstraints, OutConstraints] ++ stdFields) ShowDerivation
  1. Create a new module IMods.hs
  2. In symbMap, replace ([] :: [InstanceModel]) with iMods.
  3. In IMods.hs, create a new function iMods with type [InstanceModel] to declare your list of IM functions. E.g.
iMods :: [InstanceModel]
iMods = [iMod1, iMod2]
  1. Start defining your IM functions. See /code/drasil-theory/lib/Theory/Drasil/InstanceModel.hs for various constructors you can use in defining your instance model. Also see example projects or Haddock documentation for help. The arguments are used as follows:
    • Declare your IM constructor and the IM relational concept in the first argument.
    • Define your input and output constraints in the next argument. Ensure that your input and output constraints are already declared or defined in your Unitals.hs file.
    • Your IMs should have derivations, declare the derivation function name and use it in the third argument.
    • Declare a reference name for your IM function as a String in the fourth argument
    • You can declare a list of functions for adding notes to your IM where applicable in the fifth argument.

Your instance model will look something like this excerpt from Pendulum:

angularDisplacementIM :: InstanceModel
angularDisplacementIM = imNoRefs (OthModel angularDisplacementRC)
  [qwC lenRod $ UpFrom (Exc, exactDbl 0)
  ,qwC initialPendAngle $ UpFrom (Exc, exactDbl 0)
  , qwC gravitationalAccel $ UpFrom (Exc, exactDbl 0)]
  (qw pendDisplacementAngle) [UpFrom (Exc, exactDbl 0)]
  (Just angularDisplacementDeriv) "calOfAngularDisplacement" [angularDispConstraintNote]
  1. Define your RelationalConcept by defining the equation and a label for your IM. E.g
angularDisplacementRC :: RelationConcept
angularDisplacementRC = makeRC "angularDisplacementRC" (nounPhraseSP "calculation of angular displacement") -- Label goes here.
  EmptyS $ apply1 pendDisplacementAngle time $= sy initialPendAngle `mulRe` cos ( sy angularFrequency `mulRe` sy time) -- Equation goes here.
  1. Define functions for your derivation, declared in the third argument of your instance model. You will need the weave function to combine derivation sentences and equations. See example projects for more details. Here is an excerpt from Pendulum for the top-level angularDisplacementDeriv function (which is used in angularDisplacementTM as shown above):
angularDisplacementDeriv :: Derivation
angularDisplacementDeriv = mkDerivName (phrase angularDisplacement) (weave [angularDisplacementDerivSents, map eS angularDisplacementDerivEqns])

angularDisplacementDerivSents :: [Sentence]
angularDisplacementDerivSents = [angularDisplacementDerivSent1, angularDisplacementDerivSent2, angularDisplacementDerivSent3,
                             angularDisplacementDerivSent4, angularDisplacementDerivSent5]
  1. Define separate functions for your derivation sentences and equations.
  2. Define functions for notes where applicable, as declared in the fifth argument of your instance model. E.g.
angularDispConstraintNote :: Sentence
angularDispConstraintNote = foldlSent [atStartNP (the constraint),
     eS (sy initialPendAngle $> exactDbl 0) `S.is` (S "required" !.),
     atStartNP (the angularFrequency) `S.is` definedIn'' angFrequencyGD]
  1. Add all the required imports.
  2. Update symbols function in Unitals.hs where applicable.
  3. Update the chunk database (symbMap) as applicable.

Adding Requirements Section

  1. Declare the requirements section in mkSRS (in Body.hs):
  ReqrmntSec $ ReqsProg
    [ FReqsSub EmptyS []
  1. Create a Requirements.hs module.
  2. Define a list function to declare all your functional requirements. See example in the code excerpt under step 5.
  3. Define your requirement functions. You will need to tag every functional requirement with funcReqDom as shown below:
funcReqs :: [ConceptInstance]
funcReqs = [verifyInptVals, calcAngPos, outputValues]

verifyInptVals, calcAngPos, outputValues :: ConceptInstance

verifyInptVals = cic "verifyInptVals" verifyInptValsDesc "Verify-Input-Values" funcReqDom
calcAngPos  = cic "calcAngPos"   calcAngPosDesc   "Calculate-Angular-Position-Of-Mass" funcReqDom
outputValues = cic "outputValues" outputValuesDesc "Output-Values" funcReqDom

verifyInptValsDesc, calcAngPosDesc, outputValuesDesc :: Sentence
  1. Define the descriptions (as Sentences) for your functional requirements.
  2. Add funcReqs to concIns in Body.hs.
concIns :: [ConceptInstance]
concIns = assumptions ++ goals ++ funcReqs
  1. Add all necessary modules and parameters to the list of imports.

Adding Other Sections

Please review GamePhysics' Body.hs to see an example of this section.

  1. You can add other sections not included explicitly in this manual into your SRS body. For example, to add an "Off the Shelf Solution" section use:
  UCsSec,
  OffShelfSonsSec $ OffShelfSolnsProg offShelfSols,

For more information regarding the different possible sections, please visit the Haddock documentation for document language.

Notes

  1. Ensure that all the units used in your project are added to unit map in symbMap function. The chunk database needs to know this information to print the SRS.
  2. Helper function to build unitals are found here: Drasil-lang/language/Drasil/chunk/Unitals.hs
  3. Remember to create functions in Unitals.hs to store your input and output parameters.
  4. If you have used any references, remember to below code into Body.hs to display your references:
refDB :: ReferenceDB
refDB = rdb citations concIns
  1. Reminder to add acronymns and symbols to usedDB chunk database to display your acronymns and symbols tables:
usedDB :: ChunkDB
usedDB = cdb ([] :: [QuantityDict]) (map nw acronymn ++ map nw symbols) ([] :: [ConceptChunk])([] :: [UnitDefn]) [] [] [] [] [] [] []
  1. Your mkSRS and si functions should now look something like this example from Projectile:
mkSRS :: SRSDecl
mkSRS = [
  RefSec $
    RefProg intro
      [ TUnits
      , tsymb [TSPurpose, TypogConvention [Vector Bold], SymbOrder, VectorUnits]
      , TAandA
      ],
  IntroSec $
    IntroProg justification (phrase projectileTitle)
      [ IScope scope ],
  SSDSec $
    SSDProg
      [ SSDProblem $ PDProg prob []
        [ TermsAndDefs Nothing terms
        , PhySysDesc projectileTitle physSystParts figLaunch []
        , Goals [(phrase iVel +:+ S "vector") `S.the_ofThe` phrase projectile]]
      , SSDSolChSpec $ SCSProg
        [ Assumptions
        , TMs [] (Label : stdFields)
        , GDs [] ([Label, Units] ++ stdFields) ShowDerivation
        , DDs [] ([Label, Symbol, Units] ++ stdFields) ShowDerivation
        , IMs [] ([Label, Input, Output, InConstraints, OutConstraints] ++ stdFields) ShowDerivation
        , Constraints EmptyS inConstraints
        , CorrSolnPpties outConstraints []
        ]
      ],
  ReqrmntSec $
    ReqsProg
      [ FReqsSub EmptyS []
      , NonFReqsSub
      ],
  TraceabilitySec $ TraceabilityProg $ traceMatStandard si,
  AuxConstntSec $
    AuxConsProg projectileTitle constants,
  Bibliography
  ]

si :: System
si = SI {
  _sys         = projectileTitle,
  _kind        = Doc.srs,
  _authors     = [samCrawford, brooks, spencerSmith],
  _purpose     = [],
  _quants      = symbols,
  _concepts    = [] :: [DefinedQuantityDict],
  _instModels  = iMods,
  _datadefs    = dataDefs,
  _configFiles = [],
  _inputs      = inputs,
  _outputs     = outputs,
  _defSequence = [] :: [Block QDefinition],
  _constraints = map cnstrw constrained,
  _constants   = constants,
  _sysinfodb   = symbMap,
  _usedinfodb  = usedDB,
   refdb       = refDB
}

Code Generation

  1. Please refer to NoPCM or GlassBR to generate code for your project from Drasil.
  2. The NoPCM example can be referred to, if your project requires an ODE, otherwise, you can refer to the GlassBR example.
  3. Before you generate your code, ensure your System structure is correct, particularly the inputs, outputs, relations, and constraints should be filled in and correct.
  4. The Drasil code generator requires that you set design variabilities for your code. An overview of design variabilities can be found in Chapter 8 of this document.

Modify Main.hs

  1. Navigate to code/drasil-example/yourProjectName. Then, mirror the Main.hs file from either GlassBR or NoPCM. Also create a new Choices.hs file and mirror that from GlassBR or NoPCM. The new Choices.hs file will let you augment your generated code depending on the choices you make.
  2. Copy the content of the Main.hs file and paste in your Main.hs project file. Keep in mind there are some elements in the file that you already have in you your Main.hs file, so carefully delete duplicated or unwanted texts and modify the other content to suit your project.
  3. Begin by modifying your design choices: see Chapter 8 of this document for more information.
  4. Update your import list as required in Choices.hs:
import Language.Drasil.Code (Choices(..), CodeSpec, codeSpec, Comments(..),
  Verbosity(..), ConstraintBehaviour(..), ImplementationType(..), Lang(..), 
  Modularity(..), Structure(..), ConstantStructure(..), ConstantRepr(..), 
  InputModule(..), AuxFile(..), Visibility(..), defaultChoices)
  1. Implement the functions created from Choices.hs into Main.hs. GlassBR is a great example to figure out where these functions go.
  2. Update the Makefile in the code folder.
  3. You may need to use some of the following functions, so add some or all of these imports to Body.hs or Choices.hs as applicable:
import Language.Drasil.Code (relToQD, quantvar, listToArray)
import Data.Drasil.ExternalLibraries.ODELibraries (scipyODESymbols, osloSymbols,
  arrayVecDepVar, apacheODESymbols, odeintSymbols)
import Database.Drasil (Block(Parallel), ChunkDB, ReferenceDB,
  System(SI), cdb, rdb, refdb, _authors, _purpose, _concepts,
  _constants, _constraints, _datadefs, _instModels, _configFiles, _defSequence,
  _inputs, _kind, _outputs, _quants, _sys, _sysinfodb, _usedinfodb)
  1. Run make.
  2. Your build folder should now contain a src folder.