Skip to content

Commit 904c6f7

Browse files
authored
Make the AST mutable (#849)
The code is pretty intertwined: having the AST be truly mutable means (to me) changing parser.ypp to return non-const values, but then the way things are passed around between objects should be non-const (particularly an issue with lists), which then creates issues with construction of lists in the TypeChecker, which then TypeChecker needs to mostly be non-const. Due to the difficulties in breaking this apart, whereas I'd previously considering refactoring accessor naming in the same PR, I've largely avoided doing so. The intent is then that this PR focuses mainly on const -> non-const AST behavior. call_main moves out of interpreter.cpp so that interpreter.cpp can receive a fully const AST.
1 parent 21f8d25 commit 904c6f7

15 files changed

+282
-270
lines changed

executable_semantics/ast/ast.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct AST {
2222
// Import directives.
2323
std::vector<LibraryName> imports;
2424
// The file's ordered declarations.
25-
std::vector<Nonnull<const Declaration*>> declarations;
25+
std::vector<Nonnull<Declaration*>> declarations;
2626
};
2727

2828
} // namespace Carbon

executable_semantics/ast/declaration.h

+13-9
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "executable_semantics/ast/pattern.h"
1616
#include "executable_semantics/ast/source_location.h"
1717
#include "executable_semantics/common/nonnull.h"
18+
#include "llvm/ADT/ArrayRef.h"
1819
#include "llvm/Support/Compiler.h"
1920

2021
namespace Carbon {
@@ -60,7 +61,7 @@ class Declaration {
6061

6162
class FunctionDeclaration : public Declaration {
6263
public:
63-
FunctionDeclaration(Nonnull<const FunctionDefinition*> definition)
64+
FunctionDeclaration(Nonnull<FunctionDefinition*> definition)
6465
: Declaration(Kind::FunctionDeclaration, definition->source_loc()),
6566
definition(definition) {}
6667

@@ -69,9 +70,10 @@ class FunctionDeclaration : public Declaration {
6970
}
7071

7172
auto Definition() const -> const FunctionDefinition& { return *definition; }
73+
auto Definition() -> FunctionDefinition& { return *definition; }
7274

7375
private:
74-
Nonnull<const FunctionDefinition*> definition;
76+
Nonnull<FunctionDefinition*> definition;
7577
};
7678

7779
class ClassDeclaration : public Declaration {
@@ -88,6 +90,7 @@ class ClassDeclaration : public Declaration {
8890
}
8991

9092
auto Definition() const -> const ClassDefinition& { return definition; }
93+
auto Definition() -> ClassDefinition& { return definition; }
9194

9295
private:
9396
ClassDefinition definition;
@@ -97,15 +100,15 @@ class ChoiceDeclaration : public Declaration {
97100
public:
98101
class Alternative {
99102
public:
100-
Alternative(std::string name, Nonnull<const Expression*> signature)
103+
Alternative(std::string name, Nonnull<Expression*> signature)
101104
: name_(name), signature_(signature) {}
102105

103106
auto name() const -> const std::string& { return name_; }
104107
auto signature() const -> const Expression& { return *signature_; }
105108

106109
private:
107110
std::string name_;
108-
Nonnull<const Expression*> signature_;
111+
Nonnull<Expression*> signature_;
109112
};
110113

111114
ChoiceDeclaration(SourceLocation loc, std::string name,
@@ -131,9 +134,8 @@ class ChoiceDeclaration : public Declaration {
131134
// Global variable definition implements the Declaration concept.
132135
class VariableDeclaration : public Declaration {
133136
public:
134-
VariableDeclaration(SourceLocation loc,
135-
Nonnull<const BindingPattern*> binding,
136-
Nonnull<const Expression*> initializer)
137+
VariableDeclaration(SourceLocation loc, Nonnull<BindingPattern*> binding,
138+
Nonnull<Expression*> initializer)
137139
: Declaration(Kind::VariableDeclaration, loc),
138140
binding(binding),
139141
initializer(initializer) {}
@@ -143,14 +145,16 @@ class VariableDeclaration : public Declaration {
143145
}
144146

145147
auto Binding() const -> Nonnull<const BindingPattern*> { return binding; }
148+
auto Binding() -> Nonnull<BindingPattern*> { return binding; }
146149
auto Initializer() const -> Nonnull<const Expression*> { return initializer; }
150+
auto Initializer() -> Nonnull<Expression*> { return initializer; }
147151

148152
private:
149153
// TODO: split this into a non-optional name and a type, initialized by
150154
// a constructor that takes a BindingPattern and handles errors like a
151155
// missing name.
152-
Nonnull<const BindingPattern*> binding;
153-
Nonnull<const Expression*> initializer;
156+
Nonnull<BindingPattern*> binding;
157+
Nonnull<Expression*> initializer;
154158
};
155159

156160
} // namespace Carbon

executable_semantics/ast/expression.cpp

+3-6
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@ using llvm::cast;
1818

1919
auto ExpressionFromParenContents(
2020
Nonnull<Arena*> arena, SourceLocation loc,
21-
const ParenContents<Expression>& paren_contents)
22-
-> Nonnull<const Expression*> {
23-
std::optional<Nonnull<const Expression*>> single_term =
24-
paren_contents.SingleTerm();
21+
const ParenContents<Expression>& paren_contents) -> Nonnull<Expression*> {
22+
std::optional<Nonnull<Expression*>> single_term = paren_contents.SingleTerm();
2523
if (single_term.has_value()) {
2624
return *single_term;
2725
} else {
@@ -31,8 +29,7 @@ auto ExpressionFromParenContents(
3129

3230
auto TupleExpressionFromParenContents(
3331
Nonnull<Arena*> arena, SourceLocation loc,
34-
const ParenContents<Expression>& paren_contents)
35-
-> Nonnull<const Expression*> {
32+
const ParenContents<Expression>& paren_contents) -> Nonnull<Expression*> {
3633
return arena->New<TupleLiteral>(
3734
loc, paren_contents.TupleElements<FieldInitializer>(loc));
3835
}

executable_semantics/ast/expression.h

+32-25
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "executable_semantics/ast/paren_contents.h"
1515
#include "executable_semantics/ast/source_location.h"
1616
#include "executable_semantics/common/arena.h"
17+
#include "llvm/ADT/ArrayRef.h"
1718
#include "llvm/Support/Compiler.h"
1819

1920
namespace Carbon {
@@ -64,26 +65,24 @@ class Expression {
6465
// tuple otherwise.
6566
auto ExpressionFromParenContents(
6667
Nonnull<Arena*> arena, SourceLocation loc,
67-
const ParenContents<Expression>& paren_contents)
68-
-> Nonnull<const Expression*>;
68+
const ParenContents<Expression>& paren_contents) -> Nonnull<Expression*>;
6969

7070
// Converts paren_contents to an Expression, interpreting the parentheses as
7171
// forming a tuple.
7272
auto TupleExpressionFromParenContents(
7373
Nonnull<Arena*> arena, SourceLocation loc,
74-
const ParenContents<Expression>& paren_contents)
75-
-> Nonnull<const Expression*>;
74+
const ParenContents<Expression>& paren_contents) -> Nonnull<Expression*>;
7675

7776
// A FieldInitializer represents the initialization of a single tuple field.
7877
struct FieldInitializer {
79-
FieldInitializer(std::string name, Nonnull<const Expression*> expression)
78+
FieldInitializer(std::string name, Nonnull<Expression*> expression)
8079
: name(std::move(name)), expression(expression) {}
8180

8281
// The field name. Cannot be empty.
8382
std::string name;
8483

8584
// The expression that initializes the field.
86-
Nonnull<const Expression*> expression;
85+
Nonnull<Expression*> expression;
8786
};
8887

8988
enum class Operator {
@@ -117,7 +116,7 @@ class IdentifierExpression : public Expression {
117116
class FieldAccessExpression : public Expression {
118117
public:
119118
explicit FieldAccessExpression(SourceLocation loc,
120-
Nonnull<const Expression*> aggregate,
119+
Nonnull<Expression*> aggregate,
121120
std::string field)
122121
: Expression(Kind::FieldAccessExpression, loc),
123122
aggregate(aggregate),
@@ -128,18 +127,18 @@ class FieldAccessExpression : public Expression {
128127
}
129128

130129
auto Aggregate() const -> Nonnull<const Expression*> { return aggregate; }
130+
auto Aggregate() -> Nonnull<Expression*> { return aggregate; }
131131
auto Field() const -> const std::string& { return field; }
132132

133133
private:
134-
Nonnull<const Expression*> aggregate;
134+
Nonnull<Expression*> aggregate;
135135
std::string field;
136136
};
137137

138138
class IndexExpression : public Expression {
139139
public:
140-
explicit IndexExpression(SourceLocation loc,
141-
Nonnull<const Expression*> aggregate,
142-
Nonnull<const Expression*> offset)
140+
explicit IndexExpression(SourceLocation loc, Nonnull<Expression*> aggregate,
141+
Nonnull<Expression*> offset)
143142
: Expression(Kind::IndexExpression, loc),
144143
aggregate(aggregate),
145144
offset(offset) {}
@@ -149,11 +148,13 @@ class IndexExpression : public Expression {
149148
}
150149

151150
auto Aggregate() const -> Nonnull<const Expression*> { return aggregate; }
151+
auto Aggregate() -> Nonnull<Expression*> { return aggregate; }
152152
auto Offset() const -> Nonnull<const Expression*> { return offset; }
153+
auto Offset() -> Nonnull<Expression*> { return offset; }
153154

154155
private:
155-
Nonnull<const Expression*> aggregate;
156-
Nonnull<const Expression*> offset;
156+
Nonnull<Expression*> aggregate;
157+
Nonnull<Expression*> offset;
157158
};
158159

159160
class IntLiteral : public Expression {
@@ -233,7 +234,7 @@ class PrimitiveOperatorExpression : public Expression {
233234
public:
234235
explicit PrimitiveOperatorExpression(
235236
SourceLocation loc, Operator op,
236-
std::vector<Nonnull<const Expression*>> arguments)
237+
std::vector<Nonnull<Expression*>> arguments)
237238
: Expression(Kind::PrimitiveOperatorExpression, loc),
238239
op(op),
239240
arguments(std::move(arguments)) {}
@@ -243,20 +244,22 @@ class PrimitiveOperatorExpression : public Expression {
243244
}
244245

245246
auto Op() const -> Operator { return op; }
246-
auto Arguments() const -> const std::vector<Nonnull<const Expression*>>& {
247+
auto Arguments() const -> llvm::ArrayRef<Nonnull<Expression*>> {
248+
return arguments;
249+
}
250+
auto Arguments() -> llvm::MutableArrayRef<Nonnull<Expression*>> {
247251
return arguments;
248252
}
249253

250254
private:
251255
Operator op;
252-
std::vector<Nonnull<const Expression*>> arguments;
256+
std::vector<Nonnull<Expression*>> arguments;
253257
};
254258

255259
class CallExpression : public Expression {
256260
public:
257-
explicit CallExpression(SourceLocation loc,
258-
Nonnull<const Expression*> function,
259-
Nonnull<const Expression*> argument)
261+
explicit CallExpression(SourceLocation loc, Nonnull<Expression*> function,
262+
Nonnull<Expression*> argument)
260263
: Expression(Kind::CallExpression, loc),
261264
function(function),
262265
argument(argument) {}
@@ -266,18 +269,20 @@ class CallExpression : public Expression {
266269
}
267270

268271
auto Function() const -> Nonnull<const Expression*> { return function; }
272+
auto Function() -> Nonnull<Expression*> { return function; }
269273
auto Argument() const -> Nonnull<const Expression*> { return argument; }
274+
auto Argument() -> Nonnull<Expression*> { return argument; }
270275

271276
private:
272-
Nonnull<const Expression*> function;
273-
Nonnull<const Expression*> argument;
277+
Nonnull<Expression*> function;
278+
Nonnull<Expression*> argument;
274279
};
275280

276281
class FunctionTypeLiteral : public Expression {
277282
public:
278283
explicit FunctionTypeLiteral(SourceLocation loc,
279-
Nonnull<const Expression*> parameter,
280-
Nonnull<const Expression*> return_type,
284+
Nonnull<Expression*> parameter,
285+
Nonnull<Expression*> return_type,
281286
bool is_omitted_return_type)
282287
: Expression(Kind::FunctionTypeLiteral, loc),
283288
parameter(parameter),
@@ -289,12 +294,14 @@ class FunctionTypeLiteral : public Expression {
289294
}
290295

291296
auto Parameter() const -> Nonnull<const Expression*> { return parameter; }
297+
auto Parameter() -> Nonnull<Expression*> { return parameter; }
292298
auto ReturnType() const -> Nonnull<const Expression*> { return return_type; }
299+
auto ReturnType() -> Nonnull<Expression*> { return return_type; }
293300
auto IsOmittedReturnType() const -> bool { return is_omitted_return_type; }
294301

295302
private:
296-
Nonnull<const Expression*> parameter;
297-
Nonnull<const Expression*> return_type;
303+
Nonnull<Expression*> parameter;
304+
Nonnull<Expression*> return_type;
298305
bool is_omitted_return_type;
299306
};
300307

executable_semantics/ast/function_definition.h

+9-8
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,12 @@ class FunctionDefinition {
2626
public:
2727
FunctionDefinition(SourceLocation source_loc, std::string name,
2828
std::vector<GenericBinding> deduced_params,
29-
Nonnull<const TuplePattern*> param_pattern,
30-
Nonnull<const Pattern*> return_type,
31-
bool is_omitted_return_type,
32-
std::optional<Nonnull<const Statement*>> body)
29+
Nonnull<TuplePattern*> param_pattern,
30+
Nonnull<Pattern*> return_type, bool is_omitted_return_type,
31+
std::optional<Nonnull<Statement*>> body)
3332
: source_loc_(source_loc),
3433
name_(std::move(name)),
35-
deduced_parameters_(deduced_params),
34+
deduced_parameters_(std::move(deduced_params)),
3635
param_pattern_(param_pattern),
3736
return_type_(return_type),
3837
is_omitted_return_type_(is_omitted_return_type),
@@ -48,22 +47,24 @@ class FunctionDefinition {
4847
return deduced_parameters_;
4948
}
5049
auto param_pattern() const -> const TuplePattern& { return *param_pattern_; }
50+
auto param_pattern() -> TuplePattern& { return *param_pattern_; }
5151
auto return_type() const -> const Pattern& { return *return_type_; }
5252
auto is_omitted_return_type() const -> bool {
5353
return is_omitted_return_type_;
5454
}
5555
auto body() const -> std::optional<Nonnull<const Statement*>> {
5656
return body_;
5757
}
58+
auto body() -> std::optional<Nonnull<Statement*>> { return body_; }
5859

5960
private:
6061
SourceLocation source_loc_;
6162
std::string name_;
6263
std::vector<GenericBinding> deduced_parameters_;
63-
Nonnull<const TuplePattern*> param_pattern_;
64-
Nonnull<const Pattern*> return_type_;
64+
Nonnull<TuplePattern*> param_pattern_;
65+
Nonnull<Pattern*> return_type_;
6566
bool is_omitted_return_type_;
66-
std::optional<Nonnull<const Statement*>> body_;
67+
std::optional<Nonnull<Statement*>> body_;
6768
};
6869

6970
} // namespace Carbon

executable_semantics/ast/paren_contents.h

+4-5
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@ template <typename Term>
2828
struct ParenContents {
2929
struct Element {
3030
std::optional<std::string> name;
31-
Nonnull<const Term*> term;
31+
Nonnull<Term*> term;
3232
};
3333

3434
// If this object represents a single term, with no name and no trailing
3535
// comma, this method returns that term. This typically means the parentheses
3636
// can be interpreted as grouping.
37-
auto SingleTerm() const -> std::optional<Nonnull<const Term*>>;
37+
auto SingleTerm() const -> std::optional<Nonnull<Term*>>;
3838

3939
// Converts `elements` to std::vector<TupleElement>. TupleElement must
40-
// have a constructor that takes a std::string and a Nonnull<const Term*>.
40+
// have a constructor that takes a std::string and a Nonnull<Term*>.
4141
//
4242
// TODO: Find a way to deduce TupleElement from Term.
4343
template <typename TupleElement>
@@ -50,8 +50,7 @@ struct ParenContents {
5050
// Implementation details only below here.
5151

5252
template <typename Term>
53-
auto ParenContents<Term>::SingleTerm() const
54-
-> std::optional<Nonnull<const Term*>> {
53+
auto ParenContents<Term>::SingleTerm() const -> std::optional<Nonnull<Term*>> {
5554
if (elements.size() == 1 && !elements.front().name.has_value() &&
5655
!has_trailing_comma) {
5756
return elements.front().term;

0 commit comments

Comments
 (0)