diff --git a/executable_semantics/BUILD b/executable_semantics/BUILD index 0382a862e3b4..fed52985b1c3 100644 --- a/executable_semantics/BUILD +++ b/executable_semantics/BUILD @@ -72,6 +72,9 @@ EXAMPLES = [ "fun5", "fun6_fail_type", "funptr1", + "if1", + "if2", + "if3", "match_int_default", "match_int", "match_type", diff --git a/executable_semantics/syntax.ypp b/executable_semantics/syntax.ypp index 9887b2a77302..c7c3ecdf60ba 100644 --- a/executable_semantics/syntax.ypp +++ b/executable_semantics/syntax.ypp @@ -57,6 +57,7 @@ void yyerror(char* error) { %type function_definition %type declaration_list %type statement +%type optional_else %type statement_list %type expression %type pattern @@ -228,8 +229,8 @@ statement: { $$ = Carbon::MakeVarDef(yylineno, $2, $4); } | expression ';' { $$ = Carbon::MakeExpStmt(yylineno, $1); } -| IF '(' expression ')' statement ELSE statement - { $$ = Carbon::MakeIf(yylineno, $3, $5, $7); } +| IF '(' expression ')' statement optional_else + { $$ = Carbon::MakeIf(yylineno, $3, $5, $6); } | WHILE '(' expression ')' statement { $$ = Carbon::MakeWhile(yylineno, $3, $5); } | BREAK ';' @@ -243,6 +244,11 @@ statement: | MATCH '(' expression ')' '{' clause_list '}' { $$ = Carbon::MakeMatch(yylineno, $3, $6); } ; +optional_else: + // Empty + { $$ = 0; } +| ELSE statement { $$ = $2; } +; statement_list: // Empty { $$ = 0; } diff --git a/executable_semantics/testdata/if1.6c b/executable_semantics/testdata/if1.6c new file mode 100644 index 000000000000..83fb142020ea --- /dev/null +++ b/executable_semantics/testdata/if1.6c @@ -0,0 +1,10 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +fn main() -> Int { + if (1 == 1) + return 0; + + return 1; +} diff --git a/executable_semantics/testdata/if1.golden b/executable_semantics/testdata/if1.golden new file mode 100644 index 000000000000..334dfcc2c7fe --- /dev/null +++ b/executable_semantics/testdata/if1.golden @@ -0,0 +1,161 @@ +********** source program ********** +fn main () -> Int { +if ((1 == 1)) +return 0; +else + +return 1; + +} +********** type checking ********** +--- step exp Int ---> +--- step exp Int ---> + +********** type checking complete ********** +fn main () -> Int { +if ((1 == 1)) +return 0; +else + +return 1; +} +********** starting execution ********** +********** initializing globals ********** +--- step exp () ---> +********** calling main function ********** +{ +stack: top{main()<-1>} +heap: fun
, +env: main: fun
, +} +--- step exp main() ---> +{ +stack: top{main<-1> :: main()<0>} +heap: fun
, +env: main: fun
, +} +--- step exp main ---> +{ +stack: top{fun
<-1> :: main()<0>} +heap: fun
, +env: main: fun
, +} +--- handle value fun
with main()<1>(fun
,) ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: fun
, +env: main: fun
, +} +--- step exp () ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: fun
, +env: main: fun
, +} +--- handle value () with main()<2>(fun
,(),) ---> +pattern_match((), ()) +{ +stack: main{if ((1 == 1)) + ... +else + ... <-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step stmt if ((1 == 1)) + ... +else + ... ---> +{ +stack: main{if ((1 == 1)) + ... +else +<-1> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step stmt if ((1 == 1)) + ... +else + ---> +{ +stack: main{(1 == 1)<-1> :: if ((1 == 1)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp (1 == 1) ---> +{ +stack: main{1<-1> :: (1 == 1)<0> :: if ((1 == 1)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp 1 ---> +{ +stack: main{1<-1> :: (1 == 1)<0> :: if ((1 == 1)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value 1 with (1 == 1)<1>(1,) ---> +{ +stack: main{1<-1> :: (1 == 1)<1>(1,) :: if ((1 == 1)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp 1 ---> +{ +stack: main{1<-1> :: (1 == 1)<1>(1,) :: if ((1 == 1)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value 1 with (1 == 1)<2>(1,1,) ---> +{ +stack: main{true<-1> :: if ((1 == 1)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value true with if ((1 == 1)) + ... +else +<1>(true,) ---> +{ +stack: main{return 0;<-1> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step stmt return 0; ---> +{ +stack: main{0<-1> :: return 0;<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp 0 ---> +{ +stack: main{0<-1> :: return 0;<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value 0 with return 0;<1>(0,) ---> +{ +stack: top{0<-1>} +heap: fun
, +env: main: fun
, +} +result: 0 diff --git a/executable_semantics/testdata/if2.6c b/executable_semantics/testdata/if2.6c new file mode 100644 index 000000000000..24098a15ce18 --- /dev/null +++ b/executable_semantics/testdata/if2.6c @@ -0,0 +1,10 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +fn main() -> Int { + if (0 == 1) + return 1; + + return 0; +} diff --git a/executable_semantics/testdata/if2.golden b/executable_semantics/testdata/if2.golden new file mode 100644 index 000000000000..456b60a25954 --- /dev/null +++ b/executable_semantics/testdata/if2.golden @@ -0,0 +1,143 @@ +********** source program ********** +fn main () -> Int { +if ((0 == 1)) +return 1; +else + +return 0; + +} +********** type checking ********** +--- step exp Int ---> +--- step exp Int ---> + +********** type checking complete ********** +fn main () -> Int { +if ((0 == 1)) +return 1; +else + +return 0; +} +********** starting execution ********** +********** initializing globals ********** +--- step exp () ---> +********** calling main function ********** +{ +stack: top{main()<-1>} +heap: fun
, +env: main: fun
, +} +--- step exp main() ---> +{ +stack: top{main<-1> :: main()<0>} +heap: fun
, +env: main: fun
, +} +--- step exp main ---> +{ +stack: top{fun
<-1> :: main()<0>} +heap: fun
, +env: main: fun
, +} +--- handle value fun
with main()<1>(fun
,) ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: fun
, +env: main: fun
, +} +--- step exp () ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: fun
, +env: main: fun
, +} +--- handle value () with main()<2>(fun
,(),) ---> +pattern_match((), ()) +{ +stack: main{if ((0 == 1)) + ... +else + ... <-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step stmt if ((0 == 1)) + ... +else + ... ---> +{ +stack: main{if ((0 == 1)) + ... +else +<-1> :: return 0;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step stmt if ((0 == 1)) + ... +else + ---> +{ +stack: main{(0 == 1)<-1> :: if ((0 == 1)) + ... +else +<0> :: return 0;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp (0 == 1) ---> +{ +stack: main{0<-1> :: (0 == 1)<0> :: if ((0 == 1)) + ... +else +<0> :: return 0;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp 0 ---> +{ +stack: main{0<-1> :: (0 == 1)<0> :: if ((0 == 1)) + ... +else +<0> :: return 0;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value 0 with (0 == 1)<1>(0,) ---> +{ +stack: main{1<-1> :: (0 == 1)<1>(0,) :: if ((0 == 1)) + ... +else +<0> :: return 0;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp 1 ---> +{ +stack: main{1<-1> :: (0 == 1)<1>(0,) :: if ((0 == 1)) + ... +else +<0> :: return 0;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value 1 with (0 == 1)<2>(0,1,) ---> +{ +stack: main{false<-1> :: if ((0 == 1)) + ... +else +<0> :: return 0;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value false with if ((0 == 1)) + ... +else +<1>(false,) ---> +{ +stack: main{<-1> :: return 0;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step stmt ---> diff --git a/executable_semantics/testdata/if3.6c b/executable_semantics/testdata/if3.6c new file mode 100644 index 000000000000..d912c1781999 --- /dev/null +++ b/executable_semantics/testdata/if3.6c @@ -0,0 +1,13 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +fn main() -> Int { + if (0 == 0) + if (0 == 1) + return 1; + else + return 0; + + return 1; +} diff --git a/executable_semantics/testdata/if3.golden b/executable_semantics/testdata/if3.golden new file mode 100644 index 000000000000..3a6d6e68be7b --- /dev/null +++ b/executable_semantics/testdata/if3.golden @@ -0,0 +1,236 @@ +********** source program ********** +fn main () -> Int { +if ((0 == 0)) +if ((0 == 1)) +return 1; +else +return 0; +else + +return 1; + +} +********** type checking ********** +--- step exp Int ---> +--- step exp Int ---> + +********** type checking complete ********** +fn main () -> Int { +if ((0 == 0)) +if ((0 == 1)) +return 1; +else +return 0; +else + +return 1; +} +********** starting execution ********** +********** initializing globals ********** +--- step exp () ---> +********** calling main function ********** +{ +stack: top{main()<-1>} +heap: fun
, +env: main: fun
, +} +--- step exp main() ---> +{ +stack: top{main<-1> :: main()<0>} +heap: fun
, +env: main: fun
, +} +--- step exp main ---> +{ +stack: top{fun
<-1> :: main()<0>} +heap: fun
, +env: main: fun
, +} +--- handle value fun
with main()<1>(fun
,) ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: fun
, +env: main: fun
, +} +--- step exp () ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: fun
, +env: main: fun
, +} +--- handle value () with main()<2>(fun
,(),) ---> +pattern_match((), ()) +{ +stack: main{if ((0 == 0)) + ... +else + ... <-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step stmt if ((0 == 0)) + ... +else + ... ---> +{ +stack: main{if ((0 == 0)) + ... +else +<-1> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step stmt if ((0 == 0)) + ... +else + ---> +{ +stack: main{(0 == 0)<-1> :: if ((0 == 0)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp (0 == 0) ---> +{ +stack: main{0<-1> :: (0 == 0)<0> :: if ((0 == 0)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp 0 ---> +{ +stack: main{0<-1> :: (0 == 0)<0> :: if ((0 == 0)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value 0 with (0 == 0)<1>(0,) ---> +{ +stack: main{0<-1> :: (0 == 0)<1>(0,) :: if ((0 == 0)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp 0 ---> +{ +stack: main{0<-1> :: (0 == 0)<1>(0,) :: if ((0 == 0)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value 0 with (0 == 0)<2>(0,0,) ---> +{ +stack: main{true<-1> :: if ((0 == 0)) + ... +else +<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value true with if ((0 == 0)) + ... +else +<1>(true,) ---> +{ +stack: main{if ((0 == 1)) + ... +else + ... <-1> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step stmt if ((0 == 1)) + ... +else + ... ---> +{ +stack: main{(0 == 1)<-1> :: if ((0 == 1)) + ... +else + ... <0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp (0 == 1) ---> +{ +stack: main{0<-1> :: (0 == 1)<0> :: if ((0 == 1)) + ... +else + ... <0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp 0 ---> +{ +stack: main{0<-1> :: (0 == 1)<0> :: if ((0 == 1)) + ... +else + ... <0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value 0 with (0 == 1)<1>(0,) ---> +{ +stack: main{1<-1> :: (0 == 1)<1>(0,) :: if ((0 == 1)) + ... +else + ... <0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp 1 ---> +{ +stack: main{1<-1> :: (0 == 1)<1>(0,) :: if ((0 == 1)) + ... +else + ... <0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value 1 with (0 == 1)<2>(0,1,) ---> +{ +stack: main{false<-1> :: if ((0 == 1)) + ... +else + ... <0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value false with if ((0 == 1)) + ... +else + ... <1>(false,) ---> +{ +stack: main{return 0;<-1> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step stmt return 0; ---> +{ +stack: main{0<-1> :: return 0;<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- step exp 0 ---> +{ +stack: main{0<-1> :: return 0;<0> :: return 1;<-1>} :: top{} +heap: fun
, +env: main: fun
, +} +--- handle value 0 with return 0;<1>(0,) ---> +{ +stack: top{0<-1>} +heap: fun
, +env: main: fun
, +} +result: 0