value.cpp 18 KB

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