-
Notifications
You must be signed in to change notification settings - Fork 12
Implement support for case statements in Ada #171
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
Changes from 4 commits
7cb8f2f
8bcddce
848a008
1e639b3
4e64f08
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -146,6 +146,10 @@ package body Tree_Walk is | |
with Pre => Nkind (N) = N_Loop_Statement, | ||
Post => Kind (Do_Loop_Statement'Result) in Class_Code; | ||
|
||
function Do_Case_Statement (N : Node_Id) return Irep | ||
with Pre => Nkind (N) = N_Case_Statement, | ||
Post => Kind (Do_Case_Statement'Result) = I_Code_Block; | ||
|
||
function Do_N_Block_Statement (N : Node_Id) return Irep | ||
with Pre => Nkind (N) = N_Block_Statement, | ||
Post => Kind (Do_N_Block_Statement'Result) = I_Code_Block; | ||
|
@@ -1764,6 +1768,79 @@ package body Tree_Walk is | |
Do_Type_Declaration (New_Type, Typedef); | ||
end Do_Itype_Reference; | ||
|
||
----------------------- | ||
-- Do_Case_Statement -- | ||
----------------------- | ||
|
||
function Do_Case_Statement (N : Node_Id) return Irep is | ||
Ret : constant Irep := New_Irep (I_Code_Block); | ||
Value : constant Irep := Do_Expression (Expression (N)); | ||
|
||
-- Auxiliary function to create a single test case | ||
-- to emplace in a condition from a list of alternative | ||
-- values. | ||
function Make_Case_Test (Alts : List_Id) return Irep; | ||
function Make_Case_Test (Alts : List_Id) return Irep is | ||
function Make_Single_Test (Alt : Node_Id) return Irep; | ||
function Make_Single_Test (Alt : Node_Id) return Irep is | ||
Ret : constant Irep := New_Irep (I_Op_Eq); | ||
Rhs : constant Irep := Do_Expression (Alt); | ||
begin | ||
Set_Lhs (Ret, Value); | ||
Set_Rhs (Ret, Rhs); | ||
Set_Type (Ret, New_Irep (I_Bool_Type)); | ||
return Ret; | ||
end Make_Single_Test; | ||
First_Alt_Test : constant Irep := Make_Single_Test (First (Alts)); | ||
This_Alt : Node_Id := First (Alts); | ||
begin | ||
Next (This_Alt); | ||
if not Present (This_Alt) then | ||
return First_Alt_Test; | ||
end if; | ||
declare | ||
Big_Or : constant Irep := New_Irep (I_Op_Or); | ||
begin | ||
Append_Op (Big_Or, First_Alt_Test); | ||
Set_Type (Big_Or, New_Irep (I_Bool_Type)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
while Present (This_Alt) loop | ||
Append_Op (Big_Or, Make_Single_Test (This_Alt)); | ||
Next (This_Alt); | ||
end loop; | ||
return Big_Or; | ||
end; | ||
end Make_Case_Test; | ||
|
||
This_Alt : Node_Id := First (Alternatives (N)); | ||
begin | ||
-- Do-while loop because there must be at least one alternative. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe I am just old and paranoid BUT ... if you are assuming something it is best to make it an assert rather than a comment; even if it is 'obvious'. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Definitely worth asserting, but the grammar does indeed guarantee this is true for now (but again, worth checking anyway, who knows what's going to happen in Ada 2023) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Parent link of one Hannes posted (case statements) |
||
loop | ||
declare | ||
This_Stmt : constant Irep := | ||
Process_Statements (Statements (This_Alt)); | ||
This_Alt_Copy : constant Node_Id := This_Alt; | ||
This_Test : Irep; | ||
begin | ||
Next (This_Alt); | ||
if not Present (This_Alt) then | ||
-- Omit test, this is either `others` | ||
-- or the last case of complete coverage | ||
This_Test := This_Stmt; | ||
Append_Op (Ret, This_Test); | ||
else | ||
This_Test := New_Irep (I_Code_Ifthenelse); | ||
Set_Cond (This_Test, | ||
Make_Case_Test | ||
(Discrete_Choices (This_Alt_Copy))); | ||
Set_Then_Case (This_Test, This_Stmt); | ||
Append_Op (Ret, This_Test); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this line (and 1829) could be moved after the if-then-else block. |
||
end if; | ||
end; | ||
exit when not Present (This_Alt); | ||
end loop; | ||
return Ret; | ||
end Do_Case_Statement; | ||
|
||
----------------------- | ||
-- Do_Loop_Statement -- | ||
----------------------- | ||
|
@@ -4031,7 +4108,7 @@ package body Tree_Walk is | |
Append_Op (Block, Do_If_Statement (N)); | ||
|
||
when N_Case_Statement => | ||
Warn_Unhandled_Construct (Statement, "case"); | ||
Append_Op (Block, Do_Case_Statement (N)); | ||
|
||
when N_Loop_Statement => | ||
Append_Op (Block, Do_Loop_Statement (N)); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
function Case_Statement return String is | ||
type Sensor_Type is (Elevation, Azimuth, Distance); | ||
Sensor : Sensor_Type := Elevation; | ||
begin | ||
case Sensor is | ||
when Elevation => return "Elevation sensor"; | ||
when Azimuth => return "Azimuth sensor"; | ||
when Distance => return "Distance sensor"; | ||
when others => return ""; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assert result |
||
end case; | ||
end Case_Statement; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
VERIFICATION SUCCESSFUL |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from test_support import * | ||
|
||
prove() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
function Case_Statement_Others_Only return String is | ||
type Sensor_Type is (Elevation, Azimuth, Distance); | ||
Sensor : Sensor_Type := Elevation; | ||
begin | ||
case Sensor is | ||
when others => return ""; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assert |
||
end case; | ||
end Case_Statement_Others_Only; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
VERIFICATION SUCCESSFUL |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from test_support import * | ||
|
||
prove() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
function Case_Statement_Range return String is | ||
type T is range 0 .. 10; | ||
X : T := 6; | ||
begin | ||
case X is | ||
when 0 .. 5 => return "Zero to five"; | ||
when 6 .. 10 => return "Six to ten"; | ||
when others => return "Invalid"; | ||
end case; | ||
end Case_Statement_Range; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ALL XFAIL gnat2goto can't handle ranges in case statements |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
VERIFICATION SUCCESSFUL |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from test_support import * | ||
|
||
prove() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
function Case_Statement_Vals return String is | ||
I : Integer := 3; | ||
begin | ||
case I is | ||
when 0 | 1 | 2 => return "Valid ternary"; | ||
when 3 => return "Invalid ternary"; | ||
when others => return ""; | ||
end case; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why does this test not assert this function returns the right value? |
||
end Case_Statement_Vals; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
VERIFICATION SUCCESSFUL |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from test_support import * | ||
|
||
prove() |
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.
Cute