diff --git a/executable_semantics/ast/BUILD b/executable_semantics/ast/BUILD index 480a04048087..3348f10b157d 100644 --- a/executable_semantics/ast/BUILD +++ b/executable_semantics/ast/BUILD @@ -14,10 +14,10 @@ cc_library( "declaration.h", ], deps = [ + ":class_definition", ":function_definition", ":member", ":pattern", - ":struct_definition", "//common:ostream", "//executable_semantics/common:ptr", "@llvm-project//llvm:Support", @@ -115,8 +115,8 @@ cc_library( ) cc_library( - name = "struct_definition", - hdrs = ["struct_definition.h"], + name = "class_definition", + hdrs = ["class_definition.h"], deps = [ ":member", "//common:ostream", diff --git a/executable_semantics/ast/struct_definition.h b/executable_semantics/ast/class_definition.h similarity index 95% rename from executable_semantics/ast/struct_definition.h rename to executable_semantics/ast/class_definition.h index d7b148f254ab..dcac975363b0 100644 --- a/executable_semantics/ast/struct_definition.h +++ b/executable_semantics/ast/class_definition.h @@ -12,7 +12,7 @@ namespace Carbon { -struct StructDefinition { +struct ClassDefinition { int line_num; std::string name; std::list members; diff --git a/executable_semantics/ast/declaration.cpp b/executable_semantics/ast/declaration.cpp index 8c02873797de..b386853c2775 100644 --- a/executable_semantics/ast/declaration.cpp +++ b/executable_semantics/ast/declaration.cpp @@ -16,11 +16,11 @@ void Declaration::Print(llvm::raw_ostream& out) const { out << cast(*this).Definition(); break; - case Kind::StructDeclaration: { - const StructDefinition& struct_def = - cast(*this).Definition(); - out << "struct " << struct_def.name << " {\n"; - for (Member* m : struct_def.members) { + case Kind::ClassDeclaration: { + const ClassDefinition& class_def = + cast(*this).Definition(); + out << "class " << class_def.name << " {\n"; + for (Member* m : class_def.members) { out << *m; } out << "}\n"; diff --git a/executable_semantics/ast/declaration.h b/executable_semantics/ast/declaration.h index 6f2162afa8bd..aa5ec83d200c 100644 --- a/executable_semantics/ast/declaration.h +++ b/executable_semantics/ast/declaration.h @@ -9,10 +9,10 @@ #include #include "common/ostream.h" +#include "executable_semantics/ast/class_definition.h" #include "executable_semantics/ast/function_definition.h" #include "executable_semantics/ast/member.h" #include "executable_semantics/ast/pattern.h" -#include "executable_semantics/ast/struct_definition.h" #include "llvm/Support/Compiler.h" namespace Carbon { @@ -29,7 +29,7 @@ class Declaration { public: enum class Kind { FunctionDeclaration, - StructDeclaration, + ClassDeclaration, ChoiceDeclaration, VariableDeclaration, }; @@ -72,22 +72,22 @@ class FunctionDeclaration : public Declaration { const FunctionDefinition* definition; }; -class StructDeclaration : public Declaration { +class ClassDeclaration : public Declaration { public: - StructDeclaration(int line_num, std::string name, std::list members) - : Declaration(Kind::StructDeclaration, line_num), + ClassDeclaration(int line_num, std::string name, std::list members) + : Declaration(Kind::ClassDeclaration, line_num), definition({.line_num = line_num, .name = std::move(name), .members = std::move(members)}) {} static auto classof(const Declaration* decl) -> bool { - return decl->Tag() == Kind::StructDeclaration; + return decl->Tag() == Kind::ClassDeclaration; } - auto Definition() const -> const StructDefinition& { return definition; } + auto Definition() const -> const ClassDefinition& { return definition; } private: - StructDefinition definition; + ClassDefinition definition; }; class ChoiceDeclaration : public Declaration { diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index b64e0a84494e..caa15748137f 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -133,12 +133,11 @@ void InitEnv(const Declaration& d, Env* env) { break; } - case Declaration::Kind::StructDeclaration: { - const StructDefinition& struct_def = - cast(d).Definition(); + case Declaration::Kind::ClassDeclaration: { + const ClassDefinition& class_def = cast(d).Definition(); VarValues fields; VarValues methods; - for (const Member* m : struct_def.members) { + for (const Member* m : class_def.members) { switch (m->Tag()) { case Member::Kind::FieldMember: { const BindingPattern* binding = cast(*m).Binding(); @@ -150,10 +149,10 @@ void InitEnv(const Declaration& d, Env* env) { } } } - auto st = global_arena->RawNew( - struct_def.name, std::move(fields), std::move(methods)); + auto st = global_arena->RawNew( + class_def.name, std::move(fields), std::move(methods)); auto a = state->heap.AllocateValue(st); - env->Set(struct_def.name, a); + env->Set(class_def.name, a); break; } @@ -216,7 +215,7 @@ void CallFunction(int line_num, std::vector operas, state->stack.Push(frame); break; } - case Value::Kind::StructType: { + case Value::Kind::ClassType: { const Value* arg = CopyVal(operas[1], line_num); const Value* sv = global_arena->RawNew(operas[0], arg); Ptr frame = state->stack.Top(); diff --git a/executable_semantics/interpreter/typecheck.cpp b/executable_semantics/interpreter/typecheck.cpp index a4b067ab4922..6c4f3c4b1b40 100644 --- a/executable_semantics/interpreter/typecheck.cpp +++ b/executable_semantics/interpreter/typecheck.cpp @@ -76,9 +76,9 @@ static auto ReifyType(const Value* t, int line_num) -> const Expression* { } return global_arena->RawNew(0, args); } - case Value::Kind::StructType: + case Value::Kind::ClassType: return global_arena->RawNew( - 0, cast(*t).Name()); + 0, cast(*t).Name()); case Value::Kind::ChoiceType: return global_arena->RawNew( 0, cast(*t).Name()); @@ -174,7 +174,7 @@ static auto ArgumentDeduction(int line_num, TypeEnv deduced, const Value* param, } // For the following cases, we check for type equality. case Value::Kind::ContinuationType: - case Value::Kind::StructType: + case Value::Kind::ClassType: case Value::Kind::ChoiceType: case Value::Kind::IntType: case Value::Kind::BoolType: @@ -231,7 +231,7 @@ static auto Substitute(TypeEnv dict, const Value* type) -> const Value* { case Value::Kind::IntType: case Value::Kind::BoolType: case Value::Kind::TypeType: - case Value::Kind::StructType: + case Value::Kind::ClassType: case Value::Kind::ChoiceType: case Value::Kind::ContinuationType: case Value::Kind::StringType: @@ -316,10 +316,10 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values) auto res = TypeCheckExp(access.Aggregate(), types, values); auto t = res.type; switch (t->Tag()) { - case Value::Kind::StructType: { - const auto& t_struct = cast(*t); + case Value::Kind::ClassType: { + const auto& t_class = cast(*t); // Search for a field - for (auto& field : t_struct.Fields()) { + for (auto& field : t_class.Fields()) { if (access.Field() == field.first) { const Expression* new_e = global_arena->RawNew( @@ -328,7 +328,7 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values) } } // Search for a method - for (auto& method : t_struct.Methods()) { + for (auto& method : t_class.Methods()) { if (access.Field() == method.first) { const Expression* new_e = global_arena->RawNew( @@ -337,7 +337,7 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values) } } FATAL_COMPILATION_ERROR(e->LineNumber()) - << "struct " << t_struct.Name() << " does not have a field named " + << "class " << t_class.Name() << " does not have a field named " << access.Field(); } case Value::Kind::TupleValue: { @@ -942,8 +942,8 @@ static auto TypeOfFunDef(TypeEnv types, Env values, param_res.type, ret); } -static auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*types*/, - Env ct_top) -> const Value* { +static auto TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/, + Env ct_top) -> const Value* { VarValues fields; VarValues methods; for (const Member* m : sd->members) { @@ -966,16 +966,16 @@ static auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*types*/, } } } - return global_arena->RawNew(sd->name, std::move(fields), - std::move(methods)); + return global_arena->RawNew(sd->name, std::move(fields), + std::move(methods)); } static auto GetName(const Declaration& d) -> const std::string& { switch (d.Tag()) { case Declaration::Kind::FunctionDeclaration: return cast(d).Definition().name; - case Declaration::Kind::StructDeclaration: - return cast(d).Definition().name; + case Declaration::Kind::ClassDeclaration: + return cast(d).Definition().name; case Declaration::Kind::ChoiceDeclaration: return cast(d).Name(); case Declaration::Kind::VariableDeclaration: { @@ -996,11 +996,11 @@ auto MakeTypeChecked(const Ptr d, const TypeEnv& types, return global_arena->New(TypeCheckFunDef( &cast(*d).Definition(), types, values)); - case Declaration::Kind::StructDeclaration: { - const StructDefinition& struct_def = - cast(*d).Definition(); + case Declaration::Kind::ClassDeclaration: { + const ClassDefinition& class_def = + cast(*d).Definition(); std::list fields; - for (Member* m : struct_def.members) { + for (Member* m : class_def.members) { switch (m->Tag()) { case Member::Kind::FieldMember: // TODO: Interpret the type expression and store the result. @@ -1008,8 +1008,8 @@ auto MakeTypeChecked(const Ptr d, const TypeEnv& types, break; } } - return global_arena->New( - struct_def.line_num, struct_def.name, std::move(fields)); + return global_arena->New( + class_def.line_num, class_def.name, std::move(fields)); } case Declaration::Kind::ChoiceDeclaration: @@ -1049,21 +1049,20 @@ static void TopLevel(const Declaration& d, TypeCheckContext* tops) { break; } - case Declaration::Kind::StructDeclaration: { - const StructDefinition& struct_def = - cast(d).Definition(); - auto st = TypeOfStructDef(&struct_def, tops->types, tops->values); + case Declaration::Kind::ClassDeclaration: { + const ClassDefinition& class_def = cast(d).Definition(); + auto st = TypeOfClassDef(&class_def, tops->types, tops->values); Address a = state->heap.AllocateValue(st); - tops->values.Set(struct_def.name, a); // Is this obsolete? + tops->values.Set(class_def.name, a); // Is this obsolete? std::vector field_types; for (const auto& [field_name, field_value] : - cast(*st).Fields()) { + cast(*st).Fields()) { field_types.push_back({.name = field_name, .value = field_value}); } auto fun_ty = global_arena->RawNew( std::vector(), global_arena->RawNew(std::move(field_types)), st); - tops->types.Set(struct_def.name, fun_ty); + tops->types.Set(class_def.name, fun_ty); break; } diff --git a/executable_semantics/interpreter/value.cpp b/executable_semantics/interpreter/value.cpp index d08cbc304dda..d3ca97707a64 100644 --- a/executable_semantics/interpreter/value.cpp +++ b/executable_semantics/interpreter/value.cpp @@ -163,7 +163,7 @@ void Value::Print(llvm::raw_ostream& out) const { } case Value::Kind::StructValue: { const auto& s = cast(*this); - out << cast(*s.Type()).Name() << *s.Inits(); + out << cast(*s.Type()).Name() << *s.Inits(); break; } case Value::Kind::TupleValue: { @@ -223,8 +223,8 @@ void Value::Print(llvm::raw_ostream& out) const { out << *fn_type.Param() << " -> " << *fn_type.Ret(); break; } - case Value::Kind::StructType: - out << "struct " << cast(*this).Name(); + case Value::Kind::ClassType: + out << "struct " << cast(*this).Name(); break; case Value::Kind::ChoiceType: out << "choice " << cast(*this).Name(); @@ -307,7 +307,7 @@ auto CopyVal(const Value* val, int line_num) -> const Value* { case Value::Kind::StringValue: return global_arena->RawNew(cast(*val).Val()); case Value::Kind::VariableType: - case Value::Kind::StructType: + case Value::Kind::ClassType: case Value::Kind::ChoiceType: case Value::Kind::BindingPlaceholderValue: case Value::Kind::AlternativeConstructorValue: @@ -330,8 +330,8 @@ auto TypeEqual(const Value* t1, const Value* t2) -> bool { return TypeEqual(fn1.Param(), fn2.Param()) && TypeEqual(fn1.Ret(), fn2.Ret()); } - case Value::Kind::StructType: - return cast(*t1).Name() == cast(*t2).Name(); + case Value::Kind::ClassType: + return cast(*t1).Name() == cast(*t2).Name(); case Value::Kind::ChoiceType: return cast(*t1).Name() == cast(*t2).Name(); case Value::Kind::TupleValue: { @@ -412,7 +412,7 @@ auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool { case Value::Kind::FunctionType: case Value::Kind::PointerType: case Value::Kind::AutoType: - case Value::Kind::StructType: + case Value::Kind::ClassType: case Value::Kind::ChoiceType: case Value::Kind::ContinuationType: case Value::Kind::VariableType: diff --git a/executable_semantics/interpreter/value.h b/executable_semantics/interpreter/value.h index 553ce43775e3..278124307057 100644 --- a/executable_semantics/interpreter/value.h +++ b/executable_semantics/interpreter/value.h @@ -46,7 +46,7 @@ class Value { FunctionType, PointerType, AutoType, - StructType, + ClassType, ChoiceType, ContinuationType, // The type of a continuation. VariableType, // e.g., generic type parameters. @@ -361,16 +361,16 @@ class AutoType : public Value { }; // A struct type. -class StructType : public Value { +class ClassType : public Value { public: - StructType(std::string name, VarValues fields, VarValues methods) - : Value(Kind::StructType), + ClassType(std::string name, VarValues fields, VarValues methods) + : Value(Kind::ClassType), name(std::move(name)), fields(std::move(fields)), methods(std::move(methods)) {} static auto classof(const Value* value) -> bool { - return value->Tag() == Kind::StructType; + return value->Tag() == Kind::ClassType; } auto Name() const -> const std::string& { return name; } diff --git a/executable_semantics/syntax/lexer.lpp b/executable_semantics/syntax/lexer.lpp index e438bd16b9a7..4507900f902f 100644 --- a/executable_semantics/syntax/lexer.lpp +++ b/executable_semantics/syntax/lexer.lpp @@ -51,7 +51,7 @@ NOT "not" OR "or" RETURN "return" STRING "String" -STRUCT "struct" +CLASS "class" TRUE "true" TYPE "Type" VAR "var" @@ -100,6 +100,7 @@ operand_start [(A-Za-z0-9_"] {BREAK} { return Carbon::Parser::make_BREAK(context.current_token_position); } {CASE} { return Carbon::Parser::make_CASE(context.current_token_position); } {CHOICE} { return Carbon::Parser::make_CHOICE(context.current_token_position); } +{CLASS} { return Carbon::Parser::make_CLASS(context.current_token_position); } {CONTINUE} { return Carbon::Parser::make_CONTINUE(context.current_token_position); } {DBLARROW} { return Carbon::Parser::make_DBLARROW(context.current_token_position); } {DEFAULT} { return Carbon::Parser::make_DEFAULT(context.current_token_position); } @@ -113,7 +114,6 @@ operand_start [(A-Za-z0-9_"] {NOT} { return Carbon::Parser::make_NOT(context.current_token_position); } {OR} { return Carbon::Parser::make_OR(context.current_token_position); } {RETURN} { return Carbon::Parser::make_RETURN(context.current_token_position); } -{STRUCT} { return Carbon::Parser::make_STRUCT(context.current_token_position); } {TRUE} { return Carbon::Parser::make_TRUE(context.current_token_position); } {TYPE} { return Carbon::Parser::make_TYPE(context.current_token_position); } {VAR} { return Carbon::Parser::make_VAR(context.current_token_position); } diff --git a/executable_semantics/syntax/parser.ypp b/executable_semantics/syntax/parser.ypp index 4375c78d0dc2..f5056ba6da21 100644 --- a/executable_semantics/syntax/parser.ypp +++ b/executable_semantics/syntax/parser.ypp @@ -154,7 +154,7 @@ void Carbon::Parser::error(const location_type&, const std::string& message) { %token RETURN %token TRUE %token FALSE -%token STRUCT +%token CLASS %token CHOICE %token MATCH %token CASE @@ -570,9 +570,9 @@ declaration: { $$ = global_arena->RawNew($1); } | function_declaration { $$ = global_arena->RawNew($1); } -| STRUCT identifier "{" member_list "}" +| CLASS identifier "{" member_list "}" { - $$ = global_arena->RawNew(yylineno, $2, $4); + $$ = global_arena->RawNew(yylineno, $2, $4); } | CHOICE identifier "{" alternative_list "}" { diff --git a/executable_semantics/test_list.bzl b/executable_semantics/test_list.bzl index f1f4725d6975..5a8711cd3580 100644 --- a/executable_semantics/test_list.bzl +++ b/executable_semantics/test_list.bzl @@ -11,6 +11,12 @@ TEST_LIST = [ "block2", "break1", "choice1", + "class1", + "class2", + "class3", + "class_field_access_mismatch", + "class_field_mismatch", + "class_field_missing", "continue1", "experimental_continuation1", "experimental_continuation2", @@ -84,12 +90,6 @@ TEST_LIST = [ "string_fail4", "string_fail5", "string_fail6", - "struct1", - "struct2", - "struct3", - "struct_field_access_mismatch", - "struct_field_mismatch", - "struct_field_missing", "tuple1", "tuple2", "tuple3", diff --git a/executable_semantics/testdata/struct1.carbon b/executable_semantics/testdata/class1.carbon similarity index 95% rename from executable_semantics/testdata/struct1.carbon rename to executable_semantics/testdata/class1.carbon index 0679506e1f2d..b893bb6faa4b 100644 --- a/executable_semantics/testdata/struct1.carbon +++ b/executable_semantics/testdata/class1.carbon @@ -2,7 +2,7 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -struct Point { +class Point { var x: i32; var y: i32; } diff --git a/executable_semantics/testdata/struct1.golden b/executable_semantics/testdata/class1.golden similarity index 100% rename from executable_semantics/testdata/struct1.golden rename to executable_semantics/testdata/class1.golden diff --git a/executable_semantics/testdata/struct2.carbon b/executable_semantics/testdata/class2.carbon similarity index 95% rename from executable_semantics/testdata/struct2.carbon rename to executable_semantics/testdata/class2.carbon index e4e3f7189550..e36a85053bc3 100644 --- a/executable_semantics/testdata/struct2.carbon +++ b/executable_semantics/testdata/class2.carbon @@ -2,7 +2,7 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -struct Point { +class Point { var x: i32; var y: i32; } diff --git a/executable_semantics/testdata/struct2.golden b/executable_semantics/testdata/class2.golden similarity index 100% rename from executable_semantics/testdata/struct2.golden rename to executable_semantics/testdata/class2.golden diff --git a/executable_semantics/testdata/struct3.carbon b/executable_semantics/testdata/class3.carbon similarity index 94% rename from executable_semantics/testdata/struct3.carbon rename to executable_semantics/testdata/class3.carbon index 967ea3dee543..17b6d8e1b10a 100644 --- a/executable_semantics/testdata/struct3.carbon +++ b/executable_semantics/testdata/class3.carbon @@ -2,7 +2,7 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -struct Point { +class Point { var x: i32; var y: i32; } diff --git a/executable_semantics/testdata/struct3.golden b/executable_semantics/testdata/class3.golden similarity index 100% rename from executable_semantics/testdata/struct3.golden rename to executable_semantics/testdata/class3.golden diff --git a/executable_semantics/testdata/struct_field_access_mismatch.carbon b/executable_semantics/testdata/class_field_access_mismatch.carbon similarity index 94% rename from executable_semantics/testdata/struct_field_access_mismatch.carbon rename to executable_semantics/testdata/class_field_access_mismatch.carbon index 62f1949cc6d6..547a629a084b 100644 --- a/executable_semantics/testdata/struct_field_access_mismatch.carbon +++ b/executable_semantics/testdata/class_field_access_mismatch.carbon @@ -2,7 +2,7 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -struct Point { +class Point { var x: i32; var y: i32; } diff --git a/executable_semantics/testdata/class_field_access_mismatch.golden b/executable_semantics/testdata/class_field_access_mismatch.golden new file mode 100644 index 000000000000..87d8c65583d0 --- /dev/null +++ b/executable_semantics/testdata/class_field_access_mismatch.golden @@ -0,0 +1,2 @@ +COMPILATION ERROR: 11: class Point does not have a field named z +EXIT CODE: 255 diff --git a/executable_semantics/testdata/struct_field_mismatch.carbon b/executable_semantics/testdata/class_field_mismatch.carbon similarity index 94% rename from executable_semantics/testdata/struct_field_mismatch.carbon rename to executable_semantics/testdata/class_field_mismatch.carbon index 76900787ab3e..24126bfb0aef 100644 --- a/executable_semantics/testdata/struct_field_mismatch.carbon +++ b/executable_semantics/testdata/class_field_mismatch.carbon @@ -2,7 +2,7 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -struct Point { +class Point { var x: i32; var y: i32; } diff --git a/executable_semantics/testdata/struct_field_mismatch.golden b/executable_semantics/testdata/class_field_mismatch.golden similarity index 100% rename from executable_semantics/testdata/struct_field_mismatch.golden rename to executable_semantics/testdata/class_field_mismatch.golden diff --git a/executable_semantics/testdata/struct_field_missing.carbon b/executable_semantics/testdata/class_field_missing.carbon similarity index 94% rename from executable_semantics/testdata/struct_field_missing.carbon rename to executable_semantics/testdata/class_field_missing.carbon index 66c13f3e8d29..efe61f07294b 100644 --- a/executable_semantics/testdata/struct_field_missing.carbon +++ b/executable_semantics/testdata/class_field_missing.carbon @@ -2,7 +2,7 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -struct Point { +class Point { var x: i32; var y: i32; } diff --git a/executable_semantics/testdata/struct_field_missing.golden b/executable_semantics/testdata/class_field_missing.golden similarity index 100% rename from executable_semantics/testdata/struct_field_missing.golden rename to executable_semantics/testdata/class_field_missing.golden diff --git a/executable_semantics/testdata/struct_field_access_mismatch.golden b/executable_semantics/testdata/struct_field_access_mismatch.golden deleted file mode 100644 index 6e59576746e1..000000000000 --- a/executable_semantics/testdata/struct_field_access_mismatch.golden +++ /dev/null @@ -1,2 +0,0 @@ -COMPILATION ERROR: 11: struct Point does not have a field named z -EXIT CODE: 255