-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Drasil Research Group Meeting, Monday, Apr 29, 3:00 pm, ITB/225 #3712
Comments
Sounds like a good topic for discussion @balacij. At the moment I don't have any other ideas for discussion points, so if someone has an idea for a second agenda item, please feel free to suggest it. 😄 |
Thanks! I'm trying to map out the way the code generator works (it's proving to be a bit challenging!), so I'm hoping we can clarify things in the meeting. I'm also trying to be a bit thorough with what I bring to the discussion, so we can get some further documentation out of it! |
Sounds like a great use of our time @balacij! |
Super minor thing, but "onboarding" seems to be one word (although my Firefox spellchecker disagrees!) - the rest of the document looks good, although maybe we could add contact information to the section on team members? |
Thanks @samm82. I agree that onboarding should be one word. I thought about including contact information, but since the onboarding document is on a public repo, I'm not sure everyone would want this. |
I will be virtual today, as I need to wait for the window repair crew to arrive in the afternoon. Looking forward to discussing generator and summer work related topics :)! |
Extending the Code Generator: Fully Unmodular Code GenerationObjectiveNo modules, no functions generation (#3512) Extend the Drasil's code generator for “big ball of mud”/single-file project generation. ContextI have a vague idea of how the code generation works, but now I'm working with it, and don't want to introduce any technical debts through confused patches. So, I want to understand it and extend it properly, which can only be done by first examining the design of Drasil. ProblemThe task should not be complicated (because we have all the needed pieces of code already written), but stitching it together (in an understandable, maintainable) way is proving difficult, in part because the code is undocumented. ExplorationAssumptions
Journey0. Looking at generated artifactsProjectile under an unmodular, “program” program type with no logging appears to be the most relevant Key finding: we can generate relatively minimal forms of Projectile already using the “unpopular program” program type. Observations:
Analysis (ignoring topics unrelated to the issue at hand for now…):
1. Tracking down where
|
-- | Generates an SCS program based on the problem and the user's design choices. | |
genProgram :: (OOProg r) => GenState (GSProgram r) | |
genProgram = do | |
g <- get | |
ms <- chooseModules $ modular g | |
let n = pName $ codeSpec g | |
let p = show $ sentenceDoc (sysinfodb $ codeSpec g) Implementation OneLine $ foldlSent $ purpose $ codeSpec g | |
return $ prog n p ms | |
-- | Generates either a single module or many modules, based on the users choice | |
-- of modularity. | |
chooseModules :: (OOProg r) => Modularity -> GenState [SFile r] | |
chooseModules Unmodular = liftS genUnmodular | |
chooseModules (Modular _) = genModules |
Key finding: genUnmodular
is what orchestrates building a software package with an “unmodular” layout.
Drasil/code/drasil-code/lib/Language/Drasil/Code/Imperative/Generator.hs
Lines 176 to 191 in d5c42ef
-- | Generates an entire SCS program as a single module. | |
genUnmodular :: (OOProg r) => GenState (SFile r) | |
genUnmodular = do | |
g <- get | |
umDesc <- unmodularDesc | |
let n = pName $ codeSpec g | |
cls = any (`member` clsMap g) | |
["get_input", "derived_values", "input_constraints"] | |
genModuleWithImports n umDesc (concatMap (^. imports) (elems $ extLibMap g)) | |
(genMainFunc | |
: map (fmap Just) (map genCalcFunc (execOrder $ codeSpec g) | |
++ concatMap genModFuncs (modules g)) | |
++ ((if cls then [] else [genInputFormat Pub, genInputDerived Pub, | |
genInputConstraints Pub]) ++ [genOutputFormat])) | |
([genInputClass Auxiliary, genConstClass Auxiliary] | |
++ map (fmap Just) (concatMap genModClasses $ modules g)) |
Analysis:
- It derives a module with a name, imports, flow, program entry function, and declared functions from a “code specification.”
- To make the truly unmodular program, we need to instead derive a program entry function that encapsulates everything other than the imports and the name.
Commentary:
- Ignoring what we know about Drasil -- unclear why
drasil-code
refers to SCS at all. - I have no idea why
cls
exists in the body ofgenModular
nor how it works. It relies on implicit knowledge of certain names. - A module is declared "all in one go."
- Naively removing all declared functions in the module constructed other than
genMainFunc
permits creation of a program with references to things that don't exist, and with without any warnings or errors.
3. Investigating the Code Specification
CodeSpec
declaration:
Drasil/code/drasil-code/lib/Language/Drasil/CodeSpec.hs
Lines 40 to 75 in d5c42ef
-- | Code specifications. Holds information needed to generate code. | |
data CodeSpec where | |
CodeSpec :: (HasName a) => { | |
-- | Program name. | |
pName :: Name, | |
-- | Authors. | |
authors :: [a], | |
-- | Purpose. | |
purpose :: Purpose, | |
-- | Example Background. | |
background :: Background, | |
-- | All inputs. | |
inputs :: [Input], | |
-- | Explicit inputs (values to be supplied by a file). | |
extInputs :: [Input], | |
-- | Derived inputs (each calculated from explicit inputs in a single step). | |
derivedInputs :: [Derived], | |
-- | All outputs. | |
outputs :: [Output], | |
-- | List of files that must be in same directory for running the executable. | |
configFiles :: [FilePath], | |
-- | Mathematical definitions, ordered so that they form a path from inputs to | |
-- outputs. | |
execOrder :: [Def], | |
-- | Map from 'UID's to constraints for all constrained chunks used in the problem. | |
cMap :: ConstraintCEMap, | |
-- | List of all constants used in the problem. | |
constants :: [Const], | |
-- | Map containing all constants used in the problem. | |
constMap :: ConstantMap, | |
-- | Additional modules required in the generated code, which Drasil cannot yet | |
-- automatically define. | |
mods :: [Mod], -- medium hack | |
-- | The database of all chunks used in the problem. | |
sysinfodb :: ChunkDB | |
} -> CodeSpec |
CodeSpec
constructor:
Drasil/code/drasil-code/lib/Language/Drasil/CodeSpec.hs
Lines 95 to 138 in d5c42ef
-- | Defines a 'CodeSpec' based on the 'SystemInformation', 'Choices', and 'Mod's | |
-- defined by the user. | |
codeSpec :: SystemInformation -> Choices -> [Mod] -> CodeSpec | |
codeSpec SI {_sys = sys | |
, _authors = as | |
, _purpose = ps | |
, _background = bk | |
, _instModels = ims | |
, _datadefs = ddefs | |
, _configFiles = cfp | |
, _inputs = ins | |
, _outputs = outs | |
, _constraints = cs | |
, _constants = cnsts | |
, _sysinfodb = db} chs ms = | |
let n = programName sys | |
inputs' = map quantvar ins | |
const' = map qtov (filter ((`Map.notMember` conceptMatch (maps chs)) . (^. uid)) | |
cnsts) | |
derived = map qtov $ getDerivedInputs ddefs inputs' const' db | |
rels = (map qtoc (getEqModQdsFromIm ims ++ mapMaybe qdEFromDD ddefs) \\ derived) | |
++ mapODE (getODE $ extLibs chs) | |
-- TODO: When we have better DEModels, we should be deriving our ODE information | |
-- directly from the instance models (ims) instead of directly from the choices. | |
outs' = map quantvar outs | |
allInputs = nub $ inputs' ++ map quantvar derived | |
exOrder = getExecOrder rels (allInputs ++ map quantvar cnsts) outs' db | |
in CodeSpec { | |
pName = n, | |
authors = as, | |
purpose = ps, | |
background = bk, | |
inputs = allInputs, | |
extInputs = inputs', | |
derivedInputs = derived, | |
outputs = outs', | |
configFiles = cfp, | |
execOrder = exOrder, | |
cMap = constraintMap cs, | |
constants = const', | |
constMap = assocToMap const', | |
mods = ms, | |
sysinfodb = db | |
} |
Analysis:
- A
CodeSpec
copies some information directly from aSystemInformation
into itself, implying that uses of thatCodeSpec
relies on "higher-level" knowledge (I'm saying this in the Multi-level Modelling sense, all features dependent on thisCodeSpec
are also dependent on a specific higher-levelSystemInformation
). - A
CodeSpec
derives input and output variables, and a list of “relations” (formulas) from aSystemInformation
.- The IO variables are of type
CodeVarChunk
, which are really just wrappers around aCodeChunk
, which are really just wrappers around aQuantityDict
. However, aCodeChunk
carries one additional piece of information:VarOrFunc
(comment on the chunk definition: "the kind of code", presuming to mean how we want it to be represented [?]). - Constant variables and derived variables are captured using
CodeDefinition
s (constructed usingqtov
orqtoc
, variables or functions, respectively), which are more or less clones of aQDefinition
, except using aCodeChunk
and aCodeExpr
instead of aQuantityDict
and polymorphic type parameter. Derived variables, notably, are defined usingqtoc
(functions!) declarations.
- The IO variables are of type
Comments:
- I don't think the name fits what's in the record. A “code”/codebase specification, to me, either refers to the design of a codebase (implementation-design knowledge), expectations of a codebase (axiomatic behaviour of an implementation), or both.
Relevant snippets:
Drasil/code/drasil-lang/lib/Language/Drasil/Chunk/CodeVar.hs
Lines 46 to 54 in d5c42ef
-- | Details if a piece of code is meant to be a variable or a function. | |
data VarOrFunc = Var | Func | |
-- | Basic chunk representation in the code generation context. | |
-- Contains a QuantityDict and the kind of code (variable or function). | |
data CodeChunk = CodeC { _qc :: QuantityDict | |
, kind :: VarOrFunc -- TODO: Jason: Once we have function spaces, I believe we won't need to store this | |
} | |
makeLenses ''CodeChunk |
Drasil/code/drasil-lang/lib/Language/Drasil/Chunk/CodeVar.hs
Lines 73 to 77 in d5c42ef
-- | Chunk representing a variable. The @obv@ field represents the object containing | |
-- this variable, if it is an object field. | |
data CodeVarChunk = CodeVC {_ccv :: CodeChunk, | |
_obv :: Maybe CodeChunk} | |
makeLenses ''CodeVarChunk |
4. Attempt #1: Naïvely
Since a CodeSpec
appears to merely declare how we want variables and such from an SRS to appear in a codebase: we should be able to change our declaration type of derived variables from Func
to Var
to inline their definition, right?
rels = (map qtoc (getEqModQdsFromIm ims ++ mapMaybe qdEFromDD ddefs) \\ derived)
++ mapODE (getODE $ extLibs chs)
->
rels = (map qtov (getEqModQdsFromIm ims ++ mapMaybe qdEFromDD ddefs) \\ derived)
++ mapODE (getODE $ extLibs chs)
Diff:
diff --strip-trailing-cr -r -X ../.gitignore stable/projectile/projectile_u_p_nol_u_wi_v_d/src/python/Projectile.py build/projectile/projectile_u_p_nol_u_wi_v_d/src/python/Projectile.py
13c13
< def func_t_flight(v_launch, theta, g):
---
> def t_flight(v_launch, theta, g):
21c21
< def func_p_land(v_launch, theta, g):
---
> def p_land(v_launch, theta, g):
28c28
< def func_d_offset(p_target, p_land):
---
> def d_offset(p_target, p_land):
36c36
< def func_s(p_target, epsilon, d_offset):
---
> def s(p_target, epsilon, d_offset):
113,116c113,116
< t_flight = func_t_flight(v_launch, theta, g)
< p_land = func_p_land(v_launch, theta, g)
< d_offset = func_d_offset(p_target, p_land)
< s = func_s(p_target, epsilon, d_offset)
---
> t_flight = t_flight(v_launch, theta, g)
> p_land = p_land(v_launch, theta, g)
> d_offset = d_offset(p_target, p_land)
> s = s(p_target, epsilon, d_offset)
Analysis:
CodeSpec
does not specify what I thought it does, nor is it clear what it specifies.VarOrFunc
is only used to decide whether to append afunc_
to aQuantityDict
s symbol or not.QuantityDict
s are carried, within aCodeSpec
, in containers of conflicting types:CodeVarChunk
and aCodeFuncChunk
can both relate to the sameQuantityDict
, and there won't be any sort of scoping issue found by theCodeSpec
(but it seems to be a part of the design?).
5. Attempt #2. Modifying genMainFunc
genMainFunc
:
-- | Generates a main function, to act as the controller for an SCS program. | |
-- The controller declares input and constant variables, then calls the | |
-- functions for reading input values, calculating derived inputs, checking | |
-- constraints, calculating outputs, and printing outputs. | |
-- Returns Nothing if the user chose to generate a library. | |
genMainFunc :: (OOProg r) => GenState (Maybe (SMethod r)) | |
genMainFunc = do | |
g <- get | |
let mainFunc Library = return Nothing | |
mainFunc Program = do | |
v_filename <- mkVar $ quantvar inFileName | |
logInFile <- maybeLog v_filename | |
co <- initConsts | |
ip <- getInputDecl | |
ics <- getAllInputCalls | |
varDef <- mapM getCalcCall (execOrder $ codeSpec g) | |
wo <- getOutputCall | |
return $ Just $ (if CommentFunc `elem` commented g then docMain else | |
mainFunction) $ bodyStatements $ initLogFileVar (logKind g) | |
++ varDecDef v_filename (arg 0) | |
: logInFile | |
-- Constants must be declared before inputs because some derived | |
-- input definitions or input constraints may use the constants | |
++ catMaybes [co, ip] ++ ics ++ catMaybes (varDef ++ [wo]) | |
mainFunc $ implType g |
The line of interest that generates the calculation-assignment steps using strictly function calls.
varDef <- mapM getCalcCall (execOrder $ codeSpec g) |
The function calls:
Drasil/code/drasil-code/lib/Language/Drasil/Code/Imperative/FunctionCalls.hs
Lines 50 to 58 in d5c42ef
-- | Generates a call to a calculation function, given the 'CodeDefinition' for the | |
-- value being calculated. | |
getCalcCall :: (OOProg r) => CodeDefinition -> GenState (Maybe (MSStatement r)) | |
getCalcCall c = do | |
t <- codeType c | |
val <- getFuncCall (codeName c) (convType t) (getCalcParams c) | |
v <- mkVar $ quantvar c | |
l <- maybeLog v | |
return $ fmap (multi . (: l) . varDecDef v) val |
We can naively modify this area of code to, instead of generate function calls, inline the CodeDefinition
-provided formulas necessary to calculating things, but:
- there is no sanity checking (scopes, types, etc.),
CodeSpec
is left confused,Modularity
would need to be passed around to areas related but also that heavily diverge,CodeXChunk
s andCodeChunks
remain data wrappers that add little information, but would also always be generated despite their irrelevance.
This solution is hacky, in my opinion. To me, the Modularity
should denote two kinds, as they are now, but those two modularity kinds should also denote unique transformers that derive program designs from SCS calculation schemes. SCS calculation schemes are what CodeSpec
really should denote, too.
drasil-code's data types
ripgrep-searched for 'data/(new)?type' declarations
rg "(data\s+[A-Z]+[A-Za-z]+|(new)?type\s+[A-Z]+[A-Za-z]+\s+=)" -ths > drasil-code-data-types.out
lib/Language/Drasil/Code/ExternalLibrary.hs:type Condition = CodeExpr
lib/Language/Drasil/Code/ExternalLibrary.hs:type Requires = String
lib/Language/Drasil/Code/ExternalLibrary.hs:type ExternalLibrary = [StepGroup]
lib/Language/Drasil/Code/ExternalLibrary.hs:type StepGroup = NonEmpty [Step]
lib/Language/Drasil/Code/ExternalLibrary.hs:data Step = Call FunctionInterface
lib/Language/Drasil/Code/ExternalLibrary.hs:data FunctionInterface = FI (NonEmpty Requires) FuncType CodeFuncChunk [Argument] (Maybe Result)
lib/Language/Drasil/Code/ExternalLibrary.hs:data Result = Assign CodeVarChunk | Return
lib/Language/Drasil/Code/ExternalLibrary.hs:data Argument = Arg (Maybe NamedArgument) ArgumentInfo -- Maybe named argument
lib/Language/Drasil/Code/ExternalLibrary.hs:data ArgumentInfo =
lib/Language/Drasil/Code/ExternalLibrary.hs:data Parameter = LockedParam ParameterChunk | NameableParam Space
lib/Language/Drasil/Code/ExternalLibrary.hs:data ClassInfo = Regular [MethodInfo] | Implements String [MethodInfo]
lib/Language/Drasil/Code/ExternalLibrary.hs:data MethodInfo = CI Description [Parameter] [Step]
lib/Language/Drasil/Code/ExternalLibrary.hs:data FuncType = Function | Method CodeVarChunk | Constructor
lib/Language/Drasil/Code/Code.hs:newtype Code = Code { unCode :: [(FilePath, Doc)]}
lib/Language/Drasil/Code/Lang.hs:data Lang = Cpp
lib/Language/Drasil/Code/ExternalLibraryCall.hs:type ExternalLibraryCall = [StepGroupFill]
lib/Language/Drasil/Code/ExternalLibraryCall.hs:data StepGroupFill = SGF Int [StepFill]
lib/Language/Drasil/Code/ExternalLibraryCall.hs:data StepFill = CallF FunctionIntFill
lib/Language/Drasil/Code/ExternalLibraryCall.hs:newtype FunctionIntFill = FIF [ArgumentFill]
lib/Language/Drasil/Code/ExternalLibraryCall.hs:data ArgumentFill = UserDefinedArgF (Maybe NamedArgument) CodeExpr -- ^ For arguments that are completely dependent on use case.
lib/Language/Drasil/Code/ExternalLibraryCall.hs:data ParameterFill = NameableParamF ParameterChunk | UserDefined ParameterChunk
lib/Language/Drasil/Code/ExternalLibraryCall.hs:data ClassInfoFill = RegularF [MethodInfoFill] | ImplementsF [MethodInfoFill]
lib/Language/Drasil/Code/ExternalLibraryCall.hs:data MethodInfoFill = CIF [ParameterFill] [Initializer] [StepFill]
lib/Language/Drasil/Code/ExtLibImport.hs:data ExtLibState = ELS {
lib/Language/Drasil/Chunk/CodeDefinition.hs:data DefinitionType = Definition | ODE
lib/Language/Drasil/Chunk/CodeDefinition.hs:data CodeDefinition = CD { _cchunk :: CodeChunk
lib/Language/Drasil/Chunk/ConstraintMap.hs:type ConstraintCE = Constraint CodeExpr
lib/Language/Drasil/Chunk/ConstraintMap.hs:type ConstraintCEMap = Map.Map UID [ConstraintCE]
lib/Language/Drasil/Choices.hs:data Choices = Choices {
lib/Language/Drasil/Choices.hs:data Architecture = Archt {
lib/Language/Drasil/Choices.hs:data Modularity = Modular InputModule -- ^ Different modules. For controller,
lib/Language/Drasil/Choices.hs:data InputModule = Combined -- ^ Input-related functions combined in one module.
lib/Language/Drasil/Choices.hs:data ImplementationType = Library -- ^ Generated code does not include Controller.
lib/Language/Drasil/Choices.hs:data DataInfo = DataInfo {
lib/Language/Drasil/Choices.hs:data Structure = Unbundled -- ^ Individual variables
lib/Language/Drasil/Choices.hs:data ConstantStructure = Inline -- ^ Inline values for constants.
lib/Language/Drasil/Choices.hs:data ConstantRepr = Var -- ^ Constants represented as regular variables.
lib/Language/Drasil/Choices.hs:data Maps = Maps {
lib/Language/Drasil/Choices.hs:type ConceptMatchMap = Map UID [CodeConcept]
lib/Language/Drasil/Choices.hs:type MatchedConceptMap = Map UID CodeConcept
lib/Language/Drasil/Choices.hs:data CodeConcept = Pi deriving Eq
lib/Language/Drasil/Choices.hs:type SpaceMatch = Space -> [CodeType]
lib/Language/Drasil/Choices.hs:data OptionalFeatures = OptFeats{
lib/Language/Drasil/Choices.hs:data DocConfig = DocConfig {
lib/Language/Drasil/Choices.hs:data Comments = CommentFunc -- ^ Function/method-level comments.
lib/Language/Drasil/Choices.hs:data Verbosity = Verbose | Quiet
lib/Language/Drasil/Choices.hs:data Visibility = Show
lib/Language/Drasil/Choices.hs:data LogConfig = LogConfig {
lib/Language/Drasil/Choices.hs:data Logging = LogFunc -- ^ Log messages generated for function calls.
lib/Language/Drasil/Choices.hs:data AuxFile = SampleInput FilePath
lib/Language/Drasil/Choices.hs:data Constraints = Constraints{
lib/Language/Drasil/Choices.hs:data ConstraintBehaviour = Warning -- ^ Print warning when constraint violated.
lib/Language/Drasil/Choices.hs:newtype ExtLib = Math ODE
lib/Language/Drasil/Choices.hs:data ODE = ODE{
lib/Language/Drasil/Chunk/NamedArgument.hs:newtype NamedArgument = NA {_qtd :: QuantityDict}
lib/Language/Drasil/CodeSpec.hs:type Input = CodeVarChunk
lib/Language/Drasil/CodeSpec.hs:type Output = CodeVarChunk
lib/Language/Drasil/CodeSpec.hs:type Const = CodeDefinition
lib/Language/Drasil/CodeSpec.hs:type Derived = CodeDefinition
lib/Language/Drasil/CodeSpec.hs:type Def = CodeDefinition
lib/Language/Drasil/CodeSpec.hs:data CodeSpec where
lib/Language/Drasil/CodeSpec.hs:type ConstantMap = Map.Map UID CodeDefinition
lib/Language/Drasil/CodeSpec.hs:type Known = CodeVarChunk
lib/Language/Drasil/CodeSpec.hs:type Need = CodeVarChunk
lib/Language/Drasil/Chunk/Parameter.hs:data PassBy = Val | Ref
lib/Language/Drasil/Chunk/Parameter.hs:data ParameterChunk = PC {_pcc :: CodeChunk
lib/Language/Drasil/Mod.hs:type Name = String
lib/Language/Drasil/Mod.hs:type Description = String
lib/Language/Drasil/Mod.hs:type Import = String
lib/Language/Drasil/Mod.hs:type Version = String
lib/Language/Drasil/Mod.hs:data Mod = Mod Name Description [Import] [Class] [Func]
lib/Language/Drasil/Mod.hs:data Class = ClassDef {
lib/Language/Drasil/Mod.hs:data StateVariable = SV {
lib/Language/Drasil/Mod.hs:data Func = FDef FuncDef
lib/Language/Drasil/Mod.hs:data FuncData where
lib/Language/Drasil/Mod.hs:data FuncDef where
lib/Language/Drasil/Mod.hs:type Initializer = (CodeVarChunk, CodeExpr)
lib/Language/Drasil/Mod.hs:data FuncStmt where
lib/Language/Drasil/Code/Imperative/Parameters.hs:data ParamType = In | Out deriving Eq
lib/Language/Drasil/Data/ODEInfo.hs:data ODEInfo = ODEInfo {
lib/Language/Drasil/Data/ODEInfo.hs:data ODEOptions = ODEOpts {
lib/Language/Drasil/Data/ODEInfo.hs:data ODEMethod = RK45 | BDF | Adams
lib/Language/Drasil/Code/Imperative/GenerateGOOL.hs:data ClassType = Primary | Auxiliary
lib/Language/Drasil/Data/ODELibPckg.hs:data ODELibPckg = ODELib {
lib/Language/Drasil/Code/Imperative/GenODE.hs:type ODEGenInfo = (Maybe FilePath, [(Name, ExtLibState)], (Name,Version))
lib/Language/Drasil/Code/DataDesc.hs:type DataItem = CodeVarChunk
lib/Language/Drasil/Code/DataDesc.hs:data DataDesc' = DD Data' Delimiter DataDesc' | End Data'
lib/Language/Drasil/Code/DataDesc.hs:data Data' = Datum DataItem' -- ^ Single data item.
lib/Language/Drasil/Code/DataDesc.hs:data DataItem' = DI
lib/Language/Drasil/Code/DataDesc.hs:type Delimiter = String
lib/Language/Drasil/Code/DataDesc.hs:type DataDesc = [Data]
lib/Language/Drasil/Code/DataDesc.hs:type Delim = Char -- delimiter
lib/Language/Drasil/Code/DataDesc.hs:data Data = Singleton DataItem -- ^ Single datum.
lib/Language/Drasil/Code/DataDesc.hs:data LinePattern = Straight [DataItem] -- ^ Line of data with no pattern.
lib/Language/Drasil/Code/Imperative/DrasilState.hs:type MatchedSpaces = Space -> GenState CodeType
lib/Language/Drasil/Code/Imperative/DrasilState.hs:type ExtLibMap = Map String ExtLibState
lib/Language/Drasil/Code/Imperative/DrasilState.hs:type ModExportMap = Map String String
lib/Language/Drasil/Code/Imperative/DrasilState.hs:type ClassDefinitionMap = Map String String
lib/Language/Drasil/Code/Imperative/DrasilState.hs:type GenState = State DrasilState
lib/Language/Drasil/Code/Imperative/DrasilState.hs:data DrasilState = DrasilState {
lib/Language/Drasil/Code/Imperative/DrasilState.hs:type ModExp = (String, String)
lib/Language/Drasil/Code/Imperative/DrasilState.hs:type ClassDef = (String, String)
lib/Language/Drasil/Code/Imperative/GOOL/Data.hs:data AuxData = AD {auxFilePath :: FilePath, auxDoc :: Doc}
lib/Language/Drasil/Code/Imperative/GOOL/Data.hs:data PackData = PackD {packProg :: ProgData, packAux :: [AuxData]}
lib/Language/Drasil/Code/Imperative/Doxygen/Import.hs:type OptimizeChoice = Doc
lib/Language/Drasil/Code/Imperative/Doxygen/Import.hs:type ProjName = String
lib/Language/Drasil/Code/Imperative/GOOL/ClassInterface.hs:type LangAbbrev = String
lib/Language/Drasil/Code/Imperative/GOOL/ClassInterface.hs:type LangVers = String
lib/Language/Drasil/Code/Imperative/GOOL/ClassInterface.hs:type CaseName = String
lib/Language/Drasil/Code/Imperative/GOOL/ClassInterface.hs:type ExamplePurpose = String
lib/Language/Drasil/Code/Imperative/GOOL/ClassInterface.hs:type ExampleDescr = String
lib/Language/Drasil/Code/Imperative/GOOL/ClassInterface.hs:type Contributor = String
lib/Language/Drasil/Code/Imperative/GOOL/ClassInterface.hs:type InFile = String -- TODO: There may not always be an Input/Output File
lib/Language/Drasil/Code/Imperative/GOOL/ClassInterface.hs:type OutFile = String
lib/Language/Drasil/Code/Imperative/GOOL/ClassInterface.hs:data ReadMeInfo = ReadMeInfo {
lib/Language/Drasil/Code/Imperative/Parsers/ConfigParser.hs:data Configuration = Config {genLang :: String, exImp :: Maybe String, opts :: Options}
lib/Language/Drasil/Code/Imperative/Modules.hs:type ConstraintCE = Constraint CodeExpr
lib/Language/Drasil/Code/Imperative/Modules.hs:data CalcType = CalcAssign | CalcReturn deriving Eq
lib/Language/Drasil/Code/Imperative/Build/AST.hs:type CommandFragment = MakeString
lib/Language/Drasil/Code/Imperative/Build/AST.hs:data BuildName = BMain
lib/Language/Drasil/Code/Imperative/Build/AST.hs:data Ext = CodeExt
lib/Language/Drasil/Code/Imperative/Build/AST.hs:data BuildDependencies = BcSource
lib/Language/Drasil/Code/Imperative/Build/AST.hs:data BuildConfig = BuildConfig
lib/Language/Drasil/Code/Imperative/Build/AST.hs:data RunType = Standalone
lib/Language/Drasil/Code/Imperative/Build/AST.hs:data Runnable = Runnable BuildName NameOpts RunType
lib/Language/Drasil/Code/Imperative/Build/AST.hs:data DocConfig = DocConfig Dependencies [Command]
lib/Language/Drasil/Code/Imperative/Build/AST.hs:data NameOpts = NameOpts {
lib/Language/Drasil/Code/Imperative/Build/AST.hs:type BuildCommand = [CommandFragment]
lib/Language/Drasil/Code/Imperative/Build/AST.hs:type InterpreterCommand = String
lib/Language/Drasil/Code/Imperative/Build/AST.hs:type InterpreterOption = String
lib/Language/Drasil/Code/Imperative/Build/Import.hs:data CodeHarness = Ch {
My TakeawaysLibrary version of Projectile
Our generator makes a lot of assumptions
How
|
-- | Generates either a single module or many modules, based on the users choice | |
-- of modularity. | |
chooseModules :: (OOProg r) => Modularity -> GenState [SFile r] | |
chooseModules Unmodular = liftS genUnmodular | |
chooseModules (Modular _) = genModules |
which is defined here:
Drasil/code/drasil-code/lib/Language/Drasil/Code/Imperative/Generator.hs
Lines 193 to 203 in d5c42ef
-- | Generates all modules for an SCS program. | |
genModules :: (OOProg r) => GenState [SFile r] | |
genModules = do | |
g <- get | |
mn <- genMain | |
inp <- chooseInModule $ inMod g | |
con <- genConstMod | |
cal <- genCalcMod | |
out <- genOutputMod | |
moddef <- traverse genModDef (modules g) -- hack ? | |
return $ mn : inp ++ con ++ cal : out ++ moddef |
Note that inMod
gets whether the code to generate is Separate
or Combined
:
Drasil/code/drasil-code/lib/Language/Drasil/Code/Imperative/DrasilState.hs
Lines 82 to 87 in d5c42ef
-- | Determines whether input modules are 'Combined' or 'Separated' based on the | |
-- 'Modularity' stored in 'DrasilState'. | |
inMod :: DrasilState -> InputModule | |
inMod ds = inMod' $ modular ds | |
where inMod' Unmodular = Combined | |
inMod' (Modular im) = im |
which is then handled by chooseInModule
:
Drasil/code/drasil-code/lib/Language/Drasil/Code/Imperative/Modules.hs
Lines 174 to 179 in d5c42ef
-- | Generates either a single module containing all input-related components, or | |
-- separate modules for each input-related component, depending on the user's | |
-- modularity choice. | |
chooseInModule :: (OOProg r) => InputModule -> GenState [SFile r] | |
chooseInModule Combined = genInputModCombined | |
chooseInModule Separated = genInputModSeparated |
All agenda items were covered. |
The onboarding document is excellent, @smiths 😄 ! Regarding the Learn You a Haskell link, the current one has issues with rendering. The new (and updated content-wise) link is: https://learnyouahaskell.github.io/ . Regarding point 10 in the Initial Tasks section, it might also be worth noting that they can ask us for help with (a) solving issues (the 'newcomers' issues notably are expected to have a concrete set of steps that a newcomer can follow), and (b) finding new issues (we can assign them at the start, or they can find some on their own, but we also have the issue tracker which they can scavenge through). |
Good advice @balacij. I've modified the onboarding document to reflect your feedback. |
Regrets: ?
Virtual: Levi
The text was updated successfully, but these errors were encountered: