const-ify Value*s in preparation for value semantic transformation (#409)

Making Values const allows us to separate the actual mutations (search for "*&" in this change) from places where the Value is effectively passed by-value.
This commit is contained in:
Dave Abrahams
2021-03-21 09:00:00 -07:00
committed by GitHub
parent 1da97fc9cf
commit dd4e37e761
9 changed files with 149 additions and 139 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ namespace Carbon {
struct Value;
using Address = unsigned int;
using TypeEnv = Dictionary<std::string, Value*>;
using TypeEnv = Dictionary<std::string, const Value*>;
using Env = Dictionary<std::string, Address>;
struct TypeCheckContext {
+1 -1
View File
@@ -83,7 +83,7 @@ auto MakeStmtAct(Statement* s) -> Action* {
return act;
}
auto MakeValAct(Value* v) -> Action* {
auto MakeValAct(const Value* v) -> Action* {
auto* act = new Action();
act->tag = ActionKind::ValAction;
act->u.val = v;
+4 -4
View File
@@ -29,11 +29,11 @@ struct Action {
union {
Expression* exp; // for LValAction and ExpressionAction
Statement* stmt;
Value* val; // for finished actions with a value (ValAction)
const Value* val; // for finished actions with a value (ValAction)
Address delete_tmp;
} u;
int pos; // position or state of the action
std::vector<Value*> results; // results from subexpression
int pos; // position or state of the action
std::vector<const Value*> results; // results from subexpression
};
void PrintAct(Action* act, std::ostream& out);
@@ -41,7 +41,7 @@ void PrintActList(Stack<Action*> ls, std::ostream& out);
auto MakeExpAct(Expression* e) -> Action*;
auto MakeLvalAct(Expression* e) -> Action*;
auto MakeStmtAct(Statement* s) -> Action*;
auto MakeValAct(Value* v) -> Action*;
auto MakeValAct(const Value* v) -> Action*;
auto MakeExpToLvalAct() -> Action*;
auto MakeDeleteAct(Address a) -> Action*;
@@ -22,8 +22,8 @@ namespace Carbon {
State* state = nullptr;
auto PatternMatch(Value* pat, Value* val, Env, std::list<std::string>*, int)
-> std::optional<Env>;
auto PatternMatch(const Value* pat, const Value* val, Env,
std::list<std::string>*, int) -> std::optional<Env>;
void HandleValue();
template <class T>
@@ -42,37 +42,37 @@ static auto FindField(const std::string& field,
// Auxiliary Functions
//
auto AllocateValue(Value* v) -> Address {
auto AllocateValue(const Value* v) -> Address {
// Putting the following two side effects together in this function
// ensures that we don't do anything else in between, which is really bad!
// Consider whether to include a copy of the input v in this function
// or to leave it up to the caller.
Address a = state->heap.size();
state->heap.push_back(v);
state->heap.push_back(new Value(*v));
state->alive.push_back(true);
return a;
}
auto CopyVal(Value* val, int line_num) -> Value* {
auto CopyVal(const Value* val, int line_num) -> const Value* {
switch (val->tag) {
case ValKind::TupleV: {
auto elts = new std::vector<std::pair<std::string, Address>>();
for (auto& i : *val->u.tuple.elts) {
CheckAlive(i.second, line_num);
Value* elt = CopyVal(state->heap[i.second], line_num);
const Value* elt = CopyVal(state->heap[i.second], line_num);
Address new_address = AllocateValue(elt);
elts->push_back(make_pair(i.first, new_address));
}
return MakeTupleVal(elts);
}
case ValKind::AltV: {
Value* arg = CopyVal(state->heap[val->u.alt.argument], line_num);
const Value* arg = CopyVal(state->heap[val->u.alt.argument], line_num);
Address argument_address = AllocateValue(arg);
return MakeAltVal(*val->u.alt.alt_name, *val->u.alt.choice_name,
argument_address);
}
case ValKind::StructV: {
Value* inits = CopyVal(val->u.struct_val.inits, line_num);
const Value* inits = CopyVal(val->u.struct_val.inits, line_num);
return MakeStructVal(val->u.struct_val.type, inits);
}
case ValKind::IntV:
@@ -119,7 +119,7 @@ auto CopyVal(Value* val, int line_num) -> Value* {
void KillObject(Address address);
// Marks all of the sub-objects of this value as dead.
void KillSubObjects(Value* val) {
void KillSubObjects(const Value* val) {
switch (val->tag) {
case ValKind::AltV:
KillObject(val->u.alt.argument);
@@ -177,7 +177,7 @@ void PrintStack(Stack<Frame*> ls, std::ostream& out) {
}
}
void PrintHeap(const std::vector<Value*>& heap, std::ostream& out) {
void PrintHeap(const std::vector<const Value*>& heap, std::ostream& out) {
for (auto& iter : heap) {
if (iter) {
PrintValue(iter, out);
@@ -208,7 +208,7 @@ void PrintState(std::ostream& out) {
// More Auxiliary Functions
//
auto ValToInt(Value* v, int line_num) -> int {
auto ValToInt(const Value* v, int line_num) -> int {
switch (v->tag) {
case ValKind::IntV:
return v->u.integer;
@@ -219,7 +219,7 @@ auto ValToInt(Value* v, int line_num) -> int {
}
}
auto ValToBool(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;
@@ -229,7 +229,7 @@ auto ValToBool(Value* v, int line_num) -> int {
}
}
auto ValToPtr(Value* v, int line_num) -> Address {
auto ValToPtr(const Value* v, int line_num) -> Address {
CheckAlive(v->u.ptr, line_num);
switch (v->tag) {
case ValKind::PtrV:
@@ -242,8 +242,8 @@ auto ValToPtr(Value* v, int line_num) -> Address {
}
}
auto EvalPrim(Operator op, const std::vector<Value*>& args, int line_num)
-> Value* {
auto EvalPrim(Operator op, const std::vector<const Value*>& args, int line_num)
-> const Value* {
switch (op) {
case Operator::Neg:
return MakeIntVal(-ValToInt(args[0], line_num));
@@ -325,7 +325,8 @@ auto VariableDeclaration::InitGlobals(Env& globals) const -> void {
// where C is the body of the function,
// E is the environment (functions + parameters + locals)
// F is the function
void CallFunction(int line_num, std::vector<Value*> operas, State* state) {
void CallFunction(int line_num, std::vector<const Value*> operas,
State* state) {
switch (operas[0]->tag) {
case ValKind::FunV: {
// Bind arguments to parameters
@@ -345,15 +346,15 @@ void CallFunction(int line_num, std::vector<Value*> operas, State* state) {
break;
}
case ValKind::StructTV: {
Value* arg = CopyVal(operas[1], line_num);
Value* sv = MakeStructVal(operas[0], arg);
const Value* arg = CopyVal(operas[1], line_num);
const Value* sv = MakeStructVal(operas[0], arg);
Frame* frame = state->stack.Top();
frame->todo.Push(MakeValAct(sv));
break;
}
case ValKind::AltConsV: {
Value* arg = CopyVal(operas[1], line_num);
Value* av =
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, AllocateValue(arg));
Frame* frame = state->stack.Top();
@@ -394,7 +395,7 @@ void CreateTuple(Frame* frame, Action* act, Expression* /*exp*/) {
Address a = AllocateValue(*i); // copy?
elts->push_back(make_pair(f->first, a));
}
Value* tv = MakeTupleVal(elts);
const Value* tv = MakeTupleVal(elts);
frame->todo.Pop(1);
frame->todo.Push(MakeValAct(tv));
}
@@ -404,8 +405,9 @@ void CreateTuple(Frame* frame, Action* act, Expression* /*exp*/) {
//
// The names of the pattern variables are added to the vars parameter.
// Returns nullopt if the value doesn't match the pattern.
auto PatternMatch(Value* p, Value* v, Env env, std::list<std::string>* vars,
int line_num) -> std::optional<Env> {
auto PatternMatch(const Value* p, const Value* v, Env env,
std::list<std::string>* vars, int line_num)
-> std::optional<Env> {
switch (p->tag) {
case ValKind::VarPatV: {
Address a = AllocateValue(CopyVal(v, line_num));
@@ -491,7 +493,7 @@ auto PatternMatch(Value* p, Value* v, Env env, std::list<std::string>* vars,
}
}
void PatternAssignment(Value* pat, Value* val, int line_num) {
void PatternAssignment(const Value* pat, const Value* val, int line_num) {
switch (pat->tag) {
case ValKind::PtrV:
state->heap[ValToPtr(pat, line_num)] = val;
@@ -579,7 +581,7 @@ void StepLvalue() {
<< *(exp->u.variable.name) << "`" << std::endl;
exit(-1);
}
Value* v = MakePtrVal(*pointer);
const Value* v = MakePtrVal(*pointer);
CheckAlive(*pointer, exp->line_num);
frame->todo.Pop();
frame->todo.Push(MakeValAct(v));
@@ -676,7 +678,7 @@ void StepExp() {
<< *(exp->u.variable.name) << "`" << std::endl;
exit(-1);
}
Value* pointee = state->heap[*pointer];
const Value* pointee = state->heap[*pointer];
frame->todo.Pop(1);
frame->todo.Push(MakeValAct(pointee));
break;
@@ -700,7 +702,7 @@ void StepExp() {
} else {
// { {v :: op(]) :: C, E, F} :: S, H}
// -> { {eval_prim(op, ()) :: C, E, F} :: S, H}
Value* v =
const Value* v =
EvalPrim(exp->u.primitive_op.op, act->results, exp->line_num);
frame->todo.Pop(2);
frame->todo.Push(MakeValAct(v));
@@ -713,25 +715,25 @@ void StepExp() {
act->pos++;
break;
case ExpressionKind::IntT: {
Value* v = MakeIntTypeVal();
const Value* v = MakeIntTypeVal();
frame->todo.Pop(1);
frame->todo.Push(MakeValAct(v));
break;
}
case ExpressionKind::BoolT: {
Value* v = MakeBoolTypeVal();
const Value* v = MakeBoolTypeVal();
frame->todo.Pop(1);
frame->todo.Push(MakeValAct(v));
break;
}
case ExpressionKind::AutoT: {
Value* v = MakeAutoTypeVal();
const Value* v = MakeAutoTypeVal();
frame->todo.Pop(1);
frame->todo.Push(MakeValAct(v));
break;
}
case ExpressionKind::TypeT: {
Value* v = MakeTypeTypeVal();
const Value* v = MakeTypeTypeVal();
frame->todo.Pop(1);
frame->todo.Push(MakeValAct(v));
break;
@@ -878,7 +880,7 @@ void StepStmt() {
}
auto GetMember(Address a, const std::string& f) -> Address {
Value* v = state->heap[a];
const Value* v = state->heap[a];
switch (v->tag) {
case ValKind::StructV: {
auto a = FindField(f, *v->u.struct_val.inits->u.tuple.elts);
@@ -980,7 +982,7 @@ void HandleValue() {
case ExpressionKind::GetField: {
// { v :: [].f :: C, E, F} :: S, H}
// -> { { &v.f :: C, E, F} :: S, H }
Value* str = act->results[0];
const Value* str = act->results[0];
Address a =
GetMember(ValToPtr(str, exp->line_num), *exp->u.get_field.field);
frame->todo.Pop(2);
@@ -994,7 +996,7 @@ void HandleValue() {
} else if (act->pos == 2) {
// { v :: [][i] :: C, E, F} :: S, H}
// -> { { &v[i] :: C, E, F} :: S, H }
Value* tuple = act->results[0];
const Value* tuple = act->results[0];
std::string f = std::to_string(ToInteger(act->results[1]));
auto a = FindField(f, *tuple->u.tuple.elts);
if (a == std::nullopt) {
@@ -1107,7 +1109,7 @@ void HandleValue() {
} else {
// { {v :: op(vs,[]) :: C, E, F} :: S, H}
// -> { {eval_prim(op, (vs,v)) :: C, E, F} :: S, H}
Value* v =
const Value* v =
EvalPrim(exp->u.primitive_op.op, act->results, exp->line_num);
frame->todo.Pop(2);
frame->todo.Push(MakeValAct(v));
@@ -1136,7 +1138,7 @@ void HandleValue() {
if (act->pos == 2) {
// { { rt :: fn pt -> [] :: C, E, F} :: S, H}
// -> { fn pt -> rt :: {C, E, F} :: S, H}
Value* v = MakeFunTypeVal(act->results[0], act->results[1]);
const Value* v = MakeFunTypeVal(act->results[0], act->results[1]);
frame->todo.Pop(2);
frame->todo.Push(MakeValAct(v));
} else {
@@ -1173,8 +1175,8 @@ void HandleValue() {
} else if (act->pos == 2) {
// { { v :: (x = []) :: C, E, F} :: S, H}
// -> { { C, E(x := a), F} :: S, H(a := copy(v))}
Value* v = act->results[0];
Value* p = act->results[1];
const Value* v = act->results[0];
const Value* p = act->results[1];
std::optional<Env> env_with_matches =
PatternMatch(p, v, frame->scopes.Top()->env,
@@ -1302,7 +1304,7 @@ void HandleValue() {
case StatementKind::Return: {
// { {v :: return [] :: C, E, F} :: {C', E', F'} :: S, H}
// -> { {v :: C', E', F'} :: S, H}
Value* ret_val = CopyVal(val_act->u.val, stmt->line_num);
const Value* ret_val = CopyVal(val_act->u.val, stmt->line_num);
KillLocals(stmt->line_num, frame);
state->stack.Pop(1);
frame = state->stack.Top();
@@ -1389,12 +1391,12 @@ auto InterpProgram(std::list<Declaration>* fs) -> int {
PrintState(std::cout);
}
}
Value* v = state->stack.Top()->todo.Top()->u.val;
const Value* v = state->stack.Top()->todo.Top()->u.val;
return ValToInt(v, 0);
}
// Interpret an expression at compile-time.
auto InterpExp(Env env, Expression* e) -> Value* {
auto InterpExp(Env env, Expression* e) -> const Value* {
auto todo = Stack(MakeExpAct(e));
auto* scope = new Scope(env, std::list<std::string>());
auto* frame = new Frame("InterpExp", Stack(scope), todo);
@@ -1405,7 +1407,7 @@ auto InterpExp(Env env, Expression* e) -> Value* {
state->stack.Top()->todo.Top()->tag != ActionKind::ValAction) {
Step();
}
Value* v = state->stack.Top()->todo.Top()->u.val;
const Value* v = state->stack.Top()->todo.Top()->u.val;
return v;
}
@@ -40,21 +40,21 @@ struct Frame {
struct State {
Stack<Frame*> stack;
std::vector<Value*> heap;
std::vector<const Value*> heap;
std::vector<bool> alive;
};
extern State* state;
void PrintEnv(Env env);
auto AllocateValue(Value* v) -> Address;
auto CopyVal(Value* val, int line_num) -> Value*;
auto ToInteger(Value* v) -> int;
auto AllocateValue(const Value* v) -> Address;
auto CopyVal(const Value* val, int line_num) -> const Value*;
auto ToInteger(const Value* v) -> int;
/***** Interpreters *****/
auto InterpProgram(std::list<Declaration>* fs) -> int;
auto InterpExp(Env env, Expression* e) -> Value*;
auto InterpExp(Env env, Expression* e) -> const Value*;
} // namespace Carbon
+21 -20
View File
@@ -16,8 +16,8 @@
namespace Carbon {
void ExpectType(int line_num, const std::string& context, Value* expected,
Value* actual) {
void ExpectType(int line_num, const std::string& context, const Value* expected,
const Value* actual) {
if (!TypeEqual(expected, actual)) {
std::cerr << line_num << ": type error in " << context << std::endl;
std::cerr << "expected: ";
@@ -40,12 +40,12 @@ void PrintTypeEnv(TypeEnv env, std::ostream& out) {
}
// Convert tuples to tuple types.
auto ToType(int line_num, Value* val) -> Value* {
auto ToType(int line_num, const Value* val) -> const Value* {
switch (val->tag) {
case ValKind::TupleV: {
auto fields = new VarValues();
for (auto& elt : *val->u.tuple.elts) {
Value* ty = ToType(line_num, state->heap[elt.second]);
const Value* ty = ToType(line_num, state->heap[elt.second]);
fields->push_back(std::make_pair(elt.first, ty));
}
return MakeTupleTypeVal(fields);
@@ -53,7 +53,7 @@ auto ToType(int line_num, Value* val) -> Value* {
case ValKind::TupleTV: {
auto fields = new VarValues();
for (auto& field : *val->u.tuple_type.fields) {
Value* ty = ToType(line_num, field.second);
const Value* ty = ToType(line_num, field.second);
fields->push_back(std::make_pair(field.first, ty));
}
return MakeTupleTypeVal(fields);
@@ -86,7 +86,7 @@ auto ToType(int line_num, Value* val) -> Value* {
}
// Reify type to type expression.
auto ReifyType(Value* t, int line_num) -> Expression* {
auto ReifyType(const Value* t, int line_num) -> Expression* {
switch (t->tag) {
case ValKind::VarTV:
return MakeVar(0, *t->u.var_type);
@@ -137,7 +137,7 @@ auto ReifyType(Value* t, int line_num) -> Expression* {
// and it is used to implement `auto`, otherwise it is null.
// context says what kind of position this expression is nested in,
// whether it's a position that expects a value, a pattern, or a type.
auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, Value* expected,
auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
TCContext context) -> TCResult {
switch (e->tag) {
case ExpressionKind::PatternVariable: {
@@ -198,7 +198,7 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, Value* expected,
int i = 0;
for (auto arg = e->u.tuple.fields->begin();
arg != e->u.tuple.fields->end(); ++arg, ++i) {
Value* arg_expected = nullptr;
const Value* arg_expected = nullptr;
if (expected && expected->tag == ValKind::TupleTV) {
arg_expected =
FindInVarValues(arg->first, expected->u.tuple_type.fields);
@@ -281,7 +281,7 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, Value* expected,
}
}
case ExpressionKind::Variable: {
std::optional<Value*> type = env.Get(*(e->u.variable.name));
std::optional<const Value*> type = env.Get(*(e->u.variable.name));
if (type) {
return TCResult(e, *type, env);
} else {
@@ -296,7 +296,7 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, Value* expected,
return TCResult(e, MakeBoolTypeVal(), env);
case ExpressionKind::PrimitiveOp: {
auto es = new std::vector<Expression*>();
std::vector<Value*> ts;
std::vector<const Value*> ts;
auto new_env = env;
for (auto& argument : *e->u.primitive_op.arguments) {
auto res = TypeCheckExp(argument, env, ct_env, nullptr,
@@ -389,8 +389,8 @@ auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, Value* expected,
}
}
auto TypecheckCase(Value* expected, Expression* pat, Statement* body,
TypeEnv env, Env ct_env, Value* ret_type)
auto TypecheckCase(const Value* expected, Expression* pat, Statement* body,
TypeEnv env, Env ct_env, const Value*& ret_type)
-> std::pair<Expression*, Statement*> {
auto pat_res =
TypeCheckExp(pat, env, ct_env, expected, TCContext::PatternContext);
@@ -405,8 +405,8 @@ auto TypecheckCase(Value* expected, Expression* pat, Statement* body,
// It is the declared return type of the enclosing function definition.
// If the return type is "auto", then the return type is inferred from
// the first return statement.
auto TypeCheckStmt(Statement* s, TypeEnv env, Env ct_env, Value* ret_type)
-> TCStatement {
auto TypeCheckStmt(Statement* s, TypeEnv env, Env ct_env,
const Value*& ret_type) -> TCStatement {
if (!s) {
return TCStatement(s, env);
}
@@ -443,7 +443,7 @@ auto TypeCheckStmt(Statement* s, TypeEnv env, Env ct_env, Value* ret_type)
case StatementKind::VariableDefinition: {
auto res = TypeCheckExp(s->u.variable_definition.init, env, ct_env,
nullptr, TCContext::ValueContext);
Value* rhs_ty = res.type;
const Value* rhs_ty = res.type;
auto lhs_res = TypeCheckExp(s->u.variable_definition.pat, env, ct_env,
rhs_ty, TCContext::PatternContext);
Statement* new_s =
@@ -494,7 +494,7 @@ auto TypeCheckStmt(Statement* s, TypeEnv env, Env ct_env, Value* ret_type)
// The following infers the return type from the first 'return'
// statement. This will get more difficult with subtyping, when we
// should infer the least-upper bound of all the 'return' statements.
*ret_type = *res.type;
ret_type = res.type;
} else {
ExpectType(s->line_num, "return", ret_type, res.type);
}
@@ -587,7 +587,7 @@ auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv env, Env ct_env)
}
auto TypeOfFunDef(TypeEnv env, Env ct_env, const FunctionDefinition* fun_def)
-> Value* {
-> const Value* {
auto param_res = TypeCheckExp(fun_def->param_pattern, env, ct_env, nullptr,
TCContext::PatternContext);
auto param_type = ToType(fun_def->line_num, param_res.type);
@@ -600,7 +600,7 @@ auto TypeOfFunDef(TypeEnv env, Env ct_env, const FunctionDefinition* fun_def)
}
auto TypeOfStructDef(const StructDefinition* sd, TypeEnv /*env*/, Env ct_top)
-> Value* {
-> const Value* {
auto fields = new VarValues();
auto methods = new VarValues();
for (auto m = sd->members->begin(); m != sd->members->end(); ++m) {
@@ -652,7 +652,7 @@ auto VariableDeclaration::TypeChecked(TypeEnv env, Env ct_env) const
-> Declaration {
TCResult type_checked_initializer =
TypeCheckExp(initializer, env, ct_env, nullptr, TCContext::ValueContext);
Value* declared_type = ToType(source_location, InterpExp(ct_env, type));
const Value* declared_type = ToType(source_location, InterpExp(ct_env, type));
ExpectType(source_location, "initializer of variable", declared_type,
type_checked_initializer.type);
return *this;
@@ -706,7 +706,8 @@ auto ChoiceDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
// Associate the variable name with it's declared type in the
// compile-time symbol table.
auto VariableDeclaration::TopLevel(TypeCheckContext& tops) const -> void {
Value* declared_type = ToType(source_location, InterpExp(tops.values, type));
const Value* declared_type =
ToType(source_location, InterpExp(tops.values, type));
tops.types.Set(Name(), declared_type);
}
+7 -6
View File
@@ -14,17 +14,18 @@
namespace Carbon {
using TypeEnv = Dictionary<std::string, Value*>;
using TypeEnv = Dictionary<std::string, const Value*>;
void PrintTypeEnv(TypeEnv env);
enum class TCContext { ValueContext, PatternContext, TypeContext };
struct TCResult {
TCResult(Expression* e, Value* t, TypeEnv env) : exp(e), type(t), env(env) {}
TCResult(Expression* e, const Value* t, TypeEnv env)
: exp(e), type(t), env(env) {}
Expression* exp;
Value* type;
const Value* type;
TypeEnv env;
};
@@ -35,12 +36,12 @@ struct TCStatement {
TypeEnv env;
};
auto ToType(int line_num, Value* val) -> Value*;
auto ToType(int line_num, const Value* val) -> const Value*;
auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, Value* expected,
auto TypeCheckExp(Expression* e, TypeEnv env, Env ct_env, const Value* expected,
TCContext context) -> TCResult;
auto TypeCheckStmt(Statement*, TypeEnv, Env, Value*) -> TCStatement;
auto TypeCheckStmt(Statement*, TypeEnv, Env, Value const*&) -> TCStatement;
auto TypeCheckFunDef(struct FunctionDefinition*, TypeEnv)
-> struct FunctionDefinition*;
+29 -26
View File
@@ -10,7 +10,8 @@
namespace Carbon {
auto FindInVarValues(const std::string& field, VarValues* inits) -> Value* {
auto FindInVarValues(const std::string& field, VarValues* inits)
-> const Value* {
for (auto& i : *inits) {
if (i.first == field) {
return i.second;
@@ -36,21 +37,22 @@ auto FieldsEqual(VarValues* ts1, VarValues* ts2) -> bool {
}
}
auto MakeIntVal(int i) -> Value* {
auto MakeIntVal(int i) -> const Value* {
auto* v = new Value();
v->tag = ValKind::IntV;
v->u.integer = i;
return v;
}
auto MakeBoolVal(bool b) -> Value* {
auto MakeBoolVal(bool b) -> const Value* {
auto* v = new Value();
v->tag = ValKind::BoolV;
v->u.boolean = b;
return v;
}
auto MakeFunVal(std::string name, Value* param, Statement* body) -> Value* {
auto MakeFunVal(std::string name, const Value* param, Statement* body)
-> const Value* {
auto* v = new Value();
v->tag = ValKind::FunV;
v->u.fun.name = new std::string(std::move(name));
@@ -59,14 +61,14 @@ auto MakeFunVal(std::string name, Value* param, Statement* body) -> Value* {
return v;
}
auto MakePtrVal(Address addr) -> Value* {
auto MakePtrVal(Address addr) -> const Value* {
auto* v = new Value();
v->tag = ValKind::PtrV;
v->u.ptr = addr;
return v;
}
auto MakeStructVal(Value* type, Value* inits) -> Value* {
auto MakeStructVal(const Value* type, const Value* inits) -> const Value* {
auto* v = new Value();
v->tag = ValKind::StructV;
v->u.struct_val.type = type;
@@ -75,7 +77,7 @@ auto MakeStructVal(Value* type, Value* inits) -> Value* {
}
auto MakeTupleVal(std::vector<std::pair<std::string, Address>>* elts)
-> Value* {
-> const Value* {
auto* v = new Value();
v->tag = ValKind::TupleV;
v->u.tuple.elts = elts;
@@ -83,7 +85,7 @@ auto MakeTupleVal(std::vector<std::pair<std::string, Address>>* elts)
}
auto MakeAltVal(std::string alt_name, std::string choice_name, Address argument)
-> Value* {
-> const Value* {
auto* v = new Value();
v->tag = ValKind::AltV;
v->u.alt.alt_name = new std::string(std::move(alt_name));
@@ -92,7 +94,8 @@ auto MakeAltVal(std::string alt_name, std::string choice_name, Address argument)
return v;
}
auto MakeAltCons(std::string alt_name, std::string choice_name) -> Value* {
auto MakeAltCons(std::string alt_name, std::string choice_name)
-> const Value* {
auto* v = new Value();
v->tag = ValKind::AltConsV;
v->u.alt.alt_name = new std::string(std::move(alt_name));
@@ -100,7 +103,7 @@ auto MakeAltCons(std::string alt_name, std::string choice_name) -> Value* {
return v;
}
auto MakeVarPatVal(std::string name, Value* type) -> Value* {
auto 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));
@@ -108,38 +111,38 @@ auto MakeVarPatVal(std::string name, Value* type) -> Value* {
return v;
}
auto MakeVarTypeVal(std::string name) -> Value* {
auto 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() -> Value* {
auto MakeIntTypeVal() -> const Value* {
auto* v = new Value();
v->tag = ValKind::IntTV;
return v;
}
auto MakeBoolTypeVal() -> Value* {
auto MakeBoolTypeVal() -> const Value* {
auto* v = new Value();
v->tag = ValKind::BoolTV;
return v;
}
auto MakeTypeTypeVal() -> Value* {
auto MakeTypeTypeVal() -> const Value* {
auto* v = new Value();
v->tag = ValKind::TypeTV;
return v;
}
auto MakeAutoTypeVal() -> Value* {
auto MakeAutoTypeVal() -> const Value* {
auto* v = new Value();
v->tag = ValKind::AutoTV;
return v;
}
auto MakeFunTypeVal(Value* param, Value* ret) -> Value* {
auto MakeFunTypeVal(const Value* param, const Value* ret) -> const Value* {
auto* v = new Value();
v->tag = ValKind::FunctionTV;
v->u.fun_type.param = param;
@@ -147,7 +150,7 @@ auto MakeFunTypeVal(Value* param, Value* ret) -> Value* {
return v;
}
auto MakePtrTypeVal(Value* type) -> Value* {
auto MakePtrTypeVal(const Value* type) -> const Value* {
auto* v = new Value();
v->tag = ValKind::PointerTV;
v->u.ptr_type.type = type;
@@ -155,7 +158,7 @@ auto MakePtrTypeVal(Value* type) -> Value* {
}
auto MakeStructTypeVal(std::string name, VarValues* fields, VarValues* methods)
-> Value* {
-> const Value* {
auto* v = new Value();
v->tag = ValKind::StructTV;
v->u.struct_type.name = new std::string(std::move(name));
@@ -164,14 +167,14 @@ auto MakeStructTypeVal(std::string name, VarValues* fields, VarValues* methods)
return v;
}
auto MakeTupleTypeVal(VarValues* fields) -> Value* {
auto MakeTupleTypeVal(VarValues* fields) -> const Value* {
auto* v = new Value();
v->tag = ValKind::TupleTV;
v->u.tuple_type.fields = fields;
return v;
}
auto MakeVoidTypeVal() -> Value* {
auto MakeVoidTypeVal() -> const Value* {
auto* v = new Value();
v->tag = ValKind::TupleTV;
v->u.tuple_type.fields = new VarValues();
@@ -179,8 +182,8 @@ auto MakeVoidTypeVal() -> Value* {
}
auto MakeChoiceTypeVal(std::string name,
std::list<std::pair<std::string, Value*>>* alts)
-> Value* {
std::list<std::pair<std::string, const Value*>>* alts)
-> const Value* {
auto* v = new Value();
v->tag = ValKind::ChoiceTV;
// Transitional leak: when we get rid of all pointers, this will disappear.
@@ -189,7 +192,7 @@ auto MakeChoiceTypeVal(std::string name,
return v;
}
void PrintValue(Value* val, std::ostream& out) {
void PrintValue(const Value* val, std::ostream& out) {
switch (val->tag) {
case ValKind::AltConsV: {
out << *val->u.alt_cons.choice_name << "." << *val->u.alt_cons.alt_name;
@@ -291,7 +294,7 @@ void PrintValue(Value* val, std::ostream& out) {
}
}
auto TypeEqual(Value* t1, Value* t2) -> bool {
auto TypeEqual(const Value* t1, const Value* t2) -> bool {
if (t1->tag != t2->tag) {
return false;
}
@@ -334,7 +337,7 @@ static auto FieldsValueEqual(VarValues* ts1, VarValues* ts2, int line_num)
return true;
}
auto ValueEqual(Value* v1, Value* v2, int line_num) -> bool {
auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool {
if (v1->tag != v2->tag) {
return false;
}
@@ -357,7 +360,7 @@ auto ValueEqual(Value* v1, Value* v2, int line_num) -> bool {
}
}
auto ToInteger(Value* v) -> int {
auto ToInteger(const Value* v) -> int {
switch (v->tag) {
case ValKind::IntV:
return v->u.integer;
+37 -34
View File
@@ -14,9 +14,10 @@ namespace Carbon {
struct Value;
using Address = unsigned int;
using VarValues = std::list<std::pair<std::string, Value*>>;
using VarValues = std::list<std::pair<std::string, const Value*>>;
auto FindInVarValues(const std::string& field, VarValues* inits) -> Value*;
auto FindInVarValues(const std::string& field, VarValues* inits)
-> const Value*;
auto FieldsEqual(VarValues* ts1, VarValues* ts2) -> bool;
enum class ValKind {
@@ -48,12 +49,12 @@ struct Value {
bool boolean;
struct {
std::string* name;
Value* param;
const Value* param;
Statement* body;
} fun;
struct {
Value* type;
Value* inits;
const Value* type;
const Value* inits;
} struct_val;
struct {
std::string* alt_name;
@@ -71,14 +72,14 @@ struct Value {
std::string* var_type;
struct {
std::string* name;
Value* type;
const Value* type;
} var_pat;
struct {
Value* param;
Value* ret;
const Value* param;
const Value* ret;
} fun_type;
struct {
Value* type;
const Value* type;
} ptr_type;
struct {
std::string* name;
@@ -95,42 +96,44 @@ struct Value {
} choice_type;
struct {
std::list<std::string*>* params;
Value* type;
const Value* type;
} implicit;
} u;
};
auto MakeIntVal(int i) -> Value*;
auto MakeBoolVal(bool b) -> Value*;
auto MakeFunVal(std::string name, Value* param, Statement* body) -> Value*;
auto MakePtrVal(Address addr) -> Value*;
auto MakeStructVal(Value* type, Value* inits) -> Value*;
auto MakeTupleVal(std::vector<std::pair<std::string, Address>>* elts) -> Value*;
auto MakeIntVal(int i) -> const Value*;
auto MakeBoolVal(bool b) -> const Value*;
auto MakeFunVal(std::string name, const Value* param, Statement* body)
-> const Value*;
auto MakePtrVal(Address addr) -> const Value*;
auto MakeStructVal(const Value* type, const Value* inits) -> const Value*;
auto MakeTupleVal(std::vector<std::pair<std::string, Address>>* elts)
-> const Value*;
auto MakeAltVal(std::string alt_name, std::string choice_name, Address argument)
-> Value*;
auto MakeAltCons(std::string alt_name, std::string choice_name) -> Value*;
-> const Value*;
auto MakeAltCons(std::string alt_name, std::string choice_name) -> const Value*;
auto MakeVarPatVal(std::string name, Value* type) -> Value*;
auto MakeVarPatVal(std::string name, const Value* type) -> const Value*;
auto MakeVarTypeVal(std::string name) -> Value*;
auto MakeIntTypeVal() -> Value*;
auto MakeAutoTypeVal() -> Value*;
auto MakeBoolTypeVal() -> Value*;
auto MakeTypeTypeVal() -> Value*;
auto MakeFunTypeVal(Value* param, Value* ret) -> Value*;
auto MakePtrTypeVal(Value* type) -> Value*;
auto MakeVarTypeVal(std::string name) -> const Value*;
auto MakeIntTypeVal() -> 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)
-> Value*;
auto MakeTupleTypeVal(VarValues* fields) -> Value*;
auto MakeVoidTypeVal() -> Value*;
auto MakeChoiceTypeVal(std::string name, VarValues* alts) -> Value*;
-> const Value*;
auto MakeTupleTypeVal(VarValues* fields) -> const Value*;
auto MakeVoidTypeVal() -> const Value*;
auto MakeChoiceTypeVal(std::string name, VarValues* alts) -> const Value*;
void PrintValue(Value* val, std::ostream& out);
void PrintValue(const Value* val, std::ostream& out);
auto TypeEqual(Value* t1, Value* t2) -> bool;
auto ValueEqual(Value* v1, Value* v2, int line_num) -> bool;
auto TypeEqual(const Value* t1, const Value* t2) -> bool;
auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool;
auto ToInteger(Value* v) -> int;
auto ToInteger(const Value* v) -> int;
void CheckAlive(Address a, int line_num);
} // namespace Carbon