value.cpp 18 KB

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