diff --git a/executable_semantics/BUILD b/executable_semantics/BUILD index a5f4ff86d565..25f18f17285a 100644 --- a/executable_semantics/BUILD +++ b/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", diff --git a/executable_semantics/ast/declaration.cpp b/executable_semantics/ast/declaration.cpp index 6345f853e780..30ef07a5fb1e 100644 --- a/executable_semantics/ast/declaration.cpp +++ b/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 diff --git a/executable_semantics/ast/declaration.h b/executable_semantics/ast/declaration.h index 0f9b2814d741..8f416130e591 100644 --- a/executable_semantics/ast/declaration.h +++ b/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_ diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index d378566e1d28..d3d26e00ef5c 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/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) diff --git a/executable_semantics/interpreter/typecheck.cpp b/executable_semantics/interpreter/typecheck.cpp index 85df48232b4f..ac1ae248716a 100644 --- a/executable_semantics/interpreter/typecheck.cpp +++ b/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(); @@ -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* fs) -> std::pair { 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 diff --git a/executable_semantics/syntax/parser.ypp b/executable_semantics/syntax/parser.ypp index 1e2e6d29431a..3706ce436740 100644 --- a/executable_semantics/syntax/parser.ypp +++ b/executable_semantics/syntax/parser.ypp @@ -86,6 +86,7 @@ void yy::parser::error( %type return_type %type paren_expression %type tuple +%type variable_declaration %type member %type *> member_list %type 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 diff --git a/executable_semantics/testdata/global_variable1.6c b/executable_semantics/testdata/global_variable1.6c new file mode 100644 index 000000000000..3ad1fdd5409e --- /dev/null +++ b/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; +} diff --git a/executable_semantics/testdata/global_variable1.golden b/executable_semantics/testdata/global_variable1.golden new file mode 100644 index 000000000000..e77175c84da3 --- /dev/null +++ b/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
, +env: main: fun
, zero: 0, +} +--- step exp main() ---> +{ +stack: top{main<-1> :: main()<0>} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +--- step exp main ---> +{ +stack: top{fun
<-1> :: main()<0>} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +--- handle value fun
with main()<1>(fun
,) ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +--- step exp () ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +--- handle value () with main()<2>(fun
,(),) ---> +pattern_match((), ()) +{ +stack: main{return zero;<-1>} :: top{} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +--- step stmt return zero; ---> +{ +stack: main{zero<-1> :: return zero;<0>} :: top{} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +--- step exp zero ---> +{ +stack: main{0<-1> :: return zero;<0>} :: top{} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +--- handle value 0 with return zero;<1>(0,) ---> +{ +stack: top{0<-1>} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +result: 0 diff --git a/executable_semantics/testdata/global_variable2.6c b/executable_semantics/testdata/global_variable2.6c new file mode 100644 index 000000000000..166d6d9dc47b --- /dev/null +++ b/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; +} diff --git a/executable_semantics/testdata/global_variable2.golden b/executable_semantics/testdata/global_variable2.golden new file mode 100644 index 000000000000..c6fc1b852d4d --- /dev/null +++ b/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, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- step exp main() ---> +{ +stack: top{main<-1> :: main()<0>} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- step exp main ---> +{ +stack: top{fun
<-1> :: main()<0>} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- handle value fun
with main()<1>(fun
,) ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- step exp () ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- handle value () with main()<2>(fun
,(),) ---> +pattern_match((), ()) +{ +stack: main{flipFlag(); ... <-1>} :: top{} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- step stmt flipFlag(); ... ---> +{ +stack: main{flipFlag();<-1> :: return flag;<-1>} :: top{} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- step stmt flipFlag(); ---> +{ +stack: main{flipFlag()<-1> :: flipFlag();<-1> :: return flag;<-1>} :: top{} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- step exp flipFlag() ---> +{ +stack: main{flipFlag<-1> :: flipFlag()<0> :: flipFlag();<-1> :: return flag;<-1>} :: top{} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- step exp flipFlag ---> +{ +stack: main{fun<-1> :: flipFlag()<0> :: flipFlag();<-1> :: return flag;<-1>} :: top{} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- handle value fun with flipFlag()<1>(fun,) ---> +{ +stack: main{()<-1> :: flipFlag()<1>(fun,) :: flipFlag();<-1> :: return flag;<-1>} :: top{} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- step exp () ---> +{ +stack: main{()<-1> :: flipFlag()<1>(fun,) :: flipFlag();<-1> :: return flag;<-1>} :: top{} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- handle value () with flipFlag()<2>(fun,(),) ---> +pattern_match((), ()) +{ +stack: flipFlag{flag = 0; ... <-1>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 1, +} +--- step stmt flag = 0; ... ---> +{ +stack: flipFlag{flag = 0;<-1> :: return ();<-1>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{} +heap: 1, fun, fun
, +env: main: fun
, flipFlag: fun, 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, fun
, +env: main: fun
, flipFlag: fun, 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, fun
, +env: main: fun
, flipFlag: fun, 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, fun
, +env: main: fun
, flipFlag: fun, 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, fun
, +env: main: fun
, flipFlag: fun, 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, fun
, +env: main: fun
, flipFlag: fun, flag: 0, +} +--- step stmt return (); ---> +{ +stack: flipFlag{()<-1> :: return ();<0>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{} +heap: 0, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 0, +} +--- step exp () ---> +{ +stack: flipFlag{()<-1> :: return ();<0>} :: main{flipFlag();<-1> :: return flag;<-1>} :: top{} +heap: 0, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 0, +} +--- handle value () with return ();<1>((),) ---> +{ +stack: main{()<-1> :: flipFlag();<-1> :: return flag;<-1>} :: top{} +heap: 0, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 0, +} +--- handle value () with flipFlag();<0>((),) ---> +{ +stack: main{return flag;<-1>} :: top{} +heap: 0, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 0, +} +--- step stmt return flag; ---> +{ +stack: main{flag<-1> :: return flag;<0>} :: top{} +heap: 0, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 0, +} +--- step exp flag ---> +{ +stack: main{0<-1> :: return flag;<0>} :: top{} +heap: 0, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 0, +} +--- handle value 0 with return flag;<1>(0,) ---> +{ +stack: top{0<-1>} +heap: 0, fun, fun
, +env: main: fun
, flipFlag: fun, flag: 0, +} +result: 0 diff --git a/executable_semantics/testdata/global_variable3.6c b/executable_semantics/testdata/global_variable3.6c new file mode 100644 index 000000000000..1c5f99a89dfb --- /dev/null +++ b/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; +} diff --git a/executable_semantics/testdata/global_variable3.golden b/executable_semantics/testdata/global_variable3.golden new file mode 100644 index 000000000000..0ed7876bd96d --- /dev/null +++ b/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 diff --git a/executable_semantics/testdata/global_variable4.6c b/executable_semantics/testdata/global_variable4.6c new file mode 100644 index 000000000000..762d4971e318 --- /dev/null +++ b/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; +} diff --git a/executable_semantics/testdata/global_variable4.golden b/executable_semantics/testdata/global_variable4.golden new file mode 100644 index 000000000000..ddb21b120b88 --- /dev/null +++ b/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
, +env: main: fun
, zero: 1, +} +--- step exp main() ---> +{ +stack: top{main<-1> :: main()<0>} +heap: 1, fun
, +env: main: fun
, zero: 1, +} +--- step exp main ---> +{ +stack: top{fun
<-1> :: main()<0>} +heap: 1, fun
, +env: main: fun
, zero: 1, +} +--- handle value fun
with main()<1>(fun
,) ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: 1, fun
, +env: main: fun
, zero: 1, +} +--- step exp () ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: 1, fun
, +env: main: fun
, zero: 1, +} +--- handle value () with main()<2>(fun
,(),) ---> +pattern_match((), ()) +{ +stack: main{zero = 0; ... <-1>} :: top{} +heap: 1, fun
, +env: main: fun
, zero: 1, +} +--- step stmt zero = 0; ... ---> +{ +stack: main{zero = 0;<-1> :: return zero;<-1>} :: top{} +heap: 1, fun
, +env: main: fun
, zero: 1, +} +--- step stmt zero = 0; ---> +{ +stack: main{zero<-1> :: zero = 0;<0> :: return zero;<-1>} :: top{} +heap: 1, fun
, +env: main: fun
, zero: 1, +} +--- step lvalue zero ---> +{ +stack: main{ptr<0><-1> :: zero = 0;<0> :: return zero;<-1>} :: top{} +heap: 1, fun
, +env: main: fun
, 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
, +env: main: fun
, zero: 1, +} +--- step exp 0 ---> +{ +stack: main{0<-1> :: zero = 0;<1>(ptr<0>,) :: return zero;<-1>} :: top{} +heap: 1, fun
, +env: main: fun
, zero: 1, +} +--- handle value 0 with zero = 0;<2>(ptr<0>,0,) ---> +{ +stack: main{return zero;<-1>} :: top{} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +--- step stmt return zero; ---> +{ +stack: main{zero<-1> :: return zero;<0>} :: top{} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +--- step exp zero ---> +{ +stack: main{0<-1> :: return zero;<0>} :: top{} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +--- handle value 0 with return zero;<1>(0,) ---> +{ +stack: top{0<-1>} +heap: 0, fun
, +env: main: fun
, zero: 0, +} +result: 0 diff --git a/executable_semantics/testdata/global_variable5.6c b/executable_semantics/testdata/global_variable5.6c new file mode 100644 index 000000000000..e2b86f83cd2e --- /dev/null +++ b/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); +} diff --git a/executable_semantics/testdata/global_variable5.golden b/executable_semantics/testdata/global_variable5.golden new file mode 100644 index 000000000000..51ba8a2193ab --- /dev/null +++ b/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 diff --git a/executable_semantics/testdata/global_variable6.6c b/executable_semantics/testdata/global_variable6.6c new file mode 100644 index 000000000000..3a48b6976873 --- /dev/null +++ b/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; +} diff --git a/executable_semantics/testdata/global_variable6.golden b/executable_semantics/testdata/global_variable6.golden new file mode 100644 index 000000000000..a637eb1b4d38 --- /dev/null +++ b/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
, +env: main: fun
, y: 0, x: 0, +} +--- step exp main() ---> +{ +stack: top{main<-1> :: main()<0>} +heap: 0, 0, fun
, +env: main: fun
, y: 0, x: 0, +} +--- step exp main ---> +{ +stack: top{fun
<-1> :: main()<0>} +heap: 0, 0, fun
, +env: main: fun
, y: 0, x: 0, +} +--- handle value fun
with main()<1>(fun
,) ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: 0, 0, fun
, +env: main: fun
, y: 0, x: 0, +} +--- step exp () ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: 0, 0, fun
, +env: main: fun
, y: 0, x: 0, +} +--- handle value () with main()<2>(fun
,(),) ---> +pattern_match((), ()) +{ +stack: main{return y;<-1>} :: top{} +heap: 0, 0, fun
, +env: main: fun
, y: 0, x: 0, +} +--- step stmt return y; ---> +{ +stack: main{y<-1> :: return y;<0>} :: top{} +heap: 0, 0, fun
, +env: main: fun
, y: 0, x: 0, +} +--- step exp y ---> +{ +stack: main{0<-1> :: return y;<0>} :: top{} +heap: 0, 0, fun
, +env: main: fun
, y: 0, x: 0, +} +--- handle value 0 with return y;<1>(0,) ---> +{ +stack: top{0<-1>} +heap: 0, 0, fun
, +env: main: fun
, y: 0, x: 0, +} +result: 0 diff --git a/executable_semantics/testdata/global_variable7.6c b/executable_semantics/testdata/global_variable7.6c new file mode 100644 index 000000000000..a6bb8eeb341e --- /dev/null +++ b/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; +} diff --git a/executable_semantics/testdata/global_variable7.golden b/executable_semantics/testdata/global_variable7.golden new file mode 100644 index 000000000000..74666387b11b --- /dev/null +++ b/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 with f()<1>(fun,) ---> +--- step exp () ---> +--- handle value () with f()<2>(fun,(),) ---> +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, 0, fun
, +env: main: fun
, y: 0, f: fun, +} +--- step exp main() ---> +{ +stack: top{main<-1> :: main()<0>} +heap: fun, 0, fun
, +env: main: fun
, y: 0, f: fun, +} +--- step exp main ---> +{ +stack: top{fun
<-1> :: main()<0>} +heap: fun, 0, fun
, +env: main: fun
, y: 0, f: fun, +} +--- handle value fun
with main()<1>(fun
,) ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: fun, 0, fun
, +env: main: fun
, y: 0, f: fun, +} +--- step exp () ---> +{ +stack: top{()<-1> :: main()<1>(fun
,)} +heap: fun, 0, fun
, +env: main: fun
, y: 0, f: fun, +} +--- handle value () with main()<2>(fun
,(),) ---> +pattern_match((), ()) +{ +stack: main{return y;<-1>} :: top{} +heap: fun, 0, fun
, +env: main: fun
, y: 0, f: fun, +} +--- step stmt return y; ---> +{ +stack: main{y<-1> :: return y;<0>} :: top{} +heap: fun, 0, fun
, +env: main: fun
, y: 0, f: fun, +} +--- step exp y ---> +{ +stack: main{0<-1> :: return y;<0>} :: top{} +heap: fun, 0, fun
, +env: main: fun
, y: 0, f: fun, +} +--- handle value 0 with return y;<1>(0,) ---> +{ +stack: top{0<-1>} +heap: fun, 0, fun
, +env: main: fun
, y: 0, f: fun, +} +result: 0 diff --git a/executable_semantics/testdata/global_variable8.6c b/executable_semantics/testdata/global_variable8.6c new file mode 100644 index 000000000000..41bf398067c5 --- /dev/null +++ b/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; +} diff --git a/executable_semantics/testdata/global_variable8.golden b/executable_semantics/testdata/global_variable8.golden new file mode 100644 index 000000000000..4cfe0efe1027 --- /dev/null +++ b/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