Просмотр исходного кода

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
Jeremy G. Siek 5 лет назад
Родитель
Сommit
ced98ef021

+ 8 - 0
executable_semantics/BUILD

@@ -37,6 +37,14 @@ EXAMPLES = [
     "fun5",
     "fun6_fail_type",
     "funptr1",
+    "global_variable1",
+    "global_variable2",
+    "global_variable3",
+    "global_variable4",
+    "global_variable5",
+    "global_variable6",
+    "global_variable7",
+    "global_variable8",
     "if1",
     "if2",
     "if3",

+ 9 - 0
executable_semantics/ast/declaration.cpp

@@ -28,4 +28,13 @@ void ChoiceDeclaration::Print() const {
   std::cout << "}" << std::endl;
 }
 
+// Print a global variable declaration to standard out.
+void VariableDeclaration::Print() const {
+  std::cout << "var ";
+  PrintExp(type);
+  std::cout << " : " << name << " = ";
+  PrintExp(initializer);
+  std::cout << std::endl;
+}
+
 }  // namespace Carbon

+ 31 - 0
executable_semantics/ast/declaration.h

@@ -38,10 +38,18 @@ class Declaration {
  public:  // Declaration concept API, in addition to ValueSemantic.
   void Print() const { box->Print(); }
   auto Name() const -> std::string { return box->Name(); }
+
+  // Signals a type error if the declaration is not well typed,
+  // otherwise returns this declaration with annotated types.
+  //
+  // - Parameter env: types of run-time names.
+  // - Paraemter ct_env: values of compile-time names.
   auto TypeChecked(TypeEnv env, Env ct_env) const -> Declaration {
     return box->TypeChecked(env, ct_env);
   }
+  // Add an entry in the runtime global symbol table for this declaration.
   void InitGlobals(Env& globals) const { return box->InitGlobals(globals); }
+  // Add an entry in the compile time global symbol tables for this declaration.
   auto TopLevel(ExecutionEnvironment& e) const -> void {
     return box->TopLevel(e);
   }
@@ -130,6 +138,29 @@ struct ChoiceDeclaration {
   auto TopLevel(ExecutionEnvironment&) const -> void;
 };
 
+// Global variable definition implements the Declaration concept.
+class VariableDeclaration {
+ public:
+  VariableDeclaration(int sourceLocation, std::string name, Expression* type,
+                      Expression* initializer)
+      : sourceLocation(sourceLocation),
+        name(name),
+        type(type),
+        initializer(initializer) {}
+
+  void Print() const;
+  auto Name() const -> std::string;
+  auto TypeChecked(TypeEnv env, Env ct_env) const -> Declaration;
+  void InitGlobals(Env& globals) const;
+  auto TopLevel(ExecutionEnvironment&) const -> void;
+
+ private:
+  int sourceLocation;
+  std::string name;
+  Expression* type;
+  Expression* initializer;
+};
+
 }  // namespace Carbon
 
 #endif  // EXECUTABLE_SEMANTICS_AST_DECLARATION_H_

+ 8 - 0
executable_semantics/interpreter/interpreter.cpp

@@ -304,6 +304,14 @@ auto FunctionDeclaration::InitGlobals(Env& globals) const -> void {
   globals.Set(definition->name, a);
 }
 
+// Adds an entry in `globals` mapping the variable's name to the
+// result of evaluating the initializer.
+auto VariableDeclaration::InitGlobals(Env& globals) const -> void {
+  auto v = InterpExp(globals, initializer);
+  Address a = AllocateValue(v);
+  globals.Set(name, a);
+}
+
 //    { S, H} -> { { C, E, F} :: S, H}
 // where C is the body of the function,
 //       E is the environment (functions + parameters + locals)

+ 23 - 0
executable_semantics/interpreter/typecheck.cpp

@@ -620,6 +620,9 @@ auto StructDeclaration::Name() const -> std::string { return *definition.name; }
 
 auto ChoiceDeclaration::Name() const -> std::string { return name; }
 
+// Returns the name of the declared variable.
+auto VariableDeclaration::Name() const -> std::string { return name; }
+
 auto StructDeclaration::TypeChecked(TypeEnv env, Env ct_env) const
     -> Declaration {
   auto fields = new std::list<Member*>();
@@ -642,6 +645,19 @@ auto ChoiceDeclaration::TypeChecked(TypeEnv env, Env ct_env) const
   return *this;  // TODO.
 }
 
+// Signals a type error if the initializing expression does not have
+// the declared type of the variable, otherwise returns this
+// declaration with annotated types.
+auto VariableDeclaration::TypeChecked(TypeEnv env, Env ct_env) const
+    -> Declaration {
+  TCResult typeCheckedInitializer =
+      TypeCheckExp(initializer, env, ct_env, nullptr, TCContext::ValueContext);
+  Value* declaredType = ToType(sourceLocation, InterpExp(ct_env, type));
+  ExpectType(sourceLocation, "initializer of variable", declaredType,
+             typeCheckedInitializer.type);
+  return *this;
+}
+
 auto TopLevel(std::list<Declaration>* fs) -> std::pair<TypeEnv, Env> {
   ExecutionEnvironment tops;
   bool found_main = false;
@@ -687,4 +703,11 @@ auto ChoiceDeclaration::TopLevel(ExecutionEnvironment& tops) const -> void {
   tops.first.Set(Name(), ct);
 }
 
+// Associate the variable name with it's declared type in the
+// compile-time symbol table.
+auto VariableDeclaration::TopLevel(ExecutionEnvironment& tops) const -> void {
+  Value* declaredType = ToType(sourceLocation, InterpExp(tops.second, type));
+  tops.first.Set(Name(), declaredType);
+}
+
 }  // namespace Carbon

+ 11 - 3
executable_semantics/syntax/parser.ypp

@@ -86,6 +86,7 @@ void yy::parser::error(
 %type <Carbon::Expression*> return_type
 %type <Carbon::Expression*> paren_expression
 %type <Carbon::Expression*> tuple
+%type <Carbon::Member*> variable_declaration
 %type <Carbon::Member*> member
 %type <std::list<Carbon::Member*>*> member_list
 %type <Carbon::FieldList*> field
@@ -321,9 +322,11 @@ function_declaration:
   FN identifier tuple return_type ";"
     { $$ = MakeFunDef(yylineno, $2, $4, $3, 0); }
 ;
-member:
-  VAR expression ":" identifier ";"
-    { $$ = MakeField(yylineno, $4, $2); }
+variable_declaration: expression ":" identifier
+    { $$ = MakeField(yylineno, $3, $1); }
+;
+member: VAR variable_declaration ";"
+    { $$ = $2; }
 ;
 member_list:
   // Empty
@@ -368,6 +371,11 @@ declaration:
       $$ = new Carbon::Declaration(
         Carbon::ChoiceDeclaration{yylineno, $2, std::list(*$4)});
     }
+| VAR variable_declaration "=" expression ";"
+    {
+      $$ = new Carbon::Declaration(
+        Carbon::VariableDeclaration(yylineno, *$2->u.field.name, $2->u.field.type, $4));
+    }
 ;
 declaration_list:
   // Empty

+ 11 - 0
executable_semantics/testdata/global_variable1.6c

@@ -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 - 0
executable_semantics/testdata/global_variable1.golden

@@ -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 - 0
executable_semantics/testdata/global_variable2.6c

@@ -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 - 0
executable_semantics/testdata/global_variable2.golden

@@ -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 - 0
executable_semantics/testdata/global_variable3.6c

@@ -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 - 0
executable_semantics/testdata/global_variable3.golden

@@ -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 - 0
executable_semantics/testdata/global_variable4.6c

@@ -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 - 0
executable_semantics/testdata/global_variable4.golden

@@ -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 - 0
executable_semantics/testdata/global_variable5.6c

@@ -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 - 0
executable_semantics/testdata/global_variable5.golden

@@ -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 - 0
executable_semantics/testdata/global_variable6.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
+
+// Test a global variable depending on another global.
+
+var Int: x = 0;
+
+var Int: y = x;
+
+fn main() -> Int {
+  return y;
+}

+ 82 - 0
executable_semantics/testdata/global_variable6.golden

@@ -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 - 0
executable_semantics/testdata/global_variable7.6c

@@ -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 - 0
executable_semantics/testdata/global_variable7.golden

@@ -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 - 0
executable_semantics/testdata/global_variable8.6c

@@ -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 - 0
executable_semantics/testdata/global_variable8.golden

@@ -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