value.cpp 18 KB

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