diff --git a/executable_semantics/ast/declaration.h b/executable_semantics/ast/declaration.h index 48934045cf86..13c706456f25 100644 --- a/executable_semantics/ast/declaration.h +++ b/executable_semantics/ast/declaration.h @@ -18,7 +18,7 @@ namespace Carbon { struct Value; using Address = unsigned int; -using TypeEnv = Dictionary; +using TypeEnv = Dictionary; using Env = Dictionary; struct TypeCheckContext { diff --git a/executable_semantics/interpreter/action.cpp b/executable_semantics/interpreter/action.cpp index c35186f03fa4..e35397e7ef92 100644 --- a/executable_semantics/interpreter/action.cpp +++ b/executable_semantics/interpreter/action.cpp @@ -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; diff --git a/executable_semantics/interpreter/action.h b/executable_semantics/interpreter/action.h index 72643287b1cc..c8eb132f1e96 100644 --- a/executable_semantics/interpreter/action.h +++ b/executable_semantics/interpreter/action.h @@ -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 results; // results from subexpression + int pos; // position or state of the action + std::vector results; // results from subexpression }; void PrintAct(Action* act, std::ostream& out); @@ -41,7 +41,7 @@ void PrintActList(Stack 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*; diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index e4852e28cd9c..654f3317204f 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -22,8 +22,8 @@ namespace Carbon { State* state = nullptr; -auto PatternMatch(Value* pat, Value* val, Env, std::list*, int) - -> std::optional; +auto PatternMatch(const Value* pat, const Value* val, Env, + std::list*, int) -> std::optional; void HandleValue(); template @@ -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>(); 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 ls, std::ostream& out) { } } -void PrintHeap(const std::vector& heap, std::ostream& out) { +void PrintHeap(const std::vector& 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& args, int line_num) - -> Value* { +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)); @@ -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 operas, State* state) { +void CallFunction(int line_num, std::vector 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 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* vars, - int line_num) -> std::optional { +auto PatternMatch(const Value* p, const Value* v, Env env, + std::list* vars, int line_num) + -> std::optional { 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* 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_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* 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()); 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; } diff --git a/executable_semantics/interpreter/interpreter.h b/executable_semantics/interpreter/interpreter.h index 345d3d87c359..79ea809e4dd3 100644 --- a/executable_semantics/interpreter/interpreter.h +++ b/executable_semantics/interpreter/interpreter.h @@ -40,21 +40,21 @@ struct Frame { struct State { Stack stack; - std::vector heap; + std::vector heap; std::vector 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* fs) -> int; -auto InterpExp(Env env, Expression* e) -> Value*; +auto InterpExp(Env env, Expression* e) -> const Value*; } // namespace Carbon diff --git a/executable_semantics/interpreter/typecheck.cpp b/executable_semantics/interpreter/typecheck.cpp index 1dea406d2c80..f3f7fae19019 100644 --- a/executable_semantics/interpreter/typecheck.cpp +++ b/executable_semantics/interpreter/typecheck.cpp @@ -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 type = env.Get(*(e->u.variable.name)); + std::optional 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(); - std::vector ts; + std::vector 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 { 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); } diff --git a/executable_semantics/interpreter/typecheck.h b/executable_semantics/interpreter/typecheck.h index 419d2b46aa7a..de1628def1ec 100644 --- a/executable_semantics/interpreter/typecheck.h +++ b/executable_semantics/interpreter/typecheck.h @@ -14,17 +14,18 @@ namespace Carbon { -using TypeEnv = Dictionary; +using TypeEnv = Dictionary; 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*; diff --git a/executable_semantics/interpreter/value.cpp b/executable_semantics/interpreter/value.cpp index d08f2eed751c..d085bfbdf742 100644 --- a/executable_semantics/interpreter/value.cpp +++ b/executable_semantics/interpreter/value.cpp @@ -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>* 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>* 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>* alts) - -> Value* { + std::list>* 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; diff --git a/executable_semantics/interpreter/value.h b/executable_semantics/interpreter/value.h index 2b26894cd9d6..0027d1c378db 100644 --- a/executable_semantics/interpreter/value.h +++ b/executable_semantics/interpreter/value.h @@ -14,9 +14,10 @@ namespace Carbon { struct Value; using Address = unsigned int; -using VarValues = std::list>; +using VarValues = std::list>; -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* 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>* 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>* 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