mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
;
|
||||
%%
|
||||
|
||||
Reference in New Issue
Block a user