-
Notifications
You must be signed in to change notification settings - Fork 56
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
Fix uninitialized variables #171
Fix uninitialized variables #171
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @Mido-sys,
I am sorry for my late code review for this PR. I am not able to make enough time nowadays. I reviewed your PR today, and I found that the direction to solve this issue should be changed. I would like to revert this PR and will explain more details in a separate comment.
@@ -107,7 +108,9 @@ func (p *parser) parseProgram() *ast.Program { | |||
} | |||
} | |||
|
|||
if stmt != nil && strings.TrimSpace(stmt.String()) != "" { | |||
if stmt != nil && | |||
(reflect.ValueOf(stmt).Kind() == reflect.Ptr && !reflect.ValueOf(stmt).IsNil()) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to prevent using reflect in this loop. Too much reflection, and actually this is not necessary. I will leave another comment for the solution, based on the real issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sio4 , Yes, there's another way to update the parseLetStatement()
function
if !p.expectPeek(token.ASSIGN) {
return nil
}
to return stmt
instead of nil
. However, we will have to update all the parser functions to not return nil as calling stmt.String()
will panic if any of the parser functions return nil
. I made the decision to use reflection as it's the safest route considering how heavily plush relies on interfaces{} and reflections.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. also, we can fix parseStatement()
, and that could be the best. (See my another comment) With your PR, the for loop on tokens will reflect all statements returned and it is expensive and not necessary.
@@ -27,7 +27,19 @@ func Test_Let_Reassignment(t *testing.T) { | |||
r.NoError(err) | |||
r.Equal("bar\n \n \nbaz", strings.TrimSpace(s)) | |||
} | |||
func Test_Let_Ident_NotInitialized(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add a line before function start and end
Hi @Mido-sys, First of all, thank you for reporting this issue and the PR. I really appreciate it! Your solution on the original PR to use reflect to check In the method However, for this issue, the problematic method is our own and we can control it. Currently, method With this patch, your test will not get panic. Could you please take a look at this patch and let me know your concern if any? --- a/parser/parser.go
+++ b/parser/parser.go
@@ -156,9 +156,14 @@ func (p *parser) noPrefixParseFnError(t token.Type) {
}
func (p *parser) parseStatement() ast.Statement {
+ // NOTE: It returns interface. Prevent possiblity of returning a non-nil
+ // with nil value.
switch p.curToken.Type {
case token.LET:
l := p.parseLetStatement()
+ if l == nil {
+ return nil
+ }
return l
case token.S_START:
p.nextToken()
@@ -192,14 +197,15 @@ func (p *parser) parseReturnStatement(t string) *ast.ReturnStatement {
func (p *parser) parseLetStatement() *ast.LetStatement {
stmt := &ast.LetStatement{TokenAble: ast.TokenAble{Token: p.curToken}}
+ // NOTE: do not return nil but return empty structure!
if !p.expectPeek(token.IDENT) {
- return nil
+ return stmt
}
stmt.Name = &ast.Identifier{TokenAble: ast.TokenAble{Token: p.curToken}, Value: p.curToken.Literal}
if !p.expectPeek(token.ASSIGN) {
- return nil
+ return stmt
}
p.nextToken() |
What is being done in this PR?
What are the main choices made to get to this solution?
List the manual test cases you've covered before sending this PR: