value.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #include "executable_semantics/interpreter/value.h"
  5. #include <algorithm>
  6. #include <iostream>
  7. #include "common/check.h"
  8. namespace Carbon {
  9. auto Value::GetIntValue() const -> int {
  10. return std::get<IntValue>(value).value;
  11. }
  12. auto Value::GetBoolValue() const -> bool {
  13. return std::get<BoolValue>(value).value;
  14. }
  15. auto Value::GetFunctionValue() const -> const FunctionValue& {
  16. return std::get<FunctionValue>(value);
  17. }
  18. auto Value::GetStructValue() const -> const StructValue& {
  19. return std::get<StructValue>(value);
  20. }
  21. auto Value::GetAlternativeConstructorValue() const
  22. -> const AlternativeConstructorValue& {
  23. return std::get<AlternativeConstructorValue>(value);
  24. }
  25. auto Value::GetAlternativeValue() const -> const AlternativeValue& {
  26. return std::get<AlternativeValue>(value);
  27. }
  28. auto Value::GetTupleValue() const -> const TupleValue& {
  29. return std::get<TupleValue>(value);
  30. }
  31. auto Value::GetPointerValue() const -> Address {
  32. return std::get<PointerValue>(value).value;
  33. }
  34. auto Value::GetBindingPlaceholderValue() const
  35. -> const BindingPlaceholderValue& {
  36. return std::get<BindingPlaceholderValue>(value);
  37. }
  38. auto Value::GetFunctionType() const -> const FunctionType& {
  39. return std::get<FunctionType>(value);
  40. }
  41. auto Value::GetPointerType() const -> const PointerType& {
  42. return std::get<PointerType>(value);
  43. }
  44. auto Value::GetStructType() const -> const StructType& {
  45. return std::get<StructType>(value);
  46. }
  47. auto Value::GetChoiceType() const -> const ChoiceType& {
  48. return std::get<ChoiceType>(value);
  49. }
  50. auto Value::GetContinuationValue() const -> const ContinuationValue& {
  51. return std::get<ContinuationValue>(value);
  52. }
  53. auto FindInVarValues(const std::string& field, const VarValues& inits)
  54. -> const Value* {
  55. for (auto& i : inits) {
  56. if (i.first == field) {
  57. return i.second;
  58. }
  59. }
  60. return nullptr;
  61. }
  62. auto FieldsEqual(const VarValues& ts1, const VarValues& ts2) -> bool {
  63. if (ts1.size() == ts2.size()) {
  64. for (auto& iter1 : ts1) {
  65. auto t2 = FindInVarValues(iter1.first, ts2);
  66. if (t2 == nullptr) {
  67. return false;
  68. }
  69. if (!TypeEqual(iter1.second, t2)) {
  70. return false;
  71. }
  72. }
  73. return true;
  74. } else {
  75. return false;
  76. }
  77. }
  78. auto TupleValue::FindField(const std::string& name) const -> const Value* {
  79. for (const TupleElement& element : elements) {
  80. if (element.name == name) {
  81. return element.value;
  82. }
  83. }
  84. return nullptr;
  85. }
  86. auto Value::MakeIntValue(int i) -> const Value* {
  87. auto* v = new Value();
  88. v->value = IntValue({.value = i});
  89. return v;
  90. }
  91. auto Value::MakeBoolValue(bool b) -> const Value* {
  92. auto* v = new Value();
  93. v->value = BoolValue({.value = b});
  94. return v;
  95. }
  96. auto Value::MakeFunctionValue(std::string name, const Value* param,
  97. const Statement* body) -> const Value* {
  98. auto* v = new Value();
  99. v->value =
  100. FunctionValue({.name = std::move(name), .param = param, .body = body});
  101. return v;
  102. }
  103. auto Value::MakePointerValue(Address addr) -> const Value* {
  104. auto* v = new Value();
  105. v->value = PointerValue({.value = addr});
  106. return v;
  107. }
  108. auto Value::MakeStructValue(const Value* type, const Value* inits)
  109. -> const Value* {
  110. auto* v = new Value();
  111. v->value = StructValue({.type = type, .inits = inits});
  112. return v;
  113. }
  114. auto Value::MakeTupleValue(std::vector<TupleElement> elements) -> const Value* {
  115. auto* v = new Value();
  116. v->value = TupleValue({.elements = std::move(elements)});
  117. return v;
  118. }
  119. auto Value::MakeAlternativeValue(std::string alt_name, std::string choice_name,
  120. const Value* argument) -> const Value* {
  121. auto* v = new Value();
  122. v->value = AlternativeValue({.alt_name = std::move(alt_name),
  123. .choice_name = std::move(choice_name),
  124. .argument = argument});
  125. return v;
  126. }
  127. auto Value::MakeAlternativeConstructorValue(std::string alt_name,
  128. std::string choice_name)
  129. -> const Value* {
  130. auto* v = new Value();
  131. v->value = AlternativeConstructorValue(
  132. {.alt_name = std::move(alt_name), .choice_name = std::move(choice_name)});
  133. return v;
  134. }
  135. // Return a first-class continuation represented a fragment
  136. // of the stack.
  137. auto Value::MakeContinuationValue(std::vector<Frame*> stack) -> Value* {
  138. auto* v = new Value();
  139. v->value = ContinuationValue({.stack = std::move(stack)});
  140. return v;
  141. }
  142. auto Value::MakeBindingPlaceholderValue(std::optional<std::string> name,
  143. const Value* type) -> const Value* {
  144. auto* v = new Value();
  145. v->value = BindingPlaceholderValue({.name = std::move(name), .type = type});
  146. return v;
  147. }
  148. auto Value::MakeIntType() -> const Value* {
  149. auto* v = new Value();
  150. v->value = IntType();
  151. return v;
  152. }
  153. auto Value::MakeBoolType() -> const Value* {
  154. auto* v = new Value();
  155. v->value = BoolType();
  156. return v;
  157. }
  158. auto Value::MakeTypeType() -> const Value* {
  159. auto* v = new Value();
  160. v->value = TypeType();
  161. return v;
  162. }
  163. // Return a Continuation type.
  164. auto Value::MakeContinuationType() -> const Value* {
  165. auto* v = new Value();
  166. v->value = ContinuationType();
  167. return v;
  168. }
  169. auto Value::MakeAutoType() -> const Value* {
  170. auto* v = new Value();
  171. v->value = AutoType();
  172. return v;
  173. }
  174. auto Value::MakeFunctionType(const Value* param, const Value* ret)
  175. -> const Value* {
  176. auto* v = new Value();
  177. v->value = FunctionType({.param = param, .ret = ret});
  178. return v;
  179. }
  180. auto Value::MakePointerType(const Value* type) -> const Value* {
  181. auto* v = new Value();
  182. v->value = PointerType({.type = type});
  183. return v;
  184. }
  185. auto Value::MakeStructType(std::string name, VarValues fields,
  186. VarValues methods) -> const Value* {
  187. auto* v = new Value();
  188. v->value = StructType({.name = std::move(name),
  189. .fields = std::move(fields),
  190. .methods = std::move(methods)});
  191. return v;
  192. }
  193. auto Value::MakeUnitTypeVal() -> const Value* {
  194. auto* v = new Value();
  195. v->value = TupleValue({.elements = {}});
  196. return v;
  197. }
  198. auto Value::MakeChoiceType(std::string name, VarValues alts) -> const Value* {
  199. auto* v = new Value();
  200. v->value =
  201. ChoiceType({.name = std::move(name), .alternatives = std::move(alts)});
  202. return v;
  203. }
  204. namespace {
  205. auto GetMember(const Value* v, const std::string& f, int line_num)
  206. -> const Value* {
  207. switch (v->tag()) {
  208. case ValKind::StructValue: {
  209. const Value* field =
  210. v->GetStructValue().inits->GetTupleValue().FindField(f);
  211. if (field == nullptr) {
  212. std::cerr << "runtime error, member " << f << " not in ";
  213. PrintValue(v, std::cerr);
  214. std::cerr << std::endl;
  215. exit(-1);
  216. }
  217. return field;
  218. }
  219. case ValKind::TupleValue: {
  220. const Value* field = v->GetTupleValue().FindField(f);
  221. if (field == nullptr) {
  222. std::cerr << "field " << f << " not in ";
  223. PrintValue(v, std::cerr);
  224. std::cerr << std::endl;
  225. exit(-1);
  226. }
  227. return field;
  228. }
  229. case ValKind::ChoiceType: {
  230. if (FindInVarValues(f, v->GetChoiceType().alternatives) == nullptr) {
  231. std::cerr << "alternative " << f << " not in ";
  232. PrintValue(v, std::cerr);
  233. std::cerr << std::endl;
  234. exit(-1);
  235. }
  236. return Value::MakeAlternativeConstructorValue(f, v->GetChoiceType().name);
  237. }
  238. default:
  239. std::cerr << "field access not allowed for value ";
  240. PrintValue(v, std::cerr);
  241. std::cerr << std::endl;
  242. exit(-1);
  243. }
  244. }
  245. } // namespace
  246. auto Value::GetField(const FieldPath& path, int line_num) const
  247. -> const Value* {
  248. const Value* value = this;
  249. for (const std::string& field : path.components) {
  250. value = GetMember(value, field, line_num);
  251. }
  252. return value;
  253. }
  254. namespace {
  255. auto SetFieldImpl(const Value* value,
  256. std::vector<std::string>::const_iterator path_begin,
  257. std::vector<std::string>::const_iterator path_end,
  258. const Value* field_value, int line_num) -> const Value* {
  259. if (path_begin == path_end) {
  260. return field_value;
  261. }
  262. switch (value->tag()) {
  263. case ValKind::StructValue: {
  264. return SetFieldImpl(value->GetStructValue().inits, path_begin, path_end,
  265. field_value, line_num);
  266. }
  267. case ValKind::TupleValue: {
  268. std::vector<TupleElement> elements = value->GetTupleValue().elements;
  269. auto it = std::find_if(elements.begin(), elements.end(),
  270. [path_begin](const TupleElement& element) {
  271. return element.name == *path_begin;
  272. });
  273. if (it == elements.end()) {
  274. std::cerr << "field " << *path_begin << " not in ";
  275. PrintValue(value, std::cerr);
  276. std::cerr << std::endl;
  277. exit(-1);
  278. }
  279. it->value = SetFieldImpl(it->value, path_begin + 1, path_end, field_value,
  280. line_num);
  281. return Value::MakeTupleValue(elements);
  282. }
  283. default:
  284. std::cerr << "field access not allowed for value ";
  285. PrintValue(value, std::cerr);
  286. std::cerr << std::endl;
  287. exit(-1);
  288. }
  289. }
  290. } // namespace
  291. auto Value::SetField(const FieldPath& path, const Value* field_value,
  292. int line_num) const -> const Value* {
  293. return SetFieldImpl(this, path.components.begin(), path.components.end(),
  294. field_value, line_num);
  295. }
  296. auto PrintValue(const Value* val, std::ostream& out) -> void {
  297. switch (val->tag()) {
  298. case ValKind::AlternativeConstructorValue: {
  299. out << val->GetAlternativeConstructorValue().choice_name << "."
  300. << val->GetAlternativeConstructorValue().alt_name;
  301. break;
  302. }
  303. case ValKind::BindingPlaceholderValue: {
  304. const BindingPlaceholderValue& placeholder =
  305. val->GetBindingPlaceholderValue();
  306. if (placeholder.name.has_value()) {
  307. out << *placeholder.name;
  308. } else {
  309. out << "_";
  310. }
  311. out << ": ";
  312. PrintValue(val->GetBindingPlaceholderValue().type, out);
  313. break;
  314. }
  315. case ValKind::AlternativeValue: {
  316. out << "alt " << val->GetAlternativeValue().choice_name << "."
  317. << val->GetAlternativeValue().alt_name << " ";
  318. PrintValue(val->GetAlternativeValue().argument, out);
  319. break;
  320. }
  321. case ValKind::StructValue: {
  322. out << val->GetStructValue().type->GetStructType().name;
  323. PrintValue(val->GetStructValue().inits, out);
  324. break;
  325. }
  326. case ValKind::TupleValue: {
  327. out << "(";
  328. bool add_commas = false;
  329. for (const TupleElement& element : val->GetTupleValue().elements) {
  330. if (add_commas) {
  331. out << ", ";
  332. } else {
  333. add_commas = true;
  334. }
  335. out << element.name << " = ";
  336. PrintValue(element.value, out);
  337. }
  338. out << ")";
  339. break;
  340. }
  341. case ValKind::IntValue:
  342. out << val->GetIntValue();
  343. break;
  344. case ValKind::BoolValue:
  345. out << std::boolalpha << val->GetBoolValue();
  346. break;
  347. case ValKind::FunctionValue:
  348. out << "fun<" << val->GetFunctionValue().name << ">";
  349. break;
  350. case ValKind::PointerValue:
  351. out << "ptr<" << val->GetPointerValue() << ">";
  352. break;
  353. case ValKind::BoolType:
  354. out << "Bool";
  355. break;
  356. case ValKind::IntType:
  357. out << "Int";
  358. break;
  359. case ValKind::TypeType:
  360. out << "Type";
  361. break;
  362. case ValKind::AutoType:
  363. out << "auto";
  364. break;
  365. case ValKind::ContinuationType:
  366. out << "Continuation";
  367. break;
  368. case ValKind::PointerType:
  369. PrintValue(val->GetPointerType().type, out);
  370. out << "*";
  371. break;
  372. case ValKind::FunctionType:
  373. out << "fn ";
  374. PrintValue(val->GetFunctionType().param, out);
  375. out << " -> ";
  376. PrintValue(val->GetFunctionType().ret, out);
  377. break;
  378. case ValKind::StructType:
  379. out << "struct " << val->GetStructType().name;
  380. break;
  381. case ValKind::ChoiceType:
  382. out << "choice " << val->GetChoiceType().name;
  383. break;
  384. case ValKind::ContinuationValue:
  385. out << "continuation";
  386. // TODO: Find a way to print useful information about the continuation
  387. // without creating a dependency cycle.
  388. break;
  389. }
  390. }
  391. auto CopyVal(const Value* val, int line_num) -> const Value* {
  392. switch (val->tag()) {
  393. case ValKind::TupleValue: {
  394. std::vector<TupleElement> elements;
  395. for (const TupleElement& element : val->GetTupleValue().elements) {
  396. elements.push_back(
  397. {.name = element.name, .value = CopyVal(element.value, line_num)});
  398. }
  399. return Value::MakeTupleValue(std::move(elements));
  400. }
  401. case ValKind::AlternativeValue: {
  402. const Value* arg = CopyVal(val->GetAlternativeValue().argument, line_num);
  403. return Value::MakeAlternativeValue(val->GetAlternativeValue().alt_name,
  404. val->GetAlternativeValue().choice_name,
  405. arg);
  406. }
  407. case ValKind::StructValue: {
  408. const Value* inits = CopyVal(val->GetStructValue().inits, line_num);
  409. return Value::MakeStructValue(val->GetStructValue().type, inits);
  410. }
  411. case ValKind::IntValue:
  412. return Value::MakeIntValue(val->GetIntValue());
  413. case ValKind::BoolValue:
  414. return Value::MakeBoolValue(val->GetBoolValue());
  415. case ValKind::FunctionValue:
  416. return Value::MakeFunctionValue(val->GetFunctionValue().name,
  417. val->GetFunctionValue().param,
  418. val->GetFunctionValue().body);
  419. case ValKind::PointerValue:
  420. return Value::MakePointerValue(val->GetPointerValue());
  421. case ValKind::ContinuationValue:
  422. // Copying a continuation is "shallow".
  423. return val;
  424. case ValKind::FunctionType:
  425. return Value::MakeFunctionType(
  426. CopyVal(val->GetFunctionType().param, line_num),
  427. CopyVal(val->GetFunctionType().ret, line_num));
  428. case ValKind::PointerType:
  429. return Value::MakePointerType(
  430. CopyVal(val->GetPointerType().type, line_num));
  431. case ValKind::IntType:
  432. return Value::MakeIntType();
  433. case ValKind::BoolType:
  434. return Value::MakeBoolType();
  435. case ValKind::TypeType:
  436. return Value::MakeTypeType();
  437. case ValKind::AutoType:
  438. return Value::MakeAutoType();
  439. case ValKind::ContinuationType:
  440. return Value::MakeContinuationType();
  441. case ValKind::StructType:
  442. case ValKind::ChoiceType:
  443. case ValKind::BindingPlaceholderValue:
  444. case ValKind::AlternativeConstructorValue:
  445. // TODO: These should be copied so that they don't get destructed.
  446. return val;
  447. }
  448. }
  449. auto TypeEqual(const Value* t1, const Value* t2) -> bool {
  450. if (t1->tag() != t2->tag()) {
  451. return false;
  452. }
  453. switch (t1->tag()) {
  454. case ValKind::PointerType:
  455. return TypeEqual(t1->GetPointerType().type, t2->GetPointerType().type);
  456. case ValKind::FunctionType:
  457. return TypeEqual(t1->GetFunctionType().param,
  458. t2->GetFunctionType().param) &&
  459. TypeEqual(t1->GetFunctionType().ret, t2->GetFunctionType().ret);
  460. case ValKind::StructType:
  461. return t1->GetStructType().name == t2->GetStructType().name;
  462. case ValKind::ChoiceType:
  463. return t1->GetChoiceType().name == t2->GetChoiceType().name;
  464. case ValKind::TupleValue: {
  465. if (t1->GetTupleValue().elements.size() !=
  466. t2->GetTupleValue().elements.size()) {
  467. return false;
  468. }
  469. for (size_t i = 0; i < t1->GetTupleValue().elements.size(); ++i) {
  470. if (t1->GetTupleValue().elements[i].name !=
  471. t2->GetTupleValue().elements[i].name) {
  472. return false;
  473. }
  474. if (!TypeEqual(t1->GetTupleValue().elements[i].value,
  475. t2->GetTupleValue().elements[i].value)) {
  476. return false;
  477. }
  478. }
  479. return true;
  480. }
  481. case ValKind::IntType:
  482. case ValKind::BoolType:
  483. case ValKind::ContinuationType:
  484. case ValKind::TypeType:
  485. return true;
  486. default:
  487. std::cerr << "TypeEqual used to compare non-type values" << std::endl;
  488. PrintValue(t1, std::cerr);
  489. std::cerr << std::endl;
  490. PrintValue(t2, std::cerr);
  491. exit(-1);
  492. }
  493. }
  494. // Returns true if all the fields of the two tuples contain equal values
  495. // and returns false otherwise.
  496. static auto FieldsValueEqual(const std::vector<TupleElement>& ts1,
  497. const std::vector<TupleElement>& ts2, int line_num)
  498. -> bool {
  499. if (ts1.size() != ts2.size()) {
  500. return false;
  501. }
  502. for (const TupleElement& element : ts1) {
  503. auto iter = std::find_if(
  504. ts2.begin(), ts2.end(),
  505. [&](const TupleElement& e2) { return e2.name == element.name; });
  506. if (iter == ts2.end()) {
  507. return false;
  508. }
  509. if (!ValueEqual(element.value, iter->value, line_num)) {
  510. return false;
  511. }
  512. }
  513. return true;
  514. }
  515. // Returns true if the two values are equal and returns false otherwise.
  516. //
  517. // This function implements the `==` operator of Carbon.
  518. auto ValueEqual(const Value* v1, const Value* v2, int line_num) -> bool {
  519. if (v1->tag() != v2->tag()) {
  520. return false;
  521. }
  522. switch (v1->tag()) {
  523. case ValKind::IntValue:
  524. return v1->GetIntValue() == v2->GetIntValue();
  525. case ValKind::BoolValue:
  526. return v1->GetBoolValue() == v2->GetBoolValue();
  527. case ValKind::PointerValue:
  528. return v1->GetPointerValue() == v2->GetPointerValue();
  529. case ValKind::FunctionValue:
  530. return v1->GetFunctionValue().body == v2->GetFunctionValue().body;
  531. case ValKind::TupleValue:
  532. return FieldsValueEqual(v1->GetTupleValue().elements,
  533. v2->GetTupleValue().elements, line_num);
  534. default:
  535. case ValKind::IntType:
  536. case ValKind::BoolType:
  537. case ValKind::TypeType:
  538. case ValKind::FunctionType:
  539. case ValKind::PointerType:
  540. case ValKind::AutoType:
  541. case ValKind::StructType:
  542. case ValKind::ChoiceType:
  543. case ValKind::ContinuationType:
  544. return TypeEqual(v1, v2);
  545. case ValKind::StructValue:
  546. case ValKind::AlternativeValue:
  547. case ValKind::BindingPlaceholderValue:
  548. case ValKind::AlternativeConstructorValue:
  549. case ValKind::ContinuationValue:
  550. std::cerr << "ValueEqual does not support this kind of value."
  551. << std::endl;
  552. exit(-1);
  553. }
  554. }
  555. } // namespace Carbon