Skip to content
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

go: Implement break statement #30

Merged
merged 5 commits into from
Oct 11, 2022
Merged

go: Implement break statement #30

merged 5 commits into from
Oct 11, 2022

Conversation

juliaogris
Copy link
Member

@juliaogris juliaogris commented Oct 7, 2022

Implement break statement in parser and evaluator ensuring it is only
used inside a loop. Use scope to keep track of enclosing AST node and
ensure that break's scope is within a loop (while) node's scope.
Implement unreachable code with block.AlwaysTerminates method on block.

Fix bare returns in evaluator as they accidentally got ignored and
didn't stop execution. This became apparent when thinking about breaks
in evaluator.

Also, fix AlwaysReturns method on While blocks. Loops may at times never
have their body executed so can never always return.

@github-actions
Copy link

github-actions bot commented Oct 7, 2022

firebase-deployment: https://evy-lang--30-p7ccr9tp.web.app (9f848d0)

Fix bare returns in evaluator as they accidentally got ignored and
didn't stop execution.
Fix while.AlwaysReturn() logic to always return false as a loop could
not be executing its body even once which would then not result in a
return even if the body itself always returns. This was an initial
oversight, now fixed.
Copy link
Contributor

@camh- camh- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some comments for now

p.advance() // advance past IF token
scope = newInnerScope(scope)
condition := p.parseCondition(scope)
scope = scope.innerScope(ifStmt)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure this is right. The block should be the conditional block, not the if block. the if has multiple blocks and they do not share the scope. they each have their own.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a new scope is created, each time, just always containing the same outer block == ifStmt.
It is confusing I can see this, but otherwise it doesn't line up with the else statement.

I cannot have the block create its own scope, because in the case of the While .block has to be the While statement (I suppose I could, but again unnecessary extra scoping).

I've updated this now so that the conditional block creates a new block (which means there is an unnecessary extra scope for the while, but I guess that's ok).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still feel a bit wrong about this because of the asymmetry between the else branch and the if | if-else branches.

pkg/parser/parser.go Outdated Show resolved Hide resolved
Add containing block Node to scope. This is a preparatory step for break
statement parsing to ensure that the break statement is within a loop.
Refactor alwaysReturns to alwaysTerminates as a non-functional change
and pure rename. This is another preparatory step for implementing
break statements as breaks interrupt the flow like returns but
_are not_ returns.

It will be used as follows:

	while true
		if true
			return
		else
			break
		end
		print "unreachable"
	end

We can now use AlwaysTerminates instead of AlwaysReturns to also check
that a function with return specified type always returns, because loop
statements _never_ always terminated, as the loop body could be
executed 0 times.
Implement break statement in parser and evaluator ensuring it is only
used inside a loop. Use scope to keep track of enclosing AST node and
ensure that break's scope is within a loop, a *While AST node.

Implement unreachable code with block.AlwaysTerminates method on block.
AlwaysTerminates means there is either a `return` or `break` statement
within all paths of the loop body. All code following is unreachable.
E.g.:

	while true
		if true
			return
		else
			break
		end
		print "unreachable"
	end
Copy link
Contributor

@camh- camh- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite the marathon, but this now LGTM! 🎉

🟢

@juliaogris juliaogris merged commit b8c1ecb into master Oct 11, 2022
@juliaogris juliaogris deleted the break branch October 11, 2022 01:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants