-
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
Improve variable name conflict detection in GOOL #3867
Comments
We had discussed in our meeting that a more concrete example of this would be helpful, so I modified NameGenTest.hs on a separate branch. The GOOL code can be seen here: Drasil/code/drasil-code/test/NameGenExample.hs Lines 18 to 25 in 5b8e1cd
The generated Java code can be seen here: Drasil/code/stable/gooltest/java/NameGenExample/NameGenExample/NameGenExample.java Lines 9 to 21 in 5b8e1cd
As can be seen, the generated names with the for loop avoid conflicts with the first declared variables by appending a This was generated by GOOL without any issues, using functionality that has been in place for a while now (I modified the From our meeting, we came up with two solutions:
|
Amusingly, this is somewhere we could use Haskell's laziness to our advantage: we could lazily generate names and only force them to be actually generated once the full block of code has been processed, so that it would then have the full context in place in which to do correct unique generation. I've definitely seen some code "out there" that does this (I think I recall code for the generation of labels for a one-pass generation of assembly-level code). |
Great work @B-rando1. You took what we discussed in the meeting and showed results very quickly! I like the intermediate step of your first option - showing an error if two variables have the same name. From our discussion yesterday, this doesn't seem to be that difficult a change, and it would make GOOL safer. I'm not sure if it is even that bad from the user's point of view, assuming that the error message is descriptive. The user might want control over what their variable is called, instead of relying on the system making a unique name. If we do automatically make unique names in the future from the user input, there should be a log message that lets the user know, or they might be confused by the generated code. |
@JacquesCarette that's a cool idea! I'm not quite sure what we need to do to get it there. My understanding is that Haskell is lazy by default, but some operations will force evaluation at a certain point. Is there something we need to change to allow Haskell to defer name generation? |
In theory, nothing to do. In practice, you need to make sure you're not doing certain pattern matches "too early" as that will force evaluation. Plus someone's work (Noah?) on making things strict will definitely interact with this. https://wiki.haskell.org/Maintaining_laziness is a useful resource. I think http://comonad.com/reader/2014/fast-circular-substitution/ is one example of what I mean. |
I tried locating the issue by using
I'll need to do some more digging tomorrow to see what the root causes are, and if there's a good fix for them. |
This conversation came out of work on the fix to #2179.
In GOOL, there are a number of places where GOOL checks to see if a variable name has been used in order to create a new variable. Examples include:
temp
is used to temporarily store the slice in, andbegIdx
andendIdx
may be used to store the beginning or ending index, if they need to be determined at run-time.thunkAssign
-i
is generated for afor
-loop.constDecDef
capitalize constants in Python #3858 - we check to see if it is safe to capitalize the variable name before we do so.In each of these cases,
genVarName
or one of its derivatives is used to make sure that the generated variable name has not been used before. For example, if we create GOOL code that declares a variabletemp
and then does a list slice, the Java code would look something like this:This works well, but the problem is it only looks backwards; it doesn't look over the whole program. So if we did the list slice first and then declared the variable, the Java code would look like this:
This would throw an error, since we're declaring
temp
multiple times.Ideally we would do two passes so that we know ahead of time which variable names are 'reserved by the user' - i.e. not to be generated.
If we want to do something like this, what approach should we use?
throws
declarations to methods. We could look there to see if it's the right place to add this.state
ful rendering inState
ful artifact rendering: Verify it makes sense to implement (and implications), design, and implement #3864. I'm not exactly sure what that means to be honest, but @samm82 said it might give us the functionality we need.The text was updated successfully, but these errors were encountered: