-
-
Notifications
You must be signed in to change notification settings - Fork 415
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Take exhaustive match into account when checking for field initializa…
…tion Previously, exhaustive matches were handled after we verified that an object's fields were initialized. This lead to the code such as the following not passing compiler checks: ```pony primitive Foo fun apply() : (U32 | None) => 1 type Bar is (U32 | None) actor Main let bar : Bar new create(env : Env) => match Foo() | let result : U32 => bar = result | None => bar = 0 end ``` This commit moves field initialization checking to the verify pass so that it comes after the expression pass when exhaustiveness checking is done. This also moves code to patchup matches from the refer pass to a new completeness pass that comes after the expression pass. The new `completeness_match` code is identical to `refer_match` code except that an else clause with a value of `TK_NONE` no longer means a clause exists. In the exhaustiveness checks in the expression pass, any non-exhaustive else clause that was a `TK_NONE` has since been replaced with a `else None` so, by the time we get to completeness, `TK_NONE` literally means "there's no else clause". Closes #3615
- Loading branch information
1 parent
77dfea6
commit 07750f5
Showing
10 changed files
with
173 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
## Take exhaustive match into account when checking for field initialization | ||
|
||
Previously, exhaustive matches were handled after we verified that an object's fields were initialized. This lead to the code such as the following not passing compiler checks: | ||
|
||
```pony | ||
primitive Foo | ||
fun apply() : (U32 | None) => 1 | ||
type Bar is (U32 | None) | ||
actor Main | ||
let bar : Bar | ||
new create(env : Env) => | ||
match Foo() | ||
| let result : U32 => | ||
bar = result | ||
| None => | ||
bar = 0 | ||
end | ||
``` | ||
|
||
Field initialization is now done in a later pass after exhaustiveness checking has been done. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#include "completeness.h" | ||
#include "ponyassert.h" | ||
|
||
static bool completeness_match(pass_opt_t* opt, ast_t* ast) | ||
{ | ||
(void)opt; | ||
pony_assert(ast_id(ast) == TK_MATCH); | ||
AST_GET_CHILDREN(ast, expr, cases, else_clause); | ||
|
||
size_t branch_count = 0; | ||
|
||
if(!ast_checkflag(cases, AST_FLAG_JUMPS_AWAY)) | ||
{ | ||
branch_count++; | ||
ast_inheritbranch(ast, cases); | ||
} | ||
|
||
// An else_clause of TK_NONE doesn't cont as a branch because, we are after | ||
// exhaustive match checking is done so, an else clause of TK_NONE means that | ||
// we don't need the else and have an exhaustive match. | ||
if(ast_id(else_clause) != TK_NONE && | ||
!ast_checkflag(else_clause, AST_FLAG_JUMPS_AWAY)) | ||
{ | ||
branch_count++; | ||
ast_inheritbranch(ast, else_clause); | ||
} | ||
|
||
// If all branches jump away with no value, then we do too. | ||
if(branch_count == 0) | ||
ast_setflag(ast, AST_FLAG_JUMPS_AWAY); | ||
|
||
ast_consolidate_branches(ast, branch_count); | ||
|
||
// Push our symbol status to our parent scope. | ||
ast_inheritstatus(ast_parent(ast), ast); | ||
|
||
return true; | ||
} | ||
|
||
ast_result_t pass_completeness(ast_t** astp, pass_opt_t* options) | ||
{ | ||
ast_t* ast = *astp; | ||
|
||
switch(ast_id(ast)) | ||
{ | ||
case TK_MATCH: | ||
completeness_match(options, ast); break; | ||
default: | ||
{} | ||
} | ||
|
||
return AST_OK; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#ifndef PASS_COMPLETENESS_H | ||
#define PASS_COMPLETENESS_H | ||
|
||
#include <platform.h> | ||
#include "../ast/ast.h" | ||
#include "../pass/pass.h" | ||
|
||
PONY_EXTERN_C_BEGIN | ||
|
||
ast_result_t pass_completeness(ast_t** astp, pass_opt_t* options); | ||
|
||
PONY_EXTERN_C_END | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
primitive Foo | ||
fun apply() : (U32 | None) => 1 | ||
|
||
type Bar is (U32 | None) | ||
|
||
actor Main | ||
let bar : Bar | ||
|
||
new create(env : Env) => | ||
match Foo() | ||
| let result : U32 => | ||
bar = result | ||
| None => | ||
bar = 0 | ||
end |