Move the command language interpretation system into its own module #159
No reviewers
Labels
No labels
bug
ci
design
duplicate
engine
enhancement
maintenance
prospective
question
regression
stub
todo
ui
wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
StudioInfinity/dyna3!159
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "Vectornaut/dyna3:language-module"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The branch to be merged addresses issue #154 by moving the the system for interpreting commands as actions into its own module. It positions the action system as more fundamental than the language interpretation system: the language module uses lots of stuff from the action module, while the action module barely uses anything from the language module.
Snags in factoring
The separation isn't as clean as I'd like it to be, but we could see that as a point in favor of merging: on the branch to be merged, poorly-factored code stands out more because it's in the wrong module. In one case, this motivated me to find a better organization. Here are the main snags I hit.
The
DisplayValueactionThe
DisplayValueaction is so deeply intertwined with the internals of the interpretation system that I decided to move it to the new language module rather than keeping it in the action module with the rest of the default actions. The alternative would've been making lots of interpretation system structures public just for the sake of this one action.As we've discussed, we may eventually switch to a design where the
DisplayValueaction would disappear entirely, because top-level actions would be allowed to have non-unit return values. The behavior currently encoded inDisplayValuewould instead become an aspect of the command console view.Recording constructors (now better organized)
On the main branch, the
CreateElementandCreateRegulatoractions have alternative constructors that both create an object and record it in a givenEnvironmentso that it can be resolved by other descriptors in the same command. On the branch to be merged,Environmentis part of the language module, so it's awkward to put these constructors in the action module. I therefore turned them into methods ofEnvironment(commit502746f), which in hindsight seems like a better organization anyway.The
RegulatorOperatorenumerationThe
RegulatorOperatorenumeration is the only thing from the language module which is used in the action module. I've decided that it belongs in the language module, because it's an abstract syntax tree component based directly on concrete syntax rules. However, theDoRegulatorOperationaction uses it to determine which action to do. This doesn't feel like a big deal to me, so I left it as-is rather than trying to reorganize.EnvironmentI've subdivided the language module into syntax and semantics submodules (commit
6ab4308), sort of like we planned during Monday's meeting. I decided to keeplanguageas a container forsyntaxandsemanticsfor two reasons.run_scriptmethod and the end-to-end tests, which span all stages of parsing and interpretation.@ -8,3 +5,1 @@fmt,fmt::{Debug, Display, Formatter},iter,fmt::{self, Display, Formatter},What does
selfmean in the context of thisusestatement?By example: the statement
is equivalent to the statements
@ -0,0 +122,4 @@#[grammar = "language/syntax.pest"]pub struct LanguageParser;impl<'a> From<Pair<'a, Rule>> for Statement {There are all of these
Pair<...>types floating around which I think are the types of the things called "captures" when you actually try to run the pest-generated parser. The typename is not very suggestive in terms of what we are doing with these things. Is there any chance that the equivalent of a typedef could be made so that we could write (say)CaptureforPair<Rule>and then I guess we would need some similar name likeCaptured<'a>forPair<'a, Rule>or something like that. Would that be workable? Other than that (and the unfortunate current need for both Environments and Assembly entities, which I think we are resigned to at the moment,) I don't see any code issues. Running the system.Done in commit
01e62be!Move the command language interpretation system into its own moduleto WIP: Move the command language interpretation system into its own moduleLike we discussed during Monday's meeting, I've put this pull request on hold until we address issues #157 and #160, because those issues could obscure any regressions that this pull request might introduce in the test assembly loading scripts. Once pull request #161 is merged, I'll rebase this branch onto it and then put this pull request back in review mode.
caa799519b6ab43081cbPair<'a, Rule>WIP: Move the command language interpretation system into its own moduleto Move the command language interpretation system into its own moduleI've rebased onto pull request #161 and made the requested type alias, so this branch should be ready for final review!
@ -0,0 +13,4 @@)?;for statement_capture in captures {Statement::from(statement_capture).interpret(&mut Environment::new(state), None)?Why should the outside caller of
interpretcare about this Environment object? I.e., why doesn't it just take the state and generate the Environment internally? Is there a use case in which either it would be important to pass in something other than a new Environment, or where the caller would examine the mutated Environment after the call?The code you're looking at interprets a statement that sits at the root of an abstract syntax tree. Statements can also appear deeper in the tree, as the details of a detailed descriptor. In this case, the statement has to be interpreted within a pre-existing environment rather than a fresh one.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.