Global variables (#378)

* global variables

* implemented type checking of global variable, added test case

* added a comment

* improvements based on Dave's suggestions

* improvements based on Jon's suggestions

* added test cases about global variable ordering
This commit is contained in:
Jeremy G. Siek
2021-03-15 16:06:27 -04:00
committed by GitHub
parent 41786eae25
commit ced98ef021
22 changed files with 822 additions and 3 deletions
+11
View File
@@ -0,0 +1,11 @@
// 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
// Test global variable initialization and read.
var Int: zero = 0;
fn main() -> Int {
return zero;
}
+77
View File
@@ -0,0 +1,77 @@
********** source program **********
var Int : zero = 0
fn main () -> Int {
return zero;
}
********** type checking **********
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
********** type checking complete **********
var Int : zero = 0
fn main () -> Int {
return zero;
}
********** starting execution **********
********** initializing globals **********
--- step exp 0 --->
--- step exp () --->
********** calling main function **********
{
stack: top{main()<-1>}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
--- step exp main() --->
{
stack: top{main<-1> :: main()<0>}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
--- step exp main --->
{
stack: top{fun<main><-1> :: main()<0>}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
--- handle value fun<main> with main()<1>(fun<main>,) --->
{
stack: top{()<-1> :: main()<1>(fun<main>,)}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
--- step exp () --->
{
stack: top{()<-1> :: main()<1>(fun<main>,)}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
--- handle value () with main()<2>(fun<main>,(),) --->
pattern_match((), ())
{
stack: main{return zero;<-1>} :: top{}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
--- step stmt return zero; --->
{
stack: main{zero<-1> :: return zero;<0>} :: top{}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
--- step exp zero --->
{
stack: main{0<-1> :: return zero;<0>} :: top{}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
--- handle value 0 with return zero;<1>(0,) --->
{
stack: top{0<-1>}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
result: 0
+17
View File
@@ -0,0 +1,17 @@
// 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
// Test that mutations to a global variable in one function is visible
// in another function.
var Int: flag = 1;
fn flipFlag() -> () {
flag = 0;
}
fn main() -> Int {
flipFlag();
return flag;
}
+193
View File
@@ -0,0 +1,193 @@
********** source program **********
var Int : flag = 1
fn flipFlag () -> () {
flag = 0;
}
fn main () -> Int {
flipFlag();
return flag;
}
********** type checking **********
--- step exp Int --->
--- step exp () --->
--- step exp Int --->
--- step exp Int --->
--- step exp () --->
--- step exp Int --->
********** type checking complete **********
var Int : flag = 1
fn flipFlag () -> () {
flag = 0;
return ();
}
fn main () -> Int {
flipFlag();
return flag;
}
********** starting execution **********
********** initializing globals **********
--- step exp 1 --->
--- step exp () --->
--- step exp () --->
********** calling main function **********
{
stack: top{main()<-1>}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step exp main() --->
{
stack: top{main<-1> :: main()<0>}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step exp main --->
{
stack: top{fun<main><-1> :: main()<0>}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- handle value fun<main> with main()<1>(fun<main>,) --->
{
stack: top{()<-1> :: main()<1>(fun<main>,)}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step exp () --->
{
stack: top{()<-1> :: main()<1>(fun<main>,)}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- handle value () with main()<2>(fun<main>,(),) --->
pattern_match((), ())
{
stack: main{flipFlag(); ... <-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step stmt flipFlag(); ... --->
{
stack: main{flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step stmt flipFlag(); --->
{
stack: main{flipFlag()<-1> :: flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step exp flipFlag() --->
{
stack: main{flipFlag<-1> :: flipFlag()<0> :: flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step exp flipFlag --->
{
stack: main{fun<flipFlag><-1> :: flipFlag()<0> :: flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- handle value fun<flipFlag> with flipFlag()<1>(fun<flipFlag>,) --->
{
stack: main{()<-1> :: flipFlag()<1>(fun<flipFlag>,) :: flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step exp () --->
{
stack: main{()<-1> :: flipFlag()<1>(fun<flipFlag>,) :: flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- handle value () with flipFlag()<2>(fun<flipFlag>,(),) --->
pattern_match((), ())
{
stack: flipFlag{flag = 0; ... <-1>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step stmt flag = 0; ... --->
{
stack: flipFlag{flag = 0;<-1> :: return ();<-1>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step stmt flag = 0; --->
{
stack: flipFlag{flag<-1> :: flag = 0;<0> :: return ();<-1>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step lvalue flag --->
{
stack: flipFlag{ptr<0><-1> :: flag = 0;<0> :: return ();<-1>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- handle value ptr<0> with flag = 0;<1>(ptr<0>,) --->
{
stack: flipFlag{0<-1> :: flag = 0;<1>(ptr<0>,) :: return ();<-1>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- step exp 0 --->
{
stack: flipFlag{0<-1> :: flag = 0;<1>(ptr<0>,) :: return ();<-1>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 1, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 1,
}
--- handle value 0 with flag = 0;<2>(ptr<0>,0,) --->
{
stack: flipFlag{return ();<-1>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 0, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 0,
}
--- step stmt return (); --->
{
stack: flipFlag{()<-1> :: return ();<0>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 0, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 0,
}
--- step exp () --->
{
stack: flipFlag{()<-1> :: return ();<0>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 0, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 0,
}
--- handle value () with return ();<1>((),) --->
{
stack: main{()<-1> :: flipFlag();<-1> :: return flag;<-1>} :: top{}
heap: 0, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 0,
}
--- handle value () with flipFlag();<0>((),) --->
{
stack: main{return flag;<-1>} :: top{}
heap: 0, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 0,
}
--- step stmt return flag; --->
{
stack: main{flag<-1> :: return flag;<0>} :: top{}
heap: 0, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 0,
}
--- step exp flag --->
{
stack: main{0<-1> :: return flag;<0>} :: top{}
heap: 0, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 0,
}
--- handle value 0 with return flag;<1>(0,) --->
{
stack: top{0<-1>}
heap: 0, fun<flipFlag>, fun<main>,
env: main: fun<main>, flipFlag: fun<flipFlag>, flag: 0,
}
result: 0
+11
View File
@@ -0,0 +1,11 @@
// 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
// Test type checking of global variable. Error expected.
var Int: flag = true;
fn main() -> Int {
return 0;
}
+14
View File
@@ -0,0 +1,14 @@
********** source program **********
var Int : flag = true
fn main () -> Int {
return 0;
}
********** type checking **********
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
7: type error in initializer of variable
expected: Int
actual: Bool
EXIT CODE: 255
+12
View File
@@ -0,0 +1,12 @@
// 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
// Test mutation of a global variable.
var Int: zero = 1;
fn main() -> Int {
zero = 0;
return zero;
}
+115
View File
@@ -0,0 +1,115 @@
********** source program **********
var Int : zero = 1
fn main () -> Int {
zero = 0;
return zero;
}
********** type checking **********
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
********** type checking complete **********
var Int : zero = 1
fn main () -> Int {
zero = 0;
return zero;
}
********** starting execution **********
********** initializing globals **********
--- step exp 1 --->
--- step exp () --->
********** calling main function **********
{
stack: top{main()<-1>}
heap: 1, fun<main>,
env: main: fun<main>, zero: 1,
}
--- step exp main() --->
{
stack: top{main<-1> :: main()<0>}
heap: 1, fun<main>,
env: main: fun<main>, zero: 1,
}
--- step exp main --->
{
stack: top{fun<main><-1> :: main()<0>}
heap: 1, fun<main>,
env: main: fun<main>, zero: 1,
}
--- handle value fun<main> with main()<1>(fun<main>,) --->
{
stack: top{()<-1> :: main()<1>(fun<main>,)}
heap: 1, fun<main>,
env: main: fun<main>, zero: 1,
}
--- step exp () --->
{
stack: top{()<-1> :: main()<1>(fun<main>,)}
heap: 1, fun<main>,
env: main: fun<main>, zero: 1,
}
--- handle value () with main()<2>(fun<main>,(),) --->
pattern_match((), ())
{
stack: main{zero = 0; ... <-1>} :: top{}
heap: 1, fun<main>,
env: main: fun<main>, zero: 1,
}
--- step stmt zero = 0; ... --->
{
stack: main{zero = 0;<-1> :: return zero;<-1>} :: top{}
heap: 1, fun<main>,
env: main: fun<main>, zero: 1,
}
--- step stmt zero = 0; --->
{
stack: main{zero<-1> :: zero = 0;<0> :: return zero;<-1>} :: top{}
heap: 1, fun<main>,
env: main: fun<main>, zero: 1,
}
--- step lvalue zero --->
{
stack: main{ptr<0><-1> :: zero = 0;<0> :: return zero;<-1>} :: top{}
heap: 1, fun<main>,
env: main: fun<main>, zero: 1,
}
--- handle value ptr<0> with zero = 0;<1>(ptr<0>,) --->
{
stack: main{0<-1> :: zero = 0;<1>(ptr<0>,) :: return zero;<-1>} :: top{}
heap: 1, fun<main>,
env: main: fun<main>, zero: 1,
}
--- step exp 0 --->
{
stack: main{0<-1> :: zero = 0;<1>(ptr<0>,) :: return zero;<-1>} :: top{}
heap: 1, fun<main>,
env: main: fun<main>, zero: 1,
}
--- handle value 0 with zero = 0;<2>(ptr<0>,0,) --->
{
stack: main{return zero;<-1>} :: top{}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
--- step stmt return zero; --->
{
stack: main{zero<-1> :: return zero;<0>} :: top{}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
--- step exp zero --->
{
stack: main{0<-1> :: return zero;<0>} :: top{}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
--- handle value 0 with return zero;<1>(0,) --->
{
stack: top{0<-1>}
heap: 0, fun<main>,
env: main: fun<main>, zero: 0,
}
result: 0
+15
View File
@@ -0,0 +1,15 @@
// 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
// Test overshadowing of global variable.
var Int: x = 1;
fn identity(Int: x) {
return x;
}
fn main() -> Int {
return identity(0);
}
+22
View File
@@ -0,0 +1,22 @@
********** source program **********
var Int : x = 1
fn identity (0 = Int: x) -> () {
return x;
}
fn main () -> Int {
return identity(0 = 0);
}
********** type checking **********
--- step exp Int --->
--- step exp Int --->
--- step exp () --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp () --->
10: type error in return
expected: Tuple()
actual: Int
EXIT CODE: 255
+13
View File
@@ -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
// Test a global variable depending on another global.
var Int: x = 0;
var Int: y = x;
fn main() -> Int {
return y;
}
+82
View File
@@ -0,0 +1,82 @@
********** source program **********
var Int : x = 0
var Int : y = x
fn main () -> Int {
return y;
}
********** type checking **********
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
********** type checking complete **********
var Int : x = 0
var Int : y = x
fn main () -> Int {
return y;
}
********** starting execution **********
********** initializing globals **********
--- step exp 0 --->
--- step exp x --->
--- step exp () --->
********** calling main function **********
{
stack: top{main()<-1>}
heap: 0, 0, fun<main>,
env: main: fun<main>, y: 0, x: 0,
}
--- step exp main() --->
{
stack: top{main<-1> :: main()<0>}
heap: 0, 0, fun<main>,
env: main: fun<main>, y: 0, x: 0,
}
--- step exp main --->
{
stack: top{fun<main><-1> :: main()<0>}
heap: 0, 0, fun<main>,
env: main: fun<main>, y: 0, x: 0,
}
--- handle value fun<main> with main()<1>(fun<main>,) --->
{
stack: top{()<-1> :: main()<1>(fun<main>,)}
heap: 0, 0, fun<main>,
env: main: fun<main>, y: 0, x: 0,
}
--- step exp () --->
{
stack: top{()<-1> :: main()<1>(fun<main>,)}
heap: 0, 0, fun<main>,
env: main: fun<main>, y: 0, x: 0,
}
--- handle value () with main()<2>(fun<main>,(),) --->
pattern_match((), ())
{
stack: main{return y;<-1>} :: top{}
heap: 0, 0, fun<main>,
env: main: fun<main>, y: 0, x: 0,
}
--- step stmt return y; --->
{
stack: main{y<-1> :: return y;<0>} :: top{}
heap: 0, 0, fun<main>,
env: main: fun<main>, y: 0, x: 0,
}
--- step exp y --->
{
stack: main{0<-1> :: return y;<0>} :: top{}
heap: 0, 0, fun<main>,
env: main: fun<main>, y: 0, x: 0,
}
--- handle value 0 with return y;<1>(0,) --->
{
stack: top{0<-1>}
heap: 0, 0, fun<main>,
env: main: fun<main>, y: 0, x: 0,
}
result: 0
+15
View File
@@ -0,0 +1,15 @@
// 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
// Test a global variable depending on a function.
fn f() -> Int {
return 0;
}
var Int: y = f();
fn main() -> Int {
return y;
}
+95
View File
@@ -0,0 +1,95 @@
********** source program **********
fn f () -> Int {
return 0;
}
var Int : y = f()
fn main () -> Int {
return y;
}
********** type checking **********
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
********** type checking complete **********
fn f () -> Int {
return 0;
}
var Int : y = f()
fn main () -> Int {
return y;
}
********** starting execution **********
********** initializing globals **********
--- step exp () --->
--- step exp f() --->
--- step exp f --->
--- handle value fun<f> with f()<1>(fun<f>,) --->
--- step exp () --->
--- handle value () with f()<2>(fun<f>,(),) --->
pattern_match((), ())
--- step stmt return 0; --->
--- step exp 0 --->
--- handle value 0 with return 0;<1>(0,) --->
--- step exp () --->
********** calling main function **********
{
stack: top{main()<-1>}
heap: fun<f>, 0, fun<main>,
env: main: fun<main>, y: 0, f: fun<f>,
}
--- step exp main() --->
{
stack: top{main<-1> :: main()<0>}
heap: fun<f>, 0, fun<main>,
env: main: fun<main>, y: 0, f: fun<f>,
}
--- step exp main --->
{
stack: top{fun<main><-1> :: main()<0>}
heap: fun<f>, 0, fun<main>,
env: main: fun<main>, y: 0, f: fun<f>,
}
--- handle value fun<main> with main()<1>(fun<main>,) --->
{
stack: top{()<-1> :: main()<1>(fun<main>,)}
heap: fun<f>, 0, fun<main>,
env: main: fun<main>, y: 0, f: fun<f>,
}
--- step exp () --->
{
stack: top{()<-1> :: main()<1>(fun<main>,)}
heap: fun<f>, 0, fun<main>,
env: main: fun<main>, y: 0, f: fun<f>,
}
--- handle value () with main()<2>(fun<main>,(),) --->
pattern_match((), ())
{
stack: main{return y;<-1>} :: top{}
heap: fun<f>, 0, fun<main>,
env: main: fun<main>, y: 0, f: fun<f>,
}
--- step stmt return y; --->
{
stack: main{y<-1> :: return y;<0>} :: top{}
heap: fun<f>, 0, fun<main>,
env: main: fun<main>, y: 0, f: fun<f>,
}
--- step exp y --->
{
stack: main{0<-1> :: return y;<0>} :: top{}
heap: fun<f>, 0, fun<main>,
env: main: fun<main>, y: 0, f: fun<f>,
}
--- handle value 0 with return y;<1>(0,) --->
{
stack: top{0<-1>}
heap: fun<f>, 0, fun<main>,
env: main: fun<main>, y: 0, f: fun<f>,
}
result: 0
+14
View File
@@ -0,0 +1,14 @@
// 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
// Test that a global variable may not depend on a later global.
// Error expected.
var Int: x = y;
var Int: y = 0;
fn main() -> Int {
return x;
}
+26
View File
@@ -0,0 +1,26 @@
********** source program **********
var Int : x = y
var Int : y = 0
fn main () -> Int {
return x;
}
********** type checking **********
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
--- step exp Int --->
********** type checking complete **********
var Int : x = y
var Int : y = 0
fn main () -> Int {
return x;
}
********** starting execution **********
********** initializing globals **********
--- step exp y --->
8: could not find `y`
EXIT CODE: 255