Rename Ptr<T> to Nonnull<T*> (#832)

Note that ptr.h also includes an enable_if change, to help avoid https://bugs.llvm.org/show_bug.cgi?id=51881
This commit is contained in:
Jon Meow
2021-09-16 19:22:57 -07:00
committed by GitHub
parent 5e66248db0
commit 56dc4ae375
35 changed files with 584 additions and 535 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ struct AST {
// Import directives.
std::vector<LibraryName> imports;
// The file's ordered declarations.
std::vector<Ptr<const Declaration>> declarations;
std::vector<Nonnull<const Declaration*>> declarations;
};
} // namespace Carbon
+1 -1
View File
@@ -16,7 +16,7 @@ namespace Carbon {
struct ClassDefinition {
SourceLocation loc;
std::string name;
std::vector<Ptr<Member>> members;
std::vector<Nonnull<Member*>> members;
};
} // namespace Carbon
+1 -1
View File
@@ -20,7 +20,7 @@ void Declaration::Print(llvm::raw_ostream& out) const {
const ClassDefinition& class_def =
cast<ClassDeclaration>(*this).Definition();
out << "class " << class_def.name << " {\n";
for (Ptr<Member> m : class_def.members) {
for (Nonnull<Member*> m : class_def.members) {
out << *m;
}
out << "}\n";
+15 -13
View File
@@ -60,7 +60,7 @@ class Declaration {
class FunctionDeclaration : public Declaration {
public:
FunctionDeclaration(Ptr<const FunctionDefinition> definition)
FunctionDeclaration(Nonnull<const FunctionDefinition*> definition)
: Declaration(Kind::FunctionDeclaration, definition->source_location),
definition(definition) {}
@@ -71,13 +71,13 @@ class FunctionDeclaration : public Declaration {
auto Definition() const -> const FunctionDefinition& { return *definition; }
private:
Ptr<const FunctionDefinition> definition;
Nonnull<const FunctionDefinition*> definition;
};
class ClassDeclaration : public Declaration {
public:
ClassDeclaration(SourceLocation loc, std::string name,
std::vector<Ptr<Member>> members)
std::vector<Nonnull<Member*>> members)
: Declaration(Kind::ClassDeclaration, loc),
definition({.loc = loc,
.name = std::move(name),
@@ -97,7 +97,8 @@ class ChoiceDeclaration : public Declaration {
public:
ChoiceDeclaration(
SourceLocation loc, std::string name,
std::vector<std::pair<std::string, Ptr<const Expression>>> alternatives)
std::vector<std::pair<std::string, Nonnull<const Expression*>>>
alternatives)
: Declaration(Kind::ChoiceDeclaration, loc),
name(std::move(name)),
alternatives(std::move(alternatives)) {}
@@ -107,21 +108,22 @@ class ChoiceDeclaration : public Declaration {
}
auto Name() const -> const std::string& { return name; }
auto Alternatives() const
-> const std::vector<std::pair<std::string, Ptr<const Expression>>>& {
auto Alternatives() const -> const
std::vector<std::pair<std::string, Nonnull<const Expression*>>>& {
return alternatives;
}
private:
std::string name;
std::vector<std::pair<std::string, Ptr<const Expression>>> alternatives;
std::vector<std::pair<std::string, Nonnull<const Expression*>>> alternatives;
};
// Global variable definition implements the Declaration concept.
class VariableDeclaration : public Declaration {
public:
VariableDeclaration(SourceLocation loc, Ptr<const BindingPattern> binding,
Ptr<const Expression> initializer)
VariableDeclaration(SourceLocation loc,
Nonnull<const BindingPattern*> binding,
Nonnull<const Expression*> initializer)
: Declaration(Kind::VariableDeclaration, loc),
binding(binding),
initializer(initializer) {}
@@ -130,15 +132,15 @@ class VariableDeclaration : public Declaration {
return decl->Tag() == Kind::VariableDeclaration;
}
auto Binding() const -> Ptr<const BindingPattern> { return binding; }
auto Initializer() const -> Ptr<const Expression> { return initializer; }
auto Binding() const -> Nonnull<const BindingPattern*> { return binding; }
auto Initializer() const -> Nonnull<const Expression*> { return initializer; }
private:
// TODO: split this into a non-optional name and a type, initialized by
// a constructor that takes a BindingPattern and handles errors like a
// missing name.
Ptr<const BindingPattern> binding;
Ptr<const Expression> initializer;
Nonnull<const BindingPattern*> binding;
Nonnull<const Expression*> initializer;
};
} // namespace Carbon
+7 -5
View File
@@ -17,9 +17,10 @@ namespace Carbon {
using llvm::cast;
auto ExpressionFromParenContents(
Ptr<Arena> arena, SourceLocation loc,
const ParenContents<Expression>& paren_contents) -> Ptr<const Expression> {
std::optional<Ptr<const Expression>> single_term =
Nonnull<Arena*> arena, SourceLocation loc,
const ParenContents<Expression>& paren_contents)
-> Nonnull<const Expression*> {
std::optional<Nonnull<const Expression*>> single_term =
paren_contents.SingleTerm();
if (single_term.has_value()) {
return *single_term;
@@ -29,8 +30,9 @@ auto ExpressionFromParenContents(
}
auto TupleExpressionFromParenContents(
Ptr<Arena> arena, SourceLocation loc,
const ParenContents<Expression>& paren_contents) -> Ptr<const Expression> {
Nonnull<Arena*> arena, SourceLocation loc,
const ParenContents<Expression>& paren_contents)
-> Nonnull<const Expression*> {
return arena->New<TupleLiteral>(
loc, paren_contents.TupleElements<FieldInitializer>(loc));
}
+34 -30
View File
@@ -63,25 +63,27 @@ class Expression {
// grouping if their contents permit that interpretation, or as forming a
// tuple otherwise.
auto ExpressionFromParenContents(
Ptr<Arena> arena, SourceLocation loc,
const ParenContents<Expression>& paren_contents) -> Ptr<const Expression>;
Nonnull<Arena*> arena, SourceLocation loc,
const ParenContents<Expression>& paren_contents)
-> Nonnull<const Expression*>;
// Converts paren_contents to an Expression, interpreting the parentheses as
// forming a tuple.
auto TupleExpressionFromParenContents(
Ptr<Arena> arena, SourceLocation loc,
const ParenContents<Expression>& paren_contents) -> Ptr<const Expression>;
Nonnull<Arena*> arena, SourceLocation loc,
const ParenContents<Expression>& paren_contents)
-> Nonnull<const Expression*>;
// A FieldInitializer represents the initialization of a single tuple field.
struct FieldInitializer {
FieldInitializer(std::string name, Ptr<const Expression> expression)
FieldInitializer(std::string name, Nonnull<const Expression*> expression)
: name(std::move(name)), expression(expression) {}
// The field name. Cannot be empty.
std::string name;
// The expression that initializes the field.
Ptr<const Expression> expression;
Nonnull<const Expression*> expression;
};
enum class Operator {
@@ -115,7 +117,7 @@ class IdentifierExpression : public Expression {
class FieldAccessExpression : public Expression {
public:
explicit FieldAccessExpression(SourceLocation loc,
Ptr<const Expression> aggregate,
Nonnull<const Expression*> aggregate,
std::string field)
: Expression(Kind::FieldAccessExpression, loc),
aggregate(aggregate),
@@ -125,18 +127,19 @@ class FieldAccessExpression : public Expression {
return exp->Tag() == Kind::FieldAccessExpression;
}
auto Aggregate() const -> Ptr<const Expression> { return aggregate; }
auto Aggregate() const -> Nonnull<const Expression*> { return aggregate; }
auto Field() const -> const std::string& { return field; }
private:
Ptr<const Expression> aggregate;
Nonnull<const Expression*> aggregate;
std::string field;
};
class IndexExpression : public Expression {
public:
explicit IndexExpression(SourceLocation loc, Ptr<const Expression> aggregate,
Ptr<const Expression> offset)
explicit IndexExpression(SourceLocation loc,
Nonnull<const Expression*> aggregate,
Nonnull<const Expression*> offset)
: Expression(Kind::IndexExpression, loc),
aggregate(aggregate),
offset(offset) {}
@@ -145,12 +148,12 @@ class IndexExpression : public Expression {
return exp->Tag() == Kind::IndexExpression;
}
auto Aggregate() const -> Ptr<const Expression> { return aggregate; }
auto Offset() const -> Ptr<const Expression> { return offset; }
auto Aggregate() const -> Nonnull<const Expression*> { return aggregate; }
auto Offset() const -> Nonnull<const Expression*> { return offset; }
private:
Ptr<const Expression> aggregate;
Ptr<const Expression> offset;
Nonnull<const Expression*> aggregate;
Nonnull<const Expression*> offset;
};
class IntLiteral : public Expression {
@@ -230,7 +233,7 @@ class PrimitiveOperatorExpression : public Expression {
public:
explicit PrimitiveOperatorExpression(
SourceLocation loc, Operator op,
std::vector<Ptr<const Expression>> arguments)
std::vector<Nonnull<const Expression*>> arguments)
: Expression(Kind::PrimitiveOperatorExpression, loc),
op(op),
arguments(std::move(arguments)) {}
@@ -240,19 +243,20 @@ class PrimitiveOperatorExpression : public Expression {
}
auto Op() const -> Operator { return op; }
auto Arguments() const -> const std::vector<Ptr<const Expression>>& {
auto Arguments() const -> const std::vector<Nonnull<const Expression*>>& {
return arguments;
}
private:
Operator op;
std::vector<Ptr<const Expression>> arguments;
std::vector<Nonnull<const Expression*>> arguments;
};
class CallExpression : public Expression {
public:
explicit CallExpression(SourceLocation loc, Ptr<const Expression> function,
Ptr<const Expression> argument)
explicit CallExpression(SourceLocation loc,
Nonnull<const Expression*> function,
Nonnull<const Expression*> argument)
: Expression(Kind::CallExpression, loc),
function(function),
argument(argument) {}
@@ -261,19 +265,19 @@ class CallExpression : public Expression {
return exp->Tag() == Kind::CallExpression;
}
auto Function() const -> Ptr<const Expression> { return function; }
auto Argument() const -> Ptr<const Expression> { return argument; }
auto Function() const -> Nonnull<const Expression*> { return function; }
auto Argument() const -> Nonnull<const Expression*> { return argument; }
private:
Ptr<const Expression> function;
Ptr<const Expression> argument;
Nonnull<const Expression*> function;
Nonnull<const Expression*> argument;
};
class FunctionTypeLiteral : public Expression {
public:
explicit FunctionTypeLiteral(SourceLocation loc,
Ptr<const Expression> parameter,
Ptr<const Expression> return_type,
Nonnull<const Expression*> parameter,
Nonnull<const Expression*> return_type,
bool is_omitted_return_type)
: Expression(Kind::FunctionTypeLiteral, loc),
parameter(parameter),
@@ -284,13 +288,13 @@ class FunctionTypeLiteral : public Expression {
return exp->Tag() == Kind::FunctionTypeLiteral;
}
auto Parameter() const -> Ptr<const Expression> { return parameter; }
auto ReturnType() const -> Ptr<const Expression> { return return_type; }
auto Parameter() const -> Nonnull<const Expression*> { return parameter; }
auto ReturnType() const -> Nonnull<const Expression*> { return return_type; }
auto IsOmittedReturnType() const -> bool { return is_omitted_return_type; }
private:
Ptr<const Expression> parameter;
Ptr<const Expression> return_type;
Nonnull<const Expression*> parameter;
Nonnull<const Expression*> return_type;
bool is_omitted_return_type;
};
+8 -8
View File
@@ -38,7 +38,7 @@ class ExpressionTest : public ::testing::Test {
TEST_F(ExpressionTest, EmptyAsExpression) {
ParenContents<Expression> contents = {.elements = {},
.has_trailing_comma = false};
Ptr<const Expression> expression =
Nonnull<const Expression*> expression =
ExpressionFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(expression->SourceLoc(), FakeSourceLoc(1));
ASSERT_EQ(expression->Tag(), Expression::Kind::TupleLiteral);
@@ -48,7 +48,7 @@ TEST_F(ExpressionTest, EmptyAsExpression) {
TEST_F(ExpressionTest, EmptyAsTuple) {
ParenContents<Expression> contents = {.elements = {},
.has_trailing_comma = false};
Ptr<const Expression> tuple =
Nonnull<const Expression*> tuple =
TupleExpressionFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1));
ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral);
@@ -67,7 +67,7 @@ TEST_F(ExpressionTest, UnaryNoCommaAsExpression) {
.term = arena.New<IntLiteral>(FakeSourceLoc(2), 42)}},
.has_trailing_comma = false};
Ptr<const Expression> expression =
Nonnull<const Expression*> expression =
ExpressionFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(expression->SourceLoc(), FakeSourceLoc(2));
ASSERT_EQ(expression->Tag(), Expression::Kind::IntLiteral);
@@ -79,7 +79,7 @@ TEST_F(ExpressionTest, UnaryNoCommaAsTuple) {
.term = arena.New<IntLiteral>(FakeSourceLoc(2), 42)}},
.has_trailing_comma = false};
Ptr<const Expression> tuple =
Nonnull<const Expression*> tuple =
TupleExpressionFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1));
ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral);
@@ -93,7 +93,7 @@ TEST_F(ExpressionTest, UnaryWithCommaAsExpression) {
.term = arena.New<IntLiteral>(FakeSourceLoc(2), 42)}},
.has_trailing_comma = true};
Ptr<const Expression> expression =
Nonnull<const Expression*> expression =
ExpressionFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(expression->SourceLoc(), FakeSourceLoc(1));
ASSERT_EQ(expression->Tag(), Expression::Kind::TupleLiteral);
@@ -107,7 +107,7 @@ TEST_F(ExpressionTest, UnaryWithCommaAsTuple) {
.term = arena.New<IntLiteral>(FakeSourceLoc(2), 42)}},
.has_trailing_comma = true};
Ptr<const Expression> tuple =
Nonnull<const Expression*> tuple =
TupleExpressionFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1));
ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral);
@@ -123,7 +123,7 @@ TEST_F(ExpressionTest, BinaryAsExpression) {
.term = arena.New<IntLiteral>(FakeSourceLoc(3), 42)}},
.has_trailing_comma = true};
Ptr<const Expression> expression =
Nonnull<const Expression*> expression =
ExpressionFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(expression->SourceLoc(), FakeSourceLoc(1));
ASSERT_EQ(expression->Tag(), Expression::Kind::TupleLiteral);
@@ -139,7 +139,7 @@ TEST_F(ExpressionTest, BinaryAsTuple) {
.term = arena.New<IntLiteral>(FakeSourceLoc(3), 42)}},
.has_trailing_comma = true};
Ptr<const Expression> tuple =
Nonnull<const Expression*> tuple =
TupleExpressionFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1));
ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral);
@@ -18,16 +18,16 @@ namespace Carbon {
// For now, only generic parameters are supported.
struct GenericBinding {
std::string name;
Ptr<const Expression> type;
Nonnull<const Expression*> type;
};
struct FunctionDefinition {
FunctionDefinition(SourceLocation source_location, std::string name,
std::vector<GenericBinding> deduced_params,
Ptr<const TuplePattern> param_pattern,
Ptr<const Pattern> return_type,
Nonnull<const TuplePattern*> param_pattern,
Nonnull<const Pattern*> return_type,
bool is_omitted_return_type,
std::optional<Ptr<const Statement>> body)
std::optional<Nonnull<const Statement*>> body)
: source_location(source_location),
name(std::move(name)),
deduced_parameters(deduced_params),
@@ -43,10 +43,10 @@ struct FunctionDefinition {
SourceLocation source_location;
std::string name;
std::vector<GenericBinding> deduced_parameters;
Ptr<const TuplePattern> param_pattern;
Ptr<const Pattern> return_type;
Nonnull<const TuplePattern*> param_pattern;
Nonnull<const Pattern*> return_type;
bool is_omitted_return_type;
std::optional<Ptr<const Statement>> body;
std::optional<Nonnull<const Statement*>> body;
};
} // namespace Carbon
+3 -3
View File
@@ -51,20 +51,20 @@ class Member {
class FieldMember : public Member {
public:
FieldMember(SourceLocation loc, Ptr<const BindingPattern> binding)
FieldMember(SourceLocation loc, Nonnull<const BindingPattern*> binding)
: Member(Kind::FieldMember, loc), binding(binding) {}
static auto classof(const Member* member) -> bool {
return member->Tag() == Kind::FieldMember;
}
auto Binding() const -> Ptr<const BindingPattern> { return binding; }
auto Binding() const -> Nonnull<const BindingPattern*> { return binding; }
private:
// TODO: split this into a non-optional name and a type, initialized by
// a constructor that takes a BindingPattern and handles errors like a
// missing name.
Ptr<const BindingPattern> binding;
Nonnull<const BindingPattern*> binding;
};
} // namespace Carbon
+5 -4
View File
@@ -28,16 +28,16 @@ template <typename Term>
struct ParenContents {
struct Element {
std::optional<std::string> name;
Ptr<const Term> term;
Nonnull<const Term*> term;
};
// If this object represents a single term, with no name and no trailing
// comma, this method returns that term. This typically means the parentheses
// can be interpreted as grouping.
auto SingleTerm() const -> std::optional<Ptr<const Term>>;
auto SingleTerm() const -> std::optional<Nonnull<const Term*>>;
// Converts `elements` to std::vector<TupleElement>. TupleElement must
// have a constructor that takes a std::string and a Ptr<const Term>.
// have a constructor that takes a std::string and a Nonnull<const Term*>.
//
// TODO: Find a way to deduce TupleElement from Term.
template <typename TupleElement>
@@ -50,7 +50,8 @@ struct ParenContents {
// Implementation details only below here.
template <typename Term>
auto ParenContents<Term>::SingleTerm() const -> std::optional<Ptr<const Term>> {
auto ParenContents<Term>::SingleTerm() const
-> std::optional<Nonnull<const Term*>> {
if (elements.size() == 1 && !elements.front().name.has_value() &&
!has_trailing_comma) {
return elements.front().term;
+12 -11
View File
@@ -54,8 +54,8 @@ void Pattern::Print(llvm::raw_ostream& out) const {
}
}
TuplePattern::TuplePattern(Ptr<Arena> arena,
Ptr<const Expression> tuple_literal)
TuplePattern::TuplePattern(Nonnull<Arena*> arena,
Nonnull<const Expression*> tuple_literal)
: Pattern(Kind::TuplePattern, tuple_literal->SourceLoc()) {
const auto& tuple = cast<TupleLiteral>(*tuple_literal);
for (const FieldInitializer& init : tuple.Fields()) {
@@ -64,10 +64,11 @@ TuplePattern::TuplePattern(Ptr<Arena> arena,
}
}
auto PatternFromParenContents(Ptr<Arena> arena, SourceLocation loc,
auto PatternFromParenContents(Nonnull<Arena*> arena, SourceLocation loc,
const ParenContents<Pattern>& paren_contents)
-> Ptr<const Pattern> {
std::optional<Ptr<const Pattern>> single_term = paren_contents.SingleTerm();
-> Nonnull<const Pattern*> {
std::optional<Nonnull<const Pattern*>> single_term =
paren_contents.SingleTerm();
if (single_term.has_value()) {
return *single_term;
} else {
@@ -75,9 +76,9 @@ auto PatternFromParenContents(Ptr<Arena> arena, SourceLocation loc,
}
}
auto TuplePatternFromParenContents(Ptr<Arena> arena, SourceLocation loc,
auto TuplePatternFromParenContents(Nonnull<Arena*> arena, SourceLocation loc,
const ParenContents<Pattern>& paren_contents)
-> Ptr<const TuplePattern> {
-> Nonnull<const TuplePattern*> {
return arena->New<TuplePattern>(
loc, paren_contents.TupleElements<TuplePattern::Field>(loc));
}
@@ -86,7 +87,7 @@ auto TuplePatternFromParenContents(Ptr<Arena> arena, SourceLocation loc,
// error for incorrect expressions, rather than letting a default cast error
// apply.
static const FieldAccessExpression& RequireFieldAccess(
Ptr<const Expression> alternative) {
Nonnull<const Expression*> alternative) {
if (alternative->Tag() != Expression::Kind::FieldAccessExpression) {
FATAL_PROGRAM_ERROR(alternative->SourceLoc())
<< "Alternative pattern must have the form of a field access.";
@@ -95,14 +96,14 @@ static const FieldAccessExpression& RequireFieldAccess(
}
AlternativePattern::AlternativePattern(SourceLocation loc,
Ptr<const Expression> alternative,
Ptr<const TuplePattern> arguments)
Nonnull<const Expression*> alternative,
Nonnull<const TuplePattern*> arguments)
: Pattern(Kind::AlternativePattern, loc),
choice_type(RequireFieldAccess(alternative).Aggregate()),
alternative_name(RequireFieldAccess(alternative).Field()),
arguments(arguments) {}
auto ParenExpressionToParenPattern(Ptr<Arena> arena,
auto ParenExpressionToParenPattern(Nonnull<Arena*> arena,
const ParenContents<Expression>& contents)
-> ParenContents<Pattern> {
ParenContents<Pattern> result = {
+22 -22
View File
@@ -71,7 +71,7 @@ class AutoPattern : public Pattern {
class BindingPattern : public Pattern {
public:
BindingPattern(SourceLocation loc, std::optional<std::string> name,
Ptr<const Pattern> type)
Nonnull<const Pattern*> type)
: Pattern(Kind::BindingPattern, loc), name(std::move(name)), type(type) {}
static auto classof(const Pattern* pattern) -> bool {
@@ -82,11 +82,11 @@ class BindingPattern : public Pattern {
auto Name() const -> const std::optional<std::string>& { return name; }
// The pattern specifying the type of values that this pattern matches.
auto Type() const -> Ptr<const Pattern> { return type; }
auto Type() const -> Nonnull<const Pattern*> { return type; }
private:
std::optional<std::string> name;
Ptr<const Pattern> type;
Nonnull<const Pattern*> type;
};
// A pattern that matches a tuple value field-wise.
@@ -94,14 +94,14 @@ class TuplePattern : public Pattern {
public:
// Represents a portion of a tuple pattern corresponding to a single field.
struct Field {
Field(std::string name, Ptr<const Pattern> pattern)
Field(std::string name, Nonnull<const Pattern*> pattern)
: name(std::move(name)), pattern(pattern) {}
// The field name. Cannot be empty
std::string name;
// The pattern the field must match.
Ptr<const Pattern> pattern;
Nonnull<const Pattern*> pattern;
};
TuplePattern(SourceLocation loc, std::vector<Field> fields)
@@ -111,7 +111,7 @@ class TuplePattern : public Pattern {
// ExpressionPattern.
//
// REQUIRES: tuple_literal->Tag() == Expression::Kind::TupleLiteral
TuplePattern(Ptr<Arena> arena, Ptr<const Expression> tuple_literal);
TuplePattern(Nonnull<Arena*> arena, Nonnull<const Expression*> tuple_literal);
static auto classof(const Pattern* pattern) -> bool {
return pattern->Tag() == Kind::TuplePattern;
@@ -126,19 +126,19 @@ class TuplePattern : public Pattern {
// Converts paren_contents to a Pattern, interpreting the parentheses as
// grouping if their contents permit that interpretation, or as forming a
// tuple otherwise.
auto PatternFromParenContents(Ptr<Arena> arena, SourceLocation loc,
auto PatternFromParenContents(Nonnull<Arena*> arena, SourceLocation loc,
const ParenContents<Pattern>& paren_contents)
-> Ptr<const Pattern>;
-> Nonnull<const Pattern*>;
// Converts paren_contents to a TuplePattern, interpreting the parentheses as
// forming a tuple.
auto TuplePatternFromParenContents(Ptr<Arena> arena, SourceLocation loc,
auto TuplePatternFromParenContents(Nonnull<Arena*> arena, SourceLocation loc,
const ParenContents<Pattern>& paren_contents)
-> Ptr<const TuplePattern>;
-> Nonnull<const TuplePattern*>;
// Converts `contents` to ParenContents<Pattern> by replacing each Expression
// with an ExpressionPattern.
auto ParenExpressionToParenPattern(Ptr<Arena> arena,
auto ParenExpressionToParenPattern(Nonnull<Arena*> arena,
const ParenContents<Expression>& contents)
-> ParenContents<Pattern>;
@@ -148,9 +148,9 @@ class AlternativePattern : public Pattern {
// Constructs an AlternativePattern that matches a value of the type
// specified by choice_type if it represents an alternative named
// alternative_name, and its arguments match `arguments`.
AlternativePattern(SourceLocation loc, Ptr<const Expression> choice_type,
AlternativePattern(SourceLocation loc, Nonnull<const Expression*> choice_type,
std::string alternative_name,
Ptr<const TuplePattern> arguments)
Nonnull<const TuplePattern*> arguments)
: Pattern(Kind::AlternativePattern, loc),
choice_type(choice_type),
alternative_name(std::move(alternative_name)),
@@ -158,30 +158,30 @@ class AlternativePattern : public Pattern {
// Constructs an AlternativePattern that matches the alternative specified
// by `alternative`, if its arguments match `arguments`.
AlternativePattern(SourceLocation loc, Ptr<const Expression> alternative,
Ptr<const TuplePattern> arguments);
AlternativePattern(SourceLocation loc, Nonnull<const Expression*> alternative,
Nonnull<const TuplePattern*> arguments);
static auto classof(const Pattern* pattern) -> bool {
return pattern->Tag() == Kind::AlternativePattern;
}
auto ChoiceType() const -> Ptr<const Expression> { return choice_type; }
auto ChoiceType() const -> Nonnull<const Expression*> { return choice_type; }
auto AlternativeName() const -> const std::string& {
return alternative_name;
}
auto Arguments() const -> Ptr<const TuplePattern> { return arguments; }
auto Arguments() const -> Nonnull<const TuplePattern*> { return arguments; }
private:
Ptr<const Expression> choice_type;
Nonnull<const Expression*> choice_type;
std::string alternative_name;
Ptr<const TuplePattern> arguments;
Nonnull<const TuplePattern*> arguments;
};
// A pattern that matches a value if it is equal to the value of a given
// expression.
class ExpressionPattern : public Pattern {
public:
ExpressionPattern(Ptr<const Expression> expression)
ExpressionPattern(Nonnull<const Expression*> expression)
: Pattern(Kind::ExpressionPattern, expression->SourceLoc()),
expression(expression) {}
@@ -189,10 +189,10 @@ class ExpressionPattern : public Pattern {
return pattern->Tag() == Kind::ExpressionPattern;
}
auto Expression() const -> Ptr<const Expression> { return expression; }
auto Expression() const -> Nonnull<const Expression*> { return expression; }
private:
Ptr<const Carbon::Expression> expression;
Nonnull<const Carbon::Expression*> expression;
};
} // namespace Carbon
+8 -8
View File
@@ -37,7 +37,7 @@ class PatternTest : public ::testing::Test {
TEST_F(PatternTest, EmptyAsPattern) {
ParenContents<Pattern> contents = {.elements = {},
.has_trailing_comma = false};
Ptr<const Pattern> pattern =
Nonnull<const Pattern*> pattern =
PatternFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(pattern->SourceLoc(), FakeSourceLoc(1));
ASSERT_TRUE(isa<TuplePattern>(*pattern));
@@ -47,7 +47,7 @@ TEST_F(PatternTest, EmptyAsPattern) {
TEST_F(PatternTest, EmptyAsTuplePattern) {
ParenContents<Pattern> contents = {.elements = {},
.has_trailing_comma = false};
Ptr<const TuplePattern> tuple =
Nonnull<const TuplePattern*> tuple =
TuplePatternFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1));
EXPECT_THAT(tuple->Fields(), IsEmpty());
@@ -65,7 +65,7 @@ TEST_F(PatternTest, UnaryNoCommaAsPattern) {
.term = arena.New<AutoPattern>(FakeSourceLoc(2))}},
.has_trailing_comma = false};
Ptr<const Pattern> pattern =
Nonnull<const Pattern*> pattern =
PatternFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(pattern->SourceLoc(), FakeSourceLoc(2));
ASSERT_TRUE(isa<AutoPattern>(*pattern));
@@ -77,7 +77,7 @@ TEST_F(PatternTest, UnaryNoCommaAsTuplePattern) {
.term = arena.New<AutoPattern>(FakeSourceLoc(2))}},
.has_trailing_comma = false};
Ptr<const TuplePattern> tuple =
Nonnull<const TuplePattern*> tuple =
TuplePatternFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1));
EXPECT_THAT(tuple->Fields(), ElementsAre(AutoFieldNamed("0")));
@@ -89,7 +89,7 @@ TEST_F(PatternTest, UnaryWithCommaAsPattern) {
.term = arena.New<AutoPattern>(FakeSourceLoc(2))}},
.has_trailing_comma = true};
Ptr<const Pattern> pattern =
Nonnull<const Pattern*> pattern =
PatternFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(pattern->SourceLoc(), FakeSourceLoc(1));
ASSERT_TRUE(isa<TuplePattern>(*pattern));
@@ -103,7 +103,7 @@ TEST_F(PatternTest, UnaryWithCommaAsTuplePattern) {
.term = arena.New<AutoPattern>(FakeSourceLoc(2))}},
.has_trailing_comma = true};
Ptr<const TuplePattern> tuple =
Nonnull<const TuplePattern*> tuple =
TuplePatternFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1));
EXPECT_THAT(tuple->Fields(), ElementsAre(AutoFieldNamed("0")));
@@ -117,7 +117,7 @@ TEST_F(PatternTest, BinaryAsPattern) {
.term = arena.New<AutoPattern>(FakeSourceLoc(2))}},
.has_trailing_comma = true};
Ptr<const Pattern> pattern =
Nonnull<const Pattern*> pattern =
PatternFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(pattern->SourceLoc(), FakeSourceLoc(1));
ASSERT_TRUE(isa<TuplePattern>(*pattern));
@@ -133,7 +133,7 @@ TEST_F(PatternTest, BinaryAsTuplePattern) {
.term = arena.New<AutoPattern>(FakeSourceLoc(2))}},
.has_trailing_comma = true};
Ptr<const TuplePattern> tuple =
Nonnull<const TuplePattern*> tuple =
TuplePatternFromParenContents(&arena, FakeSourceLoc(1), contents);
EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1));
EXPECT_THAT(tuple->Fields(),
+1 -1
View File
@@ -18,7 +18,7 @@ class SourceLocation {
// The filename should be eternal or arena-allocated to eliminate copies.
SourceLocation(const char* filename, int line_num)
: filename(filename), line_num(line_num) {}
SourceLocation(Ptr<const std::string> filename, int line_num)
SourceLocation(Nonnull<const std::string*> filename, int line_num)
: filename(filename->c_str()), line_num(line_num) {}
SourceLocation(const SourceLocation&) = default;
+59 -56
View File
@@ -58,60 +58,60 @@ class Statement {
class ExpressionStatement : public Statement {
public:
ExpressionStatement(SourceLocation loc, Ptr<const Expression> exp)
ExpressionStatement(SourceLocation loc, Nonnull<const Expression*> exp)
: Statement(Kind::ExpressionStatement, loc), exp(exp) {}
static auto classof(const Statement* stmt) -> bool {
return stmt->Tag() == Kind::ExpressionStatement;
}
auto Exp() const -> Ptr<const Expression> { return exp; }
auto Exp() const -> Nonnull<const Expression*> { return exp; }
private:
Ptr<const Expression> exp;
Nonnull<const Expression*> exp;
};
class Assign : public Statement {
public:
Assign(SourceLocation loc, Ptr<const Expression> lhs,
Ptr<const Expression> rhs)
Assign(SourceLocation loc, Nonnull<const Expression*> lhs,
Nonnull<const Expression*> rhs)
: Statement(Kind::Assign, loc), lhs(lhs), rhs(rhs) {}
static auto classof(const Statement* stmt) -> bool {
return stmt->Tag() == Kind::Assign;
}
auto Lhs() const -> Ptr<const Expression> { return lhs; }
auto Rhs() const -> Ptr<const Expression> { return rhs; }
auto Lhs() const -> Nonnull<const Expression*> { return lhs; }
auto Rhs() const -> Nonnull<const Expression*> { return rhs; }
private:
Ptr<const Expression> lhs;
Ptr<const Expression> rhs;
Nonnull<const Expression*> lhs;
Nonnull<const Expression*> rhs;
};
class VariableDefinition : public Statement {
public:
VariableDefinition(SourceLocation loc, Ptr<const Pattern> pat,
Ptr<const Expression> init)
VariableDefinition(SourceLocation loc, Nonnull<const Pattern*> pat,
Nonnull<const Expression*> init)
: Statement(Kind::VariableDefinition, loc), pat(pat), init(init) {}
static auto classof(const Statement* stmt) -> bool {
return stmt->Tag() == Kind::VariableDefinition;
}
auto Pat() const -> Ptr<const Pattern> { return pat; }
auto Init() const -> Ptr<const Expression> { return init; }
auto Pat() const -> Nonnull<const Pattern*> { return pat; }
auto Init() const -> Nonnull<const Expression*> { return init; }
private:
Ptr<const Pattern> pat;
Ptr<const Expression> init;
Nonnull<const Pattern*> pat;
Nonnull<const Expression*> init;
};
class If : public Statement {
public:
If(SourceLocation loc, Ptr<const Expression> cond,
Ptr<const Statement> then_stmt,
std::optional<Ptr<const Statement>> else_stmt)
If(SourceLocation loc, Nonnull<const Expression*> cond,
Nonnull<const Statement*> then_stmt,
std::optional<Nonnull<const Statement*>> else_stmt)
: Statement(Kind::If, loc),
cond(cond),
then_stmt(then_stmt),
@@ -121,23 +121,24 @@ class If : public Statement {
return stmt->Tag() == Kind::If;
}
auto Cond() const -> Ptr<const Expression> { return cond; }
auto ThenStmt() const -> Ptr<const Statement> { return then_stmt; }
auto ElseStmt() const -> std::optional<Ptr<const Statement>> {
auto Cond() const -> Nonnull<const Expression*> { return cond; }
auto ThenStmt() const -> Nonnull<const Statement*> { return then_stmt; }
auto ElseStmt() const -> std::optional<Nonnull<const Statement*>> {
return else_stmt;
}
private:
Ptr<const Expression> cond;
Ptr<const Statement> then_stmt;
std::optional<Ptr<const Statement>> else_stmt;
Nonnull<const Expression*> cond;
Nonnull<const Statement*> then_stmt;
std::optional<Nonnull<const Statement*>> else_stmt;
};
class Return : public Statement {
public:
Return(Ptr<Arena> arena, SourceLocation loc)
Return(Nonnull<Arena*> arena, SourceLocation loc)
: Return(loc, arena->New<TupleLiteral>(loc), true) {}
Return(SourceLocation loc, Ptr<const Expression> exp, bool is_omitted_exp)
Return(SourceLocation loc, Nonnull<const Expression*> exp,
bool is_omitted_exp)
: Statement(Kind::Return, loc),
exp(exp),
is_omitted_exp(is_omitted_exp) {}
@@ -146,63 +147,63 @@ class Return : public Statement {
return stmt->Tag() == Kind::Return;
}
auto Exp() const -> Ptr<const Expression> { return exp; }
auto Exp() const -> Nonnull<const Expression*> { return exp; }
auto IsOmittedExp() const -> bool { return is_omitted_exp; }
private:
Ptr<const Expression> exp;
Nonnull<const Expression*> exp;
bool is_omitted_exp;
};
class Sequence : public Statement {
public:
Sequence(SourceLocation loc, Ptr<const Statement> stmt,
std::optional<Ptr<const Statement>> next)
Sequence(SourceLocation loc, Nonnull<const Statement*> stmt,
std::optional<Nonnull<const Statement*>> next)
: Statement(Kind::Sequence, loc), stmt(stmt), next(next) {}
static auto classof(const Statement* stmt) -> bool {
return stmt->Tag() == Kind::Sequence;
}
auto Stmt() const -> Ptr<const Statement> { return stmt; }
auto Next() const -> std::optional<Ptr<const Statement>> { return next; }
auto Stmt() const -> Nonnull<const Statement*> { return stmt; }
auto Next() const -> std::optional<Nonnull<const Statement*>> { return next; }
private:
Ptr<const Statement> stmt;
std::optional<Ptr<const Statement>> next;
Nonnull<const Statement*> stmt;
std::optional<Nonnull<const Statement*>> next;
};
class Block : public Statement {
public:
Block(SourceLocation loc, std::optional<Ptr<const Statement>> stmt)
Block(SourceLocation loc, std::optional<Nonnull<const Statement*>> stmt)
: Statement(Kind::Block, loc), stmt(stmt) {}
static auto classof(const Statement* stmt) -> bool {
return stmt->Tag() == Kind::Block;
}
auto Stmt() const -> std::optional<Ptr<const Statement>> { return stmt; }
auto Stmt() const -> std::optional<Nonnull<const Statement*>> { return stmt; }
private:
std::optional<Ptr<const Statement>> stmt;
std::optional<Nonnull<const Statement*>> stmt;
};
class While : public Statement {
public:
While(SourceLocation loc, Ptr<const Expression> cond,
Ptr<const Statement> body)
While(SourceLocation loc, Nonnull<const Expression*> cond,
Nonnull<const Statement*> body)
: Statement(Kind::While, loc), cond(cond), body(body) {}
static auto classof(const Statement* stmt) -> bool {
return stmt->Tag() == Kind::While;
}
auto Cond() const -> Ptr<const Expression> { return cond; }
auto Body() const -> Ptr<const Statement> { return body; }
auto Cond() const -> Nonnull<const Expression*> { return cond; }
auto Body() const -> Nonnull<const Statement*> { return body; }
private:
Ptr<const Expression> cond;
Ptr<const Statement> body;
Nonnull<const Expression*> cond;
Nonnull<const Statement*> body;
};
class Break : public Statement {
@@ -226,23 +227,25 @@ class Continue : public Statement {
class Match : public Statement {
public:
Match(
SourceLocation loc, Ptr<const Expression> exp,
std::vector<std::pair<Ptr<const Pattern>, Ptr<const Statement>>> clauses)
SourceLocation loc, Nonnull<const Expression*> exp,
std::vector<std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>>
clauses)
: Statement(Kind::Match, loc), exp(exp), clauses(std::move(clauses)) {}
static auto classof(const Statement* stmt) -> bool {
return stmt->Tag() == Kind::Match;
}
auto Exp() const -> Ptr<const Expression> { return exp; }
auto Clauses() const -> const
std::vector<std::pair<Ptr<const Pattern>, Ptr<const Statement>>>& {
auto Exp() const -> Nonnull<const Expression*> { return exp; }
auto Clauses() const -> const std::vector<
std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>>& {
return clauses;
}
private:
Ptr<const Expression> exp;
std::vector<std::pair<Ptr<const Pattern>, Ptr<const Statement>>> clauses;
Nonnull<const Expression*> exp;
std::vector<std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>>
clauses;
};
// A continuation statement.
@@ -253,7 +256,7 @@ class Match : public Statement {
class Continuation : public Statement {
public:
Continuation(SourceLocation loc, std::string continuation_variable,
Ptr<const Statement> body)
Nonnull<const Statement*> body)
: Statement(Kind::Continuation, loc),
continuation_variable(std::move(continuation_variable)),
body(body) {}
@@ -265,11 +268,11 @@ class Continuation : public Statement {
auto ContinuationVariable() const -> const std::string& {
return continuation_variable;
}
auto Body() const -> Ptr<const Statement> { return body; }
auto Body() const -> Nonnull<const Statement*> { return body; }
private:
std::string continuation_variable;
Ptr<const Statement> body;
Nonnull<const Statement*> body;
};
// A run statement.
@@ -277,17 +280,17 @@ class Continuation : public Statement {
// __run <argument>;
class Run : public Statement {
public:
Run(SourceLocation loc, Ptr<const Expression> argument)
Run(SourceLocation loc, Nonnull<const Expression*> argument)
: Statement(Kind::Run, loc), argument(argument) {}
static auto classof(const Statement* stmt) -> bool {
return stmt->Tag() == Kind::Run;
}
auto Argument() const -> Ptr<const Expression> { return argument; }
auto Argument() const -> Nonnull<const Expression*> { return argument; }
private:
Ptr<const Expression> argument;
Nonnull<const Expression*> argument;
};
// An await statement.
+3 -3
View File
@@ -16,10 +16,10 @@ class Arena {
public:
// Allocates an object in the arena, returning a pointer to it.
template <typename T, typename... Args>
auto New(Args&&... args) -> Ptr<T> {
auto New(Args&&... args) -> Nonnull<T*> {
auto smart_ptr =
std::make_unique<ArenaEntryTyped<T>>(std::forward<Args>(args)...);
Ptr<T> ptr = smart_ptr->Instance();
Nonnull<T*> ptr = smart_ptr->Instance();
arena.push_back(std::move(smart_ptr));
return ptr;
}
@@ -40,7 +40,7 @@ class Arena {
explicit ArenaEntryTyped(Args&&... args)
: instance(std::forward<Args>(args)...) {}
auto Instance() -> Ptr<T> { return Ptr<T>(&instance); }
auto Instance() -> Nonnull<T*> { return Nonnull<T*>(&instance); }
private:
T instance;
+10 -3
View File
@@ -5,11 +5,18 @@
#ifndef EXECUTABLE_SEMANTICS_COMMON_PTR_H_
#define EXECUTABLE_SEMANTICS_COMMON_PTR_H_
#include <type_traits>
namespace Carbon {
// A non-nullable pointer. Written as `Ptr<T>` instead of `T*`.
template <typename T>
using Ptr = T* _Nonnull __attribute__((nonnull));
// A non-nullable pointer. Written as `Nonnull<T*>` instead of `T*`.
//
// Note LLVM primarily enforces the attribute on function calls that can be
// proven to be called with nullptr; in other places, this is essentially a
// comment.
template <typename T,
typename std::enable_if_t<std::is_pointer_v<T>>* = nullptr>
using Nonnull = T _Nonnull __attribute__((nonnull));
} // namespace Carbon
+2 -1
View File
@@ -47,7 +47,8 @@ void Action::Print(llvm::raw_ostream& out) const {
}
}
void Action::PrintList(const Stack<Ptr<Action>>& ls, llvm::raw_ostream& out) {
void Action::PrintList(const Stack<Nonnull<Action*>>& ls,
llvm::raw_ostream& out) {
llvm::ListSeparator sep(" :: ");
for (const auto& action : ls) {
out << sep << *action;
+17 -16
View File
@@ -38,13 +38,13 @@ class Action {
auto Pos() const -> int { return pos; }
// Results from a subexpression.
auto Results() const -> const std::vector<Ptr<const Value>>& {
auto Results() const -> const std::vector<Nonnull<const Value*>>& {
return results;
}
void SetPos(int pos) { this->pos = pos; }
void AddResult(Ptr<const Value> result) { results.push_back(result); }
void AddResult(Nonnull<const Value*> result) { results.push_back(result); }
void Clear() {
pos = 0;
@@ -55,7 +55,8 @@ class Action {
// object.
auto Tag() const -> Kind { return tag; }
static void PrintList(const Stack<Ptr<Action>>& ls, llvm::raw_ostream& out);
static void PrintList(const Stack<Nonnull<Action*>>& ls,
llvm::raw_ostream& out);
void Print(llvm::raw_ostream& out) const;
LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
@@ -67,69 +68,69 @@ class Action {
private:
int pos = 0;
std::vector<Ptr<const Value>> results;
std::vector<Nonnull<const Value*>> results;
const Kind tag;
};
class LValAction : public Action {
public:
explicit LValAction(Ptr<const Expression> exp)
explicit LValAction(Nonnull<const Expression*> exp)
: Action(Kind::LValAction), exp(exp) {}
static auto classof(const Action* action) -> bool {
return action->Tag() == Kind::LValAction;
}
auto Exp() const -> Ptr<const Expression> { return exp; }
auto Exp() const -> Nonnull<const Expression*> { return exp; }
private:
Ptr<const Expression> exp;
Nonnull<const Expression*> exp;
};
class ExpressionAction : public Action {
public:
explicit ExpressionAction(Ptr<const Expression> exp)
explicit ExpressionAction(Nonnull<const Expression*> exp)
: Action(Kind::ExpressionAction), exp(exp) {}
static auto classof(const Action* action) -> bool {
return action->Tag() == Kind::ExpressionAction;
}
auto Exp() const -> Ptr<const Expression> { return exp; }
auto Exp() const -> Nonnull<const Expression*> { return exp; }
private:
Ptr<const Expression> exp;
Nonnull<const Expression*> exp;
};
class PatternAction : public Action {
public:
explicit PatternAction(Ptr<const Pattern> pat)
explicit PatternAction(Nonnull<const Pattern*> pat)
: Action(Kind::PatternAction), pat(pat) {}
static auto classof(const Action* action) -> bool {
return action->Tag() == Kind::PatternAction;
}
auto Pat() const -> Ptr<const Pattern> { return pat; }
auto Pat() const -> Nonnull<const Pattern*> { return pat; }
private:
Ptr<const Pattern> pat;
Nonnull<const Pattern*> pat;
};
class StatementAction : public Action {
public:
explicit StatementAction(Ptr<const Statement> stmt)
explicit StatementAction(Nonnull<const Statement*> stmt)
: Action(Kind::StatementAction), stmt(stmt) {}
static auto classof(const Action* action) -> bool {
return action->Tag() == Kind::StatementAction;
}
auto Stmt() const -> Ptr<const Statement> { return stmt; }
auto Stmt() const -> Nonnull<const Statement*> { return stmt; }
private:
Ptr<const Statement> stmt;
Nonnull<const Statement*> stmt;
};
} // namespace Carbon
@@ -20,10 +20,10 @@ class Dictionary {
struct Node {
using ValueType = std::pair<K, V>;
Node(ValueType e, std::optional<Ptr<Node>> n) : curr(e), next(n) {}
Node(ValueType e, std::optional<Nonnull<Node*>> n) : curr(e), next(n) {}
const ValueType curr;
const std::optional<Ptr<Node>> next;
const std::optional<Nonnull<Node*>> next;
// Node cells are part of a "persistent data structure" and are thus
// immutable.
@@ -39,7 +39,7 @@ class Dictionary {
using reference = const value_type&;
using iterator_category = std::forward_iterator_tag;
Iterator(std::optional<Ptr<Node>> x) : p(x) {}
Iterator(std::optional<Nonnull<Node*>> x) : p(x) {}
Iterator(const Iterator& iter) : p(iter.p) {}
Iterator& operator++() {
p = (*p)->next;
@@ -56,11 +56,11 @@ class Dictionary {
const value_type* operator->() { return &(*p)->curr; }
private:
std::optional<Ptr<Node>> p;
std::optional<Nonnull<Node*>> p;
};
// Create an empty dictionary.
explicit Dictionary(Ptr<Arena> arena) : arena(arena) {}
explicit Dictionary(Nonnull<Arena*> arena) : arena(arena) {}
// Return the value associated with the given key.
// Time complexity: O(n) where n is the number of times
@@ -90,8 +90,8 @@ class Dictionary {
auto end() const -> Iterator { return Iterator(std::nullopt); }
private:
std::optional<Ptr<Node>> head;
Ptr<Arena> arena;
std::optional<Nonnull<Node*>> head;
Nonnull<Arena*> arena;
};
} // namespace Carbon
@@ -15,8 +15,9 @@ namespace Carbon {
// Adds builtins, currently only Print(). Note Print() is experimental, not
// standardized, but is made available for printing state in tests.
static void AddIntrinsics(Ptr<Arena> arena,
std::vector<Ptr<const Declaration>>* declarations) {
static void AddIntrinsics(
Nonnull<Arena*> arena,
std::vector<Nonnull<const Declaration*>>* declarations) {
SourceLocation loc("<intrinsic>", 0);
std::vector<TuplePattern::Field> print_fields = {TuplePattern::Field(
"0",
@@ -36,7 +37,7 @@ static void AddIntrinsics(Ptr<Arena> arena,
declarations->insert(declarations->begin(), print);
}
void ExecProgram(Ptr<Arena> arena, AST ast) {
void ExecProgram(Nonnull<Arena*> arena, AST ast) {
AddIntrinsics(arena, &ast.declarations);
if (tracing_output) {
llvm::outs() << "********** source program **********\n";
@@ -49,7 +50,7 @@ void ExecProgram(Ptr<Arena> arena, AST ast) {
TypeChecker::TypeCheckContext p = type_checker.TopLevel(ast.declarations);
TypeEnv top = p.types;
Env ct_top = p.values;
std::vector<Ptr<const Declaration>> new_decls;
std::vector<Nonnull<const Declaration*>> new_decls;
for (const auto decl : ast.declarations) {
new_decls.push_back(type_checker.MakeTypeChecked(decl, top, ct_top));
}
@@ -14,7 +14,7 @@
namespace Carbon {
// Runs the top-level declaration list.
void ExecProgram(Ptr<Arena> arena, AST ast);
void ExecProgram(Nonnull<Arena*> arena, AST ast);
} // namespace Carbon
+3 -3
View File
@@ -33,7 +33,7 @@ struct Frame {
Frame(const Frame&) = delete;
Frame& operator=(const Frame&) = delete;
Frame(std::string n, Stack<Ptr<Scope>> s, Stack<Ptr<Action>> c)
Frame(std::string n, Stack<Nonnull<Scope*>> s, Stack<Nonnull<Action*>> c)
: name(std::move(std::move(n))), scopes(s), todo(c), continuation() {}
void Print(llvm::raw_ostream& out) const;
@@ -47,11 +47,11 @@ struct Frame {
// blocks within the function. The scope at the top of the stack is
// the current scope and its environment is the one used for looking
// up the value associated with a variable.
Stack<Ptr<Scope>> scopes;
Stack<Nonnull<Scope*>> scopes;
// The actions that need to be executed in the future of the
// current function call. The top of the stack is the action
// that is executed first.
Stack<Ptr<Action>> todo;
Stack<Nonnull<Action*>> todo;
// If this frame is the bottom frame of a continuation, then it stores
// the address of the continuation.
std::optional<Address> continuation;
+4 -3
View File
@@ -9,7 +9,7 @@
namespace Carbon {
auto Heap::AllocateValue(Ptr<const Value> v) -> Address {
auto Heap::AllocateValue(Nonnull<const Value*> v) -> Address {
// Putting the following two side effects together in this function
// ensures that we don't do anything else in between, which is really bad!
// Consider whether to include a copy of the input v in this function
@@ -20,12 +20,13 @@ auto Heap::AllocateValue(Ptr<const Value> v) -> Address {
return a;
}
auto Heap::Read(const Address& a, SourceLocation loc) -> Ptr<const Value> {
auto Heap::Read(const Address& a, SourceLocation loc) -> Nonnull<const Value*> {
this->CheckAlive(a, loc);
return values[a.index]->GetField(arena, a.field_path, loc);
}
void Heap::Write(const Address& a, Ptr<const Value> v, SourceLocation loc) {
void Heap::Write(const Address& a, Nonnull<const Value*> v,
SourceLocation loc) {
this->CheckAlive(a, loc);
values[a.index] = values[a.index]->SetField(arena, a.field_path, v, loc);
}
+6 -6
View File
@@ -18,21 +18,21 @@ namespace Carbon {
class Heap {
public:
// Constructs an empty Heap.
explicit Heap(Ptr<Arena> arena) : arena(arena){};
explicit Heap(Nonnull<Arena*> arena) : arena(arena){};
Heap(const Heap&) = delete;
Heap& operator=(const Heap&) = delete;
// Returns the value at the given address in the heap after
// checking that it is alive.
auto Read(const Address& a, SourceLocation loc) -> Ptr<const Value>;
auto Read(const Address& a, SourceLocation loc) -> Nonnull<const Value*>;
// Writes the given value at the address in the heap after
// checking that the address is alive.
void Write(const Address& a, Ptr<const Value> v, SourceLocation loc);
void Write(const Address& a, Nonnull<const Value*> v, SourceLocation loc);
// Put the given value on the heap and mark it as alive.
auto AllocateValue(Ptr<const Value> v) -> Address;
auto AllocateValue(Nonnull<const Value*> v) -> Address;
// Marks the object at this address, and all of its sub-objects, as dead.
void Deallocate(const Address& address);
@@ -49,8 +49,8 @@ class Heap {
// Signal an error if the address is no longer alive.
void CheckAlive(const Address& address, SourceLocation loc);
Ptr<Arena> arena;
std::vector<Ptr<const Value>> values;
Nonnull<Arena*> arena;
std::vector<Nonnull<const Value*>> values;
std::vector<bool> alive;
};
@@ -46,7 +46,7 @@ void Interpreter::PrintEnv(Env values, llvm::raw_ostream& out) {
//
auto Interpreter::CurrentEnv() -> Env {
Ptr<Frame> frame = stack.Top();
Nonnull<Frame*> frame = stack.Top();
return frame->scopes.Top()->values;
}
@@ -75,8 +75,8 @@ void Interpreter::PrintState(llvm::raw_ostream& out) {
}
auto Interpreter::EvalPrim(Operator op,
const std::vector<Ptr<const Value>>& args,
SourceLocation loc) -> Ptr<const Value> {
const std::vector<Nonnull<const Value*>>& args,
SourceLocation loc) -> Nonnull<const Value*> {
switch (op) {
case Operator::Neg:
return arena->New<IntValue>(-cast<IntValue>(*args[0]).Val());
@@ -128,11 +128,12 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) {
const ClassDefinition& class_def = cast<ClassDeclaration>(d).Definition();
VarValues fields;
VarValues methods;
for (Ptr<const Member> m : class_def.members) {
for (Nonnull<const Member*> m : class_def.members) {
switch (m->Tag()) {
case Member::Kind::FieldMember: {
Ptr<const BindingPattern> binding = cast<FieldMember>(*m).Binding();
Ptr<const Expression> type_expression =
Nonnull<const BindingPattern*> binding =
cast<FieldMember>(*m).Binding();
Nonnull<const Expression*> type_expression =
cast<ExpressionPattern>(*binding->Type()).Expression();
auto type = InterpExp(Env(arena), type_expression);
fields.push_back(make_pair(*binding->Name(), type));
@@ -172,13 +173,14 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) {
}
}
void Interpreter::InitGlobals(const std::vector<Ptr<const Declaration>>& fs) {
void Interpreter::InitGlobals(
const std::vector<Nonnull<const Declaration*>>& fs) {
for (const auto d : fs) {
InitEnv(*d, &globals);
}
}
void Interpreter::DeallocateScope(Ptr<Scope> scope) {
void Interpreter::DeallocateScope(Nonnull<Scope*> scope) {
for (const auto& l : scope->locals) {
std::optional<Address> a = scope->values.Get(l);
CHECK(a);
@@ -186,15 +188,16 @@ void Interpreter::DeallocateScope(Ptr<Scope> scope) {
}
}
void Interpreter::DeallocateLocals(Ptr<Frame> frame) {
void Interpreter::DeallocateLocals(Nonnull<Frame*> frame) {
while (!frame->scopes.IsEmpty()) {
DeallocateScope(frame->scopes.Top());
frame->scopes.Pop();
}
}
auto Interpreter::CreateTuple(Ptr<Action> act, Ptr<const Expression> exp)
-> Ptr<const Value> {
auto Interpreter::CreateTuple(Nonnull<Action*> act,
Nonnull<const Expression*> exp)
-> Nonnull<const Value*> {
// { { (v1,...,vn) :: C, E, F} :: S, H}
// -> { { `(v1,...,vn) :: C, E, F} :: S, H}
const auto& tup_lit = cast<TupleLiteral>(*exp);
@@ -208,7 +211,7 @@ auto Interpreter::CreateTuple(Ptr<Action> act, Ptr<const Expression> exp)
return arena->New<TupleValue>(std::move(elements));
}
auto Interpreter::PatternMatch(Ptr<const Value> p, Ptr<const Value> v,
auto Interpreter::PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
SourceLocation loc) -> std::optional<Env> {
switch (p->Tag()) {
case Value::Kind::BindingPlaceholderValue: {
@@ -303,7 +306,8 @@ auto Interpreter::PatternMatch(Ptr<const Value> p, Ptr<const Value> v,
}
}
void Interpreter::PatternAssignment(Ptr<const Value> pat, Ptr<const Value> val,
void Interpreter::PatternAssignment(Nonnull<const Value*> pat,
Nonnull<const Value*> val,
SourceLocation loc) {
switch (pat->Tag()) {
case Value::Kind::PointerValue:
@@ -320,7 +324,7 @@ void Interpreter::PatternAssignment(Ptr<const Value> pat, Ptr<const Value> val,
<< pat_tup << "\n value: " << val_tup;
}
for (const TupleElement& pattern_element : pat_tup.Elements()) {
std::optional<Ptr<const Value>> value_field =
std::optional<Nonnull<const Value*>> value_field =
val_tup.FindField(pattern_element.name);
if (!value_field) {
FATAL_RUNTIME_ERROR(loc)
@@ -358,8 +362,8 @@ void Interpreter::PatternAssignment(Ptr<const Value> pat, Ptr<const Value> val,
}
auto Interpreter::StepLvalue() -> Transition {
Ptr<Action> act = stack.Top()->todo.Top();
Ptr<const Expression> exp = cast<LValAction>(*act).Exp();
Nonnull<Action*> act = stack.Top()->todo.Top();
Nonnull<const Expression*> exp = cast<LValAction>(*act).Exp();
if (tracing_output) {
llvm::outs() << "--- step lvalue " << *exp << " (" << exp->SourceLoc()
<< ") --->\n";
@@ -370,7 +374,7 @@ auto Interpreter::StepLvalue() -> Transition {
// -> { {E(x) :: C, E, F} :: S, H}
Address pointer =
GetFromEnv(exp->SourceLoc(), cast<IdentifierExpression>(*exp).Name());
Ptr<const Value> v = arena->New<PointerValue>(pointer);
Nonnull<const Value*> v = arena->New<PointerValue>(pointer);
return Done{v};
}
case Expression::Kind::FieldAccessExpression: {
@@ -412,7 +416,7 @@ auto Interpreter::StepLvalue() -> Transition {
if (act->Pos() == 0) {
// { {(f1=e1,...) :: C, E, F} :: S, H}
// -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H}
Ptr<const Expression> e1 =
Nonnull<const Expression*> e1 =
cast<TupleLiteral>(*exp).Fields()[0].expression;
return Spawn{arena->New<LValAction>(e1)};
} else if (act->Pos() !=
@@ -421,7 +425,7 @@ auto Interpreter::StepLvalue() -> Transition {
// H}
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
// H}
Ptr<const Expression> elt =
Nonnull<const Expression*> elt =
cast<TupleLiteral>(*exp).Fields()[act->Pos()].expression;
return Spawn{arena->New<LValAction>(elt)};
} else {
@@ -446,8 +450,8 @@ auto Interpreter::StepLvalue() -> Transition {
}
auto Interpreter::StepExp() -> Transition {
Ptr<Action> act = stack.Top()->todo.Top();
Ptr<const Expression> exp = cast<ExpressionAction>(*act).Exp();
Nonnull<Action*> act = stack.Top()->todo.Top();
Nonnull<const Expression*> exp = cast<ExpressionAction>(*act).Exp();
if (tracing_output) {
llvm::outs() << "--- step exp " << *exp << " (" << exp->SourceLoc()
<< ") --->\n";
@@ -472,7 +476,7 @@ auto Interpreter::StepExp() -> Transition {
}
std::string f =
std::to_string(cast<IntValue>(*act->Results()[1]).Val());
std::optional<Ptr<const Value>> field = tuple->FindField(f);
std::optional<Nonnull<const Value*>> field = tuple->FindField(f);
if (!field) {
FATAL_RUNTIME_ERROR_NO_LINE()
<< "field " << f << " not in " << *tuple;
@@ -485,7 +489,7 @@ auto Interpreter::StepExp() -> Transition {
if (cast<TupleLiteral>(*exp).Fields().size() > 0) {
// { {(f1=e1,...) :: C, E, F} :: S, H}
// -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H}
Ptr<const Expression> e1 =
Nonnull<const Expression*> e1 =
cast<TupleLiteral>(*exp).Fields()[0].expression;
return Spawn{arena->New<ExpressionAction>(e1)};
} else {
@@ -497,7 +501,7 @@ auto Interpreter::StepExp() -> Transition {
// H}
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
// H}
Ptr<const Expression> elt =
Nonnull<const Expression*> elt =
cast<TupleLiteral>(*exp).Fields()[act->Pos()].expression;
return Spawn{arena->New<ExpressionAction>(elt)};
} else {
@@ -537,7 +541,7 @@ auto Interpreter::StepExp() -> Transition {
if (act->Pos() != static_cast<int>(op.Arguments().size())) {
// { {v :: op(vs,[],e,es) :: C, E, F} :: S, H}
// -> { {e :: op(vs,v,[],es) :: C, E, F} :: S, H}
Ptr<const Expression> arg = op.Arguments()[act->Pos()];
Nonnull<const Expression*> arg = op.Arguments()[act->Pos()];
return Spawn{arena->New<ExpressionAction>(arg)};
} else {
// { {v :: op(vs,[]) :: C, E, F} :: S, H}
@@ -561,14 +565,14 @@ auto Interpreter::StepExp() -> Transition {
// -> { {C',E',F'} :: {C, E, F} :: S, H}
switch (act->Results()[0]->Tag()) {
case Value::Kind::ClassType: {
Ptr<const Value> arg =
Nonnull<const Value*> arg =
CopyVal(arena, act->Results()[1], exp->SourceLoc());
return Done{arena->New<StructValue>(act->Results()[0], arg)};
}
case Value::Kind::AlternativeConstructorValue: {
const auto& alt =
cast<AlternativeConstructorValue>(*act->Results()[0]);
Ptr<const Value> arg =
Nonnull<const Value*> arg =
CopyVal(arena, act->Results()[1], exp->SourceLoc());
return Done{arena->New<AlternativeValue>(alt.AltName(),
alt.ChoiceName(), arg)};
@@ -577,7 +581,7 @@ auto Interpreter::StepExp() -> Transition {
return CallFunction{
// TODO: Think about a cleaner way to cast between Ptr types.
// (multiple TODOs)
.function = Ptr<const FunctionValue>(
.function = Nonnull<const FunctionValue*>(
cast<FunctionValue>(act->Results()[0])),
.args = act->Results()[1],
.loc = exp->SourceLoc()};
@@ -594,7 +598,7 @@ auto Interpreter::StepExp() -> Transition {
switch (cast<IntrinsicExpression>(*exp).Intrinsic()) {
case IntrinsicExpression::IntrinsicKind::Print:
Address pointer = GetFromEnv(exp->SourceLoc(), "format_str");
Ptr<const Value> pointee = heap.Read(pointer, exp->SourceLoc());
Nonnull<const Value*> pointee = heap.Read(pointer, exp->SourceLoc());
CHECK(pointee->Tag() == Value::Kind::StringValue);
// TODO: This could eventually use something like llvm::formatv.
llvm::outs() << cast<StringValue>(*pointee).Val();
@@ -646,8 +650,8 @@ auto Interpreter::StepExp() -> Transition {
}
auto Interpreter::StepPattern() -> Transition {
Ptr<Action> act = stack.Top()->todo.Top();
Ptr<const Pattern> pattern = cast<PatternAction>(*act).Pat();
Nonnull<Action*> act = stack.Top()->todo.Top();
Nonnull<const Pattern*> pattern = cast<PatternAction>(*act).Pat();
if (tracing_output) {
llvm::outs() << "--- step pattern " << *pattern << " ("
<< pattern->SourceLoc() << ") --->\n";
@@ -672,7 +676,7 @@ auto Interpreter::StepPattern() -> Transition {
if (tuple.Fields().empty()) {
return Done{TupleValue::Empty()};
} else {
Ptr<const Pattern> p1 = tuple.Fields()[0].pattern;
Nonnull<const Pattern*> p1 = tuple.Fields()[0].pattern;
return Spawn{(arena->New<PatternAction>(p1))};
}
} else if (act->Pos() != static_cast<int>(tuple.Fields().size())) {
@@ -680,7 +684,7 @@ auto Interpreter::StepPattern() -> Transition {
// H}
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
// H}
Ptr<const Pattern> elt = tuple.Fields()[act->Pos()].pattern;
Nonnull<const Pattern*> elt = tuple.Fields()[act->Pos()].pattern;
return Spawn{arena->New<PatternAction>(elt)};
} else {
std::vector<TupleElement> elements;
@@ -711,7 +715,7 @@ auto Interpreter::StepPattern() -> Transition {
}
}
static auto IsWhileAct(Ptr<Action> act) -> bool {
static auto IsWhileAct(Nonnull<Action*> act) -> bool {
switch (act->Tag()) {
case Action::Kind::StatementAction:
switch (cast<StatementAction>(*act).Stmt()->Tag()) {
@@ -725,7 +729,7 @@ static auto IsWhileAct(Ptr<Action> act) -> bool {
}
}
static auto HasLocalScope(Ptr<Action> act) -> bool {
static auto HasLocalScope(Nonnull<Action*> act) -> bool {
switch (act->Tag()) {
case Action::Kind::StatementAction:
switch (cast<StatementAction>(*act).Stmt()->Tag()) {
@@ -741,9 +745,9 @@ static auto HasLocalScope(Ptr<Action> act) -> bool {
}
auto Interpreter::StepStmt() -> Transition {
Ptr<Frame> frame = stack.Top();
Ptr<Action> act = frame->todo.Top();
Ptr<const Statement> stmt = cast<StatementAction>(*act).Stmt();
Nonnull<Frame*> frame = stack.Top();
Nonnull<Action*> act = frame->todo.Top();
Nonnull<const Statement*> stmt = cast<StatementAction>(*act).Stmt();
if (tracing_output) {
llvm::outs() << "--- step stmt ";
stmt->PrintDepth(1, llvm::outs());
@@ -849,7 +853,7 @@ auto Interpreter::StepStmt() -> Transition {
return Done{};
}
} else {
Ptr<Scope> scope = frame->scopes.Top();
Nonnull<Scope*> scope = frame->scopes.Top();
DeallocateScope(scope);
frame->scopes.Pop(1);
return Done{};
@@ -867,8 +871,8 @@ auto Interpreter::StepStmt() -> Transition {
} else {
// { { v :: (x = []) :: C, E, F} :: S, H}
// -> { { C, E(x := a), F} :: S, H(a := copy(v))}
Ptr<const Value> v = act->Results()[0];
Ptr<const Value> p = act->Results()[1];
Nonnull<const Value*> v = act->Results()[0];
Nonnull<const Value*> p = act->Results()[1];
std::optional<Env> matches = PatternMatch(p, v, stmt->SourceLoc());
CHECK(matches)
@@ -934,7 +938,7 @@ auto Interpreter::StepStmt() -> Transition {
} else {
// { {v :: return [] :: C, E, F} :: {C', E', F'} :: S, H}
// -> { {v :: C', E', F'} :: S, H}
Ptr<const Value> ret_val =
Nonnull<const Value*> ret_val =
CopyVal(arena, act->Results()[0], stmt->SourceLoc());
return UnwindFunctionCall{ret_val};
}
@@ -957,8 +961,8 @@ auto Interpreter::StepStmt() -> Transition {
CHECK(act->Pos() == 0);
// Create a continuation object by creating a frame similar the
// way one is created in a function call.
auto scopes = Stack<Ptr<Scope>>(arena->New<Scope>(CurrentEnv()));
Stack<Ptr<Action>> todo;
auto scopes = Stack<Nonnull<Scope*>>(arena->New<Scope>(CurrentEnv()));
Stack<Nonnull<Action*>> todo;
todo.Push(arena->New<StatementAction>(
arena->New<Return>(arena, stmt->SourceLoc())));
todo.Push(arena->New<StatementAction>(cast<Continuation>(*stmt).Body()));
@@ -966,7 +970,7 @@ auto Interpreter::StepStmt() -> Transition {
arena->New<Frame>("__continuation", scopes, todo);
Address continuation_address =
heap.AllocateValue(arena->New<ContinuationValue>(
std::vector<Ptr<Frame>>({continuation_frame})));
std::vector<Nonnull<Frame*>>({continuation_frame})));
// Store the continuation's address in the frame.
continuation_frame->continuation = continuation_address;
// Bind the continuation object to the continuation variable
@@ -991,7 +995,7 @@ auto Interpreter::StepStmt() -> Transition {
arena->New<TupleLiteral>(stmt->SourceLoc())));
frame->todo.Push(ignore_result);
// Push the continuation onto the current stack.
const std::vector<Ptr<Frame>>& continuation_vector =
const std::vector<Nonnull<Frame*>>& continuation_vector =
cast<ContinuationValue>(*act->Results()[0]).Stack();
for (auto frame_iter = continuation_vector.rbegin();
frame_iter != continuation_vector.rend(); ++frame_iter) {
@@ -1003,7 +1007,7 @@ auto Interpreter::StepStmt() -> Transition {
CHECK(act->Pos() == 0);
// Pause the current continuation
frame->todo.Pop();
std::vector<Ptr<Frame>> paused;
std::vector<Nonnull<Frame*>> paused;
do {
paused.push_back(stack.Pop());
} while (paused.back()->continuation == std::nullopt);
@@ -1020,7 +1024,7 @@ class Interpreter::DoTransition {
DoTransition(Interpreter* interpreter) : interpreter(interpreter) {}
void operator()(const Done& done) {
Ptr<Frame> frame = interpreter->stack.Top();
Nonnull<Frame*> frame = interpreter->stack.Top();
if (frame->todo.Top()->Tag() != Action::Kind::StatementAction) {
CHECK(done.result);
frame->todo.Pop();
@@ -1036,25 +1040,25 @@ class Interpreter::DoTransition {
}
void operator()(const Spawn& spawn) {
Ptr<Frame> frame = interpreter->stack.Top();
Ptr<Action> action = frame->todo.Top();
Nonnull<Frame*> frame = interpreter->stack.Top();
Nonnull<Action*> action = frame->todo.Top();
action->SetPos(action->Pos() + 1);
frame->todo.Push(spawn.child);
}
void operator()(const Delegate& delegate) {
Ptr<Frame> frame = interpreter->stack.Top();
Nonnull<Frame*> frame = interpreter->stack.Top();
frame->todo.Pop();
frame->todo.Push(delegate.delegate);
}
void operator()(const RunAgain&) {
Ptr<Action> action = interpreter->stack.Top()->todo.Top();
Nonnull<Action*> action = interpreter->stack.Top()->todo.Top();
action->SetPos(action->Pos() + 1);
}
void operator()(const UnwindTo& unwind_to) {
Ptr<Frame> frame = interpreter->stack.Top();
Nonnull<Frame*> frame = interpreter->stack.Top();
while (frame->todo.Top() != unwind_to.new_top) {
if (HasLocalScope(frame->todo.Top())) {
interpreter->DeallocateScope(frame->scopes.Top());
@@ -1088,9 +1092,9 @@ class Interpreter::DoTransition {
params.push_back(name);
}
auto scopes =
Stack<Ptr<Scope>>(interpreter->arena->New<Scope>(values, params));
Stack<Nonnull<Scope*>>(interpreter->arena->New<Scope>(values, params));
CHECK(call.function->Body()) << "Calling a function that's missing a body";
auto todo = Stack<Ptr<Action>>(
auto todo = Stack<Nonnull<Action*>>(
interpreter->arena->New<StatementAction>(*call.function->Body()));
auto frame =
interpreter->arena->New<Frame>(call.function->Name(), scopes, todo);
@@ -1100,18 +1104,18 @@ class Interpreter::DoTransition {
void operator()(const ManualTransition&) {}
private:
Ptr<Interpreter> interpreter;
Nonnull<Interpreter*> interpreter;
};
// State transition.
void Interpreter::Step() {
Ptr<Frame> frame = stack.Top();
Nonnull<Frame*> frame = stack.Top();
if (frame->todo.IsEmpty()) {
FATAL_RUNTIME_ERROR_NO_LINE()
<< "fell off end of function " << frame->name << " without `return`";
}
Ptr<Action> act = frame->todo.Top();
Nonnull<Action*> act = frame->todo.Top();
switch (act->Tag()) {
case Action::Kind::LValAction:
std::visit(DoTransition(this), StepLvalue());
@@ -1128,8 +1132,8 @@ void Interpreter::Step() {
} // switch
}
auto Interpreter::InterpProgram(const std::vector<Ptr<const Declaration>>& fs)
-> int {
auto Interpreter::InterpProgram(
const std::vector<Nonnull<const Declaration*>>& fs) -> int {
// Check that the interpreter is in a clean state.
CHECK(globals.IsEmpty());
CHECK(stack.IsEmpty());
@@ -1142,12 +1146,12 @@ auto Interpreter::InterpProgram(const std::vector<Ptr<const Declaration>>& fs)
SourceLocation loc("<InterpProgram()>", 0);
Ptr<const Expression> arg = arena->New<TupleLiteral>(loc);
Ptr<const Expression> call_main = arena->New<CallExpression>(
Nonnull<const Expression*> arg = arena->New<TupleLiteral>(loc);
Nonnull<const Expression*> call_main = arena->New<CallExpression>(
loc, arena->New<IdentifierExpression>(loc, "main"), arg);
auto todo = Stack<Ptr<Action>>(arena->New<ExpressionAction>(call_main));
auto scopes = Stack<Ptr<Scope>>(arena->New<Scope>(globals));
stack = Stack<Ptr<Frame>>(arena->New<Frame>("top", scopes, todo));
auto todo = Stack<Nonnull<Action*>>(arena->New<ExpressionAction>(call_main));
auto scopes = Stack<Nonnull<Scope*>>(arena->New<Scope>(globals));
stack = Stack<Nonnull<Frame*>>(arena->New<Frame>("top", scopes, todo));
if (tracing_output) {
llvm::outs() << "********** calling main function **********\n";
@@ -1163,14 +1167,14 @@ auto Interpreter::InterpProgram(const std::vector<Ptr<const Declaration>>& fs)
return cast<IntValue>(**program_value).Val();
}
auto Interpreter::InterpExp(Env values, Ptr<const Expression> e)
-> Ptr<const Value> {
auto Interpreter::InterpExp(Env values, Nonnull<const Expression*> e)
-> Nonnull<const Value*> {
CHECK(program_value == std::nullopt);
auto program_value_guard =
llvm::make_scope_exit([&] { program_value = std::nullopt; });
auto todo = Stack<Ptr<Action>>(arena->New<ExpressionAction>(e));
auto scopes = Stack<Ptr<Scope>>(arena->New<Scope>(values));
stack = Stack<Ptr<Frame>>(arena->New<Frame>("InterpExp", scopes, todo));
auto todo = Stack<Nonnull<Action*>>(arena->New<ExpressionAction>(e));
auto scopes = Stack<Nonnull<Scope*>>(arena->New<Scope>(values));
stack = Stack<Nonnull<Frame*>>(arena->New<Frame>("InterpExp", scopes, todo));
while (stack.Count() > 1 || !stack.Top()->todo.IsEmpty()) {
Step();
@@ -1179,14 +1183,15 @@ auto Interpreter::InterpExp(Env values, Ptr<const Expression> e)
return *program_value;
}
auto Interpreter::InterpPattern(Env values, Ptr<const Pattern> p)
-> Ptr<const Value> {
auto Interpreter::InterpPattern(Env values, Nonnull<const Pattern*> p)
-> Nonnull<const Value*> {
CHECK(program_value == std::nullopt);
auto program_value_guard =
llvm::make_scope_exit([&] { program_value = std::nullopt; });
auto todo = Stack<Ptr<Action>>(arena->New<PatternAction>(p));
auto scopes = Stack<Ptr<Scope>>(arena->New<Scope>(values));
stack = Stack<Ptr<Frame>>(arena->New<Frame>("InterpPattern", scopes, todo));
auto todo = Stack<Nonnull<Action*>>(arena->New<PatternAction>(p));
auto scopes = Stack<Nonnull<Scope*>>(arena->New<Scope>(values));
stack =
Stack<Nonnull<Frame*>>(arena->New<Frame>("InterpPattern", scopes, todo));
while (stack.Count() > 1 || !stack.Top()->todo.IsEmpty()) {
Step();
+27 -25
View File
@@ -24,25 +24,27 @@ using Env = Dictionary<std::string, Address>;
class Interpreter {
public:
explicit Interpreter(Ptr<Arena> arena)
explicit Interpreter(Nonnull<Arena*> arena)
: arena(arena), globals(arena), heap(arena) {}
// Interpret the whole program.
auto InterpProgram(const std::vector<Ptr<const Declaration>>& fs) -> int;
auto InterpProgram(const std::vector<Nonnull<const Declaration*>>& fs) -> int;
// Interpret an expression at compile-time.
auto InterpExp(Env values, Ptr<const Expression> e) -> Ptr<const Value>;
auto InterpExp(Env values, Nonnull<const Expression*> e)
-> Nonnull<const Value*>;
// Interpret a pattern at compile-time.
auto InterpPattern(Env values, Ptr<const Pattern> p) -> Ptr<const Value>;
auto InterpPattern(Env values, Nonnull<const Pattern*> p)
-> Nonnull<const Value*>;
// Attempts to match `v` against the pattern `p`. If matching succeeds,
// returns the bindings of pattern variables to their matched values.
auto PatternMatch(Ptr<const Value> p, Ptr<const Value> v, SourceLocation loc)
-> std::optional<Env>;
auto PatternMatch(Nonnull<const Value*> p, Nonnull<const Value*> v,
SourceLocation loc) -> std::optional<Env>;
// Support TypeChecker allocating values on the heap.
auto AllocateValue(Ptr<const Value> v) -> Address {
auto AllocateValue(Nonnull<const Value*> v) -> Address {
return heap.AllocateValue(v);
}
@@ -62,19 +64,19 @@ class Interpreter {
struct Done {
// The value computed by the Action. Should always be nullopt for Statement
// Actions, and never null for any other kind of Action.
std::optional<Ptr<const Value>> result;
std::optional<Nonnull<const Value*>> result;
};
// Transition type which spawns a new Action on the todo stack above the
// current Action, and increments the current Action's position counter.
struct Spawn {
Ptr<Action> child;
Nonnull<Action*> child;
};
// Transition type which spawns a new Action that replaces the current action
// on the todo stack.
struct Delegate {
Ptr<Action> delegate;
Nonnull<Action*> delegate;
};
// Transition type which keeps the current Action at the top of the stack,
@@ -84,21 +86,21 @@ class Interpreter {
// Transition type which unwinds the `todo` and `scopes` stacks until it
// reaches a specified Action lower in the stack.
struct UnwindTo {
const Ptr<Action> new_top;
const Nonnull<Action*> new_top;
};
// Transition type which unwinds the entire current stack frame, and returns
// a specified value to the caller.
struct UnwindFunctionCall {
Ptr<const Value> return_val;
Nonnull<const Value*> return_val;
};
// Transition type which removes the current action from the top of the todo
// stack, then creates a new stack frame which calls the specified function
// with the specified arguments.
struct CallFunction {
Ptr<const FunctionValue> function;
Ptr<const Value> args;
Nonnull<const FunctionValue*> function;
Nonnull<const Value*> args;
SourceLocation loc;
};
@@ -126,32 +128,32 @@ class Interpreter {
// State transition for statements.
auto StepStmt() -> Transition;
void InitGlobals(const std::vector<Ptr<const Declaration>>& fs);
void InitGlobals(const std::vector<Nonnull<const Declaration*>>& fs);
auto CurrentEnv() -> Env;
auto GetFromEnv(SourceLocation loc, const std::string& name) -> Address;
void DeallocateScope(Ptr<Scope> scope);
void DeallocateLocals(Ptr<Frame> frame);
void DeallocateScope(Nonnull<Scope*> scope);
void DeallocateLocals(Nonnull<Frame*> frame);
auto CreateTuple(Ptr<Action> act, Ptr<const Expression> exp)
-> Ptr<const Value>;
auto CreateTuple(Nonnull<Action*> act, Nonnull<const Expression*> exp)
-> Nonnull<const Value*>;
auto EvalPrim(Operator op, const std::vector<Ptr<const Value>>& args,
SourceLocation loc) -> Ptr<const Value>;
auto EvalPrim(Operator op, const std::vector<Nonnull<const Value*>>& args,
SourceLocation loc) -> Nonnull<const Value*>;
void PatternAssignment(Ptr<const Value> pat, Ptr<const Value> val,
void PatternAssignment(Nonnull<const Value*> pat, Nonnull<const Value*> val,
SourceLocation loc);
void PrintState(llvm::raw_ostream& out);
Ptr<Arena> arena;
Nonnull<Arena*> arena;
// Globally-defined entities, such as functions, structs, or choices.
Env globals;
Stack<Ptr<Frame>> stack;
Stack<Nonnull<Frame*>> stack;
Heap heap;
std::optional<Ptr<const Value>> program_value;
std::optional<Nonnull<const Value*>> program_value;
};
} // namespace Carbon
@@ -33,7 +33,8 @@ void PrintTypeEnv(TypeEnv types, llvm::raw_ostream& out) {
}
static void ExpectType(SourceLocation loc, const std::string& context,
Ptr<const Value> expected, Ptr<const Value> actual) {
Nonnull<const Value*> expected,
Nonnull<const Value*> actual) {
if (!TypeEqual(expected, actual)) {
FATAL_COMPILATION_ERROR(loc) << "type error in " << context << "\n"
<< "expected: " << *expected << "\n"
@@ -42,7 +43,7 @@ static void ExpectType(SourceLocation loc, const std::string& context,
}
static void ExpectPointerType(SourceLocation loc, const std::string& context,
Ptr<const Value> actual) {
Nonnull<const Value*> actual) {
if (actual->Tag() != Value::Kind::PointerType) {
FATAL_COMPILATION_ERROR(loc) << "type error in " << context << "\n"
<< "expected a pointer type\n"
@@ -50,8 +51,8 @@ static void ExpectPointerType(SourceLocation loc, const std::string& context,
}
}
auto TypeChecker::ReifyType(Ptr<const Value> t, SourceLocation loc)
-> Ptr<const Expression> {
auto TypeChecker::ReifyType(Nonnull<const Value*> t, SourceLocation loc)
-> Nonnull<const Expression*> {
switch (t->Tag()) {
case Value::Kind::IntType:
return arena->New<IntTypeLiteral>(loc);
@@ -82,7 +83,7 @@ auto TypeChecker::ReifyType(Ptr<const Value> t, SourceLocation loc)
case Value::Kind::PointerType:
return arena->New<PrimitiveOperatorExpression>(
loc, Operator::Ptr,
std::vector<Ptr<const Expression>>(
std::vector<Nonnull<const Expression*>>(
{ReifyType(cast<PointerType>(*t).Type(), loc)}));
case Value::Kind::VariableType:
return arena->New<IdentifierExpression>(loc,
@@ -111,12 +112,12 @@ auto TypeChecker::ReifyType(Ptr<const Value> t, SourceLocation loc)
// The `deduced` parameter is an accumulator, that is, it holds the
// results so-far.
static auto ArgumentDeduction(SourceLocation loc, TypeEnv deduced,
Ptr<const Value> param, Ptr<const Value> arg)
-> TypeEnv {
Nonnull<const Value*> param,
Nonnull<const Value*> arg) -> TypeEnv {
switch (param->Tag()) {
case Value::Kind::VariableType: {
const auto& var_type = cast<VariableType>(*param);
std::optional<Ptr<const Value>> d = deduced.Get(var_type.Name());
std::optional<Nonnull<const Value*>> d = deduced.Get(var_type.Name());
if (!d) {
deduced.Set(var_type.Name(), arg);
} else {
@@ -192,11 +193,11 @@ static auto ArgumentDeduction(SourceLocation loc, TypeEnv deduced,
}
}
auto TypeChecker::Substitute(TypeEnv dict, Ptr<const Value> type)
-> Ptr<const Value> {
auto TypeChecker::Substitute(TypeEnv dict, Nonnull<const Value*> type)
-> Nonnull<const Value*> {
switch (type->Tag()) {
case Value::Kind::VariableType: {
std::optional<Ptr<const Value>> t =
std::optional<Nonnull<const Value*>> t =
dict.Get(cast<VariableType>(*type).Name());
if (!t) {
return type;
@@ -247,7 +248,7 @@ auto TypeChecker::Substitute(TypeEnv dict, Ptr<const Value> type)
}
}
auto TypeChecker::TypeCheckExp(Ptr<const Expression> e, TypeEnv types,
auto TypeChecker::TypeCheckExp(Nonnull<const Expression*> e, TypeEnv types,
Env values) -> TCExpression {
if (tracing_output) {
llvm::outs() << "checking expression " << *e << "\ntypes: ";
@@ -267,7 +268,7 @@ auto TypeChecker::TypeCheckExp(Ptr<const Expression> e, TypeEnv types,
cast<IntValue>(*interpreter.InterpExp(values, index.Offset()))
.Val();
std::string f = std::to_string(i);
std::optional<Ptr<const Value>> field_t =
std::optional<Nonnull<const Value*>> field_t =
cast<TupleValue>(*t).FindField(f);
if (!field_t) {
FATAL_COMPILATION_ERROR(e->SourceLoc())
@@ -306,16 +307,18 @@ auto TypeChecker::TypeCheckExp(Ptr<const Expression> e, TypeEnv types,
// Search for a field
for (auto& field : t_class.Fields()) {
if (access.Field() == field.first) {
Ptr<const Expression> new_e = arena->New<FieldAccessExpression>(
e->SourceLoc(), res.exp, access.Field());
Nonnull<const Expression*> new_e =
arena->New<FieldAccessExpression>(e->SourceLoc(), res.exp,
access.Field());
return TCExpression(new_e, field.second, res.types);
}
}
// Search for a method
for (auto& method : t_class.Methods()) {
if (access.Field() == method.first) {
Ptr<const Expression> new_e = arena->New<FieldAccessExpression>(
e->SourceLoc(), res.exp, access.Field());
Nonnull<const Expression*> new_e =
arena->New<FieldAccessExpression>(e->SourceLoc(), res.exp,
access.Field());
return TCExpression(new_e, method.second, res.types);
}
}
@@ -340,8 +343,9 @@ auto TypeChecker::TypeCheckExp(Ptr<const Expression> e, TypeEnv types,
const auto& choice = cast<ChoiceType>(*t);
for (const auto& vt : choice.Alternatives()) {
if (access.Field() == vt.first) {
Ptr<const Expression> new_e = arena->New<FieldAccessExpression>(
e->SourceLoc(), res.exp, access.Field());
Nonnull<const Expression*> new_e =
arena->New<FieldAccessExpression>(e->SourceLoc(), res.exp,
access.Field());
auto fun_ty = arena->New<FunctionType>(
std::vector<GenericBinding>(), vt.second, t);
return TCExpression(new_e, fun_ty, res.types);
@@ -359,7 +363,7 @@ auto TypeChecker::TypeCheckExp(Ptr<const Expression> e, TypeEnv types,
}
case Expression::Kind::IdentifierExpression: {
const auto& ident = cast<IdentifierExpression>(*e);
std::optional<Ptr<const Value>> type = types.Get(ident.Name());
std::optional<Nonnull<const Value*>> type = types.Get(ident.Name());
if (type) {
return TCExpression(e, *type, types);
} else {
@@ -373,10 +377,10 @@ auto TypeChecker::TypeCheckExp(Ptr<const Expression> e, TypeEnv types,
return TCExpression(e, arena->New<BoolType>(), types);
case Expression::Kind::PrimitiveOperatorExpression: {
const auto& op = cast<PrimitiveOperatorExpression>(*e);
std::vector<Ptr<const Expression>> es;
std::vector<Ptr<const Value>> ts;
std::vector<Nonnull<const Expression*>> es;
std::vector<Nonnull<const Value*>> ts;
auto new_types = types;
for (Ptr<const Expression> argument : op.Arguments()) {
for (Nonnull<const Expression*> argument : op.Arguments()) {
auto res = TypeCheckExp(argument, types, values);
new_types = res.types;
es.push_back(res.exp);
@@ -494,10 +498,9 @@ auto TypeChecker::TypeCheckExp(Ptr<const Expression> e, TypeEnv types,
}
}
auto TypeChecker::TypeCheckPattern(Ptr<const Pattern> p, TypeEnv types,
Env values,
std::optional<Ptr<const Value>> expected)
-> TCPattern {
auto TypeChecker::TypeCheckPattern(
Nonnull<const Pattern*> p, TypeEnv types, Env values,
std::optional<Nonnull<const Value*>> expected) -> TCPattern {
if (tracing_output) {
llvm::outs() << "checking pattern " << *p;
if (expected) {
@@ -517,7 +520,7 @@ auto TypeChecker::TypeCheckPattern(Ptr<const Pattern> p, TypeEnv types,
const auto& binding = cast<BindingPattern>(*p);
TCPattern binding_type_result =
TypeCheckPattern(binding.Type(), types, values, std::nullopt);
Ptr<const Value> type =
Nonnull<const Value*> type =
interpreter.InterpPattern(values, binding_type_result.pattern);
if (expected) {
std::optional<Env> values = interpreter.PatternMatch(
@@ -554,7 +557,7 @@ auto TypeChecker::TypeCheckPattern(Ptr<const Pattern> p, TypeEnv types,
}
for (size_t i = 0; i < tuple.Fields().size(); ++i) {
const TuplePattern::Field& field = tuple.Fields()[i];
std::optional<Ptr<const Value>> expected_field_type;
std::optional<Nonnull<const Value*>> expected_field_type;
if (expected) {
const TupleElement& expected_element =
cast<TupleValue>(**expected).Elements()[i];
@@ -578,7 +581,7 @@ auto TypeChecker::TypeCheckPattern(Ptr<const Pattern> p, TypeEnv types,
}
case Pattern::Kind::AlternativePattern: {
const auto& alternative = cast<AlternativePattern>(*p);
Ptr<const Value> choice_type =
Nonnull<const Value*> choice_type =
interpreter.InterpExp(values, alternative.ChoiceType());
if (choice_type->Tag() != Value::Kind::ChoiceType) {
FATAL_COMPILATION_ERROR(alternative.SourceLoc())
@@ -588,7 +591,7 @@ auto TypeChecker::TypeCheckPattern(Ptr<const Pattern> p, TypeEnv types,
ExpectType(alternative.SourceLoc(), "alternative pattern", *expected,
choice_type);
}
std::optional<Ptr<const Value>> parameter_types =
std::optional<Nonnull<const Value*>> parameter_types =
FindInVarValues(alternative.AlternativeName(),
cast<ChoiceType>(*choice_type).Alternatives());
if (parameter_types == std::nullopt) {
@@ -600,7 +603,7 @@ auto TypeChecker::TypeCheckPattern(Ptr<const Pattern> p, TypeEnv types,
values, *parameter_types);
// TODO: Think about a cleaner way to cast between Ptr types.
// (multiple TODOs)
auto arguments = Ptr<const TuplePattern>(
auto arguments = Nonnull<const TuplePattern*>(
cast<const TuplePattern>(arg_results.pattern));
return {.pattern = arena->New<AlternativePattern>(
alternative.SourceLoc(),
@@ -619,27 +622,27 @@ auto TypeChecker::TypeCheckPattern(Ptr<const Pattern> p, TypeEnv types,
}
}
auto TypeChecker::TypeCheckCase(Ptr<const Value> expected,
Ptr<const Pattern> pat,
Ptr<const Statement> body, TypeEnv types,
Env values, Ptr<const Value>& ret_type,
auto TypeChecker::TypeCheckCase(Nonnull<const Value*> expected,
Nonnull<const Pattern*> pat,
Nonnull<const Statement*> body, TypeEnv types,
Env values, Nonnull<const Value*>& ret_type,
bool is_omitted_ret_type)
-> std::pair<Ptr<const Pattern>, Ptr<const Statement>> {
-> std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>> {
auto pat_res = TypeCheckPattern(pat, types, values, expected);
auto res =
TypeCheckStmt(body, pat_res.types, values, ret_type, is_omitted_ret_type);
return std::make_pair(pat, res.stmt);
}
auto TypeChecker::TypeCheckStmt(Ptr<const Statement> s, TypeEnv types,
Env values, Ptr<const Value>& ret_type,
auto TypeChecker::TypeCheckStmt(Nonnull<const Statement*> s, TypeEnv types,
Env values, Nonnull<const Value*>& ret_type,
bool is_omitted_ret_type) -> TCStatement {
switch (s->Tag()) {
case Statement::Kind::Match: {
const auto& match = cast<Match>(*s);
auto res = TypeCheckExp(match.Exp(), types, values);
auto res_type = res.type;
std::vector<std::pair<Ptr<const Pattern>, Ptr<const Statement>>>
std::vector<std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>>
new_clauses;
for (auto& clause : match.Clauses()) {
new_clauses.push_back(TypeCheckCase(res_type, clause.first,
@@ -677,7 +680,7 @@ auto TypeChecker::TypeCheckStmt(Ptr<const Statement> s, TypeEnv types,
case Statement::Kind::VariableDefinition: {
const auto& var = cast<VariableDefinition>(*s);
auto res = TypeCheckExp(var.Init(), types, values);
Ptr<const Value> rhs_ty = res.type;
Nonnull<const Value*> rhs_ty = res.type;
auto lhs_res = TypeCheckPattern(var.Pat(), types, values, rhs_ty);
auto new_s =
arena->New<VariableDefinition>(s->SourceLoc(), var.Pat(), res.exp);
@@ -688,7 +691,7 @@ auto TypeChecker::TypeCheckStmt(Ptr<const Statement> s, TypeEnv types,
auto stmt_res = TypeCheckStmt(seq.Stmt(), types, values, ret_type,
is_omitted_ret_type);
auto checked_types = stmt_res.types;
std::optional<Ptr<const Statement>> next_stmt;
std::optional<Nonnull<const Statement*>> next_stmt;
if (seq.Next()) {
auto next_res = TypeCheckStmt(*seq.Next(), checked_types, values,
ret_type, is_omitted_ret_type);
@@ -722,7 +725,7 @@ auto TypeChecker::TypeCheckStmt(Ptr<const Statement> s, TypeEnv types,
cnd_res.type);
auto then_res = TypeCheckStmt(if_stmt.ThenStmt(), types, values, ret_type,
is_omitted_ret_type);
std::optional<Ptr<const Statement>> else_stmt;
std::optional<Nonnull<const Statement*>> else_stmt;
if (if_stmt.ElseStmt()) {
auto else_res = TypeCheckStmt(*if_stmt.ElseStmt(), types, values,
ret_type, is_omitted_ret_type);
@@ -777,8 +780,8 @@ auto TypeChecker::TypeCheckStmt(Ptr<const Statement> s, TypeEnv types,
}
auto TypeChecker::CheckOrEnsureReturn(
std::optional<Ptr<const Statement>> opt_stmt, bool omitted_ret_type,
SourceLocation loc) -> Ptr<const Statement> {
std::optional<Nonnull<const Statement*>> opt_stmt, bool omitted_ret_type,
SourceLocation loc) -> Nonnull<const Statement*> {
if (!opt_stmt) {
if (omitted_ret_type) {
return arena->New<Return>(arena, loc);
@@ -788,11 +791,11 @@ auto TypeChecker::CheckOrEnsureReturn(
"type without reaching a return statement";
}
}
Ptr<const Statement> stmt = *opt_stmt;
Nonnull<const Statement*> stmt = *opt_stmt;
switch (stmt->Tag()) {
case Statement::Kind::Match: {
const auto& match = cast<Match>(*stmt);
std::vector<std::pair<Ptr<const Pattern>, Ptr<const Statement>>>
std::vector<std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>>
new_clauses;
for (const auto& clause : match.Clauses()) {
auto s = CheckOrEnsureReturn(clause.second, omitted_ret_type,
@@ -855,7 +858,8 @@ auto TypeChecker::CheckOrEnsureReturn(
// TODO: Add checking to function definitions to ensure that
// all deduced type parameters will be deduced.
auto TypeChecker::TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types,
Env values) -> Ptr<const FunctionDefinition> {
Env values)
-> Nonnull<const FunctionDefinition*> {
// Bring the deduced parameters into scope
for (const auto& deduced : f->deduced_parameters) {
// auto t = interpreter.InterpExp(values, deduced.type);
@@ -873,7 +877,7 @@ auto TypeChecker::TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types,
arena->New<IntType>(), return_type);
// TODO: Check that main doesn't have any parameters.
}
std::optional<Ptr<const Statement>> body_stmt;
std::optional<Nonnull<const Statement*>> body_stmt;
if (f->body) {
auto res = TypeCheckStmt(*f->body, param_res.types, values, return_type,
f->is_omitted_return_type);
@@ -889,7 +893,7 @@ auto TypeChecker::TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types,
auto TypeChecker::TypeOfFunDef(TypeEnv types, Env values,
const FunctionDefinition* fun_def)
-> Ptr<const Value> {
-> Nonnull<const Value*> {
// Bring the deduced parameters into scope
for (const auto& deduced : fun_def->deduced_parameters) {
// auto t = interpreter.InterpExp(values, deduced.type);
@@ -911,13 +915,14 @@ auto TypeChecker::TypeOfFunDef(TypeEnv types, Env values,
}
auto TypeChecker::TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/,
Env ct_top) -> Ptr<const Value> {
Env ct_top) -> Nonnull<const Value*> {
VarValues fields;
VarValues methods;
for (Ptr<const Member> m : sd->members) {
for (Nonnull<const Member*> m : sd->members) {
switch (m->Tag()) {
case Member::Kind::FieldMember: {
Ptr<const BindingPattern> binding = cast<FieldMember>(*m).Binding();
Nonnull<const BindingPattern*> binding =
cast<FieldMember>(*m).Binding();
if (!binding->Name().has_value()) {
FATAL_COMPILATION_ERROR(binding->SourceLoc())
<< "Struct members must have names";
@@ -945,7 +950,7 @@ static auto GetName(const Declaration& d) -> const std::string& {
case Declaration::Kind::ChoiceDeclaration:
return cast<ChoiceDeclaration>(d).Name();
case Declaration::Kind::VariableDeclaration: {
Ptr<const BindingPattern> binding =
Nonnull<const BindingPattern*> binding =
cast<VariableDeclaration>(d).Binding();
if (!binding->Name().has_value()) {
FATAL_COMPILATION_ERROR(binding->SourceLoc())
@@ -956,9 +961,9 @@ static auto GetName(const Declaration& d) -> const std::string& {
}
}
auto TypeChecker::MakeTypeChecked(const Ptr<const Declaration> d,
auto TypeChecker::MakeTypeChecked(const Nonnull<const Declaration*> d,
const TypeEnv& types, const Env& values)
-> Ptr<const Declaration> {
-> Nonnull<const Declaration*> {
switch (d->Tag()) {
case Declaration::Kind::FunctionDeclaration:
return arena->New<FunctionDeclaration>(TypeCheckFunDef(
@@ -967,8 +972,8 @@ auto TypeChecker::MakeTypeChecked(const Ptr<const Declaration> d,
case Declaration::Kind::ClassDeclaration: {
const ClassDefinition& class_def =
cast<ClassDeclaration>(*d).Definition();
std::vector<Ptr<Member>> fields;
for (Ptr<Member> m : class_def.members) {
std::vector<Nonnull<Member*>> fields;
for (Nonnull<Member*> m : class_def.members) {
switch (m->Tag()) {
case Member::Kind::FieldMember:
// TODO: Interpret the type expression and store the result.
@@ -998,7 +1003,7 @@ auto TypeChecker::MakeTypeChecked(const Ptr<const Declaration> d,
FATAL_COMPILATION_ERROR(var.SourceLoc())
<< "Type of a top-level variable must be an expression.";
}
Ptr<const Value> declared_type =
Nonnull<const Value*> declared_type =
interpreter.InterpExp(values, binding_type->Expression());
ExpectType(var.SourceLoc(), "initializer of variable", declared_type,
type_checked_initializer.type);
@@ -1053,9 +1058,9 @@ void TypeChecker::TopLevel(const Declaration& d, TypeCheckContext* tops) {
const auto& var = cast<VariableDeclaration>(d);
// Associate the variable name with it's declared type in the
// compile-time symbol table.
Ptr<const Expression> type =
Nonnull<const Expression*> type =
cast<ExpressionPattern>(*var.Binding()->Type()).Expression();
Ptr<const Value> declared_type =
Nonnull<const Value*> declared_type =
interpreter.InterpExp(tops->values, type);
tops->types.Set(*var.Binding()->Name(), declared_type);
break;
@@ -1063,7 +1068,7 @@ void TypeChecker::TopLevel(const Declaration& d, TypeCheckContext* tops) {
}
}
auto TypeChecker::TopLevel(const std::vector<Ptr<const Declaration>>& fs)
auto TypeChecker::TopLevel(const std::vector<Nonnull<const Declaration*>>& fs)
-> TypeCheckContext {
TypeCheckContext tops(arena);
bool found_main = false;
+37 -31
View File
@@ -16,14 +16,15 @@
namespace Carbon {
using TypeEnv = Dictionary<std::string, Ptr<const Value>>;
using TypeEnv = Dictionary<std::string, Nonnull<const Value*>>;
class TypeChecker {
public:
explicit TypeChecker(Ptr<Arena> arena) : arena(arena), interpreter(arena) {}
explicit TypeChecker(Nonnull<Arena*> arena)
: arena(arena), interpreter(arena) {}
struct TypeCheckContext {
TypeCheckContext(Ptr<Arena> arena) : types(arena), values(arena) {}
TypeCheckContext(Nonnull<Arena*> arena) : types(arena), values(arena) {}
// Symbol table mapping names of runtime entities to their type.
TypeEnv types;
@@ -31,33 +32,35 @@ class TypeChecker {
Env values;
};
auto MakeTypeChecked(const Ptr<const Declaration> d, const TypeEnv& types,
const Env& values) -> Ptr<const Declaration>;
auto MakeTypeChecked(const Nonnull<const Declaration*> d,
const TypeEnv& types, const Env& values)
-> Nonnull<const Declaration*>;
auto TopLevel(const std::vector<Ptr<const Declaration>>& fs)
auto TopLevel(const std::vector<Nonnull<const Declaration*>>& fs)
-> TypeCheckContext;
private:
struct TCExpression {
TCExpression(Ptr<const Expression> e, Ptr<const Value> t, TypeEnv types)
TCExpression(Nonnull<const Expression*> e, Nonnull<const Value*> t,
TypeEnv types)
: exp(e), type(t), types(types) {}
Ptr<const Expression> exp;
Ptr<const Value> type;
Nonnull<const Expression*> exp;
Nonnull<const Value*> type;
TypeEnv types;
};
struct TCPattern {
Ptr<const Pattern> pattern;
Ptr<const Value> type;
Nonnull<const Pattern*> pattern;
Nonnull<const Value*> type;
TypeEnv types;
};
struct TCStatement {
TCStatement(Ptr<const Statement> s, TypeEnv types)
TCStatement(Nonnull<const Statement*> s, TypeEnv types)
: stmt(s), types(types) {}
Ptr<const Statement> stmt;
Nonnull<const Statement*> stmt;
TypeEnv types;
};
@@ -72,15 +75,16 @@ class TypeChecker {
// types maps variable names to the type of their run-time value.
// values maps variable names to their compile-time values. It is not
// directly used in this function but is passed to InterExp.
auto TypeCheckExp(Ptr<const Expression> e, TypeEnv types, Env values)
auto TypeCheckExp(Nonnull<const Expression*> e, TypeEnv types, Env values)
-> TCExpression;
// Equivalent to TypeCheckExp, but operates on Patterns instead of
// Expressions. `expected` is the type that this pattern is expected to have,
// if the surrounding context gives us that information. Otherwise, it is
// nullopt.
auto TypeCheckPattern(Ptr<const Pattern> p, TypeEnv types, Env values,
std::optional<Ptr<const Value>> expected) -> TCPattern;
auto TypeCheckPattern(Nonnull<const Pattern*> p, TypeEnv types, Env values,
std::optional<Nonnull<const Value*>> expected)
-> TCPattern;
// TypeCheckStmt performs semantic analysis on a statement. It returns a new
// version of the statement and a new type environment.
@@ -89,36 +93,38 @@ class TypeChecker {
// declared return type of the enclosing function definition. If the return
// type is "auto", then the return type is inferred from the first return
// statement.
auto TypeCheckStmt(Ptr<const Statement> s, TypeEnv types, Env values,
Ptr<const Value>& ret_type, bool is_omitted_ret_type)
auto TypeCheckStmt(Nonnull<const Statement*> s, TypeEnv types, Env values,
Nonnull<const Value*>& ret_type, bool is_omitted_ret_type)
-> TCStatement;
auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, Env values)
-> Ptr<const FunctionDefinition>;
-> Nonnull<const FunctionDefinition*>;
auto TypeCheckCase(Ptr<const Value> expected, Ptr<const Pattern> pat,
Ptr<const Statement> body, TypeEnv types, Env values,
Ptr<const Value>& ret_type, bool is_omitted_ret_type)
-> std::pair<Ptr<const Pattern>, Ptr<const Statement>>;
auto TypeCheckCase(Nonnull<const Value*> expected,
Nonnull<const Pattern*> pat,
Nonnull<const Statement*> body, TypeEnv types, Env values,
Nonnull<const Value*>& ret_type, bool is_omitted_ret_type)
-> std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>;
auto TypeOfFunDef(TypeEnv types, Env values,
const FunctionDefinition* fun_def) -> Ptr<const Value>;
const FunctionDefinition* fun_def) -> Nonnull<const Value*>;
auto TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/, Env ct_top)
-> Ptr<const Value>;
-> Nonnull<const Value*>;
void TopLevel(const Declaration& d, TypeCheckContext* tops);
auto CheckOrEnsureReturn(std::optional<Ptr<const Statement>> opt_stmt,
auto CheckOrEnsureReturn(std::optional<Nonnull<const Statement*>> opt_stmt,
bool omitted_ret_type, SourceLocation loc)
-> Ptr<const Statement>;
-> Nonnull<const Statement*>;
// Reify type to type expression.
auto ReifyType(Ptr<const Value> t, SourceLocation loc)
-> Ptr<const Expression>;
auto ReifyType(Nonnull<const Value*> t, SourceLocation loc)
-> Nonnull<const Expression*>;
auto Substitute(TypeEnv dict, Ptr<const Value> type) -> Ptr<const Value>;
auto Substitute(TypeEnv dict, Nonnull<const Value*> type)
-> Nonnull<const Value*>;
Ptr<Arena> arena;
Nonnull<Arena*> arena;
Interpreter interpreter;
};
+30 -27
View File
@@ -18,7 +18,7 @@ namespace Carbon {
using llvm::cast;
auto FindInVarValues(const std::string& field, const VarValues& inits)
-> std::optional<Ptr<const Value>> {
-> std::optional<Nonnull<const Value*>> {
for (auto& i : inits) {
if (i.first == field) {
return i.second;
@@ -45,7 +45,7 @@ auto FieldsEqual(const VarValues& ts1, const VarValues& ts2) -> bool {
}
auto TupleValue::FindField(const std::string& name) const
-> std::optional<Ptr<const Value>> {
-> std::optional<Nonnull<const Value*>> {
for (const TupleElement& element : elements) {
if (element.name == name) {
return element.value;
@@ -56,11 +56,12 @@ auto TupleValue::FindField(const std::string& name) const
namespace {
auto GetMember(Ptr<Arena> arena, Ptr<const Value> v, const std::string& f,
SourceLocation loc) -> Ptr<const Value> {
auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
const std::string& f, SourceLocation loc)
-> Nonnull<const Value*> {
switch (v->Tag()) {
case Value::Kind::StructValue: {
std::optional<Ptr<const Value>> field =
std::optional<Nonnull<const Value*>> field =
cast<TupleValue>(*cast<StructValue>(*v).Inits()).FindField(f);
if (field == std::nullopt) {
FATAL_RUNTIME_ERROR(loc) << "member " << f << " not in " << *v;
@@ -68,7 +69,8 @@ auto GetMember(Ptr<Arena> arena, Ptr<const Value> v, const std::string& f,
return *field;
}
case Value::Kind::TupleValue: {
std::optional<Ptr<const Value>> field = cast<TupleValue>(*v).FindField(f);
std::optional<Nonnull<const Value*>> field =
cast<TupleValue>(*v).FindField(f);
if (!field) {
FATAL_RUNTIME_ERROR(loc) << "field " << f << " not in " << *v;
}
@@ -88,9 +90,9 @@ auto GetMember(Ptr<Arena> arena, Ptr<const Value> v, const std::string& f,
} // namespace
auto Value::GetField(Ptr<Arena> arena, const FieldPath& path,
SourceLocation loc) const -> Ptr<const Value> {
Ptr<const Value> value(this);
auto Value::GetField(Nonnull<Arena*> arena, const FieldPath& path,
SourceLocation loc) const -> Nonnull<const Value*> {
Nonnull<const Value*> value(this);
for (const std::string& field : path.components) {
value = GetMember(arena, value, field, loc);
}
@@ -99,11 +101,11 @@ auto Value::GetField(Ptr<Arena> arena, const FieldPath& path,
namespace {
auto SetFieldImpl(Ptr<Arena> arena, Ptr<const Value> value,
auto SetFieldImpl(Nonnull<Arena*> arena, Nonnull<const Value*> value,
std::vector<std::string>::const_iterator path_begin,
std::vector<std::string>::const_iterator path_end,
Ptr<const Value> field_value, SourceLocation loc)
-> Ptr<const Value> {
Nonnull<const Value*> field_value, SourceLocation loc)
-> Nonnull<const Value*> {
if (path_begin == path_end) {
return field_value;
}
@@ -133,11 +135,12 @@ auto SetFieldImpl(Ptr<Arena> arena, Ptr<const Value> value,
} // namespace
auto Value::SetField(Ptr<Arena> arena, const FieldPath& path,
Ptr<const Value> field_value, SourceLocation loc) const
-> Ptr<const Value> {
return SetFieldImpl(arena, Ptr<const Value>(this), path.components.begin(),
path.components.end(), field_value, loc);
auto Value::SetField(Nonnull<Arena*> arena, const FieldPath& path,
Nonnull<const Value*> field_value,
SourceLocation loc) const -> Nonnull<const Value*> {
return SetFieldImpl(arena, Nonnull<const Value*>(this),
path.components.begin(), path.components.end(),
field_value, loc);
}
void Value::Print(llvm::raw_ostream& out) const {
@@ -237,7 +240,7 @@ void Value::Print(llvm::raw_ostream& out) const {
case Value::Kind::ContinuationValue: {
out << "{";
llvm::ListSeparator sep(" :: ");
for (Ptr<Frame> frame : cast<ContinuationValue>(*this).Stack()) {
for (Nonnull<Frame*> frame : cast<ContinuationValue>(*this).Stack()) {
out << sep << *frame;
}
out << "}";
@@ -254,8 +257,8 @@ void Value::Print(llvm::raw_ostream& out) const {
}
}
auto CopyVal(Ptr<Arena> arena, Ptr<const Value> val, SourceLocation loc)
-> Ptr<const Value> {
auto CopyVal(Nonnull<Arena*> arena, Nonnull<const Value*> val,
SourceLocation loc) -> Nonnull<const Value*> {
switch (val->Tag()) {
case Value::Kind::TupleValue: {
std::vector<TupleElement> elements;
@@ -267,12 +270,12 @@ auto CopyVal(Ptr<Arena> arena, Ptr<const Value> val, SourceLocation loc)
}
case Value::Kind::AlternativeValue: {
const auto& alt = cast<AlternativeValue>(*val);
Ptr<const Value> arg = CopyVal(arena, alt.Argument(), loc);
Nonnull<const Value*> arg = CopyVal(arena, alt.Argument(), loc);
return arena->New<AlternativeValue>(alt.AltName(), alt.ChoiceName(), arg);
}
case Value::Kind::StructValue: {
const auto& s = cast<StructValue>(*val);
Ptr<const Value> inits = CopyVal(arena, s.Inits(), loc);
Nonnull<const Value*> inits = CopyVal(arena, s.Inits(), loc);
return arena->New<StructValue>(s.Type(), inits);
}
case Value::Kind::IntValue:
@@ -322,7 +325,7 @@ auto CopyVal(Ptr<Arena> arena, Ptr<const Value> val, SourceLocation loc)
}
}
auto TypeEqual(Ptr<const Value> t1, Ptr<const Value> t2) -> bool {
auto TypeEqual(Nonnull<const Value*> t1, Nonnull<const Value*> t2) -> bool {
if (t1->Tag() != t2->Tag()) {
return false;
}
@@ -394,8 +397,8 @@ static auto FieldsValueEqual(const std::vector<TupleElement>& ts1,
// Returns true if the two values are equal and returns false otherwise.
//
// This function implements the `==` operator of Carbon.
auto ValueEqual(Ptr<const Value> v1, Ptr<const Value> v2, SourceLocation loc)
-> bool {
auto ValueEqual(Nonnull<const Value*> v1, Nonnull<const Value*> v2,
SourceLocation loc) -> bool {
if (v1->Tag() != v2->Tag()) {
return false;
}
@@ -407,9 +410,9 @@ auto ValueEqual(Ptr<const Value> v1, Ptr<const Value> v2, SourceLocation loc)
case Value::Kind::PointerValue:
return cast<PointerValue>(*v1).Val() == cast<PointerValue>(*v2).Val();
case Value::Kind::FunctionValue: {
std::optional<Ptr<const Statement>> body1 =
std::optional<Nonnull<const Statement*>> body1 =
cast<FunctionValue>(*v1).Body();
std::optional<Ptr<const Statement>> body2 =
std::optional<Nonnull<const Statement*>> body2 =
cast<FunctionValue>(*v2).Body();
return body1.has_value() == body2.has_value() &&
(!body1.has_value() || *body1 == *body2);
+45 -45
View File
@@ -68,14 +68,14 @@ class Value {
// Returns the sub-Value specified by `path`, which must be a valid field
// path for *this.
auto GetField(Ptr<Arena> arena, const FieldPath& path,
SourceLocation loc) const -> Ptr<const Value>;
auto GetField(Nonnull<Arena*> arena, const FieldPath& path,
SourceLocation loc) const -> Nonnull<const Value*>;
// Returns a copy of *this, but with the sub-Value specified by `path`
// set to `field_value`. `path` must be a valid field path for *this.
auto SetField(Ptr<Arena> arena, const FieldPath& path,
Ptr<const Value> field_value, SourceLocation loc) const
-> Ptr<const Value>;
auto SetField(Nonnull<Arena*> arena, const FieldPath& path,
Nonnull<const Value*> field_value, SourceLocation loc) const
-> Nonnull<const Value*>;
protected:
// Constructs a Value. `tag` must be the enumerator corresponding to the
@@ -86,10 +86,10 @@ class Value {
const Kind tag;
};
using VarValues = std::vector<std::pair<std::string, Ptr<const Value>>>;
using VarValues = std::vector<std::pair<std::string, Nonnull<const Value*>>>;
auto FindInVarValues(const std::string& field, const VarValues& inits)
-> std::optional<Ptr<const Value>>;
-> std::optional<Nonnull<const Value*>>;
auto FieldsEqual(const VarValues& ts1, const VarValues& ts2) -> bool;
// A TupleElement represents the value of a single tuple field.
@@ -98,7 +98,7 @@ struct TupleElement {
std::string name;
// The field's value.
Ptr<const Value> value;
Nonnull<const Value*> value;
};
struct Frame; // Used by continuation.
@@ -121,8 +121,8 @@ class IntValue : public Value {
// A function value.
class FunctionValue : public Value {
public:
FunctionValue(std::string name, Ptr<const Value> param,
std::optional<Ptr<const Statement>> body)
FunctionValue(std::string name, Nonnull<const Value*> param,
std::optional<Nonnull<const Statement*>> body)
: Value(Kind::FunctionValue),
name(std::move(name)),
param(param),
@@ -133,13 +133,13 @@ class FunctionValue : public Value {
}
auto Name() const -> const std::string& { return name; }
auto Param() const -> Ptr<const Value> { return param; }
auto Body() const -> std::optional<Ptr<const Statement>> { return body; }
auto Param() const -> Nonnull<const Value*> { return param; }
auto Body() const -> std::optional<Nonnull<const Statement*>> { return body; }
private:
std::string name;
Ptr<const Value> param;
std::optional<Ptr<const Statement>> body;
Nonnull<const Value*> param;
std::optional<Nonnull<const Statement*>> body;
};
// A pointer value.
@@ -176,19 +176,19 @@ class BoolValue : public Value {
// A function value.
class StructValue : public Value {
public:
StructValue(Ptr<const Value> type, Ptr<const Value> inits)
StructValue(Nonnull<const Value*> type, Nonnull<const Value*> inits)
: Value(Kind::StructValue), type(type), inits(inits) {}
static auto classof(const Value* value) -> bool {
return value->Tag() == Kind::StructValue;
}
auto Type() const -> Ptr<const Value> { return type; }
auto Inits() const -> Ptr<const Value> { return inits; }
auto Type() const -> Nonnull<const Value*> { return type; }
auto Inits() const -> Nonnull<const Value*> { return inits; }
private:
Ptr<const Value> type;
Ptr<const Value> inits;
Nonnull<const Value*> type;
Nonnull<const Value*> inits;
};
// An alternative constructor value.
@@ -215,7 +215,7 @@ class AlternativeConstructorValue : public Value {
class AlternativeValue : public Value {
public:
AlternativeValue(std::string alt_name, std::string choice_name,
Ptr<const Value> argument)
Nonnull<const Value*> argument)
: Value(Kind::AlternativeValue),
alt_name(std::move(alt_name)),
choice_name(std::move(choice_name)),
@@ -227,21 +227,21 @@ class AlternativeValue : public Value {
auto AltName() const -> const std::string& { return alt_name; }
auto ChoiceName() const -> const std::string& { return choice_name; }
auto Argument() const -> Ptr<const Value> { return argument; }
auto Argument() const -> Nonnull<const Value*> { return argument; }
private:
std::string alt_name;
std::string choice_name;
Ptr<const Value> argument;
Nonnull<const Value*> argument;
};
// A function value.
class TupleValue : public Value {
public:
// An empty tuple, also known as the unit type.
static Ptr<const TupleValue> Empty() {
static Nonnull<const TupleValue*> Empty() {
static const TupleValue empty = TupleValue(std::vector<TupleElement>());
return Ptr<const TupleValue>(&empty);
return Nonnull<const TupleValue*>(&empty);
}
explicit TupleValue(std::vector<TupleElement> elements)
@@ -256,7 +256,7 @@ class TupleValue : public Value {
// Returns the value of the field named `name` in this tuple, or
// nullopt if there is no such field.
auto FindField(const std::string& name) const
-> std::optional<Ptr<const Value>>;
-> std::optional<Nonnull<const Value*>>;
private:
std::vector<TupleElement> elements;
@@ -267,7 +267,7 @@ class BindingPlaceholderValue : public Value {
public:
// nullopt represents the `_` placeholder.
BindingPlaceholderValue(std::optional<std::string> name,
Ptr<const Value> type)
Nonnull<const Value*> type)
: Value(Kind::BindingPlaceholderValue),
name(std::move(name)),
type(type) {}
@@ -277,11 +277,11 @@ class BindingPlaceholderValue : public Value {
}
auto Name() const -> const std::optional<std::string>& { return name; }
auto Type() const -> Ptr<const Value> { return type; }
auto Type() const -> Nonnull<const Value*> { return type; }
private:
std::optional<std::string> name;
Ptr<const Value> type;
Nonnull<const Value*> type;
};
// The int type.
@@ -317,8 +317,8 @@ class TypeType : public Value {
// A function type.
class FunctionType : public Value {
public:
FunctionType(std::vector<GenericBinding> deduced, Ptr<const Value> param,
Ptr<const Value> ret)
FunctionType(std::vector<GenericBinding> deduced, Nonnull<const Value*> param,
Nonnull<const Value*> ret)
: Value(Kind::FunctionType),
deduced(std::move(deduced)),
param(param),
@@ -329,29 +329,29 @@ class FunctionType : public Value {
}
auto Deduced() const -> const std::vector<GenericBinding>& { return deduced; }
auto Param() const -> Ptr<const Value> { return param; }
auto Ret() const -> Ptr<const Value> { return ret; }
auto Param() const -> Nonnull<const Value*> { return param; }
auto Ret() const -> Nonnull<const Value*> { return ret; }
private:
std::vector<GenericBinding> deduced;
Ptr<const Value> param;
Ptr<const Value> ret;
Nonnull<const Value*> param;
Nonnull<const Value*> ret;
};
// A pointer type.
class PointerType : public Value {
public:
explicit PointerType(Ptr<const Value> type)
explicit PointerType(Nonnull<const Value*> type)
: Value(Kind::PointerType), type(type) {}
static auto classof(const Value* value) -> bool {
return value->Tag() == Kind::PointerType;
}
auto Type() const -> Ptr<const Value> { return type; }
auto Type() const -> Nonnull<const Value*> { return type; }
private:
Ptr<const Value> type;
Nonnull<const Value*> type;
};
// The `auto` type.
@@ -436,17 +436,17 @@ class VariableType : public Value {
// A first-class continuation representation of a fragment of the stack.
class ContinuationValue : public Value {
public:
explicit ContinuationValue(std::vector<Ptr<Frame>> stack)
explicit ContinuationValue(std::vector<Nonnull<Frame*>> stack)
: Value(Kind::ContinuationValue), stack(std::move(stack)) {}
static auto classof(const Value* value) -> bool {
return value->Tag() == Kind::ContinuationValue;
}
auto Stack() const -> const std::vector<Ptr<Frame>>& { return stack; }
auto Stack() const -> const std::vector<Nonnull<Frame*>>& { return stack; }
private:
std::vector<Ptr<Frame>> stack;
std::vector<Nonnull<Frame*>> stack;
};
// The String type.
@@ -475,12 +475,12 @@ class StringValue : public Value {
std::string val;
};
auto CopyVal(Ptr<Arena> arena, Ptr<const Value> val, SourceLocation loc)
-> Ptr<const Value>;
auto CopyVal(Nonnull<Arena*> arena, Nonnull<const Value*> val,
SourceLocation loc) -> Nonnull<const Value*>;
auto TypeEqual(Ptr<const Value> t1, Ptr<const Value> t2) -> bool;
auto ValueEqual(Ptr<const Value> v1, Ptr<const Value> v2, SourceLocation loc)
-> bool;
auto TypeEqual(Nonnull<const Value*> t1, Nonnull<const Value*> t2) -> bool;
auto ValueEqual(Nonnull<const Value*> v1, Nonnull<const Value*> v2,
SourceLocation loc) -> bool;
} // namespace Carbon
+1 -1
View File
@@ -13,7 +13,7 @@
namespace Carbon {
auto Parse(Ptr<Arena> arena, const std::string& input_file_name)
auto Parse(Nonnull<Arena*> arena, const std::string& input_file_name)
-> std::variant<AST, SyntaxErrorCode> {
FILE* input_file = fopen(input_file_name.c_str(), "r");
if (input_file == nullptr) {
+1 -1
View File
@@ -18,7 +18,7 @@ using SyntaxErrorCode = int;
// Returns the AST representing the contents of the named file, or an error code
// if parsing fails. Allocations go into the provided arena.
auto Parse(Ptr<Arena> arena, const std::string& input_file_name)
auto Parse(Nonnull<Arena*> arena, const std::string& input_file_name)
-> std::variant<Carbon::AST, SyntaxErrorCode>;
} // namespace Carbon
@@ -17,7 +17,7 @@ namespace Carbon {
class ParseAndLexContext {
public:
// Creates an instance analyzing the given input file.
ParseAndLexContext(Ptr<const std::string> input_file_name)
ParseAndLexContext(Nonnull<const std::string*> input_file_name)
: input_file_name(input_file_name) {}
// Writes a syntax error diagnostic containing message to standard error.
@@ -34,15 +34,15 @@ class ParseAndLexContext {
private:
// A path to the file processed, relative to the current working directory
// when *this is called.
Ptr<const std::string> input_file_name;
Nonnull<const std::string*> input_file_name;
};
} // namespace Carbon
// Gives flex the yylex prototype we want.
#define YY_DECL \
Carbon::Parser::symbol_type yylex(Carbon::Ptr<Carbon::Arena> arena, \
yyscan_t yyscanner, \
#define YY_DECL \
Carbon::Parser::symbol_type yylex(Carbon::Nonnull<Carbon::Arena*> arena, \
yyscan_t yyscanner, \
Carbon::ParseAndLexContext& context)
// Declares yylex for the parser's sake.
+49 -45
View File
@@ -38,7 +38,7 @@
// thus available to its methods.
// "inout" parameters passed to both the parser and the lexer.
%param {Ptr<Arena> arena}
%param {Nonnull<Arena*> arena}
%param {yyscan_t yyscanner}
%param {ParseAndLexContext& context}
@@ -98,43 +98,43 @@
%type <std::vector<LibraryName>> import_directives
%type <std::string> optional_library_path
%type <bool> api_or_impl
%type <BisonWrap<Ptr<const Declaration>>> declaration
%type <BisonWrap<Ptr<const FunctionDefinition>>> function_declaration
%type <BisonWrap<Ptr<const FunctionDefinition>>> function_definition
%type <std::vector<Ptr<const Declaration>>> declaration_list
%type <BisonWrap<Ptr<const Statement>>> statement
%type <BisonWrap<Ptr<const Statement>>> if_statement
%type <std::optional<Ptr<const Statement>>> optional_else
%type <BisonWrap<std::pair<Ptr<const Expression>, bool>>> return_expression
%type <BisonWrap<Ptr<const Statement>>> block
%type <std::optional<Ptr<const Statement>>> statement_list
%type <BisonWrap<Ptr<const Expression>>> expression
%type <BisonWrap<Nonnull<const Declaration*>>> declaration
%type <BisonWrap<Nonnull<const FunctionDefinition*>>> function_declaration
%type <BisonWrap<Nonnull<const FunctionDefinition*>>> function_definition
%type <std::vector<Nonnull<const Declaration*>>> declaration_list
%type <BisonWrap<Nonnull<const Statement*>>> statement
%type <BisonWrap<Nonnull<const Statement*>>> if_statement
%type <std::optional<Nonnull<const Statement*>>> optional_else
%type <BisonWrap<std::pair<Nonnull<const Expression*>, bool>>> return_expression
%type <BisonWrap<Nonnull<const Statement*>>> block
%type <std::optional<Nonnull<const Statement*>>> statement_list
%type <BisonWrap<Nonnull<const Expression*>>> expression
%type <BisonWrap<GenericBinding>> generic_binding
%type <std::vector<GenericBinding>> deduced_params
%type <std::vector<GenericBinding>> deduced_param_list
%type <BisonWrap<Ptr<const Pattern>>> pattern
%type <BisonWrap<Ptr<const Pattern>>> non_expression_pattern
%type <BisonWrap<std::pair<Ptr<const Expression>, bool>>> return_type
%type <BisonWrap<Ptr<const Expression>>> paren_expression
%type <BisonWrap<Ptr<const Expression>>> tuple
%type <BisonWrap<Nonnull<const Pattern*>>> pattern
%type <BisonWrap<Nonnull<const Pattern*>>> non_expression_pattern
%type <BisonWrap<std::pair<Nonnull<const Expression*>, bool>>> return_type
%type <BisonWrap<Nonnull<const Expression*>>> paren_expression
%type <BisonWrap<Nonnull<const Expression*>>> tuple
%type <std::optional<std::string>> binding_lhs
%type <BisonWrap<Ptr<const BindingPattern>>> variable_declaration
%type <BisonWrap<Ptr<Member>>> member
%type <std::vector<Ptr<Member>>> member_list
%type <BisonWrap<Nonnull<const BindingPattern*>>> variable_declaration
%type <BisonWrap<Nonnull<Member*>>> member
%type <std::vector<Nonnull<Member*>>> member_list
%type <BisonWrap<ParenContents<Expression>::Element>> paren_expression_element
%type <ParenContents<Expression>> paren_expression_base
%type <ParenContents<Expression>> paren_expression_contents
%type <BisonWrap<Ptr<const Pattern>>> paren_pattern
%type <BisonWrap<Ptr<const TuplePattern>>> tuple_pattern
%type <BisonWrap<Ptr<const TuplePattern>>> maybe_empty_tuple_pattern
%type <BisonWrap<Nonnull<const Pattern*>>> paren_pattern
%type <BisonWrap<Nonnull<const TuplePattern*>>> tuple_pattern
%type <BisonWrap<Nonnull<const TuplePattern*>>> maybe_empty_tuple_pattern
%type <ParenContents<Pattern>> paren_pattern_base
%type <BisonWrap<ParenContents<Pattern>::Element>> paren_pattern_element
%type <ParenContents<Pattern>> paren_pattern_contents
%type <BisonWrap<std::pair<std::string, Ptr<const Expression>>>> alternative
%type <std::vector<std::pair<std::string, Ptr<const Expression>>>> alternative_list
%type <std::vector<std::pair<std::string, Ptr<const Expression>>>> alternative_list_contents
%type <BisonWrap<std::pair<Ptr<const Pattern>, Ptr<const Statement>>>> clause
%type <std::vector<std::pair<Ptr<const Pattern>, Ptr<const Statement>>>> clause_list
%type <BisonWrap<std::pair<std::string, Nonnull<const Expression*>>>> alternative
%type <std::vector<std::pair<std::string, Nonnull<const Expression*>>>> alternative_list
%type <std::vector<std::pair<std::string, Nonnull<const Expression*>>>> alternative_list_contents
%type <BisonWrap<std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>>> clause
%type <std::vector<std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>>> clause_list
%token
// Most tokens have their spelling defined in lexer.lpp.
@@ -303,61 +303,61 @@ expression:
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::Eq,
std::vector<Ptr<const Expression>>({$1, $3}));
std::vector<Nonnull<const Expression*>>({$1, $3}));
}
| expression PLUS expression
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::Add,
std::vector<Ptr<const Expression>>({$1, $3}));
std::vector<Nonnull<const Expression*>>({$1, $3}));
}
| expression MINUS expression
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::Sub,
std::vector<Ptr<const Expression>>({$1, $3}));
std::vector<Nonnull<const Expression*>>({$1, $3}));
}
| expression BINARY_STAR expression
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::Mul,
std::vector<Ptr<const Expression>>({$1, $3}));
std::vector<Nonnull<const Expression*>>({$1, $3}));
}
| expression AND expression
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::And,
std::vector<Ptr<const Expression>>({$1, $3}));
std::vector<Nonnull<const Expression*>>({$1, $3}));
}
| expression OR expression
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::Or,
std::vector<Ptr<const Expression>>({$1, $3}));
std::vector<Nonnull<const Expression*>>({$1, $3}));
}
| NOT expression
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::Not,
std::vector<Ptr<const Expression>>({$2}));
std::vector<Nonnull<const Expression*>>({$2}));
}
| MINUS expression %prec UNARY_MINUS
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::Neg,
std::vector<Ptr<const Expression>>({$2}));
std::vector<Nonnull<const Expression*>>({$2}));
}
| PREFIX_STAR expression
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::Deref,
std::vector<Ptr<const Expression>>({$2}));
std::vector<Nonnull<const Expression*>>({$2}));
}
| UNARY_STAR expression %prec PREFIX_STAR
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::Deref,
std::vector<Ptr<const Expression>>({$2}));
std::vector<Nonnull<const Expression*>>({$2}));
}
| expression tuple
{ $$ = arena->New<CallExpression>(context.SourceLoc(), $1, $2); }
@@ -365,13 +365,13 @@ expression:
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::Ptr,
std::vector<Ptr<const Expression>>({$1}));
std::vector<Nonnull<const Expression*>>({$1}));
}
| expression UNARY_STAR
{
$$ = arena->New<PrimitiveOperatorExpression>(
context.SourceLoc(), Operator::Ptr,
std::vector<Ptr<const Expression>>({$1}));
std::vector<Nonnull<const Expression*>>({$1}));
}
| FNTY tuple return_type
{
@@ -502,13 +502,17 @@ maybe_empty_tuple_pattern:
;
clause:
CASE pattern DOUBLE_ARROW statement
{ $$ = std::pair<Ptr<const Pattern>, Ptr<const Statement>>($2, $4); }
{
$$ =
std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>($2, $4);
}
| DEFAULT DOUBLE_ARROW statement
{
auto vp = arena -> New<BindingPattern>(
context.SourceLoc(), std::nullopt,
arena->New<AutoPattern>(context.SourceLoc()));
$$ = std::pair<Ptr<const Pattern>, Ptr<const Statement>>(vp, $3);
$$ =
std::pair<Nonnull<const Pattern*>, Nonnull<const Statement*>>(vp, $3);
}
;
clause_list:
@@ -656,10 +660,10 @@ member_list:
;
alternative:
identifier tuple
{ $$ = std::pair<std::string, Ptr<const Expression>>($1, $2); }
{ $$ = std::pair<std::string, Nonnull<const Expression*>>($1, $2); }
| identifier
{
$$ = std::pair<std::string, Ptr<const Expression>>(
$$ = std::pair<std::string, Nonnull<const Expression*>>(
$1, arena->New<TupleLiteral>(context.SourceLoc()));
}
;
@@ -698,7 +702,7 @@ declaration_list:
| declaration_list declaration
{
$$ = $1;
$$.push_back(Ptr<const Declaration>($2));
$$.push_back(Nonnull<const Declaration*>($2));
}
;
%%