mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Switch Expression to use inheritance+cast (#712)
Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
committed by
GitHub
co-authored by
Geoff Romer
parent
4e0307efbc
commit
dbcd6ad20d
@@ -9,10 +9,13 @@
|
||||
#include "executable_semantics/common/arena.h"
|
||||
#include "executable_semantics/common/error.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
using llvm::cast;
|
||||
|
||||
auto ExpressionFromParenContents(
|
||||
int line_num, const ParenContents<Expression>& paren_contents)
|
||||
-> const Expression* {
|
||||
@@ -27,161 +30,10 @@ auto ExpressionFromParenContents(
|
||||
auto TupleExpressionFromParenContents(
|
||||
int line_num, const ParenContents<Expression>& paren_contents)
|
||||
-> const Expression* {
|
||||
return Expression::MakeTupleLiteral(
|
||||
return global_arena->New<TupleLiteral>(
|
||||
line_num, paren_contents.TupleElements<FieldInitializer>(line_num));
|
||||
}
|
||||
|
||||
auto Expression::GetIdentifierExpression() const
|
||||
-> const IdentifierExpression& {
|
||||
return std::get<IdentifierExpression>(value);
|
||||
}
|
||||
|
||||
auto Expression::GetFieldAccessExpression() const
|
||||
-> const FieldAccessExpression& {
|
||||
return std::get<FieldAccessExpression>(value);
|
||||
}
|
||||
|
||||
auto Expression::GetIndexExpression() const -> const IndexExpression& {
|
||||
return std::get<IndexExpression>(value);
|
||||
}
|
||||
|
||||
auto Expression::GetIntLiteral() const -> int {
|
||||
return std::get<IntLiteral>(value).value;
|
||||
}
|
||||
|
||||
auto Expression::GetBoolLiteral() const -> bool {
|
||||
return std::get<BoolLiteral>(value).value;
|
||||
}
|
||||
|
||||
auto Expression::GetTupleLiteral() const -> const TupleLiteral& {
|
||||
return std::get<TupleLiteral>(value);
|
||||
}
|
||||
|
||||
auto Expression::GetPrimitiveOperatorExpression() const
|
||||
-> const PrimitiveOperatorExpression& {
|
||||
return std::get<PrimitiveOperatorExpression>(value);
|
||||
}
|
||||
|
||||
auto Expression::GetCallExpression() const -> const CallExpression& {
|
||||
return std::get<CallExpression>(value);
|
||||
}
|
||||
|
||||
auto Expression::GetFunctionTypeLiteral() const -> const FunctionTypeLiteral& {
|
||||
return std::get<FunctionTypeLiteral>(value);
|
||||
}
|
||||
|
||||
auto Expression::MakeTypeTypeLiteral(int line_num) -> const Expression* {
|
||||
auto* t = global_arena->New<Expression>();
|
||||
t->line_num = line_num;
|
||||
t->value = TypeTypeLiteral();
|
||||
return t;
|
||||
}
|
||||
|
||||
auto Expression::MakeIntTypeLiteral(int line_num) -> const Expression* {
|
||||
auto* t = global_arena->New<Expression>();
|
||||
t->line_num = line_num;
|
||||
t->value = IntTypeLiteral();
|
||||
return t;
|
||||
}
|
||||
|
||||
auto Expression::MakeBoolTypeLiteral(int line_num) -> const Expression* {
|
||||
auto* t = global_arena->New<Expression>();
|
||||
t->line_num = line_num;
|
||||
t->value = BoolTypeLiteral();
|
||||
return t;
|
||||
}
|
||||
|
||||
// Returns a Continuation type AST node at the given source location.
|
||||
auto Expression::MakeContinuationTypeLiteral(int line_num)
|
||||
-> const Expression* {
|
||||
auto* type = global_arena->New<Expression>();
|
||||
type->line_num = line_num;
|
||||
type->value = ContinuationTypeLiteral();
|
||||
return type;
|
||||
}
|
||||
|
||||
auto Expression::MakeFunctionTypeLiteral(int line_num,
|
||||
const Expression* parameter,
|
||||
const Expression* return_type,
|
||||
bool is_omitted_return_type)
|
||||
-> const Expression* {
|
||||
auto* t = global_arena->New<Expression>();
|
||||
t->line_num = line_num;
|
||||
t->value =
|
||||
FunctionTypeLiteral({.parameter = parameter,
|
||||
.return_type = return_type,
|
||||
.is_omitted_return_type = is_omitted_return_type});
|
||||
return t;
|
||||
}
|
||||
|
||||
auto Expression::MakeIdentifierExpression(int line_num, std::string var)
|
||||
-> const Expression* {
|
||||
auto* v = global_arena->New<Expression>();
|
||||
v->line_num = line_num;
|
||||
v->value = IdentifierExpression({.name = std::move(var)});
|
||||
return v;
|
||||
}
|
||||
|
||||
auto Expression::MakeIntLiteral(int line_num, int i) -> const Expression* {
|
||||
auto* e = global_arena->New<Expression>();
|
||||
e->line_num = line_num;
|
||||
e->value = IntLiteral({.value = i});
|
||||
return e;
|
||||
}
|
||||
|
||||
auto Expression::MakeBoolLiteral(int line_num, bool b) -> const Expression* {
|
||||
auto* e = global_arena->New<Expression>();
|
||||
e->line_num = line_num;
|
||||
e->value = BoolLiteral({.value = b});
|
||||
return e;
|
||||
}
|
||||
|
||||
auto Expression::MakePrimitiveOperatorExpression(
|
||||
int line_num, enum Operator op, std::vector<const Expression*> args)
|
||||
-> const Expression* {
|
||||
auto* e = global_arena->New<Expression>();
|
||||
e->line_num = line_num;
|
||||
e->value =
|
||||
PrimitiveOperatorExpression({.op = op, .arguments = std::move(args)});
|
||||
return e;
|
||||
}
|
||||
|
||||
auto Expression::MakeCallExpression(int line_num, const Expression* fun,
|
||||
const Expression* arg)
|
||||
-> const Expression* {
|
||||
auto* e = global_arena->New<Expression>();
|
||||
e->line_num = line_num;
|
||||
e->value = CallExpression({.function = fun, .argument = arg});
|
||||
return e;
|
||||
}
|
||||
|
||||
auto Expression::MakeFieldAccessExpression(int line_num, const Expression* exp,
|
||||
std::string field)
|
||||
-> const Expression* {
|
||||
auto* e = global_arena->New<Expression>();
|
||||
e->line_num = line_num;
|
||||
e->value =
|
||||
FieldAccessExpression({.aggregate = exp, .field = std::move(field)});
|
||||
return e;
|
||||
}
|
||||
|
||||
auto Expression::MakeTupleLiteral(int line_num,
|
||||
std::vector<FieldInitializer> args)
|
||||
-> const Expression* {
|
||||
auto* e = global_arena->New<Expression>();
|
||||
e->line_num = line_num;
|
||||
e->value = TupleLiteral({.fields = std::move(args)});
|
||||
return e;
|
||||
}
|
||||
|
||||
auto Expression::MakeIndexExpression(int line_num, const Expression* exp,
|
||||
const Expression* i) -> const Expression* {
|
||||
auto* e = global_arena->New<Expression>();
|
||||
e->line_num = line_num;
|
||||
e->value = IndexExpression({.aggregate = exp, .offset = i});
|
||||
return e;
|
||||
}
|
||||
|
||||
static void PrintOp(llvm::raw_ostream& out, Operator op) {
|
||||
switch (op) {
|
||||
case Operator::Add:
|
||||
@@ -220,69 +72,74 @@ static void PrintFields(llvm::raw_ostream& out,
|
||||
}
|
||||
|
||||
void Expression::Print(llvm::raw_ostream& out) const {
|
||||
switch (tag()) {
|
||||
case ExpressionKind::IndexExpression:
|
||||
out << *GetIndexExpression().aggregate << "["
|
||||
<< *GetIndexExpression().offset << "]";
|
||||
switch (Tag()) {
|
||||
case Expression::Kind::IndexExpression: {
|
||||
const auto& index = cast<IndexExpression>(*this);
|
||||
out << *index.Aggregate() << "[" << *index.Offset() << "]";
|
||||
break;
|
||||
case ExpressionKind::FieldAccessExpression:
|
||||
out << *GetFieldAccessExpression().aggregate << "."
|
||||
<< GetFieldAccessExpression().field;
|
||||
}
|
||||
case Expression::Kind::FieldAccessExpression: {
|
||||
const auto& access = cast<FieldAccessExpression>(*this);
|
||||
out << *access.Aggregate() << "." << access.Field();
|
||||
break;
|
||||
case ExpressionKind::TupleLiteral:
|
||||
}
|
||||
case Expression::Kind::TupleLiteral:
|
||||
out << "(";
|
||||
PrintFields(out, GetTupleLiteral().fields);
|
||||
PrintFields(out, cast<TupleLiteral>(*this).Fields());
|
||||
out << ")";
|
||||
break;
|
||||
case ExpressionKind::IntLiteral:
|
||||
out << GetIntLiteral();
|
||||
case Expression::Kind::IntLiteral:
|
||||
out << cast<IntLiteral>(*this).Val();
|
||||
break;
|
||||
case ExpressionKind::BoolLiteral:
|
||||
out << (GetBoolLiteral() ? "true" : "false");
|
||||
case Expression::Kind::BoolLiteral:
|
||||
out << (cast<BoolLiteral>(*this).Val() ? "true" : "false");
|
||||
break;
|
||||
case ExpressionKind::PrimitiveOperatorExpression: {
|
||||
case Expression::Kind::PrimitiveOperatorExpression: {
|
||||
out << "(";
|
||||
PrimitiveOperatorExpression op = GetPrimitiveOperatorExpression();
|
||||
if (op.arguments.size() == 0) {
|
||||
PrintOp(out, op.op);
|
||||
} else if (op.arguments.size() == 1) {
|
||||
PrintOp(out, op.op);
|
||||
out << " " << *op.arguments[0];
|
||||
} else if (op.arguments.size() == 2) {
|
||||
out << *op.arguments[0] << " ";
|
||||
PrintOp(out, op.op);
|
||||
out << " " << *op.arguments[1];
|
||||
PrimitiveOperatorExpression op = cast<PrimitiveOperatorExpression>(*this);
|
||||
if (op.Arguments().size() == 0) {
|
||||
PrintOp(out, op.Op());
|
||||
} else if (op.Arguments().size() == 1) {
|
||||
PrintOp(out, op.Op());
|
||||
out << " " << *op.Arguments()[0];
|
||||
} else if (op.Arguments().size() == 2) {
|
||||
out << *op.Arguments()[0] << " ";
|
||||
PrintOp(out, op.Op());
|
||||
out << " " << *op.Arguments()[1];
|
||||
}
|
||||
out << ")";
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::IdentifierExpression:
|
||||
out << GetIdentifierExpression().name;
|
||||
case Expression::Kind::IdentifierExpression:
|
||||
out << cast<IdentifierExpression>(*this).Name();
|
||||
break;
|
||||
case ExpressionKind::CallExpression:
|
||||
out << *GetCallExpression().function;
|
||||
if (GetCallExpression().argument->tag() == ExpressionKind::TupleLiteral) {
|
||||
out << *GetCallExpression().argument;
|
||||
case Expression::Kind::CallExpression: {
|
||||
const auto& call = cast<CallExpression>(*this);
|
||||
out << *call.Function();
|
||||
if (call.Argument()->Tag() == Expression::Kind::TupleLiteral) {
|
||||
out << *call.Argument();
|
||||
} else {
|
||||
out << "(" << *GetCallExpression().argument << ")";
|
||||
out << "(" << *call.Argument() << ")";
|
||||
}
|
||||
break;
|
||||
case ExpressionKind::BoolTypeLiteral:
|
||||
}
|
||||
case Expression::Kind::BoolTypeLiteral:
|
||||
out << "Bool";
|
||||
break;
|
||||
case ExpressionKind::IntTypeLiteral:
|
||||
case Expression::Kind::IntTypeLiteral:
|
||||
out << "i32";
|
||||
break;
|
||||
case ExpressionKind::TypeTypeLiteral:
|
||||
case Expression::Kind::TypeTypeLiteral:
|
||||
out << "Type";
|
||||
break;
|
||||
case ExpressionKind::ContinuationTypeLiteral:
|
||||
case Expression::Kind::ContinuationTypeLiteral:
|
||||
out << "Continuation";
|
||||
break;
|
||||
case ExpressionKind::FunctionTypeLiteral:
|
||||
out << "fn " << *GetFunctionTypeLiteral().parameter << " -> "
|
||||
<< *GetFunctionTypeLiteral().return_type;
|
||||
case Expression::Kind::FunctionTypeLiteral: {
|
||||
const auto& fn = cast<FunctionTypeLiteral>(*this);
|
||||
out << "fn " << *fn.Parameter() << " -> " << *fn.ReturnType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,43 @@
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
struct Expression;
|
||||
class Pattern;
|
||||
class Expression {
|
||||
public:
|
||||
enum class Kind {
|
||||
BoolTypeLiteral,
|
||||
BoolLiteral,
|
||||
CallExpression,
|
||||
FunctionTypeLiteral,
|
||||
FieldAccessExpression,
|
||||
IndexExpression,
|
||||
IntTypeLiteral,
|
||||
ContinuationTypeLiteral, // The type of a continuation value.
|
||||
IntLiteral,
|
||||
PrimitiveOperatorExpression,
|
||||
TupleLiteral,
|
||||
TypeTypeLiteral,
|
||||
IdentifierExpression,
|
||||
};
|
||||
|
||||
// Returns the enumerator corresponding to the most-derived type of this
|
||||
// object.
|
||||
auto Tag() const -> Kind { return tag; }
|
||||
|
||||
auto LineNumber() const -> int { return line_num; }
|
||||
|
||||
void Print(llvm::raw_ostream& out) const;
|
||||
LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
|
||||
|
||||
protected:
|
||||
// Constructs an Expression representing syntax at the given line number.
|
||||
// `tag` must be the enumerator corresponding to the most-derived type being
|
||||
// constructed.
|
||||
Expression(Kind tag, int line_num) : tag(tag), line_num(line_num) {}
|
||||
|
||||
private:
|
||||
const Kind tag;
|
||||
int line_num;
|
||||
};
|
||||
|
||||
// Converts paren_contents to an Expression, interpreting the parentheses as
|
||||
// grouping if their contents permit that interpretation, or as forming a
|
||||
@@ -44,22 +79,6 @@ struct FieldInitializer {
|
||||
const Expression* expression;
|
||||
};
|
||||
|
||||
enum class ExpressionKind {
|
||||
BoolTypeLiteral,
|
||||
BoolLiteral,
|
||||
CallExpression,
|
||||
FunctionTypeLiteral,
|
||||
FieldAccessExpression,
|
||||
IndexExpression,
|
||||
IntTypeLiteral,
|
||||
ContinuationTypeLiteral, // The type of a continuation value.
|
||||
IntLiteral,
|
||||
PrimitiveOperatorExpression,
|
||||
TupleLiteral,
|
||||
TypeTypeLiteral,
|
||||
IdentifierExpression,
|
||||
};
|
||||
|
||||
enum class Operator {
|
||||
Add,
|
||||
And,
|
||||
@@ -73,129 +92,213 @@ enum class Operator {
|
||||
Ptr,
|
||||
};
|
||||
|
||||
struct Expression;
|
||||
class IdentifierExpression : public Expression {
|
||||
public:
|
||||
explicit IdentifierExpression(int line_num, std::string name)
|
||||
: Expression(Kind::IdentifierExpression, line_num),
|
||||
name(std::move(name)) {}
|
||||
|
||||
struct IdentifierExpression {
|
||||
static constexpr ExpressionKind Kind = ExpressionKind::IdentifierExpression;
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::IdentifierExpression;
|
||||
}
|
||||
|
||||
auto Name() const -> const std::string& { return name; }
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct FieldAccessExpression {
|
||||
static constexpr ExpressionKind Kind = ExpressionKind::FieldAccessExpression;
|
||||
class FieldAccessExpression : public Expression {
|
||||
public:
|
||||
explicit FieldAccessExpression(int line_num, const Expression* aggregate,
|
||||
std::string field)
|
||||
: Expression(Kind::FieldAccessExpression, line_num),
|
||||
aggregate(aggregate),
|
||||
field(std::move(field)) {}
|
||||
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::FieldAccessExpression;
|
||||
}
|
||||
|
||||
auto Aggregate() const -> const Expression* { return aggregate; }
|
||||
auto Field() const -> const std::string& { return field; }
|
||||
|
||||
private:
|
||||
const Expression* aggregate;
|
||||
std::string field;
|
||||
};
|
||||
|
||||
struct IndexExpression {
|
||||
static constexpr ExpressionKind Kind = ExpressionKind::IndexExpression;
|
||||
class IndexExpression : public Expression {
|
||||
public:
|
||||
explicit IndexExpression(int line_num, const Expression* aggregate,
|
||||
const Expression* offset)
|
||||
: Expression(Kind::IndexExpression, line_num),
|
||||
aggregate(aggregate),
|
||||
offset(offset) {}
|
||||
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::IndexExpression;
|
||||
}
|
||||
|
||||
auto Aggregate() const -> const Expression* { return aggregate; }
|
||||
auto Offset() const -> const Expression* { return offset; }
|
||||
|
||||
private:
|
||||
const Expression* aggregate;
|
||||
const Expression* offset;
|
||||
};
|
||||
|
||||
struct IntLiteral {
|
||||
static constexpr ExpressionKind Kind = ExpressionKind::IntLiteral;
|
||||
int value;
|
||||
class IntLiteral : public Expression {
|
||||
public:
|
||||
explicit IntLiteral(int line_num, int val)
|
||||
: Expression(Kind::IntLiteral, line_num), val(val) {}
|
||||
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::IntLiteral;
|
||||
}
|
||||
|
||||
auto Val() const -> int { return val; }
|
||||
|
||||
private:
|
||||
int val;
|
||||
};
|
||||
|
||||
struct BoolLiteral {
|
||||
static constexpr ExpressionKind Kind = ExpressionKind::BoolLiteral;
|
||||
bool value;
|
||||
class BoolLiteral : public Expression {
|
||||
public:
|
||||
explicit BoolLiteral(int line_num, bool val)
|
||||
: Expression(Kind::BoolLiteral, line_num), val(val) {}
|
||||
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::BoolLiteral;
|
||||
}
|
||||
|
||||
auto Val() const -> bool { return val; }
|
||||
|
||||
private:
|
||||
bool val;
|
||||
};
|
||||
|
||||
struct TupleLiteral {
|
||||
static constexpr ExpressionKind Kind = ExpressionKind::TupleLiteral;
|
||||
class TupleLiteral : public Expression {
|
||||
public:
|
||||
explicit TupleLiteral(int line_num) : TupleLiteral(line_num, {}) {}
|
||||
|
||||
explicit TupleLiteral(int line_num, std::vector<FieldInitializer> fields)
|
||||
: Expression(Kind::TupleLiteral, line_num), fields(std::move(fields)) {}
|
||||
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::TupleLiteral;
|
||||
}
|
||||
|
||||
auto Fields() const -> const std::vector<FieldInitializer>& { return fields; }
|
||||
|
||||
private:
|
||||
std::vector<FieldInitializer> fields;
|
||||
};
|
||||
|
||||
struct PrimitiveOperatorExpression {
|
||||
static constexpr ExpressionKind Kind =
|
||||
ExpressionKind::PrimitiveOperatorExpression;
|
||||
class PrimitiveOperatorExpression : public Expression {
|
||||
public:
|
||||
explicit PrimitiveOperatorExpression(int line_num, Operator op,
|
||||
std::vector<const Expression*> arguments)
|
||||
: Expression(Kind::PrimitiveOperatorExpression, line_num),
|
||||
op(op),
|
||||
arguments(std::move(arguments)) {}
|
||||
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::PrimitiveOperatorExpression;
|
||||
}
|
||||
|
||||
auto Op() const -> Operator { return op; }
|
||||
auto Arguments() const -> const std::vector<const Expression*>& {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
private:
|
||||
Operator op;
|
||||
std::vector<const Expression*> arguments;
|
||||
};
|
||||
|
||||
struct CallExpression {
|
||||
static constexpr ExpressionKind Kind = ExpressionKind::CallExpression;
|
||||
class CallExpression : public Expression {
|
||||
public:
|
||||
explicit CallExpression(int line_num, const Expression* function,
|
||||
const Expression* argument)
|
||||
: Expression(Kind::CallExpression, line_num),
|
||||
function(function),
|
||||
argument(argument) {}
|
||||
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::CallExpression;
|
||||
}
|
||||
|
||||
auto Function() const -> const Expression* { return function; }
|
||||
auto Argument() const -> const Expression* { return argument; }
|
||||
|
||||
private:
|
||||
const Expression* function;
|
||||
const Expression* argument;
|
||||
};
|
||||
|
||||
struct FunctionTypeLiteral {
|
||||
static constexpr ExpressionKind Kind = ExpressionKind::FunctionTypeLiteral;
|
||||
class FunctionTypeLiteral : public Expression {
|
||||
public:
|
||||
explicit FunctionTypeLiteral(int line_num, const Expression* parameter,
|
||||
const Expression* return_type,
|
||||
bool is_omitted_return_type)
|
||||
: Expression(Kind::FunctionTypeLiteral, line_num),
|
||||
parameter(parameter),
|
||||
return_type(return_type),
|
||||
is_omitted_return_type(is_omitted_return_type) {}
|
||||
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::FunctionTypeLiteral;
|
||||
}
|
||||
|
||||
auto Parameter() const -> const Expression* { return parameter; }
|
||||
auto ReturnType() const -> const Expression* { return return_type; }
|
||||
auto IsOmittedReturnType() const -> bool { return is_omitted_return_type; }
|
||||
|
||||
private:
|
||||
const Expression* parameter;
|
||||
const Expression* return_type;
|
||||
bool is_omitted_return_type;
|
||||
};
|
||||
|
||||
struct BoolTypeLiteral {
|
||||
static constexpr ExpressionKind Kind = ExpressionKind::BoolTypeLiteral;
|
||||
};
|
||||
class BoolTypeLiteral : public Expression {
|
||||
public:
|
||||
explicit BoolTypeLiteral(int line_num)
|
||||
: Expression(Kind::BoolTypeLiteral, line_num) {}
|
||||
|
||||
struct IntTypeLiteral {
|
||||
static constexpr ExpressionKind Kind = ExpressionKind::IntTypeLiteral;
|
||||
};
|
||||
|
||||
struct ContinuationTypeLiteral {
|
||||
static constexpr ExpressionKind Kind =
|
||||
ExpressionKind::ContinuationTypeLiteral;
|
||||
};
|
||||
|
||||
struct TypeTypeLiteral {
|
||||
static constexpr ExpressionKind Kind = ExpressionKind::TypeTypeLiteral;
|
||||
};
|
||||
|
||||
struct Expression {
|
||||
static auto MakeIdentifierExpression(int line_num, std::string var)
|
||||
-> const Expression*;
|
||||
static auto MakeIntLiteral(int line_num, int i) -> const Expression*;
|
||||
static auto MakeBoolLiteral(int line_num, bool b) -> const Expression*;
|
||||
static auto MakePrimitiveOperatorExpression(
|
||||
int line_num, Operator op, std::vector<const Expression*> args)
|
||||
-> const Expression*;
|
||||
static auto MakeCallExpression(int line_num, const Expression* fun,
|
||||
const Expression* arg) -> const Expression*;
|
||||
static auto MakeFieldAccessExpression(int line_num, const Expression* exp,
|
||||
std::string field) -> const Expression*;
|
||||
static auto MakeTupleLiteral(int line_num, std::vector<FieldInitializer> args)
|
||||
-> const Expression*;
|
||||
static auto MakeIndexExpression(int line_num, const Expression* exp,
|
||||
const Expression* i) -> const Expression*;
|
||||
static auto MakeTypeTypeLiteral(int line_num) -> const Expression*;
|
||||
static auto MakeIntTypeLiteral(int line_num) -> const Expression*;
|
||||
static auto MakeBoolTypeLiteral(int line_num) -> const Expression*;
|
||||
static auto MakeFunctionTypeLiteral(int line_num, const Expression* parameter,
|
||||
const Expression* return_type,
|
||||
bool is_omitted_return_type)
|
||||
-> const Expression*;
|
||||
static auto MakeContinuationTypeLiteral(int line_num) -> const Expression*;
|
||||
|
||||
auto GetIdentifierExpression() const -> const IdentifierExpression&;
|
||||
auto GetFieldAccessExpression() const -> const FieldAccessExpression&;
|
||||
auto GetIndexExpression() const -> const IndexExpression&;
|
||||
auto GetIntLiteral() const -> int;
|
||||
auto GetBoolLiteral() const -> bool;
|
||||
auto GetTupleLiteral() const -> const TupleLiteral&;
|
||||
auto GetPrimitiveOperatorExpression() const
|
||||
-> const PrimitiveOperatorExpression&;
|
||||
auto GetCallExpression() const -> const CallExpression&;
|
||||
auto GetFunctionTypeLiteral() const -> const FunctionTypeLiteral&;
|
||||
|
||||
void Print(llvm::raw_ostream& out) const;
|
||||
LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); }
|
||||
|
||||
inline auto tag() const -> ExpressionKind {
|
||||
return std::visit([](const auto& t) { return t.Kind; }, value);
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::BoolTypeLiteral;
|
||||
}
|
||||
};
|
||||
|
||||
int line_num;
|
||||
class IntTypeLiteral : public Expression {
|
||||
public:
|
||||
explicit IntTypeLiteral(int line_num)
|
||||
: Expression(Kind::IntTypeLiteral, line_num) {}
|
||||
|
||||
private:
|
||||
std::variant<IdentifierExpression, FieldAccessExpression, IndexExpression,
|
||||
IntLiteral, BoolLiteral, TupleLiteral,
|
||||
PrimitiveOperatorExpression, CallExpression, FunctionTypeLiteral,
|
||||
BoolTypeLiteral, IntTypeLiteral, ContinuationTypeLiteral,
|
||||
TypeTypeLiteral>
|
||||
value;
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::IntTypeLiteral;
|
||||
}
|
||||
};
|
||||
|
||||
class ContinuationTypeLiteral : public Expression {
|
||||
public:
|
||||
explicit ContinuationTypeLiteral(int line_num)
|
||||
: Expression(Kind::ContinuationTypeLiteral, line_num) {}
|
||||
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::ContinuationTypeLiteral;
|
||||
}
|
||||
};
|
||||
|
||||
class TypeTypeLiteral : public Expression {
|
||||
public:
|
||||
explicit TypeTypeLiteral(int line_num)
|
||||
: Expression(Kind::TypeTypeLiteral, line_num) {}
|
||||
|
||||
static auto classof(const Expression* exp) -> bool {
|
||||
return exp->Tag() == Kind::TypeTypeLiteral;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Carbon
|
||||
|
||||
@@ -6,13 +6,16 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "executable_semantics/common/arena.h"
|
||||
#include "executable_semantics/syntax/paren_contents.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
||||
namespace Carbon {
|
||||
namespace {
|
||||
|
||||
using llvm::cast;
|
||||
using testing::ElementsAre;
|
||||
using testing::IsEmpty;
|
||||
|
||||
@@ -20,7 +23,7 @@ using testing::IsEmpty;
|
||||
// `IntLiteral`
|
||||
MATCHER_P(IntFieldNamed, name, "") {
|
||||
return arg.name == std::string(name) &&
|
||||
arg.expression->tag() == ExpressionKind::IntLiteral;
|
||||
arg.expression->Tag() == Expression::Kind::IntLiteral;
|
||||
}
|
||||
|
||||
TEST(ExpressionTest, EmptyAsExpression) {
|
||||
@@ -28,9 +31,9 @@ TEST(ExpressionTest, EmptyAsExpression) {
|
||||
.has_trailing_comma = false};
|
||||
const Expression* expression =
|
||||
ExpressionFromParenContents(/*line_num=*/1, contents);
|
||||
EXPECT_EQ(expression->line_num, 1);
|
||||
ASSERT_EQ(expression->tag(), ExpressionKind::TupleLiteral);
|
||||
EXPECT_THAT(expression->GetTupleLiteral().fields, IsEmpty());
|
||||
EXPECT_EQ(expression->LineNumber(), 1);
|
||||
ASSERT_EQ(expression->Tag(), Expression::Kind::TupleLiteral);
|
||||
EXPECT_THAT(cast<TupleLiteral>(*expression).Fields(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST(ExpressionTest, EmptyAsTuple) {
|
||||
@@ -38,9 +41,9 @@ TEST(ExpressionTest, EmptyAsTuple) {
|
||||
.has_trailing_comma = false};
|
||||
const Expression* tuple =
|
||||
TupleExpressionFromParenContents(/*line_num=*/1, contents);
|
||||
EXPECT_EQ(tuple->line_num, 1);
|
||||
ASSERT_EQ(tuple->tag(), ExpressionKind::TupleLiteral);
|
||||
EXPECT_THAT(tuple->GetTupleLiteral().fields, IsEmpty());
|
||||
EXPECT_EQ(tuple->LineNumber(), 1);
|
||||
ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral);
|
||||
EXPECT_THAT(cast<TupleLiteral>(*tuple).Fields(), IsEmpty());
|
||||
}
|
||||
|
||||
TEST(ExpressionTest, UnaryNoCommaAsExpression) {
|
||||
@@ -52,84 +55,86 @@ TEST(ExpressionTest, UnaryNoCommaAsExpression) {
|
||||
// ```
|
||||
ParenContents<Expression> contents = {
|
||||
.elements = {{.name = std::nullopt,
|
||||
.term = Expression::MakeIntLiteral(/*line_num=*/2, 42)}},
|
||||
.term = global_arena->New<IntLiteral>(/*line_num=*/2, 42)}},
|
||||
.has_trailing_comma = false};
|
||||
|
||||
const Expression* expression =
|
||||
ExpressionFromParenContents(/*line_num=*/1, contents);
|
||||
EXPECT_EQ(expression->line_num, 2);
|
||||
ASSERT_EQ(expression->tag(), ExpressionKind::IntLiteral);
|
||||
EXPECT_EQ(expression->LineNumber(), 2);
|
||||
ASSERT_EQ(expression->Tag(), Expression::Kind::IntLiteral);
|
||||
}
|
||||
|
||||
TEST(ExpressionTest, UnaryNoCommaAsTuple) {
|
||||
ParenContents<Expression> contents = {
|
||||
.elements = {{.name = std::nullopt,
|
||||
.term = Expression::MakeIntLiteral(/*line_num=*/2, 42)}},
|
||||
.term = global_arena->New<IntLiteral>(/*line_num=*/2, 42)}},
|
||||
.has_trailing_comma = false};
|
||||
|
||||
const Expression* tuple =
|
||||
TupleExpressionFromParenContents(/*line_num=*/1, contents);
|
||||
EXPECT_EQ(tuple->line_num, 1);
|
||||
ASSERT_EQ(tuple->tag(), ExpressionKind::TupleLiteral);
|
||||
EXPECT_THAT(tuple->GetTupleLiteral().fields, ElementsAre(IntFieldNamed("0")));
|
||||
EXPECT_EQ(tuple->LineNumber(), 1);
|
||||
ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral);
|
||||
EXPECT_THAT(cast<TupleLiteral>(*tuple).Fields(),
|
||||
ElementsAre(IntFieldNamed("0")));
|
||||
}
|
||||
|
||||
TEST(ExpressionTest, UnaryWithCommaAsExpression) {
|
||||
ParenContents<Expression> contents = {
|
||||
.elements = {{.name = std::nullopt,
|
||||
.term = Expression::MakeIntLiteral(/*line_num=*/2, 42)}},
|
||||
.term = global_arena->New<IntLiteral>(/*line_num=*/2, 42)}},
|
||||
.has_trailing_comma = true};
|
||||
|
||||
const Expression* expression =
|
||||
ExpressionFromParenContents(/*line_num=*/1, contents);
|
||||
EXPECT_EQ(expression->line_num, 1);
|
||||
ASSERT_EQ(expression->tag(), ExpressionKind::TupleLiteral);
|
||||
EXPECT_THAT(expression->GetTupleLiteral().fields,
|
||||
EXPECT_EQ(expression->LineNumber(), 1);
|
||||
ASSERT_EQ(expression->Tag(), Expression::Kind::TupleLiteral);
|
||||
EXPECT_THAT(cast<TupleLiteral>(*expression).Fields(),
|
||||
ElementsAre(IntFieldNamed("0")));
|
||||
}
|
||||
|
||||
TEST(ExpressionTest, UnaryWithCommaAsTuple) {
|
||||
ParenContents<Expression> contents = {
|
||||
.elements = {{.name = std::nullopt,
|
||||
.term = Expression::MakeIntLiteral(/*line_num=*/2, 42)}},
|
||||
.term = global_arena->New<IntLiteral>(/*line_num=*/2, 42)}},
|
||||
.has_trailing_comma = true};
|
||||
|
||||
const Expression* tuple =
|
||||
TupleExpressionFromParenContents(/*line_num=*/1, contents);
|
||||
EXPECT_EQ(tuple->line_num, 1);
|
||||
ASSERT_EQ(tuple->tag(), ExpressionKind::TupleLiteral);
|
||||
EXPECT_THAT(tuple->GetTupleLiteral().fields, ElementsAre(IntFieldNamed("0")));
|
||||
EXPECT_EQ(tuple->LineNumber(), 1);
|
||||
ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral);
|
||||
EXPECT_THAT(cast<TupleLiteral>(*tuple).Fields(),
|
||||
ElementsAre(IntFieldNamed("0")));
|
||||
}
|
||||
|
||||
TEST(ExpressionTest, BinaryAsExpression) {
|
||||
ParenContents<Expression> contents = {
|
||||
.elements = {{.name = std::nullopt,
|
||||
.term = Expression::MakeIntLiteral(/*line_num=*/2, 42)},
|
||||
.term = global_arena->New<IntLiteral>(/*line_num=*/2, 42)},
|
||||
{.name = std::nullopt,
|
||||
.term = Expression::MakeIntLiteral(/*line_num=*/3, 42)}},
|
||||
.term = global_arena->New<IntLiteral>(/*line_num=*/3, 42)}},
|
||||
.has_trailing_comma = true};
|
||||
|
||||
const Expression* expression =
|
||||
ExpressionFromParenContents(/*line_num=*/1, contents);
|
||||
EXPECT_EQ(expression->line_num, 1);
|
||||
ASSERT_EQ(expression->tag(), ExpressionKind::TupleLiteral);
|
||||
EXPECT_THAT(expression->GetTupleLiteral().fields,
|
||||
EXPECT_EQ(expression->LineNumber(), 1);
|
||||
ASSERT_EQ(expression->Tag(), Expression::Kind::TupleLiteral);
|
||||
EXPECT_THAT(cast<TupleLiteral>(*expression).Fields(),
|
||||
ElementsAre(IntFieldNamed("0"), IntFieldNamed("1")));
|
||||
}
|
||||
|
||||
TEST(ExpressionTest, BinaryAsTuple) {
|
||||
ParenContents<Expression> contents = {
|
||||
.elements = {{.name = std::nullopt,
|
||||
.term = Expression::MakeIntLiteral(/*line_num=*/2, 42)},
|
||||
.term = global_arena->New<IntLiteral>(/*line_num=*/2, 42)},
|
||||
{.name = std::nullopt,
|
||||
.term = Expression::MakeIntLiteral(/*line_num=*/3, 42)}},
|
||||
.term = global_arena->New<IntLiteral>(/*line_num=*/3, 42)}},
|
||||
.has_trailing_comma = true};
|
||||
|
||||
const Expression* tuple =
|
||||
TupleExpressionFromParenContents(/*line_num=*/1, contents);
|
||||
EXPECT_EQ(tuple->line_num, 1);
|
||||
ASSERT_EQ(tuple->tag(), ExpressionKind::TupleLiteral);
|
||||
EXPECT_THAT(tuple->GetTupleLiteral().fields,
|
||||
EXPECT_EQ(tuple->LineNumber(), 1);
|
||||
ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral);
|
||||
EXPECT_THAT(cast<TupleLiteral>(*tuple).Fields(),
|
||||
ElementsAre(IntFieldNamed("0"), IntFieldNamed("1")));
|
||||
}
|
||||
|
||||
|
||||
@@ -55,9 +55,9 @@ void Pattern::Print(llvm::raw_ostream& out) const {
|
||||
}
|
||||
|
||||
TuplePattern::TuplePattern(const Expression* tuple_literal)
|
||||
: Pattern(Kind::TuplePattern, tuple_literal->line_num) {
|
||||
const auto& tuple = tuple_literal->GetTupleLiteral();
|
||||
for (const FieldInitializer& init : tuple.fields) {
|
||||
: Pattern(Kind::TuplePattern, tuple_literal->LineNumber()) {
|
||||
const auto& tuple = cast<TupleLiteral>(*tuple_literal);
|
||||
for (const FieldInitializer& init : tuple.Fields()) {
|
||||
fields.push_back(Field(
|
||||
init.name, global_arena->New<ExpressionPattern>(init.expression)));
|
||||
}
|
||||
@@ -85,13 +85,13 @@ AlternativePattern::AlternativePattern(int line_num,
|
||||
const Expression* alternative,
|
||||
const TuplePattern* arguments)
|
||||
: Pattern(Kind::AlternativePattern, line_num), arguments(arguments) {
|
||||
if (alternative->tag() != ExpressionKind::FieldAccessExpression) {
|
||||
FATAL_PROGRAM_ERROR(alternative->line_num)
|
||||
if (alternative->Tag() != Expression::Kind::FieldAccessExpression) {
|
||||
FATAL_PROGRAM_ERROR(alternative->LineNumber())
|
||||
<< "Alternative pattern must have the form of a field access.";
|
||||
}
|
||||
const auto& field_access = alternative->GetFieldAccessExpression();
|
||||
choice_type = field_access.aggregate;
|
||||
alternative_name = field_access.field;
|
||||
const auto& field_access = cast<FieldAccessExpression>(*alternative);
|
||||
choice_type = field_access.Aggregate();
|
||||
alternative_name = field_access.Field();
|
||||
}
|
||||
|
||||
auto ParenExpressionToParenPattern(const ParenContents<Expression>& contents)
|
||||
|
||||
@@ -111,7 +111,7 @@ class TuplePattern : public Pattern {
|
||||
// Converts tuple_literal to a TuplePattern, by wrapping each field in an
|
||||
// ExpressionPattern.
|
||||
//
|
||||
// REQUIRES: tuple_literal->Tag() == ExpressionKind::TupleLiteral
|
||||
// REQUIRES: tuple_literal->Tag() == Expression::Kind::TupleLiteral
|
||||
explicit TuplePattern(const Expression* tuple_literal);
|
||||
|
||||
static auto classof(const Pattern* pattern) -> bool {
|
||||
@@ -182,7 +182,7 @@ class AlternativePattern : public Pattern {
|
||||
class ExpressionPattern : public Pattern {
|
||||
public:
|
||||
ExpressionPattern(const Expression* expression)
|
||||
: Pattern(Kind::ExpressionPattern, expression->line_num),
|
||||
: Pattern(Kind::ExpressionPattern, expression->LineNumber()),
|
||||
expression(expression) {}
|
||||
|
||||
static auto classof(const Pattern* pattern) -> bool {
|
||||
|
||||
@@ -123,7 +123,7 @@ auto Statement::MakeReturn(int line_num, const Expression* exp,
|
||||
s->line_num = line_num;
|
||||
if (exp == nullptr) {
|
||||
CHECK(is_omitted_exp);
|
||||
exp = Expression::MakeTupleLiteral(line_num, {});
|
||||
exp = global_arena->New<TupleLiteral>(line_num);
|
||||
}
|
||||
s->value = Return({.exp = exp, .is_omitted_exp = is_omitted_exp});
|
||||
return s;
|
||||
|
||||
@@ -243,12 +243,12 @@ void DeallocateLocals(int line_num, Frame* frame) {
|
||||
void CreateTuple(Frame* frame, Action* act, const Expression* exp) {
|
||||
// { { (v1,...,vn) :: C, E, F} :: S, H}
|
||||
// -> { { `(v1,...,vn) :: C, E, F} :: S, H}
|
||||
const auto& tup_lit = exp->GetTupleLiteral();
|
||||
CHECK(act->Results().size() == tup_lit.fields.size());
|
||||
const auto& tup_lit = cast<TupleLiteral>(*exp);
|
||||
CHECK(act->Results().size() == tup_lit.Fields().size());
|
||||
std::vector<TupleElement> elements;
|
||||
for (size_t i = 0; i < act->Results().size(); ++i) {
|
||||
elements.push_back(
|
||||
{.name = tup_lit.fields[i].name, .value = act->Results()[i]});
|
||||
{.name = tup_lit.Fields()[i].name, .value = act->Results()[i]});
|
||||
}
|
||||
|
||||
const Value* tv = global_arena->New<TupleValue>(std::move(elements));
|
||||
@@ -407,50 +407,51 @@ void StepLvalue() {
|
||||
if (tracing_output) {
|
||||
llvm::outs() << "--- step lvalue " << *exp << " --->\n";
|
||||
}
|
||||
switch (exp->tag()) {
|
||||
case ExpressionKind::IdentifierExpression: {
|
||||
switch (exp->Tag()) {
|
||||
case Expression::Kind::IdentifierExpression: {
|
||||
// { {x :: C, E, F} :: S, H}
|
||||
// -> { {E(x) :: C, E, F} :: S, H}
|
||||
std::optional<Address> pointer =
|
||||
CurrentEnv(state).Get(exp->GetIdentifierExpression().name);
|
||||
CurrentEnv(state).Get(cast<IdentifierExpression>(*exp).Name());
|
||||
if (!pointer) {
|
||||
FATAL_RUNTIME_ERROR(exp->line_num)
|
||||
<< "could not find `" << exp->GetIdentifierExpression().name << "`";
|
||||
FATAL_RUNTIME_ERROR(exp->LineNumber())
|
||||
<< "could not find `" << cast<IdentifierExpression>(*exp).Name()
|
||||
<< "`";
|
||||
}
|
||||
const Value* v = global_arena->New<PointerValue>(*pointer);
|
||||
frame->todo.Pop();
|
||||
frame->todo.Push(global_arena->New<ValAction>(v));
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::FieldAccessExpression: {
|
||||
case Expression::Kind::FieldAccessExpression: {
|
||||
if (act->Pos() == 0) {
|
||||
// { {e.f :: C, E, F} :: S, H}
|
||||
// -> { e :: [].f :: C, E, F} :: S, H}
|
||||
frame->todo.Push(global_arena->New<LValAction>(
|
||||
exp->GetFieldAccessExpression().aggregate));
|
||||
cast<FieldAccessExpression>(*exp).Aggregate()));
|
||||
act->IncrementPos();
|
||||
} else {
|
||||
// { v :: [].f :: C, E, F} :: S, H}
|
||||
// -> { { &v.f :: C, E, F} :: S, H }
|
||||
Address aggregate = cast<PointerValue>(*act->Results()[0]).Val();
|
||||
Address field =
|
||||
aggregate.SubobjectAddress(exp->GetFieldAccessExpression().field);
|
||||
Address field = aggregate.SubobjectAddress(
|
||||
cast<FieldAccessExpression>(*exp).Field());
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(
|
||||
global_arena->New<PointerValue>(field)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::IndexExpression: {
|
||||
case Expression::Kind::IndexExpression: {
|
||||
if (act->Pos() == 0) {
|
||||
// { {e[i] :: C, E, F} :: S, H}
|
||||
// -> { e :: [][i] :: C, E, F} :: S, H}
|
||||
frame->todo.Push(
|
||||
global_arena->New<LValAction>(exp->GetIndexExpression().aggregate));
|
||||
frame->todo.Push(global_arena->New<LValAction>(
|
||||
cast<IndexExpression>(*exp).Aggregate()));
|
||||
act->IncrementPos();
|
||||
} else if (act->Pos() == 1) {
|
||||
frame->todo.Push(global_arena->New<ExpressionAction>(
|
||||
exp->GetIndexExpression().offset));
|
||||
cast<IndexExpression>(*exp).Offset()));
|
||||
act->IncrementPos();
|
||||
} else if (act->Pos() == 2) {
|
||||
// { v :: [][i] :: C, E, F} :: S, H}
|
||||
@@ -465,21 +466,21 @@ void StepLvalue() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::TupleLiteral: {
|
||||
case Expression::Kind::TupleLiteral: {
|
||||
if (act->Pos() == 0) {
|
||||
// { {(f1=e1,...) :: C, E, F} :: S, H}
|
||||
// -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H}
|
||||
const Expression* e1 = exp->GetTupleLiteral().fields[0].expression;
|
||||
const Expression* e1 = cast<TupleLiteral>(*exp).Fields()[0].expression;
|
||||
frame->todo.Push(global_arena->New<LValAction>(e1));
|
||||
act->IncrementPos();
|
||||
} else if (act->Pos() !=
|
||||
static_cast<int>(exp->GetTupleLiteral().fields.size())) {
|
||||
static_cast<int>(cast<TupleLiteral>(*exp).Fields().size())) {
|
||||
// { { vk :: (f1=v1,..., fk=[],fk+1=ek+1,...) :: C, E, F} :: S,
|
||||
// H}
|
||||
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
|
||||
// H}
|
||||
const Expression* elt =
|
||||
exp->GetTupleLiteral().fields[act->Pos()].expression;
|
||||
cast<TupleLiteral>(*exp).Fields()[act->Pos()].expression;
|
||||
frame->todo.Push(global_arena->New<LValAction>(elt));
|
||||
act->IncrementPos();
|
||||
} else {
|
||||
@@ -487,15 +488,15 @@ void StepLvalue() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::IntLiteral:
|
||||
case ExpressionKind::BoolLiteral:
|
||||
case ExpressionKind::CallExpression:
|
||||
case ExpressionKind::PrimitiveOperatorExpression:
|
||||
case ExpressionKind::IntTypeLiteral:
|
||||
case ExpressionKind::BoolTypeLiteral:
|
||||
case ExpressionKind::TypeTypeLiteral:
|
||||
case ExpressionKind::FunctionTypeLiteral:
|
||||
case ExpressionKind::ContinuationTypeLiteral: {
|
||||
case Expression::Kind::IntLiteral:
|
||||
case Expression::Kind::BoolLiteral:
|
||||
case Expression::Kind::CallExpression:
|
||||
case Expression::Kind::PrimitiveOperatorExpression:
|
||||
case Expression::Kind::IntTypeLiteral:
|
||||
case Expression::Kind::BoolTypeLiteral:
|
||||
case Expression::Kind::TypeTypeLiteral:
|
||||
case Expression::Kind::FunctionTypeLiteral:
|
||||
case Expression::Kind::ContinuationTypeLiteral: {
|
||||
FATAL_RUNTIME_ERROR_NO_LINE()
|
||||
<< "Can't treat expression as lvalue: " << *exp;
|
||||
}
|
||||
@@ -511,17 +512,17 @@ void StepExp() {
|
||||
if (tracing_output) {
|
||||
llvm::outs() << "--- step exp " << *exp << " --->\n";
|
||||
}
|
||||
switch (exp->tag()) {
|
||||
case ExpressionKind::IndexExpression: {
|
||||
switch (exp->Tag()) {
|
||||
case Expression::Kind::IndexExpression: {
|
||||
if (act->Pos() == 0) {
|
||||
// { { e[i] :: C, E, F} :: S, H}
|
||||
// -> { { e :: [][i] :: C, E, F} :: S, H}
|
||||
frame->todo.Push(global_arena->New<ExpressionAction>(
|
||||
exp->GetIndexExpression().aggregate));
|
||||
cast<IndexExpression>(*exp).Aggregate()));
|
||||
act->IncrementPos();
|
||||
} else if (act->Pos() == 1) {
|
||||
frame->todo.Push(global_arena->New<ExpressionAction>(
|
||||
exp->GetIndexExpression().offset));
|
||||
cast<IndexExpression>(*exp).Offset()));
|
||||
act->IncrementPos();
|
||||
} else if (act->Pos() == 2) {
|
||||
auto tuple = act->Results()[0];
|
||||
@@ -547,25 +548,26 @@ void StepExp() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::TupleLiteral: {
|
||||
case Expression::Kind::TupleLiteral: {
|
||||
if (act->Pos() == 0) {
|
||||
if (exp->GetTupleLiteral().fields.size() > 0) {
|
||||
if (cast<TupleLiteral>(*exp).Fields().size() > 0) {
|
||||
// { {(f1=e1,...) :: C, E, F} :: S, H}
|
||||
// -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H}
|
||||
const Expression* e1 = exp->GetTupleLiteral().fields[0].expression;
|
||||
const Expression* e1 =
|
||||
cast<TupleLiteral>(*exp).Fields()[0].expression;
|
||||
frame->todo.Push(global_arena->New<ExpressionAction>(e1));
|
||||
act->IncrementPos();
|
||||
} else {
|
||||
CreateTuple(frame, act, exp);
|
||||
}
|
||||
} else if (act->Pos() !=
|
||||
static_cast<int>(exp->GetTupleLiteral().fields.size())) {
|
||||
static_cast<int>(cast<TupleLiteral>(*exp).Fields().size())) {
|
||||
// { { vk :: (f1=v1,..., fk=[],fk+1=ek+1,...) :: C, E, F} :: S,
|
||||
// H}
|
||||
// -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S,
|
||||
// H}
|
||||
const Expression* elt =
|
||||
exp->GetTupleLiteral().fields[act->Pos()].expression;
|
||||
cast<TupleLiteral>(*exp).Fields()[act->Pos()].expression;
|
||||
frame->todo.Push(global_arena->New<ExpressionAction>(elt));
|
||||
act->IncrementPos();
|
||||
} else {
|
||||
@@ -573,123 +575,122 @@ void StepExp() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::FieldAccessExpression: {
|
||||
case Expression::Kind::FieldAccessExpression: {
|
||||
const auto& access = cast<FieldAccessExpression>(*exp);
|
||||
if (act->Pos() == 0) {
|
||||
// { { e.f :: C, E, F} :: S, H}
|
||||
// -> { { e :: [].f :: C, E, F} :: S, H}
|
||||
frame->todo.Push(global_arena->New<ExpressionAction>(
|
||||
exp->GetFieldAccessExpression().aggregate));
|
||||
frame->todo.Push(
|
||||
global_arena->New<ExpressionAction>(access.Aggregate()));
|
||||
act->IncrementPos();
|
||||
} else {
|
||||
// { { v :: [].f :: C, E, F} :: S, H}
|
||||
// -> { { v_f :: C, E, F} : S, H}
|
||||
const Value* element = act->Results()[0]->GetField(
|
||||
FieldPath(exp->GetFieldAccessExpression().field), exp->line_num);
|
||||
FieldPath(access.Field()), exp->LineNumber());
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(element));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::IdentifierExpression: {
|
||||
case Expression::Kind::IdentifierExpression: {
|
||||
CHECK(act->Pos() == 0);
|
||||
const auto& ident = cast<IdentifierExpression>(*exp);
|
||||
// { {x :: C, E, F} :: S, H} -> { {H(E(x)) :: C, E, F} :: S, H}
|
||||
std::optional<Address> pointer =
|
||||
CurrentEnv(state).Get(exp->GetIdentifierExpression().name);
|
||||
std::optional<Address> pointer = CurrentEnv(state).Get(ident.Name());
|
||||
if (!pointer) {
|
||||
FATAL_RUNTIME_ERROR(exp->line_num)
|
||||
<< "could not find `" << exp->GetIdentifierExpression().name << "`";
|
||||
FATAL_RUNTIME_ERROR(exp->LineNumber())
|
||||
<< "could not find `" << ident.Name() << "`";
|
||||
}
|
||||
const Value* pointee = state->heap.Read(*pointer, exp->line_num);
|
||||
const Value* pointee = state->heap.Read(*pointer, exp->LineNumber());
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(pointee));
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::IntLiteral:
|
||||
case Expression::Kind::IntLiteral:
|
||||
CHECK(act->Pos() == 0);
|
||||
// { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H}
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(
|
||||
global_arena->New<IntValue>(exp->GetIntLiteral())));
|
||||
global_arena->New<IntValue>(cast<IntLiteral>(*exp).Val())));
|
||||
break;
|
||||
case ExpressionKind::BoolLiteral:
|
||||
case Expression::Kind::BoolLiteral:
|
||||
CHECK(act->Pos() == 0);
|
||||
// { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H}
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(
|
||||
global_arena->New<BoolValue>(exp->GetBoolLiteral())));
|
||||
global_arena->New<BoolValue>(cast<BoolLiteral>(*exp).Val())));
|
||||
break;
|
||||
case ExpressionKind::PrimitiveOperatorExpression:
|
||||
if (act->Pos() !=
|
||||
static_cast<int>(
|
||||
exp->GetPrimitiveOperatorExpression().arguments.size())) {
|
||||
case Expression::Kind::PrimitiveOperatorExpression: {
|
||||
const auto& op = cast<PrimitiveOperatorExpression>(*exp);
|
||||
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}
|
||||
const Expression* arg =
|
||||
exp->GetPrimitiveOperatorExpression().arguments[act->Pos()];
|
||||
const Expression* arg = op.Arguments()[act->Pos()];
|
||||
frame->todo.Push(global_arena->New<ExpressionAction>(arg));
|
||||
act->IncrementPos();
|
||||
} else {
|
||||
// { {v :: op(vs,[]) :: C, E, F} :: S, H}
|
||||
// -> { {eval_prim(op, (vs,v)) :: C, E, F} :: S, H}
|
||||
const Value* v = EvalPrim(exp->GetPrimitiveOperatorExpression().op,
|
||||
act->Results(), exp->line_num);
|
||||
const Value* v = EvalPrim(op.Op(), act->Results(), exp->LineNumber());
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(v));
|
||||
}
|
||||
break;
|
||||
case ExpressionKind::CallExpression:
|
||||
}
|
||||
case Expression::Kind::CallExpression:
|
||||
if (act->Pos() == 0) {
|
||||
// { {e1(e2) :: C, E, F} :: S, H}
|
||||
// -> { {e1 :: [](e2) :: C, E, F} :: S, H}
|
||||
frame->todo.Push(global_arena->New<ExpressionAction>(
|
||||
exp->GetCallExpression().function));
|
||||
cast<CallExpression>(*exp).Function()));
|
||||
act->IncrementPos();
|
||||
} else if (act->Pos() == 1) {
|
||||
// { { v :: [](e) :: C, E, F} :: S, H}
|
||||
// -> { { e :: v([]) :: C, E, F} :: S, H}
|
||||
frame->todo.Push(global_arena->New<ExpressionAction>(
|
||||
exp->GetCallExpression().argument));
|
||||
cast<CallExpression>(*exp).Argument()));
|
||||
act->IncrementPos();
|
||||
} else if (act->Pos() == 2) {
|
||||
// { { v2 :: v1([]) :: C, E, F} :: S, H}
|
||||
// -> { {C',E',F'} :: {C, E, F} :: S, H}
|
||||
frame->todo.Pop(1);
|
||||
CallFunction(exp->line_num, act->Results(), state);
|
||||
CallFunction(exp->LineNumber(), act->Results(), state);
|
||||
} else {
|
||||
FATAL() << "in handle_value with Call pos " << act->Pos();
|
||||
}
|
||||
break;
|
||||
case ExpressionKind::IntTypeLiteral: {
|
||||
case Expression::Kind::IntTypeLiteral: {
|
||||
CHECK(act->Pos() == 0);
|
||||
const Value* v = global_arena->New<IntType>();
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(v));
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::BoolTypeLiteral: {
|
||||
case Expression::Kind::BoolTypeLiteral: {
|
||||
CHECK(act->Pos() == 0);
|
||||
const Value* v = global_arena->New<BoolType>();
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(v));
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::TypeTypeLiteral: {
|
||||
case Expression::Kind::TypeTypeLiteral: {
|
||||
CHECK(act->Pos() == 0);
|
||||
const Value* v = global_arena->New<TypeType>();
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(v));
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::FunctionTypeLiteral: {
|
||||
case Expression::Kind::FunctionTypeLiteral: {
|
||||
if (act->Pos() == 0) {
|
||||
frame->todo.Push(global_arena->New<ExpressionAction>(
|
||||
exp->GetFunctionTypeLiteral().parameter));
|
||||
cast<FunctionTypeLiteral>(*exp).Parameter()));
|
||||
act->IncrementPos();
|
||||
} else if (act->Pos() == 1) {
|
||||
// { { pt :: fn [] -> e :: C, E, F} :: S, H}
|
||||
// -> { { e :: fn pt -> []) :: C, E, F} :: S, H}
|
||||
frame->todo.Push(global_arena->New<ExpressionAction>(
|
||||
exp->GetFunctionTypeLiteral().return_type));
|
||||
cast<FunctionTypeLiteral>(*exp).ReturnType()));
|
||||
act->IncrementPos();
|
||||
} else if (act->Pos() == 2) {
|
||||
// { { rt :: fn pt -> [] :: C, E, F} :: S, H}
|
||||
@@ -702,14 +703,14 @@ void StepExp() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::ContinuationTypeLiteral: {
|
||||
case Expression::Kind::ContinuationTypeLiteral: {
|
||||
CHECK(act->Pos() == 0);
|
||||
const Value* v = global_arena->New<ContinuationType>();
|
||||
frame->todo.Pop(1);
|
||||
frame->todo.Push(global_arena->New<ValAction>(v));
|
||||
break;
|
||||
}
|
||||
} // switch (exp->tag)
|
||||
} // switch (exp->Tag)
|
||||
}
|
||||
|
||||
void StepPattern() {
|
||||
@@ -1124,7 +1125,7 @@ void StepStmt() {
|
||||
Action* ignore_result = global_arena->New<StatementAction>(
|
||||
Statement::MakeExpressionStatement(
|
||||
stmt->line_num,
|
||||
Expression::MakeTupleLiteral(stmt->line_num, {})));
|
||||
global_arena->New<TupleLiteral>(stmt->line_num)));
|
||||
frame->todo.Push(ignore_result);
|
||||
// Push the continuation onto the current stack.
|
||||
const std::vector<Frame*>& continuation_vector =
|
||||
@@ -1190,9 +1191,9 @@ auto InterpProgram(const std::list<const Declaration*>& fs) -> int {
|
||||
}
|
||||
InitGlobals(fs);
|
||||
|
||||
const Expression* arg = Expression::MakeTupleLiteral(0, {});
|
||||
const Expression* call_main = Expression::MakeCallExpression(
|
||||
0, Expression::MakeIdentifierExpression(0, "main"), arg);
|
||||
const Expression* arg = global_arena->New<TupleLiteral>(0);
|
||||
const Expression* call_main = global_arena->New<CallExpression>(
|
||||
0, global_arena->New<IdentifierExpression>(0, "main"), arg);
|
||||
auto todo = Stack<Action*>(global_arena->New<ExpressionAction>(call_main));
|
||||
auto* scope = global_arena->New<Scope>(globals, std::list<std::string>());
|
||||
auto* frame = global_arena->New<Frame>("top", Stack(scope), todo);
|
||||
|
||||
@@ -46,16 +46,16 @@ static void ExpectPointerType(int line_num, const std::string& context,
|
||||
static auto ReifyType(const Value* t, int line_num) -> const Expression* {
|
||||
switch (t->Tag()) {
|
||||
case Value::Kind::IntType:
|
||||
return Expression::MakeIntTypeLiteral(0);
|
||||
return global_arena->New<IntTypeLiteral>(0);
|
||||
case Value::Kind::BoolType:
|
||||
return Expression::MakeBoolTypeLiteral(0);
|
||||
return global_arena->New<BoolTypeLiteral>(0);
|
||||
case Value::Kind::TypeType:
|
||||
return Expression::MakeTypeTypeLiteral(0);
|
||||
return global_arena->New<TypeTypeLiteral>(0);
|
||||
case Value::Kind::ContinuationType:
|
||||
return Expression::MakeContinuationTypeLiteral(0);
|
||||
return global_arena->New<ContinuationTypeLiteral>(0);
|
||||
case Value::Kind::FunctionType: {
|
||||
const auto& fn_type = cast<FunctionType>(*t);
|
||||
return Expression::MakeFunctionTypeLiteral(
|
||||
return global_arena->New<FunctionTypeLiteral>(
|
||||
0, ReifyType(fn_type.Param(), line_num),
|
||||
ReifyType(fn_type.Ret(), line_num),
|
||||
/*is_omitted_return_type=*/false);
|
||||
@@ -66,20 +66,21 @@ static auto ReifyType(const Value* t, int line_num) -> const Expression* {
|
||||
args.push_back(
|
||||
FieldInitializer(field.name, ReifyType(field.value, line_num)));
|
||||
}
|
||||
return Expression::MakeTupleLiteral(0, args);
|
||||
return global_arena->New<TupleLiteral>(0, args);
|
||||
}
|
||||
case Value::Kind::StructType:
|
||||
return Expression::MakeIdentifierExpression(0,
|
||||
cast<StructType>(*t).Name());
|
||||
return global_arena->New<IdentifierExpression>(
|
||||
0, cast<StructType>(*t).Name());
|
||||
case Value::Kind::ChoiceType:
|
||||
return Expression::MakeIdentifierExpression(0,
|
||||
cast<ChoiceType>(*t).Name());
|
||||
return global_arena->New<IdentifierExpression>(
|
||||
0, cast<ChoiceType>(*t).Name());
|
||||
case Value::Kind::PointerType:
|
||||
return Expression::MakePrimitiveOperatorExpression(
|
||||
return global_arena->New<PrimitiveOperatorExpression>(
|
||||
0, Operator::Ptr,
|
||||
{ReifyType(cast<PointerType>(*t).Type(), line_num)});
|
||||
std::vector<const Expression*>(
|
||||
{ReifyType(cast<PointerType>(*t).Type(), line_num)}));
|
||||
case Value::Kind::VariableType:
|
||||
return Expression::MakeIdentifierExpression(
|
||||
return global_arena->New<IdentifierExpression>(
|
||||
0, cast<VariableType>(*t).Name());
|
||||
default:
|
||||
FATAL() << "expected a type, not " << *t;
|
||||
@@ -245,202 +246,204 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
|
||||
if (tracing_output) {
|
||||
llvm::outs() << "checking expression " << *e << "\n";
|
||||
}
|
||||
switch (e->tag()) {
|
||||
case ExpressionKind::IndexExpression: {
|
||||
auto res = TypeCheckExp(e->GetIndexExpression().aggregate, types, values);
|
||||
switch (e->Tag()) {
|
||||
case Expression::Kind::IndexExpression: {
|
||||
const auto& index = cast<IndexExpression>(*e);
|
||||
auto res = TypeCheckExp(index.Aggregate(), types, values);
|
||||
auto t = res.type;
|
||||
switch (t->Tag()) {
|
||||
case Value::Kind::TupleValue: {
|
||||
auto i =
|
||||
cast<IntValue>(*InterpExp(values, e->GetIndexExpression().offset))
|
||||
.Val();
|
||||
auto i = cast<IntValue>(*InterpExp(values, index.Offset())).Val();
|
||||
std::string f = std::to_string(i);
|
||||
const Value* field_t = cast<TupleValue>(*t).FindField(f);
|
||||
if (field_t == nullptr) {
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
FATAL_COMPILATION_ERROR(e->LineNumber())
|
||||
<< "field " << f << " is not in the tuple " << *t;
|
||||
}
|
||||
auto new_e = Expression::MakeIndexExpression(
|
||||
e->line_num, res.exp, Expression::MakeIntLiteral(e->line_num, i));
|
||||
auto new_e = global_arena->New<IndexExpression>(
|
||||
e->LineNumber(), res.exp,
|
||||
global_arena->New<IntLiteral>(e->LineNumber(), i));
|
||||
return TCExpression(new_e, field_t, res.types);
|
||||
}
|
||||
default:
|
||||
FATAL_COMPILATION_ERROR(e->line_num) << "expected a tuple";
|
||||
FATAL_COMPILATION_ERROR(e->LineNumber()) << "expected a tuple";
|
||||
}
|
||||
}
|
||||
case ExpressionKind::TupleLiteral: {
|
||||
case Expression::Kind::TupleLiteral: {
|
||||
std::vector<FieldInitializer> new_args;
|
||||
std::vector<TupleElement> arg_types;
|
||||
auto new_types = types;
|
||||
int i = 0;
|
||||
for (auto arg = e->GetTupleLiteral().fields.begin();
|
||||
arg != e->GetTupleLiteral().fields.end(); ++arg, ++i) {
|
||||
auto arg_res = TypeCheckExp(arg->expression, new_types, values);
|
||||
for (const auto& arg : cast<TupleLiteral>(*e).Fields()) {
|
||||
auto arg_res = TypeCheckExp(arg.expression, new_types, values);
|
||||
new_types = arg_res.types;
|
||||
new_args.push_back(FieldInitializer(arg->name, arg_res.exp));
|
||||
arg_types.push_back({.name = arg->name, .value = arg_res.type});
|
||||
new_args.push_back(FieldInitializer(arg.name, arg_res.exp));
|
||||
arg_types.push_back({.name = arg.name, .value = arg_res.type});
|
||||
}
|
||||
auto tuple_e = Expression::MakeTupleLiteral(e->line_num, new_args);
|
||||
auto tuple_e = global_arena->New<TupleLiteral>(e->LineNumber(), new_args);
|
||||
auto tuple_t = global_arena->New<TupleValue>(std::move(arg_types));
|
||||
return TCExpression(tuple_e, tuple_t, new_types);
|
||||
}
|
||||
case ExpressionKind::FieldAccessExpression: {
|
||||
auto res =
|
||||
TypeCheckExp(e->GetFieldAccessExpression().aggregate, types, values);
|
||||
case Expression::Kind::FieldAccessExpression: {
|
||||
const auto& access = cast<FieldAccessExpression>(*e);
|
||||
auto res = TypeCheckExp(access.Aggregate(), types, values);
|
||||
auto t = res.type;
|
||||
switch (t->Tag()) {
|
||||
case Value::Kind::StructType: {
|
||||
const auto& t_struct = cast<StructType>(*t);
|
||||
// Search for a field
|
||||
for (auto& field : t_struct.Fields()) {
|
||||
if (e->GetFieldAccessExpression().field == field.first) {
|
||||
const Expression* new_e = Expression::MakeFieldAccessExpression(
|
||||
e->line_num, res.exp, e->GetFieldAccessExpression().field);
|
||||
if (access.Field() == field.first) {
|
||||
const Expression* new_e =
|
||||
global_arena->New<FieldAccessExpression>(
|
||||
e->LineNumber(), res.exp, access.Field());
|
||||
return TCExpression(new_e, field.second, res.types);
|
||||
}
|
||||
}
|
||||
// Search for a method
|
||||
for (auto& method : t_struct.Methods()) {
|
||||
if (e->GetFieldAccessExpression().field == method.first) {
|
||||
const Expression* new_e = Expression::MakeFieldAccessExpression(
|
||||
e->line_num, res.exp, e->GetFieldAccessExpression().field);
|
||||
if (access.Field() == method.first) {
|
||||
const Expression* new_e =
|
||||
global_arena->New<FieldAccessExpression>(
|
||||
e->LineNumber(), res.exp, access.Field());
|
||||
return TCExpression(new_e, method.second, res.types);
|
||||
}
|
||||
}
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
FATAL_COMPILATION_ERROR(e->LineNumber())
|
||||
<< "struct " << t_struct.Name() << " does not have a field named "
|
||||
<< e->GetFieldAccessExpression().field;
|
||||
<< access.Field();
|
||||
}
|
||||
case Value::Kind::TupleValue: {
|
||||
const auto& tup = cast<TupleValue>(*t);
|
||||
for (const TupleElement& field : tup.Elements()) {
|
||||
if (e->GetFieldAccessExpression().field == field.name) {
|
||||
auto new_e = Expression::MakeFieldAccessExpression(
|
||||
e->line_num, res.exp, e->GetFieldAccessExpression().field);
|
||||
if (access.Field() == field.name) {
|
||||
auto new_e = global_arena->New<FieldAccessExpression>(
|
||||
e->LineNumber(), res.exp, access.Field());
|
||||
return TCExpression(new_e, field.value, res.types);
|
||||
}
|
||||
}
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
FATAL_COMPILATION_ERROR(e->LineNumber())
|
||||
<< "tuple " << tup << " does not have a field named "
|
||||
<< e->GetFieldAccessExpression().field;
|
||||
<< access.Field();
|
||||
}
|
||||
case Value::Kind::ChoiceType: {
|
||||
const auto& choice = cast<ChoiceType>(*t);
|
||||
for (const auto& vt : choice.Alternatives()) {
|
||||
if (e->GetFieldAccessExpression().field == vt.first) {
|
||||
const Expression* new_e = Expression::MakeFieldAccessExpression(
|
||||
e->line_num, res.exp, e->GetFieldAccessExpression().field);
|
||||
if (access.Field() == vt.first) {
|
||||
const Expression* new_e =
|
||||
global_arena->New<FieldAccessExpression>(
|
||||
e->LineNumber(), res.exp, access.Field());
|
||||
auto fun_ty = global_arena->New<FunctionType>(
|
||||
std::vector<GenericBinding>(), vt.second, t);
|
||||
return TCExpression(new_e, fun_ty, res.types);
|
||||
}
|
||||
}
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
FATAL_COMPILATION_ERROR(e->LineNumber())
|
||||
<< "choice " << choice.Name() << " does not have a field named "
|
||||
<< e->GetFieldAccessExpression().field;
|
||||
<< access.Field();
|
||||
}
|
||||
default:
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
FATAL_COMPILATION_ERROR(e->LineNumber())
|
||||
<< "field access, expected a struct\n"
|
||||
<< *e;
|
||||
}
|
||||
}
|
||||
case ExpressionKind::IdentifierExpression: {
|
||||
std::optional<const Value*> type =
|
||||
types.Get(e->GetIdentifierExpression().name);
|
||||
case Expression::Kind::IdentifierExpression: {
|
||||
const auto& ident = cast<IdentifierExpression>(*e);
|
||||
std::optional<const Value*> type = types.Get(ident.Name());
|
||||
if (type) {
|
||||
return TCExpression(e, *type, types);
|
||||
} else {
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
<< "could not find `" << e->GetIdentifierExpression().name << "`";
|
||||
FATAL_COMPILATION_ERROR(e->LineNumber())
|
||||
<< "could not find `" << ident.Name() << "`";
|
||||
}
|
||||
}
|
||||
case ExpressionKind::IntLiteral:
|
||||
case Expression::Kind::IntLiteral:
|
||||
return TCExpression(e, global_arena->New<IntType>(), types);
|
||||
case ExpressionKind::BoolLiteral:
|
||||
case Expression::Kind::BoolLiteral:
|
||||
return TCExpression(e, global_arena->New<BoolType>(), types);
|
||||
case ExpressionKind::PrimitiveOperatorExpression: {
|
||||
case Expression::Kind::PrimitiveOperatorExpression: {
|
||||
const auto& op = cast<PrimitiveOperatorExpression>(*e);
|
||||
std::vector<const Expression*> es;
|
||||
std::vector<const Value*> ts;
|
||||
auto new_types = types;
|
||||
for (const Expression* argument :
|
||||
e->GetPrimitiveOperatorExpression().arguments) {
|
||||
for (const Expression* argument : op.Arguments()) {
|
||||
auto res = TypeCheckExp(argument, types, values);
|
||||
new_types = res.types;
|
||||
es.push_back(res.exp);
|
||||
ts.push_back(res.type);
|
||||
}
|
||||
auto new_e = Expression::MakePrimitiveOperatorExpression(
|
||||
e->line_num, e->GetPrimitiveOperatorExpression().op, es);
|
||||
switch (e->GetPrimitiveOperatorExpression().op) {
|
||||
auto new_e = global_arena->New<PrimitiveOperatorExpression>(
|
||||
e->LineNumber(), op.Op(), es);
|
||||
switch (op.Op()) {
|
||||
case Operator::Neg:
|
||||
ExpectType(e->line_num, "negation", global_arena->New<IntType>(),
|
||||
ExpectType(e->LineNumber(), "negation", global_arena->New<IntType>(),
|
||||
ts[0]);
|
||||
return TCExpression(new_e, global_arena->New<IntType>(), new_types);
|
||||
case Operator::Add:
|
||||
ExpectType(e->line_num, "addition(1)", global_arena->New<IntType>(),
|
||||
ts[0]);
|
||||
ExpectType(e->line_num, "addition(2)", global_arena->New<IntType>(),
|
||||
ts[1]);
|
||||
ExpectType(e->LineNumber(), "addition(1)",
|
||||
global_arena->New<IntType>(), ts[0]);
|
||||
ExpectType(e->LineNumber(), "addition(2)",
|
||||
global_arena->New<IntType>(), ts[1]);
|
||||
return TCExpression(new_e, global_arena->New<IntType>(), new_types);
|
||||
case Operator::Sub:
|
||||
ExpectType(e->line_num, "subtraction(1)",
|
||||
ExpectType(e->LineNumber(), "subtraction(1)",
|
||||
global_arena->New<IntType>(), ts[0]);
|
||||
ExpectType(e->line_num, "subtraction(2)",
|
||||
ExpectType(e->LineNumber(), "subtraction(2)",
|
||||
global_arena->New<IntType>(), ts[1]);
|
||||
return TCExpression(new_e, global_arena->New<IntType>(), new_types);
|
||||
case Operator::Mul:
|
||||
ExpectType(e->line_num, "multiplication(1)",
|
||||
ExpectType(e->LineNumber(), "multiplication(1)",
|
||||
global_arena->New<IntType>(), ts[0]);
|
||||
ExpectType(e->line_num, "multiplication(2)",
|
||||
ExpectType(e->LineNumber(), "multiplication(2)",
|
||||
global_arena->New<IntType>(), ts[1]);
|
||||
return TCExpression(new_e, global_arena->New<IntType>(), new_types);
|
||||
case Operator::And:
|
||||
ExpectType(e->line_num, "&&(1)", global_arena->New<BoolType>(),
|
||||
ExpectType(e->LineNumber(), "&&(1)", global_arena->New<BoolType>(),
|
||||
ts[0]);
|
||||
ExpectType(e->line_num, "&&(2)", global_arena->New<BoolType>(),
|
||||
ExpectType(e->LineNumber(), "&&(2)", global_arena->New<BoolType>(),
|
||||
ts[1]);
|
||||
return TCExpression(new_e, global_arena->New<BoolType>(), new_types);
|
||||
case Operator::Or:
|
||||
ExpectType(e->line_num, "||(1)", global_arena->New<BoolType>(),
|
||||
ExpectType(e->LineNumber(), "||(1)", global_arena->New<BoolType>(),
|
||||
ts[0]);
|
||||
ExpectType(e->line_num, "||(2)", global_arena->New<BoolType>(),
|
||||
ExpectType(e->LineNumber(), "||(2)", global_arena->New<BoolType>(),
|
||||
ts[1]);
|
||||
return TCExpression(new_e, global_arena->New<BoolType>(), new_types);
|
||||
case Operator::Not:
|
||||
ExpectType(e->line_num, "!", global_arena->New<BoolType>(), ts[0]);
|
||||
ExpectType(e->LineNumber(), "!", global_arena->New<BoolType>(),
|
||||
ts[0]);
|
||||
return TCExpression(new_e, global_arena->New<BoolType>(), new_types);
|
||||
case Operator::Eq:
|
||||
ExpectType(e->line_num, "==", ts[0], ts[1]);
|
||||
ExpectType(e->LineNumber(), "==", ts[0], ts[1]);
|
||||
return TCExpression(new_e, global_arena->New<BoolType>(), new_types);
|
||||
case Operator::Deref:
|
||||
ExpectPointerType(e->line_num, "*", ts[0]);
|
||||
ExpectPointerType(e->LineNumber(), "*", ts[0]);
|
||||
return TCExpression(new_e, cast<PointerType>(*ts[0]).Type(),
|
||||
new_types);
|
||||
case Operator::Ptr:
|
||||
ExpectType(e->line_num, "*", global_arena->New<TypeType>(), ts[0]);
|
||||
ExpectType(e->LineNumber(), "*", global_arena->New<TypeType>(),
|
||||
ts[0]);
|
||||
return TCExpression(new_e, global_arena->New<TypeType>(), new_types);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::CallExpression: {
|
||||
auto fun_res =
|
||||
TypeCheckExp(e->GetCallExpression().function, types, values);
|
||||
case Expression::Kind::CallExpression: {
|
||||
const auto& call = cast<CallExpression>(*e);
|
||||
auto fun_res = TypeCheckExp(call.Function(), types, values);
|
||||
switch (fun_res.type->Tag()) {
|
||||
case Value::Kind::FunctionType: {
|
||||
const auto& fun_t = cast<FunctionType>(*fun_res.type);
|
||||
auto arg_res = TypeCheckExp(e->GetCallExpression().argument,
|
||||
fun_res.types, values);
|
||||
auto arg_res = TypeCheckExp(call.Argument(), fun_res.types, values);
|
||||
auto parameter_type = fun_t.Param();
|
||||
auto return_type = fun_t.Ret();
|
||||
if (!fun_t.Deduced().empty()) {
|
||||
auto deduced_args = ArgumentDeduction(e->line_num, TypeEnv(),
|
||||
auto deduced_args = ArgumentDeduction(e->LineNumber(), TypeEnv(),
|
||||
parameter_type, arg_res.type);
|
||||
for (auto& deduced_param : fun_t.Deduced()) {
|
||||
// TODO: change the following to a CHECK once the real checking
|
||||
// has been added to the type checking of function signatures.
|
||||
if (!deduced_args.Get(deduced_param.name)) {
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
FATAL_COMPILATION_ERROR(e->LineNumber())
|
||||
<< "could not deduce type argument for type parameter "
|
||||
<< deduced_param.name;
|
||||
}
|
||||
@@ -448,35 +451,37 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values)
|
||||
parameter_type = Substitute(deduced_args, parameter_type);
|
||||
return_type = Substitute(deduced_args, return_type);
|
||||
} else {
|
||||
ExpectType(e->line_num, "call", parameter_type, arg_res.type);
|
||||
ExpectType(e->LineNumber(), "call", parameter_type, arg_res.type);
|
||||
}
|
||||
auto new_e = Expression::MakeCallExpression(e->line_num, fun_res.exp,
|
||||
arg_res.exp);
|
||||
auto new_e = global_arena->New<CallExpression>(
|
||||
e->LineNumber(), fun_res.exp, arg_res.exp);
|
||||
return TCExpression(new_e, return_type, arg_res.types);
|
||||
}
|
||||
default: {
|
||||
FATAL_COMPILATION_ERROR(e->line_num)
|
||||
FATAL_COMPILATION_ERROR(e->LineNumber())
|
||||
<< "in call, expected a function\n"
|
||||
<< *e;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::FunctionTypeLiteral: {
|
||||
auto pt = InterpExp(values, e->GetFunctionTypeLiteral().parameter);
|
||||
auto rt = InterpExp(values, e->GetFunctionTypeLiteral().return_type);
|
||||
auto new_e = Expression::MakeFunctionTypeLiteral(
|
||||
e->line_num, ReifyType(pt, e->line_num), ReifyType(rt, e->line_num),
|
||||
case Expression::Kind::FunctionTypeLiteral: {
|
||||
const auto& fn = cast<FunctionTypeLiteral>(*e);
|
||||
auto pt = InterpExp(values, fn.Parameter());
|
||||
auto rt = InterpExp(values, fn.ReturnType());
|
||||
auto new_e = global_arena->New<FunctionTypeLiteral>(
|
||||
e->LineNumber(), ReifyType(pt, e->LineNumber()),
|
||||
ReifyType(rt, e->LineNumber()),
|
||||
/*is_omitted_return_type=*/false);
|
||||
return TCExpression(new_e, global_arena->New<TypeType>(), types);
|
||||
}
|
||||
case ExpressionKind::IntTypeLiteral:
|
||||
case Expression::Kind::IntTypeLiteral:
|
||||
return TCExpression(e, global_arena->New<TypeType>(), types);
|
||||
case ExpressionKind::BoolTypeLiteral:
|
||||
case Expression::Kind::BoolTypeLiteral:
|
||||
return TCExpression(e, global_arena->New<TypeType>(), types);
|
||||
case ExpressionKind::TypeTypeLiteral:
|
||||
case Expression::Kind::TypeTypeLiteral:
|
||||
return TCExpression(e, global_arena->New<TypeType>(), types);
|
||||
case ExpressionKind::ContinuationTypeLiteral:
|
||||
case Expression::Kind::ContinuationTypeLiteral:
|
||||
return TCExpression(e, global_arena->New<TypeType>(), types);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,71 +211,71 @@ input: declaration_list
|
||||
;
|
||||
expression:
|
||||
identifier
|
||||
{ $$ = Expression::MakeIdentifierExpression(yylineno, $1); }
|
||||
{ $$ = global_arena->New<IdentifierExpression>(yylineno, $1); }
|
||||
| expression designator
|
||||
{ $$ = Expression::MakeFieldAccessExpression(yylineno, $1, $2); }
|
||||
{ $$ = global_arena->New<FieldAccessExpression>(yylineno, $1, $2); }
|
||||
| expression "[" expression "]"
|
||||
{ $$ = Expression::MakeIndexExpression(yylineno, $1, $3); }
|
||||
{ $$ = global_arena->New<IndexExpression>(yylineno, $1, $3); }
|
||||
| integer_literal
|
||||
{ $$ = Expression::MakeIntLiteral(yylineno, $1); }
|
||||
{ $$ = global_arena->New<IntLiteral>(yylineno, $1); }
|
||||
| TRUE
|
||||
{ $$ = Expression::MakeBoolLiteral(yylineno, true); }
|
||||
{ $$ = global_arena->New<BoolLiteral>(yylineno, true); }
|
||||
| FALSE
|
||||
{ $$ = Expression::MakeBoolLiteral(yylineno, false); }
|
||||
{ $$ = global_arena->New<BoolLiteral>(yylineno, false); }
|
||||
| sized_type_literal
|
||||
{
|
||||
int val;
|
||||
CHECK(llvm::to_integer(llvm::StringRef($1).substr(1), val));
|
||||
CHECK($1[0] == 'i' && val == 32) << "Only i32 is supported for now: " << $1;
|
||||
$$ = Expression::MakeIntTypeLiteral(yylineno);
|
||||
$$ = global_arena->New<IntTypeLiteral>(yylineno);
|
||||
}
|
||||
| BOOL
|
||||
{ $$ = Expression::MakeBoolTypeLiteral(yylineno); }
|
||||
{ $$ = global_arena->New<BoolTypeLiteral>(yylineno); }
|
||||
| TYPE
|
||||
{ $$ = Expression::MakeTypeTypeLiteral(yylineno); }
|
||||
{ $$ = global_arena->New<TypeTypeLiteral>(yylineno); }
|
||||
| CONTINUATION_TYPE
|
||||
{ $$ = Expression::MakeContinuationTypeLiteral(yylineno); }
|
||||
{ $$ = global_arena->New<ContinuationTypeLiteral>(yylineno); }
|
||||
| paren_expression { $$ = $1; }
|
||||
| expression EQUAL_EQUAL expression
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::Eq, {$1, $3}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::Eq, std::vector<const Expression*>({$1, $3})); }
|
||||
| expression "+" expression
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::Add, {$1, $3}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::Add, std::vector<const Expression*>({$1, $3})); }
|
||||
| expression "-" expression
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::Sub, {$1, $3}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::Sub, std::vector<const Expression*>({$1, $3})); }
|
||||
| expression BINARY_STAR expression
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::Mul, {$1, $3}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::Mul, std::vector<const Expression*>({$1, $3})); }
|
||||
| expression AND expression
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::And, {$1, $3}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::And, std::vector<const Expression*>({$1, $3})); }
|
||||
| expression OR expression
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::Or, {$1, $3}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::Or, std::vector<const Expression*>({$1, $3})); }
|
||||
| NOT expression
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::Not, {$2}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::Not, std::vector<const Expression*>({$2})); }
|
||||
| "-" expression %prec UNARY_MINUS
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::Neg, {$2}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::Neg, std::vector<const Expression*>({$2})); }
|
||||
| PREFIX_STAR expression
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::Deref, {$2}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::Deref, std::vector<const Expression*>({$2})); }
|
||||
| UNARY_STAR expression %prec PREFIX_STAR
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::Deref, {$2}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::Deref, std::vector<const Expression*>({$2})); }
|
||||
| expression tuple
|
||||
{ $$ = Expression::MakeCallExpression(yylineno, $1, $2); }
|
||||
{ $$ = global_arena->New<CallExpression>(yylineno, $1, $2); }
|
||||
| expression POSTFIX_STAR
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::Ptr, {$1}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::Ptr, std::vector<const Expression*>({$1})); }
|
||||
| expression UNARY_STAR
|
||||
{ $$ = Expression::MakePrimitiveOperatorExpression(
|
||||
yylineno, Operator::Ptr, {$1}); }
|
||||
{ $$ = global_arena->New<PrimitiveOperatorExpression>(
|
||||
yylineno, Operator::Ptr, std::vector<const Expression*>({$1})); }
|
||||
| FNTY tuple return_type
|
||||
{ $$ = Expression::MakeFunctionTypeLiteral(
|
||||
{ $$ = global_arena->New<FunctionTypeLiteral>(
|
||||
yylineno, $2, $3.first, $3.second); }
|
||||
;
|
||||
designator: "." identifier { $$ = $2; }
|
||||
@@ -454,7 +454,7 @@ optional_else:
|
||||
;
|
||||
return_expression:
|
||||
// Empty
|
||||
{ $$ = {Expression::MakeTupleLiteral(yylineno, {}), true}; }
|
||||
{ $$ = {global_arena->New<TupleLiteral>(yylineno), true}; }
|
||||
| expression
|
||||
{ $$ = {$1, false}; }
|
||||
;
|
||||
@@ -470,7 +470,7 @@ block:
|
||||
;
|
||||
return_type:
|
||||
// Empty
|
||||
{ $$ = {Expression::MakeTupleLiteral(yylineno, {}), true}; }
|
||||
{ $$ = {global_arena->New<TupleLiteral>(yylineno), true}; }
|
||||
| ARROW expression %prec FNARROW
|
||||
{ $$ = {$2, false}; }
|
||||
;
|
||||
@@ -544,7 +544,7 @@ alternative:
|
||||
| identifier
|
||||
{
|
||||
$$ = std::pair<std::string, const Expression*>(
|
||||
$1, Expression::MakeTupleLiteral(yylineno, {}));
|
||||
$1, global_arena->New<TupleLiteral>(yylineno));
|
||||
}
|
||||
;
|
||||
alternative_list:
|
||||
|
||||
Reference in New Issue
Block a user