mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
@@ -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",
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
struct StructDefinition {
|
||||
struct ClassDefinition {
|
||||
int line_num;
|
||||
std::string name;
|
||||
std::list<Member*> members;
|
||||
@@ -16,11 +16,11 @@ void Declaration::Print(llvm::raw_ostream& out) const {
|
||||
out << cast<FunctionDeclaration>(*this).Definition();
|
||||
break;
|
||||
|
||||
case Kind::StructDeclaration: {
|
||||
const StructDefinition& struct_def =
|
||||
cast<StructDeclaration>(*this).Definition();
|
||||
out << "struct " << struct_def.name << " {\n";
|
||||
for (Member* m : struct_def.members) {
|
||||
case Kind::ClassDeclaration: {
|
||||
const ClassDefinition& class_def =
|
||||
cast<ClassDeclaration>(*this).Definition();
|
||||
out << "class " << class_def.name << " {\n";
|
||||
for (Member* m : class_def.members) {
|
||||
out << *m;
|
||||
}
|
||||
out << "}\n";
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
#include <string>
|
||||
|
||||
#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<Member*> members)
|
||||
: Declaration(Kind::StructDeclaration, line_num),
|
||||
ClassDeclaration(int line_num, std::string name, std::list<Member*> 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 {
|
||||
|
||||
@@ -133,12 +133,11 @@ void InitEnv(const Declaration& d, Env* env) {
|
||||
break;
|
||||
}
|
||||
|
||||
case Declaration::Kind::StructDeclaration: {
|
||||
const StructDefinition& struct_def =
|
||||
cast<StructDeclaration>(d).Definition();
|
||||
case Declaration::Kind::ClassDeclaration: {
|
||||
const ClassDefinition& class_def = cast<ClassDeclaration>(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<FieldMember>(*m).Binding();
|
||||
@@ -150,10 +149,10 @@ void InitEnv(const Declaration& d, Env* env) {
|
||||
}
|
||||
}
|
||||
}
|
||||
auto st = global_arena->RawNew<StructType>(
|
||||
struct_def.name, std::move(fields), std::move(methods));
|
||||
auto st = global_arena->RawNew<ClassType>(
|
||||
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<const Value*> 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<StructValue>(operas[0], arg);
|
||||
Ptr<Frame> frame = state->stack.Top();
|
||||
|
||||
@@ -76,9 +76,9 @@ static auto ReifyType(const Value* t, int line_num) -> const Expression* {
|
||||
}
|
||||
return global_arena->RawNew<TupleLiteral>(0, args);
|
||||
}
|
||||
case Value::Kind::StructType:
|
||||
case Value::Kind::ClassType:
|
||||
return global_arena->RawNew<IdentifierExpression>(
|
||||
0, cast<StructType>(*t).Name());
|
||||
0, cast<ClassType>(*t).Name());
|
||||
case Value::Kind::ChoiceType:
|
||||
return global_arena->RawNew<IdentifierExpression>(
|
||||
0, cast<ChoiceType>(*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<StructType>(*t);
|
||||
case Value::Kind::ClassType: {
|
||||
const auto& t_class = cast<ClassType>(*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<FieldAccessExpression>(
|
||||
@@ -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<FieldAccessExpression>(
|
||||
@@ -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<StructType>(sd->name, std::move(fields),
|
||||
std::move(methods));
|
||||
return global_arena->RawNew<ClassType>(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<FunctionDeclaration>(d).Definition().name;
|
||||
case Declaration::Kind::StructDeclaration:
|
||||
return cast<StructDeclaration>(d).Definition().name;
|
||||
case Declaration::Kind::ClassDeclaration:
|
||||
return cast<ClassDeclaration>(d).Definition().name;
|
||||
case Declaration::Kind::ChoiceDeclaration:
|
||||
return cast<ChoiceDeclaration>(d).Name();
|
||||
case Declaration::Kind::VariableDeclaration: {
|
||||
@@ -996,11 +996,11 @@ auto MakeTypeChecked(const Ptr<const Declaration> d, const TypeEnv& types,
|
||||
return global_arena->New<FunctionDeclaration>(TypeCheckFunDef(
|
||||
&cast<FunctionDeclaration>(*d).Definition(), types, values));
|
||||
|
||||
case Declaration::Kind::StructDeclaration: {
|
||||
const StructDefinition& struct_def =
|
||||
cast<StructDeclaration>(*d).Definition();
|
||||
case Declaration::Kind::ClassDeclaration: {
|
||||
const ClassDefinition& class_def =
|
||||
cast<ClassDeclaration>(*d).Definition();
|
||||
std::list<Member*> 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<const Declaration> d, const TypeEnv& types,
|
||||
break;
|
||||
}
|
||||
}
|
||||
return global_arena->New<StructDeclaration>(
|
||||
struct_def.line_num, struct_def.name, std::move(fields));
|
||||
return global_arena->New<ClassDeclaration>(
|
||||
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<StructDeclaration>(d).Definition();
|
||||
auto st = TypeOfStructDef(&struct_def, tops->types, tops->values);
|
||||
case Declaration::Kind::ClassDeclaration: {
|
||||
const ClassDefinition& class_def = cast<ClassDeclaration>(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<TupleElement> field_types;
|
||||
for (const auto& [field_name, field_value] :
|
||||
cast<StructType>(*st).Fields()) {
|
||||
cast<ClassType>(*st).Fields()) {
|
||||
field_types.push_back({.name = field_name, .value = field_value});
|
||||
}
|
||||
auto fun_ty = global_arena->RawNew<FunctionType>(
|
||||
std::vector<GenericBinding>(),
|
||||
global_arena->RawNew<TupleValue>(std::move(field_types)), st);
|
||||
tops->types.Set(struct_def.name, fun_ty);
|
||||
tops->types.Set(class_def.name, fun_ty);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ void Value::Print(llvm::raw_ostream& out) const {
|
||||
}
|
||||
case Value::Kind::StructValue: {
|
||||
const auto& s = cast<StructValue>(*this);
|
||||
out << cast<StructType>(*s.Type()).Name() << *s.Inits();
|
||||
out << cast<ClassType>(*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<StructType>(*this).Name();
|
||||
case Value::Kind::ClassType:
|
||||
out << "struct " << cast<ClassType>(*this).Name();
|
||||
break;
|
||||
case Value::Kind::ChoiceType:
|
||||
out << "choice " << cast<ChoiceType>(*this).Name();
|
||||
@@ -307,7 +307,7 @@ auto CopyVal(const Value* val, int line_num) -> const Value* {
|
||||
case Value::Kind::StringValue:
|
||||
return global_arena->RawNew<StringValue>(cast<StringValue>(*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<StructType>(*t1).Name() == cast<StructType>(*t2).Name();
|
||||
case Value::Kind::ClassType:
|
||||
return cast<ClassType>(*t1).Name() == cast<ClassType>(*t2).Name();
|
||||
case Value::Kind::ChoiceType:
|
||||
return cast<ChoiceType>(*t1).Name() == cast<ChoiceType>(*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:
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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<FunctionDeclaration>($1); }
|
||||
| function_declaration
|
||||
{ $$ = global_arena->RawNew<FunctionDeclaration>($1); }
|
||||
| STRUCT identifier "{" member_list "}"
|
||||
| CLASS identifier "{" member_list "}"
|
||||
{
|
||||
$$ = global_arena->RawNew<StructDeclaration>(yylineno, $2, $4);
|
||||
$$ = global_arena->RawNew<ClassDeclaration>(yylineno, $2, $4);
|
||||
}
|
||||
| CHOICE identifier "{" alternative_list "}"
|
||||
{
|
||||
|
||||
@@ -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",
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
COMPILATION ERROR: 11: class Point does not have a field named z
|
||||
EXIT CODE: 255
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
COMPILATION ERROR: 11: struct Point does not have a field named z
|
||||
EXIT CODE: 255
|
||||
Reference in New Issue
Block a user