From 8924f5620b21523fb01aaa3b86cd6c3bcdf3d2b2 Mon Sep 17 00:00:00 2001 From: "Jeremy G. Siek" Date: Tue, 27 Apr 2021 14:29:13 -0400 Subject: [PATCH] Private unions (#492) * changed union of Statement to be private * changed the union in Expression to be private * changed union in Value to be private * changed AST constructors to be static methods * updates to syntax unit tests --- executable_semantics/ast/expression.cpp | 155 +++++--- executable_semantics/ast/expression.h | 160 ++++---- executable_semantics/ast/statement.cpp | 140 +++++-- executable_semantics/ast/statement.h | 192 ++++++---- .../interpreter/interpreter.cpp | 339 +++++++++-------- .../interpreter/typecheck.cpp | 349 ++++++++++-------- executable_semantics/interpreter/value.cpp | 207 +++++++---- executable_semantics/interpreter/value.h | 210 ++++++----- .../syntax/paren_contents.cpp | 3 +- .../syntax/paren_contents_test.cpp | 48 +-- executable_semantics/syntax/parser.ypp | 82 ++-- 11 files changed, 1105 insertions(+), 780 deletions(-) diff --git a/executable_semantics/ast/expression.cpp b/executable_semantics/ast/expression.cpp index bd469a73a447..20c256c96c44 100644 --- a/executable_semantics/ast/expression.cpp +++ b/executable_semantics/ast/expression.cpp @@ -4,32 +4,83 @@ #include "executable_semantics/ast/expression.h" +#include #include namespace Carbon { -auto MakeTypeType(int line_num) -> const Expression* { +Variable Expression::GetVariable() const { + assert(tag == ExpressionKind::Variable); + return u.variable; +} + +FieldAccess Expression::GetFieldAccess() const { + assert(tag == ExpressionKind::GetField); + return u.get_field; +} + +Index Expression::GetIndex() const { + assert(tag == ExpressionKind::Index); + return u.index; +} + +PatternVariable Expression::GetPatternVariable() const { + assert(tag == ExpressionKind::PatternVariable); + return u.pattern_variable; +} + +int Expression::GetInteger() const { + assert(tag == ExpressionKind::Integer); + return u.integer; +} + +bool Expression::GetBoolean() const { + assert(tag == ExpressionKind::Boolean); + return u.boolean; +} + +Tuple Expression::GetTuple() const { + assert(tag == ExpressionKind::Tuple); + return u.tuple; +} + +PrimitiveOperator Expression::GetPrimitiveOperator() const { + assert(tag == ExpressionKind::PrimitiveOp); + return u.primitive_op; +} + +Call Expression::GetCall() const { + assert(tag == ExpressionKind::Call); + return u.call; +} + +FunctionType Expression::GetFunctionType() const { + assert(tag == ExpressionKind::FunctionT); + return u.function_type; +} + +auto Expression::MakeTypeType(int line_num) -> const Expression* { auto* t = new Expression(); t->tag = ExpressionKind::TypeT; t->line_num = line_num; return t; } -auto MakeIntType(int line_num) -> const Expression* { +auto Expression::MakeIntType(int line_num) -> const Expression* { auto* t = new Expression(); t->tag = ExpressionKind::IntT; t->line_num = line_num; return t; } -auto MakeBoolType(int line_num) -> const Expression* { +auto Expression::MakeBoolType(int line_num) -> const Expression* { auto* t = new Expression(); t->tag = ExpressionKind::BoolT; t->line_num = line_num; return t; } -auto MakeAutoType(int line_num) -> const Expression* { +auto Expression::MakeAutoType(int line_num) -> const Expression* { auto* t = new Expression(); t->tag = ExpressionKind::AutoT; t->line_num = line_num; @@ -37,15 +88,15 @@ auto MakeAutoType(int line_num) -> const Expression* { } // Returns a Continuation type AST node at the given source location. -auto MakeContinuationType(int line_num) -> const Expression* { +auto Expression::MakeContinuationType(int line_num) -> const Expression* { auto* type = new Expression(); type->tag = ExpressionKind::ContinuationT; type->line_num = line_num; return type; } -auto MakeFunType(int line_num, const Expression* param, const Expression* ret) - -> const Expression* { +auto Expression::MakeFunType(int line_num, const Expression* param, + const Expression* ret) -> const Expression* { auto* t = new Expression(); t->tag = ExpressionKind::FunctionT; t->line_num = line_num; @@ -54,7 +105,7 @@ auto MakeFunType(int line_num, const Expression* param, const Expression* ret) return t; } -auto MakeVar(int line_num, std::string var) -> const Expression* { +auto Expression::MakeVar(int line_num, std::string var) -> const Expression* { auto* v = new Expression(); v->line_num = line_num; v->tag = ExpressionKind::Variable; @@ -62,8 +113,8 @@ auto MakeVar(int line_num, std::string var) -> const Expression* { return v; } -auto MakeVarPat(int line_num, std::string var, const Expression* type) - -> const Expression* { +auto Expression::MakeVarPat(int line_num, std::string var, + const Expression* type) -> const Expression* { auto* v = new Expression(); v->line_num = line_num; v->tag = ExpressionKind::PatternVariable; @@ -72,7 +123,7 @@ auto MakeVarPat(int line_num, std::string var, const Expression* type) return v; } -auto MakeInt(int line_num, int i) -> const Expression* { +auto Expression::MakeInt(int line_num, int i) -> const Expression* { auto* e = new Expression(); e->line_num = line_num; e->tag = ExpressionKind::Integer; @@ -80,7 +131,7 @@ auto MakeInt(int line_num, int i) -> const Expression* { return e; } -auto MakeBool(int line_num, bool b) -> const Expression* { +auto Expression::MakeBool(int line_num, bool b) -> const Expression* { auto* e = new Expression(); e->line_num = line_num; e->tag = ExpressionKind::Boolean; @@ -88,8 +139,9 @@ auto MakeBool(int line_num, bool b) -> const Expression* { return e; } -auto MakeOp(int line_num, enum Operator op, - std::vector* args) -> const Expression* { +auto Expression::MakeOp(int line_num, enum Operator op, + std::vector* args) + -> const Expression* { auto* e = new Expression(); e->line_num = line_num; e->tag = ExpressionKind::PrimitiveOp; @@ -98,7 +150,7 @@ auto MakeOp(int line_num, enum Operator op, return e; } -auto MakeUnOp(int line_num, enum Operator op, const Expression* arg) +auto Expression::MakeUnOp(int line_num, enum Operator op, const Expression* arg) -> const Expression* { auto* e = new Expression(); e->line_num = line_num; @@ -110,8 +162,9 @@ auto MakeUnOp(int line_num, enum Operator op, const Expression* arg) return e; } -auto MakeBinOp(int line_num, enum Operator op, const Expression* arg1, - const Expression* arg2) -> const Expression* { +auto Expression::MakeBinOp(int line_num, enum Operator op, + const Expression* arg1, const Expression* arg2) + -> const Expression* { auto* e = new Expression(); e->line_num = line_num; e->tag = ExpressionKind::PrimitiveOp; @@ -123,8 +176,8 @@ auto MakeBinOp(int line_num, enum Operator op, const Expression* arg1, return e; } -auto MakeCall(int line_num, const Expression* fun, const Expression* arg) - -> const Expression* { +auto Expression::MakeCall(int line_num, const Expression* fun, + const Expression* arg) -> const Expression* { auto* e = new Expression(); e->line_num = line_num; e->tag = ExpressionKind::Call; @@ -133,8 +186,8 @@ auto MakeCall(int line_num, const Expression* fun, const Expression* arg) return e; } -auto MakeGetField(int line_num, const Expression* exp, std::string field) - -> const Expression* { +auto Expression::MakeGetField(int line_num, const Expression* exp, + std::string field) -> const Expression* { auto* e = new Expression(); e->line_num = line_num; e->tag = ExpressionKind::GetField; @@ -143,7 +196,7 @@ auto MakeGetField(int line_num, const Expression* exp, std::string field) return e; } -auto MakeTuple(int line_num, std::vector* args) +auto Expression::MakeTuple(int line_num, std::vector* args) -> const Expression* { auto* e = new Expression(); e->line_num = line_num; @@ -171,7 +224,7 @@ auto MakeTuple(int line_num, std::vector* args) // Create an AST node for an empty tuple. // TODO(geoffromer): remove this and rewrite its callers to use // `MakeTuple(line_num, {})`, once that works. -auto MakeUnit(int line_num) -> const Expression* { +auto Expression::MakeUnit(int line_num) -> const Expression* { auto* unit = new Expression(); unit->line_num = line_num; unit->tag = ExpressionKind::Tuple; @@ -180,8 +233,8 @@ auto MakeUnit(int line_num) -> const Expression* { return unit; } -auto MakeIndex(int line_num, const Expression* exp, const Expression* i) - -> const Expression* { +auto Expression::MakeIndex(int line_num, const Expression* exp, + const Expression* i) -> const Expression* { auto* e = new Expression(); e->line_num = line_num; e->tag = ExpressionKind::Index; @@ -230,63 +283,65 @@ static void PrintFields(std::vector* fields) { void PrintExp(const Expression* e) { switch (e->tag) { case ExpressionKind::Index: - PrintExp(e->u.index.aggregate); + PrintExp(e->GetIndex().aggregate); std::cout << "["; - PrintExp(e->u.index.offset); + PrintExp(e->GetIndex().offset); std::cout << "]"; break; case ExpressionKind::GetField: - PrintExp(e->u.get_field.aggregate); + PrintExp(e->GetFieldAccess().aggregate); std::cout << "."; - std::cout << *e->u.get_field.field; + std::cout << *e->GetFieldAccess().field; break; case ExpressionKind::Tuple: std::cout << "("; - PrintFields(e->u.tuple.fields); + PrintFields(e->GetTuple().fields); std::cout << ")"; break; case ExpressionKind::Integer: - std::cout << e->u.integer; + std::cout << e->GetInteger(); break; case ExpressionKind::Boolean: std::cout << std::boolalpha; - std::cout << e->u.boolean; + std::cout << e->GetBoolean(); break; - case ExpressionKind::PrimitiveOp: + case ExpressionKind::PrimitiveOp: { std::cout << "("; - if (e->u.primitive_op.arguments->size() == 0) { - PrintOp(e->u.primitive_op.op); - } else if (e->u.primitive_op.arguments->size() == 1) { - PrintOp(e->u.primitive_op.op); + PrimitiveOperator op = e->GetPrimitiveOperator(); + if (op.arguments->size() == 0) { + PrintOp(op.op); + } else if (op.arguments->size() == 1) { + PrintOp(op.op); std::cout << " "; - auto iter = e->u.primitive_op.arguments->begin(); + auto iter = op.arguments->begin(); PrintExp(*iter); - } else if (e->u.primitive_op.arguments->size() == 2) { - auto iter = e->u.primitive_op.arguments->begin(); + } else if (op.arguments->size() == 2) { + auto iter = op.arguments->begin(); PrintExp(*iter); std::cout << " "; - PrintOp(e->u.primitive_op.op); + PrintOp(op.op); std::cout << " "; ++iter; PrintExp(*iter); } std::cout << ")"; break; + } case ExpressionKind::Variable: - std::cout << *e->u.variable.name; + std::cout << *e->GetVariable().name; break; case ExpressionKind::PatternVariable: - PrintExp(e->u.pattern_variable.type); + PrintExp(e->GetPatternVariable().type); std::cout << ": "; - std::cout << *e->u.pattern_variable.name; + std::cout << *e->GetPatternVariable().name; break; case ExpressionKind::Call: - PrintExp(e->u.call.function); - if (e->u.call.argument->tag == ExpressionKind::Tuple) { - PrintExp(e->u.call.argument); + PrintExp(e->GetCall().function); + if (e->GetCall().argument->tag == ExpressionKind::Tuple) { + PrintExp(e->GetCall().argument); } else { std::cout << "("; - PrintExp(e->u.call.argument); + PrintExp(e->GetCall().argument); std::cout << ")"; } break; @@ -307,9 +362,9 @@ void PrintExp(const Expression* e) { break; case ExpressionKind::FunctionT: std::cout << "fn "; - PrintExp(e->u.function_type.parameter); + PrintExp(e->GetFunctionType().parameter); std::cout << " -> "; - PrintExp(e->u.function_type.return_type); + PrintExp(e->GetFunctionType().return_type); break; } } diff --git a/executable_semantics/ast/expression.h b/executable_semantics/ast/expression.h index 18e2e34bbd4c..8588fa0c46ff 100644 --- a/executable_semantics/ast/expression.h +++ b/executable_semantics/ast/expression.h @@ -49,86 +49,104 @@ enum class Operator { Sub, }; +struct Expression; + +struct Variable { + std::string* name; +}; + +struct FieldAccess { + const Expression* aggregate; + std::string* field; +}; + +struct Index { + const Expression* aggregate; + const Expression* offset; +}; + +struct PatternVariable { + std::string* name; + const Expression* type; +}; + +struct Tuple { + std::vector* fields; +}; + +struct PrimitiveOperator { + Operator op; + std::vector* arguments; +}; + +struct Call { + const Expression* function; + const Expression* argument; +}; + +struct FunctionType { + const Expression* parameter; + const Expression* return_type; +}; + struct Expression { int line_num; ExpressionKind tag; + + static auto MakeVar(int line_num, std::string var) -> const Expression*; + static auto MakeVarPat(int line_num, std::string var, const Expression* type) + -> const Expression*; + static auto MakeInt(int line_num, int i) -> const Expression*; + static auto MakeBool(int line_num, bool b) -> const Expression*; + static auto MakeOp(int line_num, Operator op, + std::vector* args) -> const Expression*; + static auto MakeUnOp(int line_num, enum Operator op, const Expression* arg) + -> const Expression*; + static auto MakeBinOp(int line_num, enum Operator op, const Expression* arg1, + const Expression* arg2) -> const Expression*; + static auto MakeCall(int line_num, const Expression* fun, + const Expression* arg) -> const Expression*; + static auto MakeGetField(int line_num, const Expression* exp, + std::string field) -> const Expression*; + static auto MakeTuple(int line_num, std::vector* args) + -> const Expression*; + static auto MakeUnit(int line_num) -> const Expression*; + static auto MakeIndex(int line_num, const Expression* exp, + const Expression* i) -> const Expression*; + static auto MakeTypeType(int line_num) -> const Expression*; + static auto MakeIntType(int line_num) -> const Expression*; + static auto MakeBoolType(int line_num) -> const Expression*; + static auto MakeFunType(int line_num, const Expression* param, + const Expression* ret) -> const Expression*; + static auto MakeAutoType(int line_num) -> const Expression*; + static auto MakeContinuationType(int line_num) -> const Expression*; + + Variable GetVariable() const; + FieldAccess GetFieldAccess() const; + Index GetIndex() const; + PatternVariable GetPatternVariable() const; + int GetInteger() const; + bool GetBoolean() const; + Tuple GetTuple() const; + PrimitiveOperator GetPrimitiveOperator() const; + Call GetCall() const; + FunctionType GetFunctionType() const; + + private: union { - struct { - std::string* name; - } variable; - - struct { - const Expression* aggregate; - std::string* field; - } get_field; - - struct { - const Expression* aggregate; - const Expression* offset; - } index; - - struct { - std::string* name; - const Expression* type; - } pattern_variable; - + Variable variable; + FieldAccess get_field; + Index index; + PatternVariable pattern_variable; int integer; bool boolean; - - struct { - std::vector* fields; - } tuple; - - struct { - Operator op; - std::vector* arguments; - } primitive_op; - - struct { - const Expression* function; - const Expression* argument; - } call; - - struct { - const Expression* parameter; - const Expression* return_type; - } function_type; - + Tuple tuple; + PrimitiveOperator primitive_op; + Call call; + FunctionType function_type; } u; }; -auto MakeVar(int line_num, std::string var) -> const Expression*; -auto MakeVarPat(int line_num, std::string var, const Expression* type) - -> const Expression*; -auto MakeInt(int line_num, int i) -> const Expression*; -auto MakeBool(int line_num, bool b) -> const Expression*; -auto MakeOp(int line_num, Operator op, std::vector* args) - -> const Expression*; -auto MakeUnOp(int line_num, enum Operator op, const Expression* arg) - -> const Expression*; -auto MakeBinOp(int line_num, enum Operator op, const Expression* arg1, - const Expression* arg2) -> const Expression*; -auto MakeCall(int line_num, const Expression* fun, const Expression* arg) - -> const Expression*; -auto MakeGetField(int line_num, const Expression* exp, std::string field) - -> const Expression*; -auto MakeTuple(int line_num, std::vector* args) - -> const Expression*; -// Create an AST node for an empty tuple. -auto MakeUnit(int line_num) -> const Expression*; -auto MakeIndex(int line_num, const Expression* exp, const Expression* i) - -> const Expression*; - -auto MakeTypeType(int line_num) -> const Expression*; -auto MakeIntType(int line_num) -> const Expression*; -auto MakeBoolType(int line_num) -> const Expression*; -auto MakeFunType(int line_num, const Expression* param, const Expression* ret) - -> const Expression*; -auto MakeAutoType(int line_num) -> const Expression*; -// Returns a Continuation type AST node at the given source location, -// which is the type of a continuation value. -auto MakeContinuationType(int line_num) -> const Expression*; - void PrintExp(const Expression* exp); } // namespace Carbon diff --git a/executable_semantics/ast/statement.cpp b/executable_semantics/ast/statement.cpp index 1ff9f73c3568..428e2c18c226 100644 --- a/executable_semantics/ast/statement.cpp +++ b/executable_semantics/ast/statement.cpp @@ -4,11 +4,68 @@ #include "executable_semantics/ast/statement.h" +#include #include namespace Carbon { -auto MakeExpStmt(int line_num, const Expression* exp) -> const Statement* { +const Expression* Statement::GetExpression() const { + assert(tag == StatementKind::ExpressionStatement); + return u.exp; +} + +Assignment Statement::GetAssign() const { + assert(tag == StatementKind::Assign); + return u.assign; +} + +VariableDefinition Statement::GetVariableDefinition() const { + assert(tag == StatementKind::VariableDefinition); + return u.variable_definition; +} + +IfStatement Statement::GetIf() const { + assert(tag == StatementKind::If); + return u.if_stmt; +} + +const Expression* Statement::GetReturn() const { + assert(tag == StatementKind::Return); + return u.return_stmt; +} + +Sequence Statement::GetSequence() const { + assert(tag == StatementKind::Sequence); + return u.sequence; +} + +Block Statement::GetBlock() const { + assert(tag == StatementKind::Block); + return u.block; +} + +While Statement::GetWhile() const { + assert(tag == StatementKind::While); + return u.while_stmt; +} + +Match Statement::GetMatch() const { + assert(tag == StatementKind::Match); + return u.match_stmt; +} + +Continuation Statement::GetContinuation() const { + assert(tag == StatementKind::Continuation); + return u.continuation; +} + +Run Statement::GetRun() const { + assert(tag == StatementKind::Run); + return u.run; +} + +auto Statement::MakeExpStmt(int line_num, const Expression* exp) + -> const Statement* { auto* s = new Statement(); s->line_num = line_num; s->tag = StatementKind::ExpressionStatement; @@ -16,8 +73,8 @@ auto MakeExpStmt(int line_num, const Expression* exp) -> const Statement* { return s; } -auto MakeAssign(int line_num, const Expression* lhs, const Expression* rhs) - -> const Statement* { +auto Statement::MakeAssign(int line_num, const Expression* lhs, + const Expression* rhs) -> const Statement* { auto* s = new Statement(); s->line_num = line_num; s->tag = StatementKind::Assign; @@ -26,8 +83,8 @@ auto MakeAssign(int line_num, const Expression* lhs, const Expression* rhs) return s; } -auto MakeVarDef(int line_num, const Expression* pat, const Expression* init) - -> const Statement* { +auto Statement::MakeVarDef(int line_num, const Expression* pat, + const Expression* init) -> const Statement* { auto* s = new Statement(); s->line_num = line_num; s->tag = StatementKind::VariableDefinition; @@ -36,8 +93,9 @@ auto MakeVarDef(int line_num, const Expression* pat, const Expression* init) return s; } -auto MakeIf(int line_num, const Expression* cond, const Statement* then_stmt, - const Statement* else_stmt) -> const Statement* { +auto Statement::MakeIf(int line_num, const Expression* cond, + const Statement* then_stmt, const Statement* else_stmt) + -> const Statement* { auto* s = new Statement(); s->line_num = line_num; s->tag = StatementKind::If; @@ -47,8 +105,8 @@ auto MakeIf(int line_num, const Expression* cond, const Statement* then_stmt, return s; } -auto MakeWhile(int line_num, const Expression* cond, const Statement* body) - -> const Statement* { +auto Statement::MakeWhile(int line_num, const Expression* cond, + const Statement* body) -> const Statement* { auto* s = new Statement(); s->line_num = line_num; s->tag = StatementKind::While; @@ -57,21 +115,22 @@ auto MakeWhile(int line_num, const Expression* cond, const Statement* body) return s; } -auto MakeBreak(int line_num) -> const Statement* { +auto Statement::MakeBreak(int line_num) -> const Statement* { auto* s = new Statement(); s->line_num = line_num; s->tag = StatementKind::Break; return s; } -auto MakeContinue(int line_num) -> const Statement* { +auto Statement::MakeContinue(int line_num) -> const Statement* { auto* s = new Statement(); s->line_num = line_num; s->tag = StatementKind::Continue; return s; } -auto MakeReturn(int line_num, const Expression* e) -> const Statement* { +auto Statement::MakeReturn(int line_num, const Expression* e) + -> const Statement* { auto* s = new Statement(); s->line_num = line_num; s->tag = StatementKind::Return; @@ -79,7 +138,7 @@ auto MakeReturn(int line_num, const Expression* e) -> const Statement* { return s; } -auto MakeSeq(int line_num, const Statement* s1, const Statement* s2) +auto Statement::MakeSeq(int line_num, const Statement* s1, const Statement* s2) -> const Statement* { auto* s = new Statement(); s->line_num = line_num; @@ -89,7 +148,8 @@ auto MakeSeq(int line_num, const Statement* s1, const Statement* s2) return s; } -auto MakeBlock(int line_num, const Statement* stmt) -> const Statement* { +auto Statement::MakeBlock(int line_num, const Statement* stmt) + -> const Statement* { auto* s = new Statement(); s->line_num = line_num; s->tag = StatementKind::Block; @@ -97,7 +157,7 @@ auto MakeBlock(int line_num, const Statement* stmt) -> const Statement* { return s; } -auto MakeMatch( +auto Statement::MakeMatch( int line_num, const Expression* exp, std::list>* clauses) -> const Statement* { @@ -111,8 +171,9 @@ auto MakeMatch( // Returns an AST node for a continuation statement give its line number and // parts. -auto MakeContinuationStatement(int line_num, std::string continuation_variable, - const Statement* body) -> const Statement* { +auto Statement::MakeContinuation(int line_num, + std::string continuation_variable, + const Statement* body) -> const Statement* { auto* continuation = new Statement(); continuation->line_num = line_num; continuation->tag = StatementKind::Continuation; @@ -123,7 +184,8 @@ auto MakeContinuationStatement(int line_num, std::string continuation_variable, } // Returns an AST node for a run statement give its line number and argument. -auto MakeRun(int line_num, const Expression* argument) -> const Statement* { +auto Statement::MakeRun(int line_num, const Expression* argument) + -> const Statement* { auto* run = new Statement(); run->line_num = line_num; run->tag = StatementKind::Run; @@ -132,7 +194,7 @@ auto MakeRun(int line_num, const Expression* argument) -> const Statement* { } // Returns an AST node for an await statement give its line number. -auto MakeAwait(int line_num) -> const Statement* { +auto Statement::MakeAwait(int line_num) -> const Statement* { auto* await = new Statement(); await->line_num = line_num; await->tag = StatementKind::Await; @@ -150,11 +212,11 @@ void PrintStatement(const Statement* s, int depth) { switch (s->tag) { case StatementKind::Match: std::cout << "match ("; - PrintExp(s->u.match_stmt.exp); + PrintExp(s->GetMatch().exp); std::cout << ") {"; if (depth < 0 || depth > 1) { std::cout << std::endl; - for (auto& clause : *s->u.match_stmt.clauses) { + for (auto& clause : *s->GetMatch().clauses) { std::cout << "case "; PrintExp(clause.first); std::cout << " =>" << std::endl; @@ -168,9 +230,9 @@ void PrintStatement(const Statement* s, int depth) { break; case StatementKind::While: std::cout << "while ("; - PrintExp(s->u.while_stmt.cond); + PrintExp(s->GetWhile().cond); std::cout << ")" << std::endl; - PrintStatement(s->u.while_stmt.body, depth - 1); + PrintStatement(s->GetWhile().body, depth - 1); break; case StatementKind::Break: std::cout << "break;"; @@ -180,49 +242,49 @@ void PrintStatement(const Statement* s, int depth) { break; case StatementKind::VariableDefinition: std::cout << "var "; - PrintExp(s->u.variable_definition.pat); + PrintExp(s->GetVariableDefinition().pat); std::cout << " = "; - PrintExp(s->u.variable_definition.init); + PrintExp(s->GetVariableDefinition().init); std::cout << ";"; break; case StatementKind::ExpressionStatement: - PrintExp(s->u.exp); + PrintExp(s->GetExpression()); std::cout << ";"; break; case StatementKind::Assign: - PrintExp(s->u.assign.lhs); + PrintExp(s->GetAssign().lhs); std::cout << " = "; - PrintExp(s->u.assign.rhs); + PrintExp(s->GetAssign().rhs); std::cout << ";"; break; case StatementKind::If: std::cout << "if ("; - PrintExp(s->u.if_stmt.cond); + PrintExp(s->GetIf().cond); std::cout << ")" << std::endl; - PrintStatement(s->u.if_stmt.then_stmt, depth - 1); + PrintStatement(s->GetIf().then_stmt, depth - 1); std::cout << std::endl << "else" << std::endl; - PrintStatement(s->u.if_stmt.else_stmt, depth - 1); + PrintStatement(s->GetIf().else_stmt, depth - 1); break; case StatementKind::Return: std::cout << "return "; - PrintExp(s->u.return_stmt); + PrintExp(s->GetReturn()); std::cout << ";"; break; case StatementKind::Sequence: - PrintStatement(s->u.sequence.stmt, depth); + PrintStatement(s->GetSequence().stmt, depth); if (depth < 0 || depth > 1) { std::cout << std::endl; } else { std::cout << " "; } - PrintStatement(s->u.sequence.next, depth - 1); + PrintStatement(s->GetSequence().next, depth - 1); break; case StatementKind::Block: std::cout << "{"; if (depth < 0 || depth > 1) { std::cout << std::endl; } - PrintStatement(s->u.block.stmt, depth); + PrintStatement(s->GetBlock().stmt, depth); if (depth < 0 || depth > 1) { std::cout << std::endl; } @@ -232,19 +294,19 @@ void PrintStatement(const Statement* s, int depth) { } break; case StatementKind::Continuation: - std::cout << "continuation " << *s->u.continuation.continuation_variable - << " "; + std::cout << "continuation " + << *s->GetContinuation().continuation_variable << " "; if (depth < 0 || depth > 1) { std::cout << std::endl; } - PrintStatement(s->u.continuation.body, depth - 1); + PrintStatement(s->GetContinuation().body, depth - 1); if (depth < 0 || depth > 1) { std::cout << std::endl; } break; case StatementKind::Run: std::cout << "run "; - PrintExp(s->u.run.argument); + PrintExp(s->GetRun().argument); std::cout << ";"; break; case StatementKind::Await: diff --git a/executable_semantics/ast/statement.h b/executable_semantics/ast/statement.h index bebfee54d032..8f4c5c880bc7 100644 --- a/executable_semantics/ast/statement.h +++ b/executable_semantics/ast/statement.h @@ -28,98 +28,126 @@ enum class StatementKind { Await, // Pause execution of the continuation. }; +struct Statement; + +struct Assignment { + const Expression* lhs; + const Expression* rhs; +}; + +struct VariableDefinition { + const Expression* pat; + const Expression* init; +}; + +struct IfStatement { + const Expression* cond; + const Statement* then_stmt; + const Statement* else_stmt; +}; + +struct Sequence { + const Statement* stmt; + const Statement* next; +}; + +struct Block { + const Statement* stmt; +}; + +struct While { + const Expression* cond; + const Statement* body; +}; + +struct Match { + const Expression* exp; + std::list>* clauses; +}; + +struct Continuation { + std::string* continuation_variable; + const Statement* body; +}; + +struct Run { + const Expression* argument; +}; + struct Statement { + // TODO: change Statement to a class and make all members private int line_num; StatementKind tag; + // Constructors + static auto MakeExpStmt(int line_num, const Expression* exp) + -> const Statement*; + static auto MakeAssign(int line_num, const Expression* lhs, + const Expression* rhs) -> const Statement*; + static auto MakeVarDef(int line_num, const Expression* pat, + const Expression* init) -> const Statement*; + static auto MakeIf(int line_num, const Expression* cond, + const Statement* then_stmt, const Statement* else_stmt) + -> const Statement*; + static auto MakeReturn(int line_num, const Expression* e) -> const Statement*; + static auto MakeSeq(int line_num, const Statement* s1, const Statement* s2) + -> const Statement*; + static auto MakeBlock(int line_num, const Statement* s) -> const Statement*; + static auto MakeWhile(int line_num, const Expression* cond, + const Statement* body) -> const Statement*; + static auto MakeBreak(int line_num) -> const Statement*; + static auto MakeContinue(int line_num) -> const Statement*; + static auto MakeMatch( + int line_num, const Expression* exp, + std::list>* clauses) + -> const Statement*; + // Returns an AST node for a continuation statement give its line number and + // contituent parts. + // + // __continuation { + // + // } + static auto MakeContinuation(int line_num, std::string continuation_variable, + const Statement* body) -> const Statement*; + // Returns an AST node for a run statement give its line number and argument. + // + // __run ; + static auto MakeRun(int line_num, const Expression* argument) + -> const Statement*; + // Returns an AST node for an await statement give its line number. + // + // __await; + static auto MakeAwait(int line_num) -> const Statement*; + + // Access to the alternatives + const Expression* GetExpression() const; + Assignment GetAssign() const; + VariableDefinition GetVariableDefinition() const; + IfStatement GetIf() const; + const Expression* GetReturn() const; + Sequence GetSequence() const; + Block GetBlock() const; + While GetWhile() const; + Match GetMatch() const; + Continuation GetContinuation() const; + Run GetRun() const; + + private: union { const Expression* exp; - - struct { - const Expression* lhs; - const Expression* rhs; - } assign; - - struct { - const Expression* pat; - const Expression* init; - } variable_definition; - - struct { - const Expression* cond; - const Statement* then_stmt; - const Statement* else_stmt; - } if_stmt; - + Assignment assign; + VariableDefinition variable_definition; + IfStatement if_stmt; const Expression* return_stmt; - - struct { - const Statement* stmt; - const Statement* next; - } sequence; - - struct { - const Statement* stmt; - } block; - - struct { - const Expression* cond; - const Statement* body; - } while_stmt; - - struct { - const Expression* exp; - std::list>* clauses; - } match_stmt; - - struct { - std::string* continuation_variable; - const Statement* body; - } continuation; - - struct { - const Expression* argument; - } run; - + Sequence sequence; + Block block; + While while_stmt; + Match match_stmt; + Continuation continuation; + Run run; } u; }; -auto MakeExpStmt(int line_num, const Expression* exp) -> const Statement*; -auto MakeAssign(int line_num, const Expression* lhs, const Expression* rhs) - -> const Statement*; -auto MakeVarDef(int line_num, const Expression* pat, const Expression* init) - -> const Statement*; -auto MakeIf(int line_num, const Expression* cond, const Statement* then_stmt, - const Statement* else_stmt) -> const Statement*; -auto MakeReturn(int line_num, const Expression* e) -> const Statement*; -auto MakeSeq(int line_num, const Statement* s1, const Statement* s2) - -> const Statement*; -auto MakeBlock(int line_num, const Statement* s) -> const Statement*; -auto MakeWhile(int line_num, const Expression* cond, const Statement* body) - -> const Statement*; -auto MakeBreak(int line_num) -> const Statement*; -auto MakeContinue(int line_num) -> const Statement*; -auto MakeMatch( - int line_num, const Expression* exp, - std::list>* clauses) - -> const Statement*; -// Returns an AST node for a continuation statement give its line number and -// contituent parts. -// -// __continuation { -// -// } -auto MakeContinuationStatement(int line_num, std::string continuation_variable, - const Statement* body) -> const Statement*; -// Returns an AST node for a run statement give its line number and argument. -// -// __run ; -auto MakeRun(int line_num, const Expression* argument) -> const Statement*; -// Returns an AST node for an await statement give its line number. -// -// __await; -auto MakeAwait(int line_num) -> const Statement*; - void PrintStatement(const Statement*, int); } // namespace Carbon diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index a721bd3647ee..0e22dbf15987 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -67,54 +67,59 @@ auto CopyVal(const Value* val, int line_num) -> const Value* { switch (val->tag) { case ValKind::TupleV: { auto* elements = new std::vector(); - for (const TupleElement& element : *val->u.tuple.elements) { + for (const TupleElement& element : *val->GetTuple().elements) { const Value* new_element = CopyVal(state->heap.Read(element.address, line_num), line_num); Address new_address = state->heap.AllocateValue(new_element); elements->push_back({.name = element.name, .address = new_address}); } - return MakeTupleVal(elements); + return Value::MakeTupleVal(elements); } case ValKind::AltV: { - const Value* arg = - CopyVal(state->heap.Read(val->u.alt.argument, line_num), line_num); + const Value* arg = CopyVal( + state->heap.Read(val->GetAlternative().argument, line_num), line_num); Address argument_address = state->heap.AllocateValue(arg); - return MakeAltVal(*val->u.alt.alt_name, *val->u.alt.choice_name, - argument_address); + return Value::MakeAltVal(*val->GetAlternative().alt_name, + *val->GetAlternative().choice_name, + argument_address); } case ValKind::StructV: { - const Value* inits = CopyVal(val->u.struct_val.inits, line_num); - return MakeStructVal(val->u.struct_val.type, inits); + const Value* inits = CopyVal(val->GetStruct().inits, line_num); + return Value::MakeStructVal(val->GetStruct().type, inits); } case ValKind::IntV: - return MakeIntVal(val->u.integer); + return Value::MakeIntVal(val->GetInteger()); case ValKind::BoolV: - return MakeBoolVal(val->u.boolean); + return Value::MakeBoolVal(val->GetBoolean()); case ValKind::FunV: - return MakeFunVal(*val->u.fun.name, val->u.fun.param, val->u.fun.body); + return Value::MakeFunVal(*val->GetFunction().name, + val->GetFunction().param, + val->GetFunction().body); case ValKind::PtrV: - return MakePtrVal(val->u.ptr); + return Value::MakePtrVal(val->GetPointer()); case ValKind::ContinuationV: // Copying a continuation is "shallow". return val; case ValKind::FunctionTV: - return MakeFunTypeVal(CopyVal(val->u.fun_type.param, line_num), - CopyVal(val->u.fun_type.ret, line_num)); + return Value::MakeFunTypeVal( + CopyVal(val->GetFunctionType().param, line_num), + CopyVal(val->GetFunctionType().ret, line_num)); case ValKind::PointerTV: - return MakePtrTypeVal(CopyVal(val->u.ptr_type.type, line_num)); + return Value::MakePtrTypeVal( + CopyVal(val->GetPointerType().type, line_num)); case ValKind::IntTV: - return MakeIntTypeVal(); + return Value::MakeIntTypeVal(); case ValKind::BoolTV: - return MakeBoolTypeVal(); + return Value::MakeBoolTypeVal(); case ValKind::TypeTV: - return MakeTypeTypeVal(); + return Value::MakeTypeTypeVal(); case ValKind::VarTV: - return MakeVarTypeVal(*val->u.var_type); + return Value::MakeVarTypeVal(*val->GetVariableType()); case ValKind::AutoTV: - return MakeAutoTypeVal(); + return Value::MakeAutoTypeVal(); case ValKind::ContinuationTV: - return MakeContinuationTypeVal(); + return Value::MakeContinuationTypeVal(); case ValKind::StructTV: case ValKind::ChoiceTV: case ValKind::VarPatV: @@ -127,13 +132,13 @@ auto CopyVal(const Value* val, int line_num) -> const Value* { void Heap::DeallocateSubObjects(const Value* val) { switch (val->tag) { case ValKind::AltV: - Deallocate(val->u.alt.argument); + Deallocate(val->GetAlternative().argument); break; case ValKind::StructV: - DeallocateSubObjects(val->u.struct_val.inits); + DeallocateSubObjects(val->GetStruct().inits); break; case ValKind::TupleV: - for (const TupleElement& element : *val->u.tuple.elements) { + for (const TupleElement& element : *val->GetTuple().elements) { Deallocate(element.address); } break; @@ -221,7 +226,7 @@ void PrintState(std::ostream& out) { auto ValToInt(const Value* v, int line_num) -> int { switch (v->tag) { case ValKind::IntV: - return v->u.integer; + return v->GetInteger(); default: std::cerr << line_num << ": runtime error: expected an integer" << std::endl; @@ -232,7 +237,7 @@ auto ValToInt(const Value* v, int line_num) -> int { auto ValToBool(const Value* v, int line_num) -> int { switch (v->tag) { case ValKind::BoolV: - return v->u.boolean; + return v->GetBoolean(); default: std::cerr << "runtime type error: expected a Boolean" << std::endl; exit(-1); @@ -242,7 +247,7 @@ auto ValToBool(const Value* v, int line_num) -> int { auto ValToPtr(const Value* v, int line_num) -> Address { switch (v->tag) { case ValKind::PtrV: - return v->u.ptr; + return v->GetPointer(); default: std::cerr << "runtime type error: expected a pointer, not "; PrintValue(v, std::cerr); @@ -257,7 +262,7 @@ auto ValToPtr(const Value* v, int line_num) -> Address { auto ContinuationToVector(const Value* continuation, int sourceLocation) -> std::vector { if (continuation->tag == ValKind::ContinuationV) { - return *continuation->u.continuation.stack; + return *continuation->GetContinuation().stack; } else { std::cerr << sourceLocation << ": runtime error: expected an integer" << std::endl; @@ -269,23 +274,23 @@ auto EvalPrim(Operator op, const std::vector& args, int line_num) -> const Value* { switch (op) { case Operator::Neg: - return MakeIntVal(-ValToInt(args[0], line_num)); + return Value::MakeIntVal(-ValToInt(args[0], line_num)); case Operator::Add: - return MakeIntVal(ValToInt(args[0], line_num) + - ValToInt(args[1], line_num)); + return Value::MakeIntVal(ValToInt(args[0], line_num) + + ValToInt(args[1], line_num)); case Operator::Sub: - return MakeIntVal(ValToInt(args[0], line_num) - - ValToInt(args[1], line_num)); + return Value::MakeIntVal(ValToInt(args[0], line_num) - + ValToInt(args[1], line_num)); case Operator::Not: - return MakeBoolVal(!ValToBool(args[0], line_num)); + return Value::MakeBoolVal(!ValToBool(args[0], line_num)); case Operator::And: - return MakeBoolVal(ValToBool(args[0], line_num) && - ValToBool(args[1], line_num)); + return Value::MakeBoolVal(ValToBool(args[0], line_num) && + ValToBool(args[1], line_num)); case Operator::Or: - return MakeBoolVal(ValToBool(args[0], line_num) || - ValToBool(args[1], line_num)); + return Value::MakeBoolVal(ValToBool(args[0], line_num) || + ValToBool(args[1], line_num)); case Operator::Eq: - return MakeBoolVal(ValueEqual(args[0], args[1], line_num)); + return Value::MakeBoolVal(ValueEqual(args[0], args[1], line_num)); } } @@ -304,7 +309,7 @@ auto ChoiceDeclaration::InitGlobals(Env& globals) const -> void { auto t = InterpExp(Env(), kv.second); alts->push_back(make_pair(kv.first, t)); } - auto ct = MakeChoiceTypeVal(name, alts); + auto ct = Value::MakeChoiceTypeVal(name, alts); auto a = state->heap.AllocateValue(ct); globals.Set(name, a); } @@ -322,7 +327,7 @@ auto StructDeclaration::InitGlobals(Env& globals) const -> void { } } } - auto st = MakeStructTypeVal(*definition.name, fields, methods); + auto st = Value::MakeStructTypeVal(*definition.name, fields, methods); auto a = state->heap.AllocateValue(st); globals.Set(*definition.name, a); } @@ -330,7 +335,7 @@ auto StructDeclaration::InitGlobals(Env& globals) const -> void { auto FunctionDeclaration::InitGlobals(Env& globals) const -> void { Env values; auto pt = InterpExp(values, definition->param_pattern); - auto f = MakeFunVal(definition->name, pt, definition->body); + auto f = Value::MakeFunVal(definition->name, pt, definition->body); Address a = state->heap.AllocateValue(f); globals.Set(definition->name, a); } @@ -353,8 +358,9 @@ void CallFunction(int line_num, std::vector operas, case ValKind::FunV: { // Bind arguments to parameters std::list params; - std::optional matches = PatternMatch( - operas[0]->u.fun.param, operas[1], globals, ¶ms, line_num); + std::optional matches = + PatternMatch(operas[0]->GetFunction().param, operas[1], globals, + ¶ms, line_num); if (!matches) { std::cerr << "internal error in call_function, pattern match failed" << std::endl; @@ -362,23 +368,25 @@ void CallFunction(int line_num, std::vector operas, } // Create the new frame and push it on the stack auto* scope = new Scope(*matches, params); - auto* frame = new Frame(*operas[0]->u.fun.name, Stack(scope), - Stack(MakeStmtAct(operas[0]->u.fun.body))); + auto* frame = + new Frame(*operas[0]->GetFunction().name, Stack(scope), + Stack(MakeStmtAct(operas[0]->GetFunction().body))); state->stack.Push(frame); break; } case ValKind::StructTV: { const Value* arg = CopyVal(operas[1], line_num); - const Value* sv = MakeStructVal(operas[0], arg); + const Value* sv = Value::MakeStructVal(operas[0], arg); Frame* frame = state->stack.Top(); frame->todo.Push(MakeValAct(sv)); break; } case ValKind::AltConsV: { const Value* arg = CopyVal(operas[1], line_num); - const Value* av = MakeAltVal(*operas[0]->u.alt_cons.alt_name, - *operas[0]->u.alt_cons.choice_name, - state->heap.AllocateValue(arg)); + const Value* av = + Value::MakeAltVal(*operas[0]->GetAlternativeConstructor().alt_name, + *operas[0]->GetAlternativeConstructor().choice_name, + state->heap.AllocateValue(arg)); Frame* frame = state->stack.Top(); frame->todo.Push(MakeValAct(av)); break; @@ -412,12 +420,12 @@ void CreateTuple(Frame* frame, Action* act, const Expression* /*exp*/) { // { { (v1,...,vn) :: C, E, F} :: S, H} // -> { { `(v1,...,vn) :: C, E, F} :: S, H} auto elements = new std::vector(); - auto f = act->u.exp->u.tuple.fields->begin(); + auto f = act->u.exp->GetTuple().fields->begin(); for (auto i = act->results.begin(); i != act->results.end(); ++i, ++f) { Address a = state->heap.AllocateValue(*i); // copy? elements->push_back({.name = f->name, .address = a}); } - const Value* tv = MakeTupleVal(elements); + const Value* tv = Value::MakeTupleVal(elements); frame->todo.Pop(1); frame->todo.Push(MakeValAct(tv)); } @@ -433,19 +441,20 @@ auto PatternMatch(const Value* p, const Value* v, Env values, switch (p->tag) { case ValKind::VarPatV: { Address a = state->heap.AllocateValue(CopyVal(v, line_num)); - vars->push_back(*p->u.var_pat.name); - values.Set(*p->u.var_pat.name, a); + vars->push_back(*p->GetVariablePattern().name); + values.Set(*p->GetVariablePattern().name, a); return values; } case ValKind::TupleV: switch (v->tag) { case ValKind::TupleV: { - if (p->u.tuple.elements->size() != v->u.tuple.elements->size()) { + if (p->GetTuple().elements->size() != + v->GetTuple().elements->size()) { std::cerr << "runtime error: arity mismatch in tuple pattern match" << std::endl; exit(-1); } - for (const TupleElement& element : *p->u.tuple.elements) { + for (const TupleElement& element : *p->GetTuple().elements) { auto a = FindTupleField(element.name, v); if (a == std::nullopt) { std::cerr << "runtime error: field " << element.name << "not in "; @@ -473,14 +482,15 @@ auto PatternMatch(const Value* p, const Value* v, Env values, case ValKind::AltV: switch (v->tag) { case ValKind::AltV: { - if (*p->u.alt.choice_name != *v->u.alt.choice_name || - *p->u.alt.alt_name != *v->u.alt.alt_name) { + if (*p->GetAlternative().choice_name != + *v->GetAlternative().choice_name || + *p->GetAlternative().alt_name != *v->GetAlternative().alt_name) { return std::nullopt; } - std::optional matches = - PatternMatch(state->heap.Read(p->u.alt.argument, line_num), - state->heap.Read(v->u.alt.argument, line_num), - values, vars, line_num); + std::optional matches = PatternMatch( + state->heap.Read(p->GetAlternative().argument, line_num), + state->heap.Read(v->GetAlternative().argument, line_num), values, + vars, line_num); if (!matches) { return std::nullopt; } @@ -497,13 +507,15 @@ auto PatternMatch(const Value* p, const Value* v, Env values, case ValKind::FunctionTV: switch (v->tag) { case ValKind::FunctionTV: { - std::optional matches = PatternMatch( - p->u.fun_type.param, v->u.fun_type.param, values, vars, line_num); + std::optional matches = + PatternMatch(p->GetFunctionType().param, + v->GetFunctionType().param, values, vars, line_num); if (!matches) { return std::nullopt; } - return PatternMatch(p->u.fun_type.ret, v->u.fun_type.ret, *matches, - vars, line_num); + return PatternMatch(p->GetFunctionType().ret, + v->GetFunctionType().ret, *matches, vars, + line_num); } default: return std::nullopt; @@ -526,12 +538,13 @@ void PatternAssignment(const Value* pat, const Value* val, int line_num) { case ValKind::TupleV: { switch (val->tag) { case ValKind::TupleV: { - if (pat->u.tuple.elements->size() != val->u.tuple.elements->size()) { + if (pat->GetTuple().elements->size() != + val->GetTuple().elements->size()) { std::cerr << "runtime error: arity mismatch in tuple pattern match" << std::endl; exit(-1); } - for (const TupleElement& element : *pat->u.tuple.elements) { + for (const TupleElement& element : *pat->GetTuple().elements) { auto a = FindTupleField(element.name, val); if (a == std::nullopt) { std::cerr << "runtime error: field " << element.name << "not in "; @@ -557,14 +570,17 @@ void PatternAssignment(const Value* pat, const Value* val, int line_num) { case ValKind::AltV: { switch (val->tag) { case ValKind::AltV: { - if (*pat->u.alt.choice_name != *val->u.alt.choice_name || - *pat->u.alt.alt_name != *val->u.alt.alt_name) { + if (*pat->GetAlternative().choice_name != + *val->GetAlternative().choice_name || + *pat->GetAlternative().alt_name != + *val->GetAlternative().alt_name) { std::cerr << "internal error in pattern assignment" << std::endl; exit(-1); } - PatternAssignment(state->heap.Read(pat->u.alt.argument, line_num), - state->heap.Read(val->u.alt.argument, line_num), - line_num); + PatternAssignment( + state->heap.Read(pat->GetAlternative().argument, line_num), + state->heap.Read(val->GetAlternative().argument, line_num), + line_num); break; } default: @@ -601,13 +617,13 @@ void StepLvalue() { // { {x :: C, E, F} :: S, H} // -> { {E(x) :: C, E, F} :: S, H} std::optional
pointer = - CurrentEnv(state).Get(*(exp->u.variable.name)); + CurrentEnv(state).Get(*(exp->GetVariable().name)); if (!pointer) { std::cerr << exp->line_num << ": could not find `" - << *(exp->u.variable.name) << "`" << std::endl; + << *(exp->GetVariable().name) << "`" << std::endl; exit(-1); } - const Value* v = MakePtrVal(*pointer); + const Value* v = Value::MakePtrVal(*pointer); frame->todo.Pop(); frame->todo.Push(MakeValAct(v)); break; @@ -615,21 +631,21 @@ void StepLvalue() { case ExpressionKind::GetField: { // { {e.f :: C, E, F} :: S, H} // -> { e :: [].f :: C, E, F} :: S, H} - frame->todo.Push(MakeLvalAct(exp->u.get_field.aggregate)); + frame->todo.Push(MakeLvalAct(exp->GetFieldAccess().aggregate)); act->pos++; break; } case ExpressionKind::Index: { // { {e[i] :: C, E, F} :: S, H} // -> { e :: [][i] :: C, E, F} :: S, H} - frame->todo.Push(MakeExpAct(exp->u.index.aggregate)); + frame->todo.Push(MakeExpAct(exp->GetIndex().aggregate)); act->pos++; break; } case ExpressionKind::Tuple: { // { {(f1=e1,...) :: C, E, F} :: S, H} // -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H} - const Expression* e1 = (*exp->u.tuple.fields)[0].expression; + const Expression* e1 = (*exp->GetTuple().fields)[0].expression; frame->todo.Push(MakeLvalAct(e1)); act->pos++; break; @@ -665,22 +681,22 @@ void StepExp() { } switch (exp->tag) { case ExpressionKind::PatternVariable: { - frame->todo.Push(MakeExpAct(exp->u.pattern_variable.type)); + frame->todo.Push(MakeExpAct(exp->GetPatternVariable().type)); act->pos++; break; } case ExpressionKind::Index: { // { { e[i] :: C, E, F} :: S, H} // -> { { e :: [][i] :: C, E, F} :: S, H} - frame->todo.Push(MakeExpAct(exp->u.index.aggregate)); + frame->todo.Push(MakeExpAct(exp->GetIndex().aggregate)); act->pos++; break; } case ExpressionKind::Tuple: { - if (exp->u.tuple.fields->size() > 0) { + if (exp->GetTuple().fields->size() > 0) { // { {(f1=e1,...) :: C, E, F} :: S, H} // -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H} - const Expression* e1 = (*exp->u.tuple.fields)[0].expression; + const Expression* e1 = (*exp->GetTuple().fields)[0].expression; frame->todo.Push(MakeExpAct(e1)); act->pos++; } else { @@ -691,17 +707,17 @@ void StepExp() { case ExpressionKind::GetField: { // { { e.f :: C, E, F} :: S, H} // -> { { e :: [].f :: C, E, F} :: S, H} - frame->todo.Push(MakeLvalAct(exp->u.get_field.aggregate)); + frame->todo.Push(MakeLvalAct(exp->GetFieldAccess().aggregate)); act->pos++; break; } case ExpressionKind::Variable: { // { {x :: C, E, F} :: S, H} -> { {H(E(x)) :: C, E, F} :: S, H} std::optional
pointer = - CurrentEnv(state).Get(*(exp->u.variable.name)); + CurrentEnv(state).Get(*(exp->GetVariable().name)); if (!pointer) { std::cerr << exp->line_num << ": could not find `" - << *(exp->u.variable.name) << "`" << std::endl; + << *(exp->GetVariable().name) << "`" << std::endl; exit(-1); } const Value* pointee = state->heap.Read(*pointer, exp->line_num); @@ -712,24 +728,25 @@ void StepExp() { case ExpressionKind::Integer: // { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H} frame->todo.Pop(1); - frame->todo.Push(MakeValAct(MakeIntVal(exp->u.integer))); + frame->todo.Push(MakeValAct(Value::MakeIntVal(exp->GetInteger()))); break; case ExpressionKind::Boolean: // { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H} frame->todo.Pop(1); - frame->todo.Push(MakeValAct(MakeBoolVal(exp->u.boolean))); + frame->todo.Push(MakeValAct(Value::MakeBoolVal(exp->GetBoolean()))); break; case ExpressionKind::PrimitiveOp: - if (exp->u.primitive_op.arguments->size() > 0) { + if (exp->GetPrimitiveOperator().arguments->size() > 0) { // { {op(e :: es) :: C, E, F} :: S, H} // -> { e :: op([] :: es) :: C, E, F} :: S, H} - frame->todo.Push(MakeExpAct(exp->u.primitive_op.arguments->front())); + frame->todo.Push( + MakeExpAct(exp->GetPrimitiveOperator().arguments->front())); act->pos++; } else { // { {v :: op(]) :: C, E, F} :: S, H} // -> { {eval_prim(op, ()) :: C, E, F} :: S, H} - const Value* v = - EvalPrim(exp->u.primitive_op.op, act->results, exp->line_num); + const Value* v = EvalPrim(exp->GetPrimitiveOperator().op, act->results, + exp->line_num); frame->todo.Pop(2); frame->todo.Push(MakeValAct(v)); } @@ -737,40 +754,40 @@ void StepExp() { case ExpressionKind::Call: // { {e1(e2) :: C, E, F} :: S, H} // -> { {e1 :: [](e2) :: C, E, F} :: S, H} - frame->todo.Push(MakeExpAct(exp->u.call.function)); + frame->todo.Push(MakeExpAct(exp->GetCall().function)); act->pos++; break; case ExpressionKind::IntT: { - const Value* v = MakeIntTypeVal(); + const Value* v = Value::MakeIntTypeVal(); frame->todo.Pop(1); frame->todo.Push(MakeValAct(v)); break; } case ExpressionKind::BoolT: { - const Value* v = MakeBoolTypeVal(); + const Value* v = Value::MakeBoolTypeVal(); frame->todo.Pop(1); frame->todo.Push(MakeValAct(v)); break; } case ExpressionKind::AutoT: { - const Value* v = MakeAutoTypeVal(); + const Value* v = Value::MakeAutoTypeVal(); frame->todo.Pop(1); frame->todo.Push(MakeValAct(v)); break; } case ExpressionKind::TypeT: { - const Value* v = MakeTypeTypeVal(); + const Value* v = Value::MakeTypeTypeVal(); frame->todo.Pop(1); frame->todo.Push(MakeValAct(v)); break; } case ExpressionKind::FunctionT: { - frame->todo.Push(MakeExpAct(exp->u.function_type.parameter)); + frame->todo.Push(MakeExpAct(exp->GetFunctionType().parameter)); act->pos++; break; } case ExpressionKind::ContinuationT: { - const Value* v = MakeContinuationTypeVal(); + const Value* v = Value::MakeContinuationTypeVal(); frame->todo.Pop(1); frame->todo.Push(MakeValAct(v)); break; @@ -822,13 +839,13 @@ void StepStmt() { case StatementKind::Match: // { { (match (e) ...) :: C, E, F} :: S, H} // -> { { e :: (match ([]) ...) :: C, E, F} :: S, H} - frame->todo.Push(MakeExpAct(stmt->u.match_stmt.exp)); + frame->todo.Push(MakeExpAct(stmt->GetMatch().exp)); act->pos++; break; case StatementKind::While: // { { (while (e) s) :: C, E, F} :: S, H} // -> { { e :: (while ([]) s) :: C, E, F} :: S, H} - frame->todo.Push(MakeExpAct(stmt->u.while_stmt.cond)); + frame->todo.Push(MakeExpAct(stmt->GetWhile().cond)); act->pos++; break; case StatementKind::Break: @@ -858,10 +875,10 @@ void StepStmt() { break; case StatementKind::Block: { if (act->pos == -1) { - if (stmt->u.block.stmt) { + if (stmt->GetBlock().stmt) { auto* scope = new Scope(CurrentEnv(state), {}); frame->scopes.Push(scope); - frame->todo.Push(MakeStmtAct(stmt->u.block.stmt)); + frame->todo.Push(MakeStmtAct(stmt->GetBlock().stmt)); act->pos++; } else { frame->todo.Pop(); @@ -877,40 +894,40 @@ void StepStmt() { case StatementKind::VariableDefinition: // { {(var x = e) :: C, E, F} :: S, H} // -> { {e :: (var x = []) :: C, E, F} :: S, H} - frame->todo.Push(MakeExpAct(stmt->u.variable_definition.init)); + frame->todo.Push(MakeExpAct(stmt->GetVariableDefinition().init)); act->pos++; break; case StatementKind::ExpressionStatement: // { {e :: C, E, F} :: S, H} // -> { {e :: C, E, F} :: S, H} - frame->todo.Push(MakeExpAct(stmt->u.exp)); + frame->todo.Push(MakeExpAct(stmt->GetExpression())); break; case StatementKind::Assign: // { {(lv = e) :: C, E, F} :: S, H} // -> { {lv :: ([] = e) :: C, E, F} :: S, H} - frame->todo.Push(MakeLvalAct(stmt->u.assign.lhs)); + frame->todo.Push(MakeLvalAct(stmt->GetAssign().lhs)); act->pos++; break; case StatementKind::If: // { {(if (e) then_stmt else else_stmt) :: C, E, F} :: S, H} // -> { { e :: (if ([]) then_stmt else else_stmt) :: C, E, F} :: S, H} - frame->todo.Push(MakeExpAct(stmt->u.if_stmt.cond)); + frame->todo.Push(MakeExpAct(stmt->GetIf().cond)); act->pos++; break; case StatementKind::Return: // { {return e :: C, E, F} :: S, H} // -> { {e :: return [] :: C, E, F} :: S, H} - frame->todo.Push(MakeExpAct(stmt->u.return_stmt)); + frame->todo.Push(MakeExpAct(stmt->GetReturn())); act->pos++; break; case StatementKind::Sequence: // { { (s1,s2) :: C, E, F} :: S, H} // -> { { s1 :: s2 :: C, E, F} :: S, H} frame->todo.Pop(1); - if (stmt->u.sequence.next) { - frame->todo.Push(MakeStmtAct(stmt->u.sequence.next)); + if (stmt->GetSequence().next) { + frame->todo.Push(MakeStmtAct(stmt->GetSequence().next)); } - frame->todo.Push(MakeStmtAct(stmt->u.sequence.stmt)); + frame->todo.Push(MakeStmtAct(stmt->GetSequence().stmt)); break; case StatementKind::Continuation: { // Create a continuation object by creating a frame similar the @@ -919,24 +936,24 @@ void StepStmt() { Stack scopes; scopes.Push(scope); Stack todo; - todo.Push( - MakeStmtAct(MakeReturn(stmt->line_num, MakeUnit(stmt->line_num)))); - todo.Push(MakeStmtAct(stmt->u.continuation.body)); + todo.Push(MakeStmtAct(Statement::MakeReturn( + stmt->line_num, Expression::MakeUnit(stmt->line_num)))); + todo.Push(MakeStmtAct(stmt->GetContinuation().body)); Frame* continuation_frame = new Frame("__continuation", scopes, todo); - Address continuation_address = - state->heap.AllocateValue(MakeContinuation({continuation_frame})); + Address continuation_address = state->heap.AllocateValue( + Value::MakeContinuation({continuation_frame})); // Store the continuation's address in the frame. continuation_frame->continuation = continuation_address; // Bind the continuation object to the continuation variable frame->scopes.Top()->values.Set( - *stmt->u.continuation.continuation_variable, continuation_address); + *stmt->GetContinuation().continuation_variable, continuation_address); // Pop the continuation statement. frame->todo.Pop(); break; } case StatementKind::Run: // Evaluate the argument of the run statement. - frame->todo.Push(MakeExpAct(stmt->u.run.argument)); + frame->todo.Push(MakeExpAct(stmt->GetRun().argument)); act->pos++; break; case StatementKind::Await: @@ -947,8 +964,8 @@ void StepStmt() { paused.push_back(state->stack.Pop()); } while (!paused.back()->IsContinuation()); // Update the continuation with the paused stack. - state->heap.Write(paused.back()->continuation, MakeContinuation(paused), - stmt->line_num); + state->heap.Write(paused.back()->continuation, + Value::MakeContinuation(paused), stmt->line_num); break; } } @@ -957,7 +974,7 @@ auto GetMember(Address a, const std::string& f, int line_num) -> Address { const Value* v = state->heap.Read(a, line_num); switch (v->tag) { case ValKind::StructV: { - auto a = FindTupleField(f, v->u.struct_val.inits); + auto a = FindTupleField(f, v->GetStruct().inits); if (a == std::nullopt) { std::cerr << "runtime error, member " << f << " not in "; PrintValue(v, std::cerr); @@ -977,13 +994,13 @@ auto GetMember(Address a, const std::string& f, int line_num) -> Address { return *a; } case ValKind::ChoiceTV: { - if (FindInVarValues(f, v->u.choice_type.alternatives) == nullptr) { + if (FindInVarValues(f, v->GetChoiceType().alternatives) == nullptr) { std::cerr << "alternative " << f << " not in "; PrintValue(v, std::cerr); std::cerr << std::endl; exit(-1); } - auto ac = MakeAltCons(f, *v->u.choice_type.name); + auto ac = Value::MakeAltCons(f, *v->GetChoiceType().name); return state->heap.AllocateValue(ac); } default: @@ -1047,7 +1064,7 @@ void HandleValue() { auto del = MakeDeleteAct(a); frame->todo.Pop(2); InsertDelete(del, frame->todo); - frame->todo.Push(MakeValAct(MakePtrVal(a))); + frame->todo.Push(MakeValAct(Value::MakePtrVal(a))); break; } case ActionKind::LValAction: { @@ -1058,15 +1075,15 @@ void HandleValue() { // -> { { &v.f :: C, E, F} :: S, H } const Value* str = act->results[0]; Address a = GetMember(ValToPtr(str, exp->line_num), - *exp->u.get_field.field, exp->line_num); + *exp->GetFieldAccess().field, exp->line_num); frame->todo.Pop(2); - frame->todo.Push(MakeValAct(MakePtrVal(a))); + frame->todo.Push(MakeValAct(Value::MakePtrVal(a))); break; } case ExpressionKind::Index: { if (act->pos == 1) { frame->todo.Pop(1); - frame->todo.Push(MakeExpAct(exp->u.index.offset)); + frame->todo.Push(MakeExpAct(exp->GetIndex().offset)); } else if (act->pos == 2) { // { v :: [][i] :: C, E, F} :: S, H} // -> { { &v[i] :: C, E, F} :: S, H } @@ -1080,17 +1097,18 @@ void HandleValue() { exit(-1); } frame->todo.Pop(2); - frame->todo.Push(MakeValAct(MakePtrVal(*a))); + frame->todo.Push(MakeValAct(Value::MakePtrVal(*a))); } break; } case ExpressionKind::Tuple: { - if (act->pos != static_cast(exp->u.tuple.fields->size())) { + if (act->pos != static_cast(exp->GetTuple().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->u.tuple.fields)[act->pos].expression; + const Expression* elt = + (*exp->GetTuple().fields)[act->pos].expression; frame->todo.Pop(1); frame->todo.Push(MakeLvalAct(elt)); } else { @@ -1110,19 +1128,20 @@ void HandleValue() { const Expression* exp = act->u.exp; switch (exp->tag) { case ExpressionKind::PatternVariable: { - auto v = - MakeVarPatVal(*exp->u.pattern_variable.name, act->results[0]); + auto v = Value::MakeVarPatVal(*exp->GetPatternVariable().name, + act->results[0]); frame->todo.Pop(2); frame->todo.Push(MakeValAct(v)); break; } case ExpressionKind::Tuple: { - if (act->pos != static_cast(exp->u.tuple.fields->size())) { + if (act->pos != static_cast(exp->GetTuple().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->u.tuple.fields)[act->pos].expression; + const Expression* elt = + (*exp->GetTuple().fields)[act->pos].expression; frame->todo.Pop(1); frame->todo.Push(MakeExpAct(elt)); } else { @@ -1134,7 +1153,7 @@ void HandleValue() { case ExpressionKind::Index: { if (act->pos == 1) { frame->todo.Pop(1); - frame->todo.Push(MakeExpAct(exp->u.index.offset)); + frame->todo.Push(MakeExpAct(exp->GetIndex().offset)); } else if (act->pos == 2) { auto tuple = act->results[0]; switch (tuple->tag) { @@ -1168,7 +1187,7 @@ void HandleValue() { // { { v :: [].f :: C, E, F} :: S, H} // -> { { v_f :: C, E, F} : S, H} auto a = GetMember(ValToPtr(act->results[0], exp->line_num), - *exp->u.get_field.field, exp->line_num); + *exp->GetFieldAccess().field, exp->line_num); const Value* element = state->heap.Read(a, exp->line_num); frame->todo.Pop(2); frame->todo.Push(MakeValAct(element)); @@ -1176,17 +1195,18 @@ void HandleValue() { } case ExpressionKind::PrimitiveOp: { if (act->pos != - static_cast(exp->u.primitive_op.arguments->size())) { + static_cast(exp->GetPrimitiveOperator().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->u.primitive_op.arguments)[act->pos]; + const Expression* arg = + (*exp->GetPrimitiveOperator().arguments)[act->pos]; frame->todo.Pop(1); frame->todo.Push(MakeExpAct(arg)); } else { // { {v :: op(vs,[]) :: C, E, F} :: S, H} // -> { {eval_prim(op, (vs,v)) :: C, E, F} :: S, H} - const Value* v = - EvalPrim(exp->u.primitive_op.op, act->results, exp->line_num); + const Value* v = EvalPrim(exp->GetPrimitiveOperator().op, + act->results, exp->line_num); frame->todo.Pop(2); frame->todo.Push(MakeValAct(v)); } @@ -1197,7 +1217,7 @@ void HandleValue() { // { { v :: [](e) :: C, E, F} :: S, H} // -> { { e :: v([]) :: C, E, F} :: S, H} frame->todo.Pop(1); - frame->todo.Push(MakeExpAct(exp->u.call.argument)); + frame->todo.Push(MakeExpAct(exp->GetCall().argument)); } else if (act->pos == 2) { // { { v2 :: v1([]) :: C, E, F} :: S, H} // -> { {C',E',F'} :: {C, E, F} :: S, H} @@ -1214,14 +1234,15 @@ void HandleValue() { if (act->pos == 2) { // { { rt :: fn pt -> [] :: C, E, F} :: S, H} // -> { fn pt -> rt :: {C, E, F} :: S, H} - const Value* v = MakeFunTypeVal(act->results[0], act->results[1]); + const Value* v = + Value::MakeFunTypeVal(act->results[0], act->results[1]); frame->todo.Pop(2); frame->todo.Push(MakeValAct(v)); } else { // { { pt :: fn [] -> e :: C, E, F} :: S, H} // -> { { e :: fn pt -> []) :: C, E, F} :: S, H} frame->todo.Pop(1); - frame->todo.Push(MakeExpAct(exp->u.function_type.return_type)); + frame->todo.Push(MakeExpAct(exp->GetFunctionType().return_type)); } break; } @@ -1248,7 +1269,7 @@ void HandleValue() { case StatementKind::VariableDefinition: { if (act->pos == 1) { frame->todo.Pop(1); - frame->todo.Push(MakeExpAct(stmt->u.variable_definition.pat)); + frame->todo.Push(MakeExpAct(stmt->GetVariableDefinition().pat)); } else if (act->pos == 2) { // { { v :: (x = []) :: C, E, F} :: S, H} // -> { { C, E(x := a), F} :: S, H(a := copy(v))} @@ -1275,7 +1296,7 @@ void HandleValue() { // { { a :: ([] = e) :: C, E, F} :: S, H} // -> { { e :: (a = []) :: C, E, F} :: S, H} frame->todo.Pop(1); - frame->todo.Push(MakeExpAct(stmt->u.assign.rhs)); + frame->todo.Push(MakeExpAct(stmt->GetAssign().rhs)); } else if (act->pos == 2) { // { { v :: (a = []) :: C, E, F} :: S, H} // -> { { C, E, F} :: S, H(a := v)} @@ -1291,13 +1312,13 @@ void HandleValue() { // S, H} // -> { { then_stmt :: C, E, F } :: S, H} frame->todo.Pop(2); - frame->todo.Push(MakeStmtAct(stmt->u.if_stmt.then_stmt)); - } else if (stmt->u.if_stmt.else_stmt) { + frame->todo.Push(MakeStmtAct(stmt->GetIf().then_stmt)); + } else if (stmt->GetIf().else_stmt) { // { {false :: if ([]) then_stmt else else_stmt :: C, E, F} :: // S, H} // -> { { else_stmt :: C, E, F } :: S, H} frame->todo.Pop(2); - frame->todo.Push(MakeStmtAct(stmt->u.if_stmt.else_stmt)); + frame->todo.Push(MakeStmtAct(stmt->GetIf().else_stmt)); } else { frame->todo.Pop(2); } @@ -1309,7 +1330,7 @@ void HandleValue() { frame->todo.Pop(1); frame->todo.Top()->pos = -1; frame->todo.Top()->results.clear(); - frame->todo.Push(MakeStmtAct(stmt->u.while_stmt.body)); + frame->todo.Push(MakeStmtAct(stmt->GetWhile().body)); } else { // { {false :: (while ([]) s) :: C, E, F} :: S, H} // -> { { C, E, F } :: S, H} @@ -1331,11 +1352,11 @@ void HandleValue() { // * ... auto clause_num = (act->pos - 1) / 2; if (clause_num >= - static_cast(stmt->u.match_stmt.clauses->size())) { + static_cast(stmt->GetMatch().clauses->size())) { frame->todo.Pop(2); break; } - auto c = stmt->u.match_stmt.clauses->begin(); + auto c = stmt->GetMatch().clauses->begin(); std::advance(c, clause_num); if (act->pos % 2 == 1) { @@ -1355,7 +1376,7 @@ void HandleValue() { auto* new_scope = new Scope(*matches, vars); frame->scopes.Push(new_scope); const Statement* body_block = - MakeBlock(stmt->line_num, c->second); + Statement::MakeBlock(stmt->line_num, c->second); Action* body_act = MakeStmtAct(body_block); body_act->pos = 0; frame->todo.Pop(2); @@ -1366,9 +1387,9 @@ void HandleValue() { act->pos++; clause_num = (act->pos - 1) / 2; if (clause_num < - static_cast(stmt->u.match_stmt.clauses->size())) { + static_cast(stmt->GetMatch().clauses->size())) { // interpret the next clause - c = stmt->u.match_stmt.clauses->begin(); + c = stmt->GetMatch().clauses->begin(); std::advance(c, clause_num); frame->todo.Pop(1); frame->todo.Push(MakeExpAct(c->first)); @@ -1393,8 +1414,8 @@ void HandleValue() { frame->todo.Pop(2); // Push an expression statement action to ignore the result // value from the continuation. - Action* ignore_result = MakeStmtAct( - MakeExpStmt(stmt->line_num, MakeUnit(stmt->line_num))); + Action* ignore_result = MakeStmtAct(Statement::MakeExpStmt( + stmt->line_num, Expression::MakeUnit(stmt->line_num))); ignore_result->pos = 0; frame->todo.Push(ignore_result); // Push the continuation onto the current stack. @@ -1467,8 +1488,10 @@ auto InterpProgram(std::list* fs) -> int { } InitGlobals(fs); - const Expression* arg = MakeTuple(0, new std::vector()); - const Expression* call_main = MakeCall(0, MakeVar(0, "main"), arg); + const Expression* arg = + Expression::MakeTuple(0, new std::vector()); + const Expression* call_main = + Expression::MakeCall(0, Expression::MakeVar(0, "main"), arg); auto todo = Stack(MakeExpAct(call_main)); auto* scope = new Scope(globals, std::list()); auto* frame = new Frame("top", Stack(scope), todo); diff --git a/executable_semantics/interpreter/typecheck.cpp b/executable_semantics/interpreter/typecheck.cpp index 2463fd05efb6..6b79a5a5342e 100644 --- a/executable_semantics/interpreter/typecheck.cpp +++ b/executable_semantics/interpreter/typecheck.cpp @@ -44,32 +44,33 @@ void PrintTypeEnv(TypeEnv types, std::ostream& out) { auto ReifyType(const Value* t, int line_num) -> const Expression* { switch (t->tag) { case ValKind::VarTV: - return MakeVar(0, *t->u.var_type); + return Expression::MakeVar(0, *t->GetVariableType()); case ValKind::IntTV: - return MakeIntType(0); + return Expression::MakeIntType(0); case ValKind::BoolTV: - return MakeBoolType(0); + return Expression::MakeBoolType(0); case ValKind::TypeTV: - return MakeTypeType(0); + return Expression::MakeTypeType(0); case ValKind::ContinuationTV: - return MakeContinuationType(0); + return Expression::MakeContinuationType(0); case ValKind::FunctionTV: - return MakeFunType(0, ReifyType(t->u.fun_type.param, line_num), - ReifyType(t->u.fun_type.ret, line_num)); + return Expression::MakeFunType( + 0, ReifyType(t->GetFunctionType().param, line_num), + ReifyType(t->GetFunctionType().ret, line_num)); case ValKind::TupleV: { auto args = new std::vector(); - for (const TupleElement& field : *t->u.tuple.elements) { + for (const TupleElement& field : *t->GetTuple().elements) { args->push_back( {.name = field.name, .expression = ReifyType(state->heap.Read(field.address, line_num), line_num)}); } - return MakeTuple(0, args); + return Expression::MakeTuple(0, args); } case ValKind::StructTV: - return MakeVar(0, *t->u.struct_type.name); + return Expression::MakeVar(0, *t->GetStructType().name); case ValKind::ChoiceTV: - return MakeVar(0, *t->u.choice_type.name); + return Expression::MakeVar(0, *t->GetChoiceType().name); default: std::cerr << line_num << ": expected a type, not "; PrintValue(t, std::cerr); @@ -128,7 +129,7 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, << std::endl; exit(-1); } - auto t = InterpExp(values, e->u.pattern_variable.type); + auto t = InterpExp(values, e->GetPatternVariable().type); if (t->tag == ValKind::AutoTV) { if (expected == nullptr) { std::cerr << e->line_num @@ -141,18 +142,19 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, } else if (expected) { ExpectType(e->line_num, "pattern variable", t, expected); } - auto new_e = MakeVarPat(e->line_num, *e->u.pattern_variable.name, - ReifyType(t, e->line_num)); - types.Set(*e->u.pattern_variable.name, t); + auto new_e = + Expression::MakeVarPat(e->line_num, *e->GetPatternVariable().name, + ReifyType(t, e->line_num)); + types.Set(*e->GetPatternVariable().name, t); return TCResult(new_e, t, types); } case ExpressionKind::Index: { - auto res = TypeCheckExp(e->u.get_field.aggregate, types, values, nullptr, - TCContext::ValueContext); + auto res = TypeCheckExp(e->GetFieldAccess().aggregate, types, values, + nullptr, TCContext::ValueContext); auto t = res.type; switch (t->tag) { case ValKind::TupleV: { - auto i = ToInteger(InterpExp(values, e->u.index.offset)); + auto i = ToInteger(InterpExp(values, e->GetIndex().offset)); std::string f = std::to_string(i); std::optional
field_address = FindTupleField(f, t); if (field_address == std::nullopt) { @@ -163,7 +165,8 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, exit(-1); } auto field_t = state->heap.Read(*field_address, e->line_num); - auto new_e = MakeIndex(e->line_num, res.exp, MakeInt(e->line_num, i)); + auto new_e = Expression::MakeIndex( + e->line_num, res.exp, Expression::MakeInt(e->line_num, i)); return TCResult(new_e, field_t, res.types); } default: @@ -181,27 +184,27 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, << std::endl; exit(-1); } - if (expected && - e->u.tuple.fields->size() != expected->u.tuple.elements->size()) { + if (expected && e->GetTuple().fields->size() != + expected->GetTuple().elements->size()) { std::cerr << e->line_num << ": compilation error, tuples of different length" << std::endl; exit(-1); } int i = 0; - for (auto arg = e->u.tuple.fields->begin(); - arg != e->u.tuple.fields->end(); ++arg, ++i) { + for (auto arg = e->GetTuple().fields->begin(); + arg != e->GetTuple().fields->end(); ++arg, ++i) { const Value* arg_expected = nullptr; if (expected && expected->tag == ValKind::TupleV) { - if ((*expected->u.tuple.elements)[i].name != arg->name) { + if ((*expected->GetTuple().elements)[i].name != arg->name) { std::cerr << e->line_num << ": compilation error, field names do not match, " - << "expected " << (*expected->u.tuple.elements)[i].name + << "expected " << (*expected->GetTuple().elements)[i].name << " but got " << arg->name << std::endl; exit(-1); } arg_expected = state->heap.Read( - (*expected->u.tuple.elements)[i].address, e->line_num); + (*expected->GetTuple().elements)[i].address, e->line_num); } auto arg_res = TypeCheckExp(arg->expression, new_types, values, arg_expected, context); @@ -211,63 +214,66 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, {.name = arg->name, .address = state->heap.AllocateValue(arg_res.type)}); } - auto tuple_e = MakeTuple(e->line_num, new_args); - auto tuple_t = MakeTupleVal(arg_types); + auto tuple_e = Expression::MakeTuple(e->line_num, new_args); + auto tuple_t = Value::MakeTupleVal(arg_types); return TCResult(tuple_e, tuple_t, new_types); } case ExpressionKind::GetField: { - auto res = TypeCheckExp(e->u.get_field.aggregate, types, values, nullptr, - TCContext::ValueContext); + auto res = TypeCheckExp(e->GetFieldAccess().aggregate, types, values, + nullptr, TCContext::ValueContext); auto t = res.type; switch (t->tag) { case ValKind::StructTV: // Search for a field - for (auto& field : *t->u.struct_type.fields) { - if (*e->u.get_field.field == field.first) { - const Expression* new_e = - MakeGetField(e->line_num, res.exp, *e->u.get_field.field); + for (auto& field : *t->GetStructType().fields) { + if (*e->GetFieldAccess().field == field.first) { + const Expression* new_e = Expression::MakeGetField( + e->line_num, res.exp, *e->GetFieldAccess().field); return TCResult(new_e, field.second, res.types); } } // Search for a method - for (auto& method : *t->u.struct_type.methods) { - if (*e->u.get_field.field == method.first) { - const Expression* new_e = - MakeGetField(e->line_num, res.exp, *e->u.get_field.field); + for (auto& method : *t->GetStructType().methods) { + if (*e->GetFieldAccess().field == method.first) { + const Expression* new_e = Expression::MakeGetField( + e->line_num, res.exp, *e->GetFieldAccess().field); return TCResult(new_e, method.second, res.types); } } std::cerr << e->line_num << ": compilation error, struct " - << *t->u.struct_type.name << " does not have a field named " - << *e->u.get_field.field << std::endl; + << *t->GetStructType().name + << " does not have a field named " + << *e->GetFieldAccess().field << std::endl; exit(-1); case ValKind::TupleV: - for (const TupleElement& field : *t->u.tuple.elements) { - if (*e->u.get_field.field == field.name) { - auto new_e = - MakeGetField(e->line_num, res.exp, *e->u.get_field.field); + for (const TupleElement& field : *t->GetTuple().elements) { + if (*e->GetFieldAccess().field == field.name) { + auto new_e = Expression::MakeGetField(e->line_num, res.exp, + *e->GetFieldAccess().field); return TCResult(new_e, state->heap.Read(field.address, e->line_num), res.types); } } std::cerr << e->line_num << ": compilation error, struct " - << *t->u.struct_type.name << " does not have a field named " - << *e->u.get_field.field << std::endl; + << *t->GetStructType().name + << " does not have a field named " + << *e->GetFieldAccess().field << std::endl; exit(-1); case ValKind::ChoiceTV: - for (auto vt = t->u.choice_type.alternatives->begin(); - vt != t->u.choice_type.alternatives->end(); ++vt) { - if (*e->u.get_field.field == vt->first) { - const Expression* new_e = - MakeGetField(e->line_num, res.exp, *e->u.get_field.field); - auto fun_ty = MakeFunTypeVal(vt->second, t); + for (auto vt = t->GetChoiceType().alternatives->begin(); + vt != t->GetChoiceType().alternatives->end(); ++vt) { + if (*e->GetFieldAccess().field == vt->first) { + const Expression* new_e = Expression::MakeGetField( + e->line_num, res.exp, *e->GetFieldAccess().field); + auto fun_ty = Value::MakeFunTypeVal(vt->second, t); return TCResult(new_e, fun_ty, res.types); } } std::cerr << e->line_num << ": compilation error, struct " - << *t->u.struct_type.name << " does not have a field named " - << *e->u.get_field.field << std::endl; + << *t->GetStructType().name + << " does not have a field named " + << *e->GetFieldAccess().field << std::endl; exit(-1); default: @@ -280,69 +286,74 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, } } case ExpressionKind::Variable: { - std::optional type = types.Get(*(e->u.variable.name)); + std::optional type = types.Get(*(e->GetVariable().name)); if (type) { return TCResult(e, *type, types); } else { std::cerr << e->line_num << ": could not find `" - << *(e->u.variable.name) << "`" << std::endl; + << *(e->GetVariable().name) << "`" << std::endl; exit(-1); } } case ExpressionKind::Integer: - return TCResult(e, MakeIntTypeVal(), types); + return TCResult(e, Value::MakeIntTypeVal(), types); case ExpressionKind::Boolean: - return TCResult(e, MakeBoolTypeVal(), types); + return TCResult(e, Value::MakeBoolTypeVal(), types); case ExpressionKind::PrimitiveOp: { auto es = new std::vector(); std::vector ts; auto new_types = types; - for (auto& argument : *e->u.primitive_op.arguments) { + for (auto& argument : *e->GetPrimitiveOperator().arguments) { auto res = TypeCheckExp(argument, types, values, nullptr, TCContext::ValueContext); new_types = res.types; es->push_back(res.exp); ts.push_back(res.type); } - auto new_e = MakeOp(e->line_num, e->u.primitive_op.op, es); - switch (e->u.primitive_op.op) { + auto new_e = + Expression::MakeOp(e->line_num, e->GetPrimitiveOperator().op, es); + switch (e->GetPrimitiveOperator().op) { case Operator::Neg: - ExpectType(e->line_num, "negation", MakeIntTypeVal(), ts[0]); - return TCResult(new_e, MakeIntTypeVal(), new_types); + ExpectType(e->line_num, "negation", Value::MakeIntTypeVal(), ts[0]); + return TCResult(new_e, Value::MakeIntTypeVal(), new_types); case Operator::Add: case Operator::Sub: - ExpectType(e->line_num, "subtraction(1)", MakeIntTypeVal(), ts[0]); - ExpectType(e->line_num, "substration(2)", MakeIntTypeVal(), ts[1]); - return TCResult(new_e, MakeIntTypeVal(), new_types); + ExpectType(e->line_num, "subtraction(1)", Value::MakeIntTypeVal(), + ts[0]); + ExpectType(e->line_num, "substration(2)", Value::MakeIntTypeVal(), + ts[1]); + return TCResult(new_e, Value::MakeIntTypeVal(), new_types); case Operator::And: - ExpectType(e->line_num, "&&(1)", MakeBoolTypeVal(), ts[0]); - ExpectType(e->line_num, "&&(2)", MakeBoolTypeVal(), ts[1]); - return TCResult(new_e, MakeBoolTypeVal(), new_types); + ExpectType(e->line_num, "&&(1)", Value::MakeBoolTypeVal(), ts[0]); + ExpectType(e->line_num, "&&(2)", Value::MakeBoolTypeVal(), ts[1]); + return TCResult(new_e, Value::MakeBoolTypeVal(), new_types); case Operator::Or: - ExpectType(e->line_num, "||(1)", MakeBoolTypeVal(), ts[0]); - ExpectType(e->line_num, "||(2)", MakeBoolTypeVal(), ts[1]); - return TCResult(new_e, MakeBoolTypeVal(), new_types); + ExpectType(e->line_num, "||(1)", Value::MakeBoolTypeVal(), ts[0]); + ExpectType(e->line_num, "||(2)", Value::MakeBoolTypeVal(), ts[1]); + return TCResult(new_e, Value::MakeBoolTypeVal(), new_types); case Operator::Not: - ExpectType(e->line_num, "!", MakeBoolTypeVal(), ts[0]); - return TCResult(new_e, MakeBoolTypeVal(), new_types); + ExpectType(e->line_num, "!", Value::MakeBoolTypeVal(), ts[0]); + return TCResult(new_e, Value::MakeBoolTypeVal(), new_types); case Operator::Eq: ExpectType(e->line_num, "==", ts[0], ts[1]); - return TCResult(new_e, MakeBoolTypeVal(), new_types); + return TCResult(new_e, Value::MakeBoolTypeVal(), new_types); } break; } case ExpressionKind::Call: { - auto fun_res = TypeCheckExp(e->u.call.function, types, values, nullptr, + auto fun_res = TypeCheckExp(e->GetCall().function, types, values, nullptr, TCContext::ValueContext); switch (fun_res.type->tag) { case ValKind::FunctionTV: { auto fun_t = fun_res.type; - auto arg_res = TypeCheckExp(e->u.call.argument, fun_res.types, values, - fun_t->u.fun_type.param, context); - ExpectType(e->line_num, "call", fun_t->u.fun_type.param, + auto arg_res = + TypeCheckExp(e->GetCall().argument, fun_res.types, values, + fun_t->GetFunctionType().param, context); + ExpectType(e->line_num, "call", fun_t->GetFunctionType().param, arg_res.type); - auto new_e = MakeCall(e->line_num, fun_res.exp, arg_res.exp); - return TCResult(new_e, fun_t->u.fun_type.ret, arg_res.types); + auto new_e = + Expression::MakeCall(e->line_num, fun_res.exp, arg_res.exp); + return TCResult(new_e, fun_t->GetFunctionType().ret, arg_res.types); } default: { std::cerr << e->line_num @@ -359,35 +370,36 @@ auto TypeCheckExp(const Expression* e, TypeEnv types, Env values, switch (context) { case TCContext::ValueContext: case TCContext::TypeContext: { - auto pt = InterpExp(values, e->u.function_type.parameter); - auto rt = InterpExp(values, e->u.function_type.return_type); - auto new_e = MakeFunType(e->line_num, ReifyType(pt, e->line_num), - ReifyType(rt, e->line_num)); - return TCResult(new_e, MakeTypeTypeVal(), types); + auto pt = InterpExp(values, e->GetFunctionType().parameter); + auto rt = InterpExp(values, e->GetFunctionType().return_type); + auto new_e = + Expression::MakeFunType(e->line_num, ReifyType(pt, e->line_num), + ReifyType(rt, e->line_num)); + return TCResult(new_e, Value::MakeTypeTypeVal(), types); } case TCContext::PatternContext: { - auto param_res = TypeCheckExp(e->u.function_type.parameter, types, + auto param_res = TypeCheckExp(e->GetFunctionType().parameter, types, values, nullptr, context); auto ret_res = - TypeCheckExp(e->u.function_type.return_type, param_res.types, + TypeCheckExp(e->GetFunctionType().return_type, param_res.types, values, nullptr, context); - auto new_e = - MakeFunType(e->line_num, ReifyType(param_res.type, e->line_num), - ReifyType(ret_res.type, e->line_num)); - return TCResult(new_e, MakeTypeTypeVal(), ret_res.types); + auto new_e = Expression::MakeFunType( + e->line_num, ReifyType(param_res.type, e->line_num), + ReifyType(ret_res.type, e->line_num)); + return TCResult(new_e, Value::MakeTypeTypeVal(), ret_res.types); } } } case ExpressionKind::IntT: - return TCResult(e, MakeIntTypeVal(), types); + return TCResult(e, Value::MakeIntTypeVal(), types); case ExpressionKind::BoolT: - return TCResult(e, MakeBoolTypeVal(), types); + return TCResult(e, Value::MakeBoolTypeVal(), types); case ExpressionKind::TypeT: - return TCResult(e, MakeTypeTypeVal(), types); + return TCResult(e, Value::MakeTypeTypeVal(), types); case ExpressionKind::AutoT: - return TCResult(e, MakeAutoTypeVal(), types); + return TCResult(e, Value::MakeAutoTypeVal(), types); case ExpressionKind::ContinuationT: - return TCResult(e, MakeContinuationTypeVal(), types); + return TCResult(e, Value::MakeContinuationTypeVal(), types); } } @@ -415,86 +427,92 @@ auto TypeCheckStmt(const Statement* s, TypeEnv types, Env values, } switch (s->tag) { case StatementKind::Match: { - auto res = TypeCheckExp(s->u.match_stmt.exp, types, values, nullptr, + auto res = TypeCheckExp(s->GetMatch().exp, types, values, nullptr, TCContext::ValueContext); auto res_type = res.type; auto new_clauses = new std::list>(); - for (auto& clause : *s->u.match_stmt.clauses) { + for (auto& clause : *s->GetMatch().clauses) { new_clauses->push_back(TypecheckCase( res_type, clause.first, clause.second, types, values, ret_type)); } - const Statement* new_s = MakeMatch(s->line_num, res.exp, new_clauses); + const Statement* new_s = + Statement::MakeMatch(s->line_num, res.exp, new_clauses); return TCStatement(new_s, types); } case StatementKind::While: { - auto cnd_res = TypeCheckExp(s->u.while_stmt.cond, types, values, nullptr, + auto cnd_res = TypeCheckExp(s->GetWhile().cond, types, values, nullptr, TCContext::ValueContext); - ExpectType(s->line_num, "condition of `while`", MakeBoolTypeVal(), + ExpectType(s->line_num, "condition of `while`", Value::MakeBoolTypeVal(), cnd_res.type); auto body_res = - TypeCheckStmt(s->u.while_stmt.body, types, values, ret_type); - auto new_s = MakeWhile(s->line_num, cnd_res.exp, body_res.stmt); + TypeCheckStmt(s->GetWhile().body, types, values, ret_type); + auto new_s = + Statement::MakeWhile(s->line_num, cnd_res.exp, body_res.stmt); return TCStatement(new_s, types); } case StatementKind::Break: case StatementKind::Continue: return TCStatement(s, types); case StatementKind::Block: { - auto stmt_res = TypeCheckStmt(s->u.block.stmt, types, values, ret_type); - return TCStatement(MakeBlock(s->line_num, stmt_res.stmt), types); + auto stmt_res = + TypeCheckStmt(s->GetBlock().stmt, types, values, ret_type); + return TCStatement(Statement::MakeBlock(s->line_num, stmt_res.stmt), + types); } case StatementKind::VariableDefinition: { - auto res = TypeCheckExp(s->u.variable_definition.init, types, values, + auto res = TypeCheckExp(s->GetVariableDefinition().init, types, values, nullptr, TCContext::ValueContext); const Value* rhs_ty = res.type; - auto lhs_res = TypeCheckExp(s->u.variable_definition.pat, types, values, + auto lhs_res = TypeCheckExp(s->GetVariableDefinition().pat, types, values, rhs_ty, TCContext::PatternContext); - const Statement* new_s = - MakeVarDef(s->line_num, s->u.variable_definition.pat, res.exp); + const Statement* new_s = Statement::MakeVarDef( + s->line_num, s->GetVariableDefinition().pat, res.exp); return TCStatement(new_s, lhs_res.types); } case StatementKind::Sequence: { auto stmt_res = - TypeCheckStmt(s->u.sequence.stmt, types, values, ret_type); + TypeCheckStmt(s->GetSequence().stmt, types, values, ret_type); auto types2 = stmt_res.types; auto next_res = - TypeCheckStmt(s->u.sequence.next, types2, values, ret_type); + TypeCheckStmt(s->GetSequence().next, types2, values, ret_type); auto types3 = next_res.types; - return TCStatement(MakeSeq(s->line_num, stmt_res.stmt, next_res.stmt), - types3); + return TCStatement( + Statement::MakeSeq(s->line_num, stmt_res.stmt, next_res.stmt), + types3); } case StatementKind::Assign: { - auto rhs_res = TypeCheckExp(s->u.assign.rhs, types, values, nullptr, + auto rhs_res = TypeCheckExp(s->GetAssign().rhs, types, values, nullptr, TCContext::ValueContext); auto rhs_t = rhs_res.type; - auto lhs_res = TypeCheckExp(s->u.assign.lhs, types, values, rhs_t, + auto lhs_res = TypeCheckExp(s->GetAssign().lhs, types, values, rhs_t, TCContext::ValueContext); auto lhs_t = lhs_res.type; ExpectType(s->line_num, "assign", lhs_t, rhs_t); - auto new_s = MakeAssign(s->line_num, lhs_res.exp, rhs_res.exp); + auto new_s = Statement::MakeAssign(s->line_num, lhs_res.exp, rhs_res.exp); return TCStatement(new_s, lhs_res.types); } case StatementKind::ExpressionStatement: { - auto res = TypeCheckExp(s->u.exp, types, values, nullptr, + auto res = TypeCheckExp(s->GetExpression(), types, values, nullptr, TCContext::ValueContext); - auto new_s = MakeExpStmt(s->line_num, res.exp); + auto new_s = Statement::MakeExpStmt(s->line_num, res.exp); return TCStatement(new_s, types); } case StatementKind::If: { - auto cnd_res = TypeCheckExp(s->u.if_stmt.cond, types, values, nullptr, + auto cnd_res = TypeCheckExp(s->GetIf().cond, types, values, nullptr, TCContext::ValueContext); - ExpectType(s->line_num, "condition of `if`", MakeBoolTypeVal(), + ExpectType(s->line_num, "condition of `if`", Value::MakeBoolTypeVal(), cnd_res.type); auto thn_res = - TypeCheckStmt(s->u.if_stmt.then_stmt, types, values, ret_type); + TypeCheckStmt(s->GetIf().then_stmt, types, values, ret_type); auto els_res = - TypeCheckStmt(s->u.if_stmt.else_stmt, types, values, ret_type); - auto new_s = MakeIf(s->line_num, cnd_res.exp, thn_res.stmt, els_res.stmt); + TypeCheckStmt(s->GetIf().else_stmt, types, values, ret_type); + auto new_s = Statement::MakeIf(s->line_num, cnd_res.exp, thn_res.stmt, + els_res.stmt); return TCStatement(new_s, types); } case StatementKind::Return: { - auto res = TypeCheckExp(s->u.return_stmt, types, values, nullptr, + auto res = TypeCheckExp(s->GetReturn(), types, values, nullptr, TCContext::ValueContext); if (ret_type->tag == ValKind::AutoTV) { // The following infers the return type from the first 'return' @@ -504,24 +522,26 @@ auto TypeCheckStmt(const Statement* s, TypeEnv types, Env values, } else { ExpectType(s->line_num, "return", ret_type, res.type); } - return TCStatement(MakeReturn(s->line_num, res.exp), types); + return TCStatement(Statement::MakeReturn(s->line_num, res.exp), types); } case StatementKind::Continuation: { TCStatement body_result = - TypeCheckStmt(s->u.continuation.body, types, values, ret_type); - const Statement* new_continuation = MakeContinuationStatement( - s->line_num, *s->u.continuation.continuation_variable, + TypeCheckStmt(s->GetContinuation().body, types, values, ret_type); + const Statement* new_continuation = Statement::MakeContinuation( + s->line_num, *s->GetContinuation().continuation_variable, body_result.stmt); - types.Set(*s->u.continuation.continuation_variable, - MakeContinuationTypeVal()); + types.Set(*s->GetContinuation().continuation_variable, + Value::MakeContinuationTypeVal()); return TCStatement(new_continuation, types); } case StatementKind::Run: { - TCResult argument_result = TypeCheckExp(s->u.run.argument, types, values, - nullptr, TCContext::ValueContext); - ExpectType(s->line_num, "argument of `run`", MakeContinuationTypeVal(), - argument_result.type); - const Statement* new_run = MakeRun(s->line_num, argument_result.exp); + TCResult argument_result = + TypeCheckExp(s->GetRun().argument, types, values, nullptr, + TCContext::ValueContext); + ExpectType(s->line_num, "argument of `run`", + Value::MakeContinuationTypeVal(), argument_result.type); + const Statement* new_run = + Statement::MakeRun(s->line_num, argument_result.exp); return TCStatement(new_run, types); } case StatementKind::Await: { @@ -535,7 +555,7 @@ auto CheckOrEnsureReturn(const Statement* stmt, bool void_return, int line_num) -> const Statement* { if (!stmt) { if (void_return) { - return MakeReturn(line_num, MakeUnit(line_num)); + return Statement::MakeReturn(line_num, Expression::MakeUnit(line_num)); } else { std::cerr << "control-flow reaches end of non-void function without a return" @@ -547,32 +567,35 @@ auto CheckOrEnsureReturn(const Statement* stmt, bool void_return, int line_num) case StatementKind::Match: { auto new_clauses = new std::list>(); - for (auto i = stmt->u.match_stmt.clauses->begin(); - i != stmt->u.match_stmt.clauses->end(); ++i) { + for (auto i = stmt->GetMatch().clauses->begin(); + i != stmt->GetMatch().clauses->end(); ++i) { auto s = CheckOrEnsureReturn(i->second, void_return, stmt->line_num); new_clauses->push_back(std::make_pair(i->first, s)); } - return MakeMatch(stmt->line_num, stmt->u.match_stmt.exp, new_clauses); + return Statement::MakeMatch(stmt->line_num, stmt->GetMatch().exp, + new_clauses); } case StatementKind::Block: - return MakeBlock( - stmt->line_num, - CheckOrEnsureReturn(stmt->u.block.stmt, void_return, stmt->line_num)); + return Statement::MakeBlock( + stmt->line_num, CheckOrEnsureReturn(stmt->GetBlock().stmt, + void_return, stmt->line_num)); case StatementKind::If: - return MakeIf(stmt->line_num, stmt->u.if_stmt.cond, - CheckOrEnsureReturn(stmt->u.if_stmt.then_stmt, void_return, - stmt->line_num), - CheckOrEnsureReturn(stmt->u.if_stmt.else_stmt, void_return, - stmt->line_num)); + return Statement::MakeIf( + stmt->line_num, stmt->GetIf().cond, + CheckOrEnsureReturn(stmt->GetIf().then_stmt, void_return, + stmt->line_num), + CheckOrEnsureReturn(stmt->GetIf().else_stmt, void_return, + stmt->line_num)); case StatementKind::Return: return stmt; case StatementKind::Sequence: - if (stmt->u.sequence.next) { - return MakeSeq(stmt->line_num, stmt->u.sequence.stmt, - CheckOrEnsureReturn(stmt->u.sequence.next, void_return, - stmt->line_num)); + if (stmt->GetSequence().next) { + return Statement::MakeSeq( + stmt->line_num, stmt->GetSequence().stmt, + CheckOrEnsureReturn(stmt->GetSequence().next, void_return, + stmt->line_num)); } else { - return CheckOrEnsureReturn(stmt->u.sequence.stmt, void_return, + return CheckOrEnsureReturn(stmt->GetSequence().stmt, void_return, stmt->line_num); } case StatementKind::Continuation: @@ -586,8 +609,10 @@ auto CheckOrEnsureReturn(const Statement* stmt, bool void_return, int line_num) case StatementKind::Continue: case StatementKind::VariableDefinition: if (void_return) { - return MakeSeq(stmt->line_num, stmt, - MakeReturn(stmt->line_num, MakeUnit(stmt->line_num))); + return Statement::MakeSeq( + stmt->line_num, stmt, + Statement::MakeReturn(stmt->line_num, + Expression::MakeUnit(stmt->line_num))); } else { std::cerr << stmt->line_num @@ -605,12 +630,12 @@ auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, Env values) TCContext::PatternContext); auto return_type = InterpExp(values, f->return_type); if (f->name == "main") { - ExpectType(f->line_num, "return type of `main`", MakeIntTypeVal(), + ExpectType(f->line_num, "return type of `main`", Value::MakeIntTypeVal(), return_type); // TODO: Check that main doesn't have any parameters. } auto res = TypeCheckStmt(f->body, param_res.types, values, return_type); - bool void_return = TypeEqual(return_type, MakeVoidTypeVal()); + bool void_return = TypeEqual(return_type, Value::MakeVoidTypeVal()); auto body = CheckOrEnsureReturn(res.stmt, void_return, f->line_num); return MakeFunDef(f->line_num, f->name, ReifyType(return_type, f->line_num), f->param_pattern, body); @@ -625,7 +650,7 @@ auto TypeOfFunDef(TypeEnv types, Env values, const FunctionDefinition* fun_def) auto f = TypeCheckFunDef(fun_def, types, values); ret = InterpExp(values, f->return_type); } - return MakeFunTypeVal(param_res.type, ret); + return Value::MakeFunTypeVal(param_res.type, ret); } auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*types*/, Env ct_top) @@ -638,7 +663,7 @@ auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*types*/, Env ct_top) fields->push_back(std::make_pair(*(*m)->u.field.name, t)); } } - return MakeStructTypeVal(*sd->name, fields, methods); + return Value::MakeStructTypeVal(*sd->name, fields, methods); } auto FunctionDeclaration::Name() const -> std::string { @@ -716,11 +741,11 @@ auto StructDeclaration::TopLevel(TypeCheckContext& tops) const -> void { Address a = state->heap.AllocateValue(st); tops.values.Set(Name(), a); // Is this obsolete? auto field_types = new std::vector(); - for (const auto& [field_name, field_value] : *st->u.struct_type.fields) { + for (const auto& [field_name, field_value] : *st->GetStructType().fields) { field_types->push_back({.name = field_name, .address = state->heap.AllocateValue(field_value)}); } - auto fun_ty = MakeFunTypeVal(MakeTupleVal(field_types), st); + auto fun_ty = Value::MakeFunTypeVal(Value::MakeTupleVal(field_types), st); tops.types.Set(Name(), fun_ty); } @@ -730,7 +755,7 @@ auto ChoiceDeclaration::TopLevel(TypeCheckContext& tops) const -> void { auto t = InterpExp(tops.values, a.second); alts->push_back(std::make_pair(a.first, t)); } - auto ct = MakeChoiceTypeVal(name, alts); + auto ct = Value::MakeChoiceTypeVal(name, alts); Address a = state->heap.AllocateValue(ct); tops.values.Set(Name(), a); // Is this obsolete? tops.types.Set(Name(), ct); diff --git a/executable_semantics/interpreter/value.cpp b/executable_semantics/interpreter/value.cpp index 03fa2ae29896..c36a462eb63f 100644 --- a/executable_semantics/interpreter/value.cpp +++ b/executable_semantics/interpreter/value.cpp @@ -12,6 +12,81 @@ namespace Carbon { +int Value::GetInteger() const { + assert(tag == ValKind::IntV); + return u.integer; +} + +bool Value::GetBoolean() const { + assert(tag == ValKind::BoolV); + return u.boolean; +} + +Function Value::GetFunction() const { + assert(tag == ValKind::FunV); + return u.fun; +} + +StructConstructor Value::GetStruct() const { + assert(tag == ValKind::StructV); + return u.struct_val; +} + +AlternativeConstructor Value::GetAlternativeConstructor() const { + assert(tag == ValKind::AltConsV); + return u.alt_cons; +} + +Alternative Value::GetAlternative() const { + assert(tag == ValKind::AltV); + return u.alt; +} + +TupleValue Value::GetTuple() const { + assert(tag == ValKind::TupleV); + return u.tuple; +} + +Address Value::GetPointer() const { + assert(tag == ValKind::PtrV); + return u.ptr; +} + +std::string* Value::GetVariableType() const { + assert(tag == ValKind::VarTV); + return u.var_type; +} + +VariablePatternValue Value::GetVariablePattern() const { + assert(tag == ValKind::VarPatV); + return u.var_pat; +} + +FunctionTypeValue Value::GetFunctionType() const { + assert(tag == ValKind::FunctionTV); + return u.fun_type; +} + +PointerType Value::GetPointerType() const { + assert(tag == ValKind::PointerTV); + return u.ptr_type; +} + +StructType Value::GetStructType() const { + assert(tag == ValKind::StructTV); + return u.struct_type; +} + +ChoiceType Value::GetChoiceType() const { + assert(tag == ValKind::ChoiceTV); + return u.choice_type; +} + +ContinuationValue Value::GetContinuation() const { + assert(tag == ValKind::ContinuationV); + return u.continuation; +} + auto FindInVarValues(const std::string& field, VarValues* inits) -> const Value* { for (auto& i : *inits) { @@ -42,7 +117,7 @@ auto FieldsEqual(VarValues* ts1, VarValues* ts2) -> bool { auto FindTupleField(const std::string& name, const Value* tuple) -> std::optional
{ assert(tuple->tag == ValKind::TupleV); - for (const TupleElement& element : *tuple->u.tuple.elements) { + for (const TupleElement& element : *tuple->GetTuple().elements) { if (element.name == name) { return element.address; } @@ -50,22 +125,22 @@ auto FindTupleField(const std::string& name, const Value* tuple) return std::nullopt; } -auto MakeIntVal(int i) -> const Value* { +auto Value::MakeIntVal(int i) -> const Value* { auto* v = new Value(); v->tag = ValKind::IntV; v->u.integer = i; return v; } -auto MakeBoolVal(bool b) -> const Value* { +auto Value::MakeBoolVal(bool b) -> const Value* { auto* v = new Value(); v->tag = ValKind::BoolV; v->u.boolean = b; return v; } -auto MakeFunVal(std::string name, const Value* param, const Statement* body) - -> const Value* { +auto Value::MakeFunVal(std::string name, const Value* param, + const Statement* body) -> const Value* { auto* v = new Value(); v->tag = ValKind::FunV; v->u.fun.name = new std::string(std::move(name)); @@ -74,14 +149,15 @@ auto MakeFunVal(std::string name, const Value* param, const Statement* body) return v; } -auto MakePtrVal(Address addr) -> const Value* { +auto Value::MakePtrVal(Address addr) -> const Value* { auto* v = new Value(); v->tag = ValKind::PtrV; v->u.ptr = addr; return v; } -auto MakeStructVal(const Value* type, const Value* inits) -> const Value* { +auto Value::MakeStructVal(const Value* type, const Value* inits) + -> const Value* { auto* v = new Value(); v->tag = ValKind::StructV; v->u.struct_val.type = type; @@ -89,15 +165,15 @@ auto MakeStructVal(const Value* type, const Value* inits) -> const Value* { return v; } -auto MakeTupleVal(std::vector* elements) -> const Value* { +auto Value::MakeTupleVal(std::vector* elements) -> const Value* { auto* v = new Value(); v->tag = ValKind::TupleV; v->u.tuple.elements = elements; return v; } -auto MakeAltVal(std::string alt_name, std::string choice_name, Address argument) - -> const Value* { +auto Value::MakeAltVal(std::string alt_name, std::string choice_name, + Address argument) -> const Value* { auto* v = new Value(); v->tag = ValKind::AltV; v->u.alt.alt_name = new std::string(std::move(alt_name)); @@ -106,7 +182,7 @@ auto MakeAltVal(std::string alt_name, std::string choice_name, Address argument) return v; } -auto MakeAltCons(std::string alt_name, std::string choice_name) +auto Value::MakeAltCons(std::string alt_name, std::string choice_name) -> const Value* { auto* v = new Value(); v->tag = ValKind::AltConsV; @@ -117,14 +193,14 @@ auto MakeAltCons(std::string alt_name, std::string choice_name) // Return a first-class continuation represented a fragment // of the stack. -auto MakeContinuation(std::vector stack) -> Value* { +auto Value::MakeContinuation(std::vector stack) -> Value* { auto* v = new Value(); v->tag = ValKind::ContinuationV; v->u.continuation.stack = new std::vector(stack); return v; } -auto MakeVarPatVal(std::string name, const Value* type) -> const Value* { +auto Value::MakeVarPatVal(std::string name, const Value* type) -> const Value* { auto* v = new Value(); v->tag = ValKind::VarPatV; v->u.var_pat.name = new std::string(std::move(name)); @@ -132,45 +208,46 @@ auto MakeVarPatVal(std::string name, const Value* type) -> const Value* { return v; } -auto MakeVarTypeVal(std::string name) -> const Value* { +auto Value::MakeVarTypeVal(std::string name) -> const Value* { auto* v = new Value(); v->tag = ValKind::VarTV; v->u.var_type = new std::string(std::move(name)); return v; } -auto MakeIntTypeVal() -> const Value* { +auto Value::MakeIntTypeVal() -> const Value* { auto* v = new Value(); v->tag = ValKind::IntTV; return v; } -auto MakeBoolTypeVal() -> const Value* { +auto Value::MakeBoolTypeVal() -> const Value* { auto* v = new Value(); v->tag = ValKind::BoolTV; return v; } -auto MakeTypeTypeVal() -> const Value* { +auto Value::MakeTypeTypeVal() -> const Value* { auto* v = new Value(); v->tag = ValKind::TypeTV; return v; } // Return a Continuation type. -auto MakeContinuationTypeVal() -> const Value* { +auto Value::MakeContinuationTypeVal() -> const Value* { auto* v = new Value(); v->tag = ValKind::ContinuationTV; return v; } -auto MakeAutoTypeVal() -> const Value* { +auto Value::MakeAutoTypeVal() -> const Value* { auto* v = new Value(); v->tag = ValKind::AutoTV; return v; } -auto MakeFunTypeVal(const Value* param, const Value* ret) -> const Value* { +auto Value::MakeFunTypeVal(const Value* param, const Value* ret) + -> const Value* { auto* v = new Value(); v->tag = ValKind::FunctionTV; v->u.fun_type.param = param; @@ -178,15 +255,15 @@ auto MakeFunTypeVal(const Value* param, const Value* ret) -> const Value* { return v; } -auto MakePtrTypeVal(const Value* type) -> const Value* { +auto Value::MakePtrTypeVal(const Value* type) -> const Value* { auto* v = new Value(); v->tag = ValKind::PointerTV; v->u.ptr_type.type = type; return v; } -auto MakeStructTypeVal(std::string name, VarValues* fields, VarValues* methods) - -> const Value* { +auto Value::MakeStructTypeVal(std::string name, VarValues* fields, + VarValues* methods) -> const Value* { auto* v = new Value(); v->tag = ValKind::StructTV; v->u.struct_type.name = new std::string(std::move(name)); @@ -195,15 +272,15 @@ auto MakeStructTypeVal(std::string name, VarValues* fields, VarValues* methods) return v; } -auto MakeVoidTypeVal() -> const Value* { +auto Value::MakeVoidTypeVal() -> const Value* { auto* v = new Value(); v->tag = ValKind::TupleV; v->u.tuple.elements = new std::vector(); return v; } -auto MakeChoiceTypeVal(std::string name, - std::list>* alts) +auto Value::MakeChoiceTypeVal( + std::string name, std::list>* alts) -> const Value* { auto* v = new Value(); v->tag = ValKind::ChoiceTV; @@ -216,29 +293,30 @@ auto MakeChoiceTypeVal(std::string name, auto PrintValue(const Value* val, std::ostream& out) -> void { switch (val->tag) { case ValKind::AltConsV: { - out << *val->u.alt_cons.choice_name << "." << *val->u.alt_cons.alt_name; + out << *val->GetAlternativeConstructor().choice_name << "." + << *val->GetAlternativeConstructor().alt_name; break; } case ValKind::VarPatV: { - PrintValue(val->u.var_pat.type, out); - out << ": " << *val->u.var_pat.name; + PrintValue(val->GetVariablePattern().type, out); + out << ": " << *val->GetVariablePattern().name; break; } case ValKind::AltV: { - out << "alt " << *val->u.alt.choice_name << "." << *val->u.alt.alt_name - << " "; - state->heap.PrintAddress(val->u.alt.argument, out); + out << "alt " << *val->GetAlternative().choice_name << "." + << *val->GetAlternative().alt_name << " "; + state->heap.PrintAddress(val->GetAlternative().argument, out); break; } case ValKind::StructV: { - out << *val->u.struct_val.type->u.struct_type.name; - PrintValue(val->u.struct_val.inits, out); + out << *val->GetStruct().type->GetStructType().name; + PrintValue(val->GetStruct().inits, out); break; } case ValKind::TupleV: { out << "("; bool add_commas = false; - for (const TupleElement& element : *val->u.tuple.elements) { + for (const TupleElement& element : *val->GetTuple().elements) { if (add_commas) { out << ", "; } else { @@ -253,16 +331,16 @@ auto PrintValue(const Value* val, std::ostream& out) -> void { break; } case ValKind::IntV: - out << val->u.integer; + out << val->GetInteger(); break; case ValKind::BoolV: - out << std::boolalpha << val->u.boolean; + out << std::boolalpha << val->GetBoolean(); break; case ValKind::FunV: - out << "fun<" << *val->u.fun.name << ">"; + out << "fun<" << *val->GetFunction().name << ">"; break; case ValKind::PtrV: - out << "ptr<" << val->u.ptr << ">"; + out << "ptr<" << val->GetPointer() << ">"; break; case ValKind::BoolTV: out << "Bool"; @@ -281,27 +359,27 @@ auto PrintValue(const Value* val, std::ostream& out) -> void { break; case ValKind::PointerTV: out << "Ptr("; - PrintValue(val->u.ptr_type.type, out); + PrintValue(val->GetPointerType().type, out); out << ")"; break; case ValKind::FunctionTV: out << "fn "; - PrintValue(val->u.fun_type.param, out); + PrintValue(val->GetFunctionType().param, out); out << " -> "; - PrintValue(val->u.fun_type.ret, out); + PrintValue(val->GetFunctionType().ret, out); break; case ValKind::VarTV: - out << *val->u.var_type; + out << *val->GetVariableType(); break; case ValKind::StructTV: - out << "struct " << *val->u.struct_type.name; + out << "struct " << *val->GetStructType().name; break; case ValKind::ChoiceTV: - out << "choice " << *val->u.choice_type.name; + out << "choice " << *val->GetChoiceType().name; break; case ValKind::ContinuationV: out << "continuation[["; - for (Frame* frame : *val->u.continuation.stack) { + for (Frame* frame : *val->GetContinuation().stack) { PrintFrame(frame, out); out << " :: "; } @@ -316,28 +394,29 @@ auto TypeEqual(const Value* t1, const Value* t2) -> bool { } switch (t1->tag) { case ValKind::VarTV: - return *t1->u.var_type == *t2->u.var_type; + return *t1->GetVariableType() == *t2->GetVariableType(); case ValKind::PointerTV: - return TypeEqual(t1->u.ptr_type.type, t2->u.ptr_type.type); + return TypeEqual(t1->GetPointerType().type, t2->GetPointerType().type); case ValKind::FunctionTV: - return TypeEqual(t1->u.fun_type.param, t2->u.fun_type.param) && - TypeEqual(t1->u.fun_type.ret, t2->u.fun_type.ret); + return TypeEqual(t1->GetFunctionType().param, + t2->GetFunctionType().param) && + TypeEqual(t1->GetFunctionType().ret, t2->GetFunctionType().ret); case ValKind::StructTV: - return *t1->u.struct_type.name == *t2->u.struct_type.name; + return *t1->GetStructType().name == *t2->GetStructType().name; case ValKind::ChoiceTV: - return *t1->u.choice_type.name == *t2->u.choice_type.name; + return *t1->GetChoiceType().name == *t2->GetChoiceType().name; case ValKind::TupleV: { - if (t1->u.tuple.elements->size() != t2->u.tuple.elements->size()) { + if (t1->GetTuple().elements->size() != t2->GetTuple().elements->size()) { return false; } - for (size_t i = 0; i < t1->u.tuple.elements->size(); ++i) { - if ((*t1->u.tuple.elements)[i].name != - (*t2->u.tuple.elements)[i].name) { + for (size_t i = 0; i < t1->GetTuple().elements->size(); ++i) { + if ((*t1->GetTuple().elements)[i].name != + (*t2->GetTuple().elements)[i].name) { return false; } if (!TypeEqual( - state->heap.Read((*t1->u.tuple.elements)[i].address, 0), - state->heap.Read((*t2->u.tuple.elements)[i].address, 0))) { + state->heap.Read((*t1->GetTuple().elements)[i].address, 0), + state->heap.Read((*t2->GetTuple().elements)[i].address, 0))) { return false; } } @@ -389,15 +468,15 @@ auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool { } switch (v1->tag) { case ValKind::IntV: - return v1->u.integer == v2->u.integer; + return v1->GetInteger() == v2->GetInteger(); case ValKind::BoolV: - return v1->u.boolean == v2->u.boolean; + return v1->GetBoolean() == v2->GetBoolean(); case ValKind::PtrV: - return v1->u.ptr == v2->u.ptr; + return v1->GetPointer() == v2->GetPointer(); case ValKind::FunV: - return v1->u.fun.body == v2->u.fun.body; + return v1->GetFunction().body == v2->GetFunction().body; case ValKind::TupleV: - return FieldsValueEqual(v1->u.tuple.elements, v2->u.tuple.elements, + return FieldsValueEqual(v1->GetTuple().elements, v2->GetTuple().elements, line_num); default: case ValKind::VarTV: @@ -425,7 +504,7 @@ auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool { auto ToInteger(const Value* v) -> int { switch (v->tag) { case ValKind::IntV: - return v->u.integer; + return v->GetInteger(); default: std::cerr << "expected an integer, not "; PrintValue(v, std::cerr); diff --git a/executable_semantics/interpreter/value.h b/executable_semantics/interpreter/value.h index 482fc1999454..5101a2f18c06 100644 --- a/executable_semantics/interpreter/value.h +++ b/executable_semantics/interpreter/value.h @@ -61,107 +61,135 @@ enum class ValKind { struct Frame; // used by continuation +struct Function { + std::string* name; + const Value* param; + const Statement* body; +}; + +struct StructConstructor { + const Value* type; + const Value* inits; +}; + +struct AlternativeConstructor { + std::string* alt_name; + std::string* choice_name; +}; + +struct Alternative { + std::string* alt_name; + std::string* choice_name; + Address argument; +}; + +struct TupleValue { + std::vector* elements; +}; + +struct VariablePatternValue { + std::string* name; + const Value* type; +}; + +struct FunctionTypeValue { + const Value* param; + const Value* ret; +}; + +struct PointerType { + const Value* type; +}; + +struct StructType { + std::string* name; + VarValues* fields; + VarValues* methods; +}; + +struct ChoiceType { + std::string* name; + VarValues* alternatives; +}; + +struct ContinuationValue { + std::vector* stack; +}; + struct Value { ValKind tag; + + // Constructors + + // Return a first-class continuation represented by the + // given stack, down to the nearest enclosing `__continuation`. + static auto MakeContinuation(std::vector stack) -> Value*; + static auto MakeIntVal(int i) -> const Value*; + static auto MakeBoolVal(bool b) -> const Value*; + static auto MakeFunVal(std::string name, const Value* param, + const Statement* body) -> const Value*; + static auto MakePtrVal(Address addr) -> const Value*; + static auto MakeStructVal(const Value* type, const Value* inits) + -> const Value*; + static auto MakeTupleVal(std::vector* elts) -> const Value*; + static auto MakeAltVal(std::string alt_name, std::string choice_name, + Address argument) -> const Value*; + static auto MakeAltCons(std::string alt_name, std::string choice_name) + -> const Value*; + static auto MakeVarPatVal(std::string name, const Value* type) + -> const Value*; + static auto MakeVarTypeVal(std::string name) -> const Value*; + static auto MakeIntTypeVal() -> const Value*; + static auto MakeContinuationTypeVal() -> const Value*; + static auto MakeAutoTypeVal() -> const Value*; + static auto MakeBoolTypeVal() -> const Value*; + static auto MakeTypeTypeVal() -> const Value*; + static auto MakeFunTypeVal(const Value* param, const Value* ret) + -> const Value*; + static auto MakePtrTypeVal(const Value* type) -> const Value*; + static auto MakeStructTypeVal(std::string name, VarValues* fields, + VarValues* methods) -> const Value*; + static auto MakeVoidTypeVal() -> const Value*; + static auto MakeChoiceTypeVal(std::string name, VarValues* alts) + -> const Value*; + + // Access to alternatives + int GetInteger() const; + bool GetBoolean() const; + Function GetFunction() const; + StructConstructor GetStruct() const; + AlternativeConstructor GetAlternativeConstructor() const; + Alternative GetAlternative() const; + TupleValue GetTuple() const; + Address GetPointer() const; + std::string* GetVariableType() const; + VariablePatternValue GetVariablePattern() const; + FunctionTypeValue GetFunctionType() const; + PointerType GetPointerType() const; + StructType GetStructType() const; + ChoiceType GetChoiceType() const; + ContinuationValue GetContinuation() const; + + private: union { int integer; bool boolean; - - struct { - std::string* name; - const Value* param; - const Statement* body; - } fun; - - struct { - const Value* type; - const Value* inits; - } struct_val; - - struct { - std::string* alt_name; - std::string* choice_name; - } alt_cons; - - struct { - std::string* alt_name; - std::string* choice_name; - Address argument; - } alt; - - struct { - std::vector* elements; - } tuple; - + Function fun; + StructConstructor struct_val; + AlternativeConstructor alt_cons; + Alternative alt; + TupleValue tuple; Address ptr; std::string* var_type; - - struct { - std::string* name; - const Value* type; - } var_pat; - - struct { - const Value* param; - const Value* ret; - } fun_type; - - struct { - const Value* type; - } ptr_type; - - struct { - std::string* name; - VarValues* fields; - VarValues* methods; - } struct_type; - - struct { - std::string* name; - VarValues* alternatives; - } choice_type; - - struct { - std::list* params; - const Value* type; - } implicit; - - struct { - std::vector* stack; - } continuation; - + VariablePatternValue var_pat; + FunctionTypeValue fun_type; + PointerType ptr_type; + StructType struct_type; + ChoiceType choice_type; + ContinuationValue continuation; } u; }; -// Return a first-class continuation represented by the -// given stack, down to the nearest enclosing `__continuation`. -auto MakeContinuation(std::vector stack) -> Value*; -auto MakeIntVal(int i) -> const Value*; -auto MakeBoolVal(bool b) -> const Value*; -auto MakeFunVal(std::string name, const Value* param, const Statement* body) - -> const Value*; -auto MakePtrVal(Address addr) -> const Value*; -auto MakeStructVal(const Value* type, const Value* inits) -> const Value*; -auto MakeTupleVal(std::vector* elts) -> const Value*; -auto MakeAltVal(std::string alt_name, std::string choice_name, Address argument) - -> const Value*; -auto MakeAltCons(std::string alt_name, std::string choice_name) -> const Value*; - -auto MakeVarPatVal(std::string name, const Value* type) -> const Value*; - -auto MakeVarTypeVal(std::string name) -> const Value*; -auto MakeIntTypeVal() -> const Value*; -auto MakeContinuationTypeVal() -> const Value*; -auto MakeAutoTypeVal() -> const Value*; -auto MakeBoolTypeVal() -> const Value*; -auto MakeTypeTypeVal() -> const Value*; -auto MakeFunTypeVal(const Value* param, const Value* ret) -> const Value*; -auto MakePtrTypeVal(const Value* type) -> const Value*; -auto MakeStructTypeVal(std::string name, VarValues* fields, VarValues* methods) - -> const Value*; -auto MakeVoidTypeVal() -> const Value*; -auto MakeChoiceTypeVal(std::string name, VarValues* alts) -> const Value*; - void PrintValue(const Value* val, std::ostream& out); auto TypeEqual(const Value* t1, const Value* t2) -> bool; diff --git a/executable_semantics/syntax/paren_contents.cpp b/executable_semantics/syntax/paren_contents.cpp index bb494931e46e..d4b4cbe3199b 100644 --- a/executable_semantics/syntax/paren_contents.cpp +++ b/executable_semantics/syntax/paren_contents.cpp @@ -16,7 +16,8 @@ const Expression* ParenContents::AsExpression(int line_number) const { } const Expression* ParenContents::AsTuple(int line_number) const { - return MakeTuple(line_number, new std::vector(fields_)); + return Expression::MakeTuple(line_number, + new std::vector(fields_)); } } // namespace Carbon diff --git a/executable_semantics/syntax/paren_contents_test.cpp b/executable_semantics/syntax/paren_contents_test.cpp index f22636eb8b84..b9f508e363f2 100644 --- a/executable_semantics/syntax/paren_contents_test.cpp +++ b/executable_semantics/syntax/paren_contents_test.cpp @@ -14,7 +14,7 @@ TEST(ParenContentsTest, EmptyAsExpression) { const Expression* expression = contents.AsExpression(/*line_num=*/1); EXPECT_EQ(expression->line_num, 1); ASSERT_EQ(expression->tag, ExpressionKind::Tuple); - EXPECT_EQ(expression->u.tuple.fields->size(), 0); + EXPECT_EQ(expression->GetTuple().fields->size(), 0); } TEST(ParenContentsTest, EmptyAsTuple) { @@ -22,7 +22,7 @@ TEST(ParenContentsTest, EmptyAsTuple) { const Expression* tuple = contents.AsTuple(/*line_num=*/1); EXPECT_EQ(tuple->line_num, 1); ASSERT_EQ(tuple->tag, ExpressionKind::Tuple); - EXPECT_EQ(tuple->u.tuple.fields->size(), 0); + EXPECT_EQ(tuple->GetTuple().fields->size(), 0); } TEST(ParenContentsTest, UnaryNoCommaAsExpression) { @@ -32,8 +32,9 @@ TEST(ParenContentsTest, UnaryNoCommaAsExpression) { // 42 // ) // ``` - ParenContents contents({{.expression = MakeInt(/*line_num=*/2, 42)}}, - ParenContents::HasTrailingComma::No); + ParenContents contents( + {{.expression = Expression::MakeInt(/*line_num=*/2, 42)}}, + ParenContents::HasTrailingComma::No); const Expression* expression = contents.AsExpression(/*line_num=*/1); EXPECT_EQ(expression->line_num, 2); @@ -41,64 +42,69 @@ TEST(ParenContentsTest, UnaryNoCommaAsExpression) { } TEST(ParenContentsTest, UnaryNoCommaAsTuple) { - ParenContents contents({{.expression = MakeInt(/*line_num=*/2, 42)}}, - ParenContents::HasTrailingComma::No); + ParenContents contents( + {{.expression = Expression::MakeInt(/*line_num=*/2, 42)}}, + ParenContents::HasTrailingComma::No); const Expression* tuple = contents.AsTuple(/*line_num=*/1); EXPECT_EQ(tuple->line_num, 1); ASSERT_EQ(tuple->tag, ExpressionKind::Tuple); - std::vector fields = *tuple->u.tuple.fields; + std::vector fields = *tuple->GetTuple().fields; ASSERT_EQ(fields.size(), 1); EXPECT_EQ(fields[0].expression->tag, ExpressionKind::Integer); } TEST(ParenContentsTest, UnaryWithCommaAsExpression) { - ParenContents contents({{.expression = MakeInt(/*line_num=*/2, 42)}}, - ParenContents::HasTrailingComma::Yes); + ParenContents contents( + {{.expression = Expression::MakeInt(/*line_num=*/2, 42)}}, + ParenContents::HasTrailingComma::Yes); const Expression* expression = contents.AsExpression(/*line_num=*/1); EXPECT_EQ(expression->line_num, 1); ASSERT_EQ(expression->tag, ExpressionKind::Tuple); - std::vector fields = *expression->u.tuple.fields; + std::vector fields = *expression->GetTuple().fields; ASSERT_EQ(fields.size(), 1); EXPECT_EQ(fields[0].expression->tag, ExpressionKind::Integer); } TEST(ParenContentsTest, UnaryWithCommaAsTuple) { - ParenContents contents({{.expression = MakeInt(/*line_num=*/2, 42)}}, - ParenContents::HasTrailingComma::Yes); + ParenContents contents( + {{.expression = Expression::MakeInt(/*line_num=*/2, 42)}}, + ParenContents::HasTrailingComma::Yes); const Expression* tuple = contents.AsTuple(/*line_num=*/1); EXPECT_EQ(tuple->line_num, 1); ASSERT_EQ(tuple->tag, ExpressionKind::Tuple); - std::vector fields = *tuple->u.tuple.fields; + std::vector fields = *tuple->GetTuple().fields; ASSERT_EQ(fields.size(), 1); EXPECT_EQ(fields[0].expression->tag, ExpressionKind::Integer); } TEST(ParenContentsTest, BinaryAsExpression) { - ParenContents contents({{.expression = MakeInt(/*line_num=*/2, 42)}, - {.expression = MakeInt(/*line_num=*/3, 42)}}, - ParenContents::HasTrailingComma::Yes); + ParenContents contents( + {{.expression = Expression::MakeInt(/*line_num=*/2, 42)}, + {.expression = Expression::MakeInt(/*line_num=*/3, 42)}}, + ParenContents::HasTrailingComma::Yes); const Expression* expression = contents.AsExpression(/*line_num=*/1); EXPECT_EQ(expression->line_num, 1); ASSERT_EQ(expression->tag, ExpressionKind::Tuple); - std::vector fields = *expression->u.tuple.fields; + std::vector fields = *expression->GetTuple().fields; ASSERT_EQ(fields.size(), 2); EXPECT_EQ(fields[0].expression->tag, ExpressionKind::Integer); EXPECT_EQ(fields[1].expression->tag, ExpressionKind::Integer); } TEST(ParenContentsTest, BinaryAsTuple) { - ParenContents contents({{.expression = MakeInt(/*line_num=*/2, 42)}, - {.expression = MakeInt(/*line_num=*/3, 42)}}, - ParenContents::HasTrailingComma::Yes); + ParenContents contents( + {{.expression = Expression::MakeInt(/*line_num=*/2, 42)}, + {.expression = Expression::MakeInt(/*line_num=*/3, 42)}}, + ParenContents::HasTrailingComma::Yes); const Expression* tuple = contents.AsTuple(/*line_num=*/1); EXPECT_EQ(tuple->line_num, 1); ASSERT_EQ(tuple->tag, ExpressionKind::Tuple); - std::vector fields = *tuple->u.tuple.fields; + std::vector fields = *tuple->GetTuple().fields; ASSERT_EQ(fields.size(), 2); EXPECT_EQ(fields[0].expression->tag, ExpressionKind::Integer); EXPECT_EQ(fields[1].expression->tag, ExpressionKind::Integer); diff --git a/executable_semantics/syntax/parser.ypp b/executable_semantics/syntax/parser.ypp index 946b35776682..2ed74be3cb88 100644 --- a/executable_semantics/syntax/parser.ypp +++ b/executable_semantics/syntax/parser.ypp @@ -184,48 +184,48 @@ pattern: ; expression: identifier - { $$ = Carbon::MakeVar(yylineno, $1); } + { $$ = Carbon::Expression::MakeVar(yylineno, $1); } | expression designator - { $$ = Carbon::MakeGetField(yylineno, $1, $2); } + { $$ = Carbon::Expression::MakeGetField(yylineno, $1, $2); } | expression "[" expression "]" - { $$ = Carbon::MakeIndex(yylineno, $1, $3); } + { $$ = Carbon::Expression::MakeIndex(yylineno, $1, $3); } | expression ":" identifier - { $$ = Carbon::MakeVarPat(yylineno, $3, $1); } + { $$ = Carbon::Expression::MakeVarPat(yylineno, $3, $1); } | integer_literal - { $$ = Carbon::MakeInt(yylineno, $1); } + { $$ = Carbon::Expression::MakeInt(yylineno, $1); } | TRUE - { $$ = Carbon::MakeBool(yylineno, true); } + { $$ = Carbon::Expression::MakeBool(yylineno, true); } | FALSE - { $$ = Carbon::MakeBool(yylineno, false); } + { $$ = Carbon::Expression::MakeBool(yylineno, false); } | INT - { $$ = Carbon::MakeIntType(yylineno); } + { $$ = Carbon::Expression::MakeIntType(yylineno); } | BOOL - { $$ = Carbon::MakeBoolType(yylineno); } + { $$ = Carbon::Expression::MakeBoolType(yylineno); } | TYPE - { $$ = Carbon::MakeTypeType(yylineno); } + { $$ = Carbon::Expression::MakeTypeType(yylineno); } | AUTO - { $$ = Carbon::MakeAutoType(yylineno); } + { $$ = Carbon::Expression::MakeAutoType(yylineno); } | CONTINUATION_TYPE - { $$ = Carbon::MakeContinuationType(yylineno); } + { $$ = Carbon::Expression::MakeContinuationType(yylineno); } | paren_expression { $$ = $1; } | expression EQUAL_EQUAL expression - { $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Eq, $1, $3); } + { $$ = Carbon::Expression::MakeBinOp(yylineno, Carbon::Operator::Eq, $1, $3); } | expression "+" expression - { $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Add, $1, $3); } + { $$ = Carbon::Expression::MakeBinOp(yylineno, Carbon::Operator::Add, $1, $3); } | expression "-" expression - { $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Sub, $1, $3); } + { $$ = Carbon::Expression::MakeBinOp(yylineno, Carbon::Operator::Sub, $1, $3); } | expression AND expression - { $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::And, $1, $3); } + { $$ = Carbon::Expression::MakeBinOp(yylineno, Carbon::Operator::And, $1, $3); } | expression OR expression - { $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Or, $1, $3); } + { $$ = Carbon::Expression::MakeBinOp(yylineno, Carbon::Operator::Or, $1, $3); } | NOT expression - { $$ = Carbon::MakeUnOp(yylineno, Carbon::Operator::Not, $2); } + { $$ = Carbon::Expression::MakeUnOp(yylineno, Carbon::Operator::Not, $2); } | "-" expression %prec UNARY_MINUS - { $$ = Carbon::MakeUnOp(yylineno, Carbon::Operator::Neg, $2); } + { $$ = Carbon::Expression::MakeUnOp(yylineno, Carbon::Operator::Neg, $2); } | expression tuple - { $$ = Carbon::MakeCall(yylineno, $1, $2); } + { $$ = Carbon::Expression::MakeCall(yylineno, $1, $2); } | FNTY tuple return_type - { $$ = Carbon::MakeFunType(yylineno, $2, $3); } + { $$ = Carbon::Expression::MakeFunType(yylineno, $2, $3); } ; designator: "." identifier { $$ = $2; } ; @@ -269,8 +269,8 @@ clause: { $$ = new std::pair($2, $4); } | DEFAULT DBLARROW statement { - auto vp = Carbon::MakeVarPat(yylineno, "_", - Carbon::MakeAutoType(yylineno)); + auto vp = Carbon::Expression::MakeVarPat(yylineno, "_", + Carbon::Expression::MakeAutoType(yylineno)); $$ = new std::pair(vp, $3); } ; @@ -284,31 +284,31 @@ clause_list: ; statement: expression "=" expression ";" - { $$ = Carbon::MakeAssign(yylineno, $1, $3); } + { $$ = Carbon::Statement::MakeAssign(yylineno, $1, $3); } | VAR pattern "=" expression ";" - { $$ = Carbon::MakeVarDef(yylineno, $2, $4); } + { $$ = Carbon::Statement::MakeVarDef(yylineno, $2, $4); } | expression ";" - { $$ = Carbon::MakeExpStmt(yylineno, $1); } + { $$ = Carbon::Statement::MakeExpStmt(yylineno, $1); } | IF "(" expression ")" statement optional_else - { $$ = Carbon::MakeIf(yylineno, $3, $5, $6); } + { $$ = Carbon::Statement::MakeIf(yylineno, $3, $5, $6); } | WHILE "(" expression ")" statement - { $$ = Carbon::MakeWhile(yylineno, $3, $5); } + { $$ = Carbon::Statement::MakeWhile(yylineno, $3, $5); } | BREAK ";" - { $$ = Carbon::MakeBreak(yylineno); } + { $$ = Carbon::Statement::MakeBreak(yylineno); } | CONTINUE ";" - { $$ = Carbon::MakeContinue(yylineno); } + { $$ = Carbon::Statement::MakeContinue(yylineno); } | RETURN expression ";" - { $$ = Carbon::MakeReturn(yylineno, $2); } + { $$ = Carbon::Statement::MakeReturn(yylineno, $2); } | "{" statement_list "}" - { $$ = Carbon::MakeBlock(yylineno, $2); } + { $$ = Carbon::Statement::MakeBlock(yylineno, $2); } | MATCH "(" expression ")" "{" clause_list "}" - { $$ = Carbon::MakeMatch(yylineno, $3, $6); } + { $$ = Carbon::Statement::MakeMatch(yylineno, $3, $6); } | CONTINUATION identifier statement - { $$ = Carbon::MakeContinuationStatement(yylineno, $2, $3); } + { $$ = Carbon::Statement::MakeContinuation(yylineno, $2, $3); } | RUN expression ";" - { $$ = Carbon::MakeRun(yylineno, $2); } + { $$ = Carbon::Statement::MakeRun(yylineno, $2); } | AWAIT ";" - { $$ = Carbon::MakeAwait(yylineno); } + { $$ = Carbon::Statement::MakeAwait(yylineno); } ; optional_else: // Empty @@ -319,11 +319,11 @@ statement_list: // Empty { $$ = 0; } | statement statement_list - { $$ = Carbon::MakeSeq(yylineno, $1, $2); } + { $$ = Carbon::Statement::MakeSeq(yylineno, $1, $2); } ; return_type: // Empty - { $$ = Carbon::MakeUnit(yylineno); } + { $$ = Carbon::Expression::MakeUnit(yylineno); } | ARROW expression { $$ = $2; } ; @@ -332,8 +332,8 @@ function_definition: { $$ = MakeFunDef(yylineno, $2, $4, $3, $6); } | FN identifier tuple DBLARROW expression ";" { - $$ = Carbon::MakeFunDef(yylineno, $2, Carbon::MakeAutoType(yylineno), $3, - Carbon::MakeReturn(yylineno, $5)); + $$ = Carbon::MakeFunDef(yylineno, $2, Carbon::Expression::MakeAutoType(yylineno), $3, + Carbon::Statement::MakeReturn(yylineno, $5)); } ; function_declaration: @@ -358,7 +358,7 @@ alternative: | identifier { $$ = new std::pair( - $1, Carbon::MakeUnit(yylineno)); + $1, Carbon::Expression::MakeUnit(yylineno)); } ; alternative_list: