-
Notifications
You must be signed in to change notification settings - Fork 25
Debugging in Drasil
Warning: Wiki should not be edited directly. Edit the files in the ./wiki/ folder instead and make a PR.
-
Issues related to
git
- Also see
git2know
- Also see
- Issues related to Drasil
- Also see the Workflow page
Below are some of the commonly encountered issues or errors when working on Drasil: Here are also some errors that have happened in the past but should be fixed (due to updates from stack, GHC, git, etc.):
- I made changes to a file on my local branch and built, the build was successful but when I checked to see my changes in the .html file, the changes I made were not visible. What can I do?
- Make sure that your code change is valid and correct.
- run
make stackArgs=-force-dirty
, this command will your machine to recompile, using the packages on your local branch.
- I made changes to the code and stable folder files on my local branch. The build build was successful. I staged and committed all changed files (in one pull request), but the GitHub Actions tests failed. What can I do?
- See the
make test
section - Also see this comment on different types of Continuous Integration (CI) errors.
- See the
When errors are thrown from Drasil programs, we will be given specific error messages in the logs. If the error message isn't familiar to you, it's best to generally search the entire code repository for that message to see what kind of error(s) could have occurred. Using grep
, we can search through the repo fairly easily!
A common and likely useful formation for using grep
commands to find errors thrown by Drasil is to use the structure:
grep "WordYouAreLookingFor" -r * --include "*.hs"
which will recursively search all files ending with the letters .hs
in the directory for occurrences of "WordYouAreLookingFor". There are some optional flags that may be useful:
-
-w
will only search for the whole word given. Whole words are determined by whitespace or non-letter characters. So words separated with a.
will still appear. BASH users may note that they may write the"*.hs"
as just*.hs
. For example, using the commandgrep "traceMGF" -r -w * --include "*.hs"
orgrep "traceMGF" -rw * --include "*.hs"
will return:
drasil-docLang/Drasil/DocumentLanguage/TraceabilityGraph.hs:traceMGF :: [LabelledContent] -> [Sentence] -> [Contents] -> [Section] -> Section
drasil-docLang/Drasil/DocumentLanguage/TraceabilityGraph.hs:traceMGF refs trailing otherContents = SRS.traceyMandG (traceMIntro refs trailing : otherContents)
drasil-docLang/Drasil/DocumentLanguage.hs:import qualified Drasil.DocumentLanguage.TraceabilityGraph as TG (traceMGF)
drasil-docLang/Drasil/DocumentLanguage.hs:mkTraceabilitySec (TraceabilityProg progs) si = TG.traceMGF trace
-
--color
will highlight the word searched in a different colour. This is useful for largergrep
searches, where each occurrence is not instantly apparent.
Running the following set of commands may help you debug any elusive errors:
make clean
make test >& make.log
Check for any warnings or errors in the logs; these are treated as errors in GitHub Actions. Just remember to delete the log file once you are finished with it!
If a chunk is not behaving as expected, try checking out the chunk logs (under code/debug
) for the specific example. Specifically, keep an eye out for duplicate UID
s attached to different terms or any other pieces of information. It may be a signal for a deeper problem. The first three tables contain traceability information from one chunk to the next, while the rest are listed from the fields of the ChunkDB
type. ChunkDB
s are usually stored in the _sysinfodb
field of SystemInformation
.
Let's say you are working on adding a new section to an example (specifically, we will be using DblPendulum
for code excerpts, but the same concepts will apply across Drasil). When you try to compile, you receive the following error message:
Reference: parnasClements1986 not found in ReferenceMap
It will be quite difficult to manually search through all the files to find this exact error message, so let's try using grep
on a small part of the error message. Using grep "not found in" -r * --include "*.hs"
(meaning that I want to traverse all files, looking only through the .hs
files for lines containing the characters "not found in") shows us that the errors starts in code/drasil-database/Database/Drasil/ChunkDB.hs
:
-- | Looks up a 'UID' in a 'UMap' table. If nothing is found, an error is thrown.
uMapLookup :: String -> String -> UID -> UMap a -> a
uMapLookup tys ms u t = getFM $ Map.lookup u t
where getFM = maybe (error $ tys ++ ": " ++ u ++ " not found in " ++ ms) fst
-- | Looks up a 'UID' in the symbol table from the 'ChunkDB'. If nothing is found, an error is thrown.
symbResolve :: ChunkDB -> UID -> QuantityDict
symbResolve m x = uMapLookup "Symbol" "SymbolMap" x $ symbolTable m
We can see that uMapLookup
is the function that actually throws the error, but it's thrown only when a lookup fails for some map (for example, the symbResolve
function resolves QuantityDict
s from the SymbolMap
of a ChunkDB
using uMapLookup
, so it can also cause errors).
Looking around the surrounding code (which will not be added to the snippet above for the sake of conserving space), we can see that when "X not found in Y-Map" errors occur, it's usually due to something not being in some ChunkDB
(the X
represents the UID
of the missing item, and the Y
represents the Map
from which it is expected but does not exist in).
Using a similar grep
to the above (searching with ChunkDB
), we find the type declaration in code/drasil-database/Database/Drasil/ChunkDB.hs
:
-- | Our chunk databases. \Must contain all maps needed in an example.\
-- In turn, these maps must contain every chunk definition or concept
-- used in its respective example, else an error is thrown.
data ChunkDB = CDB { symbolTable :: SymbolMap
, termTable :: TermMap
, defTable :: ConceptMap
, _unitTable :: UnitMap
, _traceTable :: TraceMap
, _refbyTable :: RefbyMap
, _dataDefnTable :: DatadefnMap
, _insmodelTable :: InsModelMap
, _gendefTable :: GendefMap
, _theoryModelTable :: TheoryModelMap
, _conceptinsTable :: ConceptInstanceMap
, _sectionTable :: SectionMap
, _labelledcontentTable :: LabelledContentMap
, _refTable :: ReferenceMap
} --TODO: Expand and add more databases
The ChunkDB
is the "Chunk Database", containing all "chunk definitions and concepts" for a specific "system" (example). It contains many kinds of Map
s from UIDs to various chunks.
This means that some example (likely the named one throwing the error in the first place) is missing some chunk information in it's ChunkDB
!
To resolve this, we generally want to:
-
Find where the thing we're missing was created - Again, I like to do this using
grep
usinggrep "X" -r * --include "*.hs"
. Taking the example ofparnasClements1986
, we get:
home:~/Programming/Drasil/code$ grep "parnasClements1986" -r * --include *.hs
drasil-data/Data/Drasil/Citations.hs: parnasClements1986, smithLai2005, lineSource, pointSource :: Citation
drasil-data/Data/Drasil/Citations.hs:parnasClements1986 = cArticle [dParnas, pcClements]
drasil-data/Data/Drasil/Citations.hs: "parnasClements1986"
drasil-docLang/Drasil/Sections/Introduction.hs:import Data.Drasil.Citations (parnasClements1986)
drasil-docLang/Drasil/Sections/Introduction.hs: S "Parnas and Clements point out", refS parnasClements1986 `sC`
drasil-example/Drasil/GlassBR/References.hs:import Data.Drasil.Citations (campidelli, koothoor2013, smithLai2005, parnasClements1986)
drasil-example/Drasil/GlassBR/References.hs: astm2012, beasonEtAl1998, parnasClements1986]
drasil-example/Drasil/SSP/References.hs:import Data.Drasil.Citations (jnlCGJ, koothoor2013, parnasClements1986, smithLai2005)
drasil-example/Drasil/SSP/References.hs:citations = [chen2005, parnasClements1986, koothoor2013,
drasil-example/Drasil/NoPCM/References.hs: parnasClements1986, smithLai2005)
drasil-example/Drasil/NoPCM/References.hs:citations = [incroperaEtAl2007, koothoor2013, lightstone2012, parnasClements1986, smithLai2005]
drasil-example/Drasil/GamePhysics/References.hs:import Data.Drasil.Citations (cartesianWiki, koothoor2013, parnasClements1986,
drasil-example/Drasil/GamePhysics/References.hs:citations = [parnas1978, sciComp2013, chaslesWiki, parnasClements1986,
drasil-example/Drasil/SWHS/References.hs: parnasClements1986, smithLai2005, citeRefs) where
drasil-example/Drasil/SWHS/References.hs:import Data.Drasil.Citations (koothoor2013, parnasClements1986, smithLai2005)
drasil-example/Drasil/SWHS/References.hs:citations = [bueche1986, incroperaEtAl2007, koothoor2013, lightstone2012, parnasClements1986,
Here, we can see that parnasClements1986
was created in drasil-data/Data/Drasil/Citations.hs
(we also see some examples of imports of it, so that will be helpful later too).
If no suitable results appeared, then it's likely that you will either need to create the desired function or that a UID
reference was incorrect.
-
Find where we were supposed to place it in the
ChunkDB
of that system/example - For example, with DblPendulum, we instantiate ourChunkDB
inBody.hs
here:
symbMap :: ChunkDB
symbMap = cdb (map qw iMods ++ map qw symbols)
(nw newtonSLR : nw pendulumTitle : nw mass : nw len : nw kilogram : nw inValue : nw newton : nw degree : nw radian
: nw unitVect : nw unitVectj : [nw errMsg, nw program] ++ map nw symbols ++
map nw doccon ++ map nw doccon' ++ map nw physicCon ++ map nw mathcon ++ map nw physicCon' ++
map nw physicscon ++ concepts ++ map nw physicalcon ++ map nw acronyms ++ map nw symbols ++ map nw [metre, hertz])
(map cw iMods ++ srsDomains) (map unitWrapper [metre, second, newton, kilogram, degree, radian, hertz]) dataDefs
iMods genDefns tMods concIns [] [] allRefs
-
Figure out which list we should placing it in - You will need to analyze the error message for which
Map
it is related to, and then you will need to know how thecdb
smart constructor works. This can be done through the Haddock documentation or by usinggrep
again. For ease of reference, the declaration forcdb
is as follows:
cdb :: (Quantity q, MayHaveUnit q, Idea t, Concept c, IsUnit u) =>
[q] -> [t] -> [c] -> [u] -> [DataDefinition] -> [InstanceModel] ->
[GenDefn] -> [TheoryModel] -> [ConceptInstance] -> [Section] ->
[LabelledContent] -> [Reference] -> ChunkDB
cdb s t c u d ins gd tm ci sect lc r = CDB (symbolMap s) (termMap t) (conceptMap c)
(unitMap u) Map.empty Map.empty (idMap d) (idMap ins) (idMap gd) (idMap tm)
(idMap ci) (idMap sect) (idMap lc) (idMap r)
Looking at the type signature + surrounding comments are very helpful for this.
-
Add it to that chunk map - This step heavily depends on the example, but we usually can just prepend it to the list of references. In this case, there is an
allRefs
list inside ofBody.hs
:
allRefs :: [Reference]
allRefs = nub (assumpRefs ++ bodyRefs ++ figRefs ++ goalRefs ++ dataDefRefs ++ genDefRefs
++ iModRefs ++ tModRefs ++ citeRefs ++ reqRefs ++ secRefs)
We know parnasClements1986
is a Citation
from our above grep
search, so we look for the corresponding reference function, citeRefs
:
citeRefs :: [Reference]
citeRefs = map ref citations
We then look where citations
is defined and finally add our desired reference:
citations :: BibRef
citations = [accelerationWiki, velocityWiki, hibbeler2004, cartesianWiki, parnasClements1986]
Like learning any new language, getting started with grammar in Drasil is sometimes tough and a little confusing. To help new users jump in to working with Drasil, this section will note a variety of issues that can occur when starting out.
Often in Drasil, duplicate periods can crop up in seemingly mysterious ways. Through a mix of automatically generated content and the information that the user may input into an example, keeping track of punctuation has been an increasingly complicated task. The language of Drasil has seen consistent growth in this respect, and this section will demonstrate some of the common culprits of duplicate or missing periods.
The first step in any of these grammatically related problems should always be to double check the user input. Before we even get into the different kinds of functions available for use, making sure that a sneaky hard-coded period has not cropped up is key to having an enjoyable editing experience. This can be done in many different ways, most notably:
- Using
grep
orripgrep
to search for periods. It may also be worthwhile to usegrep
including the last word before the period or quotation marks after the period, as using grep on just.
will also return all instances of the composition function native to Haskell. - Use
grep
on some words near the offending period. Often, there will be functions that are used in place of literal strings (meaning that thegrep
may fail to work if you only look for one certain word or phrase that happened to be replaced by a function). Try to avoid looking with words likeof
,a
,and
,the
, as those are often functions in the form of combinators and will not pattern match with thegrep
search. - Searching through the code manually and trying to find the spare period.
Next, we will introduce some common functions that include sentences in them. These are also very easy to mix up, so close attention is key:
-
!.
- This function should always be used in place of a literal period and as a post-fix operator (see bottom of linked page). It appends a period onto theSentence
in front of it. You may have to include the following at the top of the.hs
file where it is used:{#- LANGUAGE PostfixOperators -#}
. In addition, its (prefixed) argument and the function itself will need to be encased in brackets. -
+:+
and+:+.
- These two functions look extremely similar, so it may be difficult to see where they are used. A common case of this becoming a source of error is when+:+.
is used in conjunction with!.
or a literal period. The first one only adds a space between twoSentences
, while the latter adds a space and then appends a period to the end of the secondSentence
. When possible, using+:+.
will give a cleaner result than using both+:+
and!.
, though they will both do the same thing. -
foldLSent_
andfoldLSent
- Found inUtils.Drasil
, these functions combine a list ofSentences
into one longSentence
by placing spaces in between eachSentence
element. However, the one with the underscore does not include a period at the end, whilefoldLSent
does. These functions are often used with+:+
and+:+.
, so be on the lookout for double missing periods.
Other functions to watch out for that use the +:+.
operator:
The primary forms of capitalization within Drasil (aside from hard-coding capital letters) are to use the functions atStart
, atStartNP
, titleize
and titleizeNP
(and their plural variants). Often, these work as expected: atStart
will capitalize the first letter of a Sentence
(as if it were at the start of a sentence), and titleize
will capitalize all words in a Sentence
. However, there are some specific cases where using these functions in Drasil may cause odd behaviour. Sometimes, capitalizing a term with symbols may cause that term to render with lowercase letters only. This is currently being addressed in #2651, but for more information on the way Drasil works with capitalization, see drasil-lang/Drasil/NounPhrase.hs
(specifically, the cap
function). There were also some known issues with using combinators and capitalization, but were addressed in #2635 and #2489.
Often a rarer problem in Drasil, sometimes an unexpected term may pop up in an SRS. To investigate:
- Find the unuxpected term in the generated HTML or PDF document. Remember the section name (eg. Specific System Description, General System Description, etc.)
- Navigate through the example files to find the section where the term was used. If the section file is not obvious, try looking through
Body.hs
or the other sections around it.CTRL+F
is your friend here. - If you have found the problem, try and address a proper fix for it. This may often be caused by using a wrong term or hardcoded text in the wrong spot.
- If the problem has not been resolved, it may be have something to do with the files in
drasil-docLang
. Unfortunately, there is not really any good advice for this step other than to try and track where that term is used (using section names,grep
, andCTRL+F
should help some). - If the problem persists, it could be that a
UID
is being used for two different things. Double check to make sure each UID is unique to a specific Chunk.
This type of error can also be quite tricky to resolve, as there are many different and ever-changing parts of Drasil that rely on all the References being in a Reference Map. In order of likely cause or places to look through first:
- Start off by using
grep
on theUID
that appears and briefly searching through the path thatUID
takes. Knowing where your functions are coming from and then following through to the places they are used will always be helpful. You might even find a mistake in one of your other functions that indirectly use that specificUID
. - Check your
Main.hs
andBody.hs
files and make sure that all the functions take the complete system information (fullSI
) rather than the incomplete one (si
). Since references are automatically collected, users need to make sure that the generator functions (notablysrs
,printSetting
,genDot
, andcode
) always take in the complete system information (defined asfullSI
under most examples). - Check
drasil-docLang/DocumentLanguage.hs
to find more information on how exactly the references are gathered. This may help give you an idea of where a possible problem could arise. - Make sure all your
HasRefAddress
content is in the database. This includes data definitions, general definitions, theory models, instance models, labelled content, sections, concept instances, etc. For more information on theHasRefAddress
class, please see the Haddock documentation. - If all else fails, you can manually add in your own
References
to the chunk database by placing them in the last argument of thesymbMap
function found in theBody.hs
file of every example. For clarity, please see the excerpt from DblPendulum below:
symbMap :: ChunkDB
symbMap = cdb (map qw iMods ++ map qw symbols)
(nw newtonSLR : nw pendulumTitle : nw mass : nw len : nw kilogram : nw inValue : nw newton : nw degree : nw radian
: nw unitVect : nw unitVectj : [nw errMsg, nw program] ++ map nw symbols ++
map nw doccon ++ map nw doccon' ++ map nw physicCon ++ map nw mathcon ++ map nw mathcon' ++ map nw physicCon' ++
map nw physicscon ++ concepts ++ map nw physicalcon ++ map nw acronyms ++ map nw symbols ++ map nw [metre, hertz] ++
[nw algorithm] ++ map nw compcon ++ map nw educon ++ map nw prodtcon)
(map cw iMods ++ srsDomains) (map unitWrapper [metre, second, newton, kilogram, degree, radian, hertz]) dataDefs
iMods genDefns tMods concIns [] [] ([] :: [Reference]) -- add your references here
- Home
- Getting Started
- Documentation (of Drasil specifics)
- Design
-
Readings
- Drasil Papers and Documents
- Related Work and Inspiration
- Writing Documentation
- Compression as a Means to Learn Structure
- Glossary, Taxonomy, Ontology
- Grounded Theory
- Model Driven Scrapbook
- Model Transformation Languages
- ODE Definitions
- The Code Generator
- Suggested Reading
- Sustainability
- Productivity
- Reuse
- Formal Concept Analysis
- Generative Programming
- Software Documentation
- Units and Quantities
- Misc.
- WIP Projects